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  }