v20.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // Copyright 2022 The Gogs 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. "github.com/pkg/errors"
  7. "gorm.io/gorm"
  8. "gogs.io/gogs/internal/cryptoutil"
  9. )
  10. func migrateAccessTokenToSHA256(db *gorm.DB) error {
  11. type accessToken struct {
  12. ID int64
  13. Sha1 string
  14. SHA256 string `gorm:"TYPE:VARCHAR(64)"`
  15. }
  16. if db.Migrator().HasColumn(&accessToken{}, "SHA256") {
  17. return errMigrationSkipped
  18. }
  19. return db.Transaction(func(tx *gorm.DB) error {
  20. // 1. Add column without constraints because all rows have NULL values for the
  21. // "sha256" column.
  22. err := tx.Migrator().AddColumn(&accessToken{}, "SHA256")
  23. if err != nil {
  24. return errors.Wrap(err, "add column")
  25. }
  26. // 2. Generate SHA256 for existing rows from their values in the "sha1" column.
  27. var accessTokens []*accessToken
  28. err = tx.Where("sha256 IS NULL").Find(&accessTokens).Error
  29. if err != nil {
  30. return errors.Wrap(err, "list")
  31. }
  32. for _, t := range accessTokens {
  33. sha256 := cryptoutil.SHA256(t.Sha1)
  34. err = tx.Model(&accessToken{}).Where("id = ?", t.ID).Update("sha256", sha256).Error
  35. if err != nil {
  36. return errors.Wrap(err, "update")
  37. }
  38. }
  39. // 3. We are now safe to apply constraints to the "sha256" column.
  40. type accessTokenWithConstraint struct {
  41. SHA256 string `gorm:"type:VARCHAR(64);unique;not null"`
  42. }
  43. err = tx.Table("access_token").AutoMigrate(&accessTokenWithConstraint{})
  44. if err != nil {
  45. return errors.Wrap(err, "auto migrate")
  46. }
  47. return nil
  48. })
  49. }