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 }