You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.1 KiB

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