code.gitea.io/gitea@v1.21.7/models/migrations/v1_9/v85.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_9 //nolint 5 6 import ( 7 "fmt" 8 9 "code.gitea.io/gitea/models/migrations/base" 10 "code.gitea.io/gitea/modules/log" 11 "code.gitea.io/gitea/modules/timeutil" 12 "code.gitea.io/gitea/modules/util" 13 14 "xorm.io/xorm" 15 ) 16 17 func HashAppToken(x *xorm.Engine) error { 18 // AccessToken see models/token.go 19 type AccessToken struct { 20 ID int64 `xorm:"pk autoincr"` 21 UID int64 `xorm:"INDEX"` 22 Name string 23 Sha1 string 24 Token string `xorm:"-"` 25 TokenHash string // sha256 of token - we will ensure UNIQUE later 26 TokenSalt string 27 TokenLastEight string `xorm:"token_last_eight"` 28 29 CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` 30 UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` 31 HasRecentActivity bool `xorm:"-"` 32 HasUsed bool `xorm:"-"` 33 } 34 35 // First remove the index 36 sess := x.NewSession() 37 defer sess.Close() 38 39 if err := sess.Begin(); err != nil { 40 return err 41 } 42 43 if err := sess.Sync(new(AccessToken)); err != nil { 44 return fmt.Errorf("Sync: %w", err) 45 } 46 47 if err := sess.Commit(); err != nil { 48 return err 49 } 50 51 if err := sess.Begin(); err != nil { 52 return err 53 } 54 55 // transform all tokens to hashes 56 const batchSize = 100 57 for start := 0; ; start += batchSize { 58 tokens := make([]*AccessToken, 0, batchSize) 59 if err := sess.Limit(batchSize, start).Find(&tokens); err != nil { 60 return err 61 } 62 if len(tokens) == 0 { 63 break 64 } 65 66 for _, token := range tokens { 67 // generate salt 68 salt, err := util.CryptoRandomString(10) 69 if err != nil { 70 return err 71 } 72 token.TokenSalt = salt 73 token.TokenHash = base.HashToken(token.Sha1, salt) 74 if len(token.Sha1) < 8 { 75 log.Warn("Unable to transform token %s with name %s belonging to user ID %d, skipping transformation", token.Sha1, token.Name, token.UID) 76 continue 77 } 78 token.TokenLastEight = token.Sha1[len(token.Sha1)-8:] 79 token.Sha1 = "" // ensure to blank out column in case drop column doesn't work 80 81 if _, err := sess.ID(token.ID).Cols("token_hash, token_salt, token_last_eight, sha1").Update(token); err != nil { 82 return fmt.Errorf("couldn't add in sha1, token_hash, token_salt and token_last_eight: %w", err) 83 } 84 85 } 86 } 87 88 // Commit and begin new transaction for dropping columns 89 if err := sess.Commit(); err != nil { 90 return err 91 } 92 if err := sess.Begin(); err != nil { 93 return err 94 } 95 96 if err := base.DropTableColumns(sess, "access_token", "sha1"); err != nil { 97 return err 98 } 99 if err := sess.Commit(); err != nil { 100 return err 101 } 102 return resyncHashAppTokenWithUniqueHash(x) 103 } 104 105 func resyncHashAppTokenWithUniqueHash(x *xorm.Engine) error { 106 // AccessToken see models/token.go 107 type AccessToken struct { 108 TokenHash string `xorm:"UNIQUE"` // sha256 of token - we will ensure UNIQUE later 109 } 110 sess := x.NewSession() 111 defer sess.Close() 112 if err := sess.Begin(); err != nil { 113 return err 114 } 115 if err := sess.Sync(new(AccessToken)); err != nil { 116 return fmt.Errorf("Sync: %w", err) 117 } 118 return sess.Commit() 119 }