code.gitea.io/gitea@v1.21.7/models/migrations/v1_6/v71.go (about)

     1  // Copyright 2018 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package v1_6 //nolint
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"code.gitea.io/gitea/models/migrations/base"
    10  	"code.gitea.io/gitea/modules/timeutil"
    11  	"code.gitea.io/gitea/modules/util"
    12  
    13  	"xorm.io/xorm"
    14  )
    15  
    16  func AddScratchHash(x *xorm.Engine) error {
    17  	// TwoFactor see models/twofactor.go
    18  	type TwoFactor struct {
    19  		ID               int64 `xorm:"pk autoincr"`
    20  		UID              int64 `xorm:"UNIQUE"`
    21  		Secret           string
    22  		ScratchToken     string
    23  		ScratchSalt      string
    24  		ScratchHash      string
    25  		LastUsedPasscode string             `xorm:"VARCHAR(10)"`
    26  		CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
    27  		UpdatedUnix      timeutil.TimeStamp `xorm:"INDEX updated"`
    28  	}
    29  
    30  	if err := x.Sync(new(TwoFactor)); err != nil {
    31  		return fmt.Errorf("Sync: %w", err)
    32  	}
    33  
    34  	sess := x.NewSession()
    35  	defer sess.Close()
    36  
    37  	if err := sess.Begin(); err != nil {
    38  		return err
    39  	}
    40  
    41  	// transform all tokens to hashes
    42  	const batchSize = 100
    43  	for start := 0; ; start += batchSize {
    44  		tfas := make([]*TwoFactor, 0, batchSize)
    45  		if err := sess.Limit(batchSize, start).Find(&tfas); err != nil {
    46  			return err
    47  		}
    48  		if len(tfas) == 0 {
    49  			break
    50  		}
    51  
    52  		for _, tfa := range tfas {
    53  			// generate salt
    54  			salt, err := util.CryptoRandomString(10)
    55  			if err != nil {
    56  				return err
    57  			}
    58  			tfa.ScratchSalt = salt
    59  			tfa.ScratchHash = base.HashToken(tfa.ScratchToken, salt)
    60  
    61  			if _, err := sess.ID(tfa.ID).Cols("scratch_salt, scratch_hash").Update(tfa); err != nil {
    62  				return fmt.Errorf("couldn't add in scratch_hash and scratch_salt: %w", err)
    63  			}
    64  
    65  		}
    66  	}
    67  
    68  	// Commit and begin new transaction for dropping columns
    69  	if err := sess.Commit(); err != nil {
    70  		return err
    71  	}
    72  	if err := sess.Begin(); err != nil {
    73  		return err
    74  	}
    75  
    76  	if err := base.DropTableColumns(sess, "two_factor", "scratch_token"); err != nil {
    77  		return err
    78  	}
    79  	return sess.Commit()
    80  }