github.com/adecaro/fabric-ca@v2.0.0-alpha+incompatible/lib/server/db/postgres/migrator.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package postgres 8 9 import ( 10 "strings" 11 12 "github.com/cloudflare/cfssl/log" 13 "github.com/hyperledger/fabric-ca/lib/server/db" 14 "github.com/hyperledger/fabric-ca/lib/server/db/util" 15 "github.com/hyperledger/fabric-ca/lib/server/user" 16 "github.com/pkg/errors" 17 ) 18 19 // Migrator defines migrator 20 type Migrator struct { 21 Tx db.FabricCATx 22 CurLevels *util.Levels 23 SrvLevels *util.Levels 24 } 25 26 // NewMigrator returns a migrator instance 27 func NewMigrator(tx db.FabricCATx, curLevels, srvLevels *util.Levels) *Migrator { 28 return &Migrator{ 29 Tx: tx, 30 CurLevels: curLevels, 31 SrvLevels: srvLevels, 32 } 33 } 34 35 // MigrateUsersTable is responsible for migrating users table 36 func (m *Migrator) MigrateUsersTable() error { 37 tx := m.Tx 38 // Future schema updates should add to the logic below to handle other levels 39 curLevel := m.CurLevels.Identity 40 res := []struct { 41 columnName string `db:"column_name"` 42 }{} 43 const funcName = "MigrateUsersTable" 44 if curLevel < 1 { 45 log.Debug("Upgrade identity table to level 1") 46 _, err := tx.Exec(funcName, "ALTER TABLE users ALTER COLUMN id TYPE VARCHAR(255), ALTER COLUMN type TYPE VARCHAR(256), ALTER COLUMN affiliation TYPE VARCHAR(1024)") 47 if err != nil { 48 return err 49 } 50 _, err = tx.Exec(funcName, "ALTER TABLE users ALTER COLUMN attributes TYPE TEXT") 51 if err != nil { 52 return err 53 } 54 query := "SELECT column_name FROM information_schema.columns WHERE table_name='users' and column_name='level'" 55 err = tx.Select(funcName, &res, tx.Rebind(query)) 56 if err != nil { 57 return err 58 } 59 if len(res) == 0 { 60 _, err = tx.Exec(funcName, "ALTER TABLE users ADD COLUMN level INTEGER DEFAULT 0") 61 if err != nil { 62 if !strings.Contains(err.Error(), "already exists") { 63 return err 64 } 65 } 66 } 67 curLevel++ 68 } 69 if curLevel < 2 { 70 log.Debug("Upgrade identity table to level 2") 71 query := "SELECT column_name FROM information_schema.columns WHERE table_name='users' and column_name='incorrect_password_attempts'" 72 err := tx.Select(funcName, &res, tx.Rebind(query)) 73 if err != nil { 74 return err 75 } 76 if len(res) == 0 { 77 _, err = tx.Exec(funcName, "ALTER TABLE users ADD COLUMN incorrect_password_attempts INTEGER DEFAULT 0") 78 if err != nil { 79 if !strings.Contains(err.Error(), "already exists") { 80 return err 81 } 82 } 83 } 84 curLevel++ 85 } 86 87 users, err := user.GetUserLessThanLevel(tx, m.SrvLevels.Identity) 88 if err != nil { 89 return err 90 } 91 92 for _, u := range users { 93 err := u.Migrate(tx) 94 if err != nil { 95 return err 96 } 97 } 98 99 _, err = tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'identity.level')"), m.SrvLevels.Identity) 100 if err != nil { 101 return err 102 } 103 return nil 104 } 105 106 // MigrateCertificatesTable is responsible for migrating certificates table 107 func (m *Migrator) MigrateCertificatesTable() error { 108 tx := m.Tx 109 const funcName = "MigrateCertificatesTable" 110 // Future schema updates should add to the logic below to handle other levels 111 if m.CurLevels.Certificate < 1 { 112 log.Debug("Upgrade certificates table to level 1") 113 res := []struct { 114 columnName string `db:"column_name"` 115 }{} 116 query := "SELECT column_name FROM information_schema.columns WHERE table_name='certificates' and column_name='level'" 117 err := tx.Select(funcName, &res, tx.Rebind(query)) 118 if err != nil { 119 return err 120 } 121 if len(res) == 0 { 122 _, err := tx.Exec(funcName, "ALTER TABLE certificates ADD COLUMN level INTEGER DEFAULT 0") 123 if err != nil { 124 if !strings.Contains(err.Error(), "already exists") { 125 return err 126 } 127 } 128 } 129 _, err = tx.Exec(funcName, "ALTER TABLE certificates ALTER COLUMN id TYPE VARCHAR(255)") 130 if err != nil { 131 return err 132 } 133 } 134 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'certificate.level')"), m.SrvLevels.Certificate) 135 if err != nil { 136 return err 137 } 138 return nil 139 } 140 141 // MigrateAffiliationsTable is responsible for migrating affiliations table 142 func (m *Migrator) MigrateAffiliationsTable() error { 143 tx := m.Tx 144 const funcName = "MigrateAffiliationsTable" 145 // Future schema updates should add to the logic below to handle other levels 146 if m.CurLevels.Affiliation < 1 { 147 log.Debug("Upgrade affiliations table to level 1") 148 res := []struct { 149 columnName string `db:"column_name"` 150 }{} 151 query := "SELECT column_name FROM information_schema.columns WHERE table_name='affiliations' and column_name='level'" 152 err := tx.Select(funcName, &res, tx.Rebind(query)) 153 if err != nil { 154 return err 155 } 156 if len(res) == 0 { 157 _, err := tx.Exec(funcName, "ALTER TABLE affiliations ADD COLUMN level INTEGER DEFAULT 0") 158 if err != nil { 159 if !strings.Contains(err.Error(), "already exists") { 160 return err 161 } 162 } 163 } 164 _, err = tx.Exec(funcName, "ALTER TABLE affiliations ALTER COLUMN name TYPE VARCHAR(1024), ALTER COLUMN prekey TYPE VARCHAR(1024)") 165 if err != nil { 166 return err 167 } 168 } 169 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'affiliation.level')"), m.SrvLevels.Affiliation) 170 if err != nil { 171 return err 172 } 173 return nil 174 } 175 176 // MigrateCredentialsTable is responsible for migrating credentials table 177 func (m *Migrator) MigrateCredentialsTable() error { 178 _, err := m.Tx.Exec("MigrateCredentialsTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'credential.level')"), m.SrvLevels.Credential) 179 return err 180 } 181 182 // MigrateRAInfoTable is responsible for migrating rainfo table 183 func (m *Migrator) MigrateRAInfoTable() error { 184 _, err := m.Tx.Exec("MigrateRAInfoTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'rcinfo.level')"), m.SrvLevels.RAInfo) 185 return err 186 } 187 188 // MigrateNoncesTable is responsible for migrating nonces table 189 func (m *Migrator) MigrateNoncesTable() error { 190 _, err := m.Tx.Exec("MigrateNoncesTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'nonce.level')"), m.SrvLevels.Nonce) 191 return err 192 } 193 194 // Rollback is responsible for rollback transaction if an error is encountered 195 func (m *Migrator) Rollback() error { 196 err := m.Tx.Rollback("Migration") 197 if err != nil { 198 log.Errorf("Error encountered while rolling back database migration changes: %s", err) 199 return err 200 } 201 return nil 202 } 203 204 // Commit is responsible for committing the migration db transcation 205 func (m *Migrator) Commit() error { 206 err := m.Tx.Commit("Migration") 207 if err != nil { 208 return errors.Wrap(err, "Error encountered while committing database migration changes") 209 } 210 return nil 211 }