github.com/hyperledger/fabric-ca@v2.0.0-alpha.0.20201120210307-7b4f34729db1+incompatible/lib/server/db/mysql/migrator.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package mysql 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 const funcName = "MigrateUsersTable" 39 // Future schema updates should add to the logic below to handle other levels 40 curLevel := m.CurLevels.Identity 41 if curLevel < 1 { 42 log.Debug("Upgrade identity table to level 1") 43 _, err := tx.Exec(funcName, "ALTER TABLE users MODIFY id VARCHAR(255), MODIFY type VARCHAR(256), MODIFY affiliation VARCHAR(1024)") 44 if err != nil { 45 return err 46 } 47 _, err = tx.Exec(funcName, "ALTER TABLE users MODIFY attributes TEXT") 48 if err != nil { 49 return err 50 } 51 _, err = tx.Exec(funcName, "ALTER TABLE users ADD COLUMN level INTEGER DEFAULT 0 AFTER max_enrollments") 52 if err != nil { 53 if !strings.Contains(err.Error(), "1060") { // Already using the latest schema 54 return err 55 } 56 } 57 curLevel++ 58 } 59 if curLevel < 2 { 60 log.Debug("Upgrade identity table to level 2") 61 _, err := tx.Exec(funcName, "ALTER TABLE users ADD COLUMN incorrect_password_attempts INTEGER DEFAULT 0 AFTER level") 62 if err != nil { 63 if !strings.Contains(err.Error(), "1060") { // Already using the latest schema 64 return err 65 } 66 } 67 curLevel++ 68 } 69 70 users, err := user.GetUserLessThanLevel(tx, m.SrvLevels.Identity) 71 if err != nil { 72 return err 73 } 74 75 for _, u := range users { 76 err := u.Migrate(tx) 77 if err != nil { 78 return err 79 } 80 } 81 82 _, err = tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'identity.level')"), m.SrvLevels.Identity) 83 if err != nil { 84 return err 85 } 86 return nil 87 } 88 89 // MigrateCertificatesTable is responsible for migrating certificates table 90 func (m *Migrator) MigrateCertificatesTable() error { 91 tx := m.Tx 92 const funcName = "MigrateCertificatesTable" 93 // Future schema updates should add to the logic below to handle other levels 94 curLevel := m.CurLevels.Certificate 95 if curLevel < 1 { 96 log.Debug("Upgrade certificates table to level 1") 97 _, err := tx.Exec(funcName, "ALTER TABLE certificates ADD COLUMN level INTEGER DEFAULT 0 AFTER pem") 98 if err != nil { 99 if !strings.Contains(err.Error(), "1060") { // Already using the latest schema 100 return err 101 } 102 } 103 _, err = tx.Exec(funcName, "ALTER TABLE certificates MODIFY id VARCHAR(255)") 104 if err != nil { 105 return err 106 } 107 curLevel++ 108 } 109 if curLevel < 2 { 110 log.Debug("Upgrade certificates table to level 2") 111 _, err := tx.Exec(funcName, "ALTER TABLE certificates MODIFY pem varbinary(8192)") 112 if err != nil { 113 return err 114 } 115 curLevel++ 116 } 117 118 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'certificate.level')"), m.SrvLevels.Certificate) 119 if err != nil { 120 return err 121 } 122 return nil 123 } 124 125 // MigrateAffiliationsTable is responsible for migrating affiliations table 126 func (m *Migrator) MigrateAffiliationsTable() error { 127 tx := m.Tx 128 const funcName = "MigrateAffiliationsTable" 129 // Future schema updates should add to the logic below to handle other levels 130 if m.CurLevels.Affiliation < 1 { 131 log.Debug("Upgrade affiliations table to level 1") 132 _, err := tx.Exec(funcName, "ALTER TABLE affiliations ADD COLUMN level INTEGER DEFAULT 0 AFTER prekey") 133 if err != nil { 134 if !strings.Contains(err.Error(), "1060") { // Already using the latest schema 135 return err 136 } 137 } 138 _, err = tx.Exec(funcName, "ALTER TABLE affiliations DROP INDEX name;") 139 if err != nil { 140 if !strings.Contains(err.Error(), "Error 1091") { // Indicates that index not found 141 return err 142 } 143 } 144 _, err = tx.Exec(funcName, "ALTER TABLE affiliations ADD COLUMN id INT NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST") 145 if err != nil { 146 if !strings.Contains(err.Error(), "1060") { // Already using the latest schema 147 return err 148 } 149 } 150 _, err = tx.Exec(funcName, "ALTER TABLE affiliations MODIFY name VARCHAR(1024), MODIFY prekey VARCHAR(1024)") 151 if err != nil { 152 return err 153 } 154 _, err = tx.Exec(funcName, "ALTER TABLE affiliations ADD INDEX name_index (name)") 155 if err != nil { 156 if !strings.Contains(err.Error(), "Error 1061") { // Error 1061: Duplicate key name, index already exists 157 return err 158 } 159 } 160 } 161 162 _, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'affiliation.level')"), m.SrvLevels.Affiliation) 163 if err != nil { 164 return err 165 } 166 167 return nil 168 } 169 170 // MigrateCredentialsTable is responsible for migrating credentials table 171 func (m *Migrator) MigrateCredentialsTable() error { 172 _, err := m.Tx.Exec("MigrateCredentialsTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'credential.level')"), m.SrvLevels.Credential) 173 return err 174 } 175 176 // MigrateRAInfoTable is responsible for migrating rainfo table 177 func (m *Migrator) MigrateRAInfoTable() error { 178 _, err := m.Tx.Exec("MigrateRAInfoTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'rcinfo.level')"), m.SrvLevels.RAInfo) 179 return err 180 } 181 182 // MigrateNoncesTable is responsible for migrating nonces table 183 func (m *Migrator) MigrateNoncesTable() error { 184 _, err := m.Tx.Exec("MigrateNoncesTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'nonce.level')"), m.SrvLevels.Nonce) 185 return err 186 } 187 188 // Rollback is responsible for rollback transaction if an error is encountered 189 func (m *Migrator) Rollback() error { 190 err := m.Tx.Rollback("Migration") 191 if err != nil { 192 log.Errorf("Error encountered while rolling back database migration changes: %s", err) 193 return err 194 } 195 return nil 196 } 197 198 // Commit is responsible for committing the migration db transcation 199 func (m *Migrator) Commit() error { 200 err := m.Tx.Commit("Migration") 201 if err != nil { 202 return errors.Wrap(err, "Error encountered while committing database migration changes") 203 } 204 return nil 205 }