github.com/adecaro/fabric-ca@v2.0.0-alpha+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  	if m.CurLevels.Certificate < 1 {
    95  		log.Debug("Upgrade certificates table to level 1")
    96  		_, err := tx.Exec(funcName, "ALTER TABLE certificates ADD COLUMN level INTEGER DEFAULT 0 AFTER pem")
    97  		if err != nil {
    98  			if !strings.Contains(err.Error(), "1060") { // Already using the latest schema
    99  				return err
   100  			}
   101  		}
   102  		_, err = tx.Exec(funcName, "ALTER TABLE certificates MODIFY id VARCHAR(255)")
   103  		if err != nil {
   104  			return err
   105  		}
   106  	}
   107  	_, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'certificate.level')"), m.SrvLevels.Certificate)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	return nil
   112  }
   113  
   114  // MigrateAffiliationsTable is responsible for migrating affiliations table
   115  func (m *Migrator) MigrateAffiliationsTable() error {
   116  	tx := m.Tx
   117  	const funcName = "MigrateAffiliationsTable"
   118  	// Future schema updates should add to the logic below to handle other levels
   119  	if m.CurLevels.Affiliation < 1 {
   120  		log.Debug("Upgrade affiliations table to level 1")
   121  		_, err := tx.Exec(funcName, "ALTER TABLE affiliations ADD COLUMN level INTEGER DEFAULT 0 AFTER prekey")
   122  		if err != nil {
   123  			if !strings.Contains(err.Error(), "1060") { // Already using the latest schema
   124  				return err
   125  			}
   126  		}
   127  		_, err = tx.Exec(funcName, "ALTER TABLE affiliations DROP INDEX name;")
   128  		if err != nil {
   129  			if !strings.Contains(err.Error(), "Error 1091") { // Indicates that index not found
   130  				return err
   131  			}
   132  		}
   133  		_, err = tx.Exec(funcName, "ALTER TABLE affiliations ADD COLUMN id INT NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST")
   134  		if err != nil {
   135  			if !strings.Contains(err.Error(), "1060") { // Already using the latest schema
   136  				return err
   137  			}
   138  		}
   139  		_, err = tx.Exec(funcName, "ALTER TABLE affiliations MODIFY name VARCHAR(1024), MODIFY prekey VARCHAR(1024)")
   140  		if err != nil {
   141  			return err
   142  		}
   143  		_, err = tx.Exec(funcName, "ALTER TABLE affiliations ADD INDEX name_index (name)")
   144  		if err != nil {
   145  			if !strings.Contains(err.Error(), "Error 1061") { // Error 1061: Duplicate key name, index already exists
   146  				return err
   147  			}
   148  		}
   149  	}
   150  
   151  	_, err := tx.Exec(funcName, tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'affiliation.level')"), m.SrvLevels.Affiliation)
   152  	if err != nil {
   153  		return err
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  // MigrateCredentialsTable is responsible for migrating credentials table
   160  func (m *Migrator) MigrateCredentialsTable() error {
   161  	_, err := m.Tx.Exec("MigrateCredentialsTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'credential.level')"), m.SrvLevels.Credential)
   162  	return err
   163  }
   164  
   165  // MigrateRAInfoTable is responsible for migrating rainfo table
   166  func (m *Migrator) MigrateRAInfoTable() error {
   167  	_, err := m.Tx.Exec("MigrateRAInfoTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'rcinfo.level')"), m.SrvLevels.RAInfo)
   168  	return err
   169  }
   170  
   171  // MigrateNoncesTable is responsible for migrating nonces table
   172  func (m *Migrator) MigrateNoncesTable() error {
   173  	_, err := m.Tx.Exec("MigrateNoncesTable", m.Tx.Rebind("UPDATE properties SET value = ? WHERE (property = 'nonce.level')"), m.SrvLevels.Nonce)
   174  	return err
   175  }
   176  
   177  // Rollback is responsible for rollback transaction if an error is encountered
   178  func (m *Migrator) Rollback() error {
   179  	err := m.Tx.Rollback("Migration")
   180  	if err != nil {
   181  		log.Errorf("Error encountered while rolling back database migration changes: %s", err)
   182  		return err
   183  	}
   184  	return nil
   185  }
   186  
   187  // Commit is responsible for committing the migration db transcation
   188  func (m *Migrator) Commit() error {
   189  	err := m.Tx.Commit("Migration")
   190  	if err != nil {
   191  		return errors.Wrap(err, "Error encountered while committing database migration changes")
   192  	}
   193  	return nil
   194  }