github.com/adecaro/fabric-ca@v2.0.0-alpha+incompatible/lib/server/db/sqlite/migrator.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package sqlite 8 9 import ( 10 "github.com/cloudflare/cfssl/log" 11 "github.com/hyperledger/fabric-ca/lib/server/db" 12 "github.com/hyperledger/fabric-ca/lib/server/db/util" 13 "github.com/hyperledger/fabric-ca/lib/server/user" 14 "github.com/pkg/errors" 15 ) 16 17 // Migrator defines migrator 18 type Migrator struct { 19 Tx db.FabricCATx 20 CurLevels *util.Levels 21 SrvLevels *util.Levels 22 } 23 24 // NewMigrator returns a migrator instance 25 func NewMigrator(tx db.FabricCATx, curLevels, srvLevels *util.Levels) *Migrator { 26 return &Migrator{ 27 Tx: tx, 28 CurLevels: curLevels, 29 SrvLevels: srvLevels, 30 } 31 } 32 33 // MigrateUsersTable is responsible for migrating users table 34 func (m *Migrator) MigrateUsersTable() error { 35 tx := m.Tx 36 const funcName = "MigrateUsersTable" 37 // Future schema updates should add to the logic below to handle other levels 38 curLevel := m.CurLevels.Identity 39 if curLevel < 1 { 40 log.Debug("Upgrade identity table to level 1") 41 _, err := tx.Exec(funcName, "ALTER TABLE users RENAME TO users_old") 42 if err != nil { 43 return err 44 } 45 err = createIdentityTable(tx) 46 if err != nil { 47 return err 48 } 49 // If coming from a table that did not yet have the level column then we can only copy columns that exist in both the tables 50 _, err = tx.Exec(funcName, "INSERT INTO users (id, token, type, affiliation, attributes, state, max_enrollments) SELECT id, token, type, affiliation, attributes, state, max_enrollments FROM users_old") 51 if err != nil { 52 return err 53 } 54 _, err = tx.Exec(funcName, "DROP TABLE users_old") 55 if err != nil { 56 return err 57 } 58 curLevel++ 59 } 60 if curLevel < 2 { 61 log.Debug("Upgrade identity table to level 2") 62 _, err := tx.Exec(funcName, "ALTER TABLE users RENAME TO users_old") 63 if err != nil { 64 return err 65 } 66 err = createIdentityTable(tx) 67 if err != nil { 68 return err 69 } 70 // If coming from a table that did not yet have the level column then we can only copy columns that exist in both the tables 71 _, err = tx.Exec(funcName, "INSERT INTO users (id, token, type, affiliation, attributes, state, max_enrollments, level) SELECT id, token, type, affiliation, attributes, state, max_enrollments, level FROM users_old") 72 if err != nil { 73 return err 74 } 75 _, err = tx.Exec(funcName, "DROP TABLE users_old") 76 if err != nil { 77 return err 78 } 79 curLevel++ 80 } 81 82 users, err := user.GetUserLessThanLevel(tx, m.SrvLevels.Identity) 83 if err != nil { 84 return err 85 } 86 87 for _, u := range users { 88 err := u.Migrate(tx) 89 if err != nil { 90 return err 91 } 92 } 93 94 _, err = tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'identity.level')"), m.SrvLevels.Identity) 95 if err != nil { 96 return err 97 } 98 return nil 99 } 100 101 // MigrateCertificatesTable is responsible for migrating certificates table 102 // SQLite has limited support for altering table columns, to upgrade the schema we 103 // require renaming the current certificates table to certificates_old and then creating a new certificates 104 // table using the new schema definition. Next, we proceed to copy the data from the old table to 105 // new table, and then drop the old table. 106 func (m *Migrator) MigrateCertificatesTable() error { 107 tx := m.Tx 108 const funcName = "MigrateCertificatesTable" 109 // Future schema updates should add to the logic below to handle other levels 110 if m.CurLevels.Certificate < 1 { 111 log.Debug("Upgrade certificates table to level 1") 112 _, err := tx.Exec(funcName, "ALTER TABLE certificates RENAME TO certificates_old") 113 if err != nil { 114 return err 115 } 116 err = createCertificateTable(tx) 117 if err != nil { 118 return err 119 } 120 // If coming from a table that did not yet have the level column then we can only copy columns that exist in both the tables 121 _, err = tx.Exec(funcName, "INSERT INTO certificates (id, serial_number, authority_key_identifier, ca_label, status, reason, expiry, revoked_at, pem) SELECT id, serial_number, authority_key_identifier, ca_label, status, reason, expiry, revoked_at, pem FROM certificates_old") 122 if err != nil { 123 return err 124 } 125 _, err = tx.Exec(funcName, "DROP TABLE certificates_old") 126 if err != nil { 127 return err 128 } 129 } 130 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'certificate.level')"), m.SrvLevels.Certificate) 131 if err != nil { 132 return err 133 } 134 return nil 135 } 136 137 // MigrateAffiliationsTable is responsible for migrating affiliations table 138 // SQLite has limited support for altering table columns, to upgrade the schema we 139 // require renaming the current affiliations table to affiliations_old and then creating a new user 140 // table using the new schema definition. Next, we proceed to copy the data from the old table to 141 // new table, and then drop the old 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 _, err := tx.Exec(funcName, "ALTER TABLE affiliations RENAME TO affiliations_old") 149 if err != nil { 150 return err 151 } 152 err = createAffiliationTable(tx) 153 if err != nil { 154 return err 155 } 156 // If coming from a table that did not yet have the level column then we can only copy columns that exist in both the tables 157 _, err = tx.Exec(funcName, "INSERT INTO affiliations (name, prekey) SELECT name, prekey FROM affiliations_old") 158 if err != nil { 159 return err 160 } 161 _, err = tx.Exec(funcName, "DROP TABLE affiliations_old") 162 if err != nil { 163 return err 164 } 165 } 166 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'affiliation.level')"), m.SrvLevels.Affiliation) 167 if err != nil { 168 return err 169 } 170 return nil 171 } 172 173 // MigrateCredentialsTable is responsible for migrating credentials table 174 func (m *Migrator) MigrateCredentialsTable() error { 175 _, err := m.Tx.Exec("MigrateCredentialsTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'credential.level')"), m.SrvLevels.Credential) 176 return err 177 } 178 179 // MigrateRAInfoTable is responsible for migrating rainfo table 180 func (m *Migrator) MigrateRAInfoTable() error { 181 _, err := m.Tx.Exec("MigrateRAInfoTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'rcinfo.level')"), m.SrvLevels.RAInfo) 182 return err 183 } 184 185 // MigrateNoncesTable is responsible for migrating nonces table 186 func (m *Migrator) MigrateNoncesTable() error { 187 _, err := m.Tx.Exec("MigrateNoncesTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'nonce.level')"), m.SrvLevels.Nonce) 188 return err 189 } 190 191 // Rollback is responsible for rollback transaction if an error is encountered 192 func (m *Migrator) Rollback() error { 193 err := m.Tx.Rollback("Migration") 194 if err != nil { 195 log.Errorf("Error encountered while rolling back database migration changes: %s", err) 196 return err 197 } 198 return nil 199 } 200 201 // Commit is responsible for committing the migration db transcation 202 func (m *Migrator) Commit() error { 203 err := m.Tx.Commit("Migration") 204 if err != nil { 205 return errors.Wrap(err, "Error encountered while committing database migration changes") 206 } 207 return nil 208 }