migrations.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package migrations
  2. import (
  3. "errors"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "github.com/go-xorm/xorm"
  8. )
  9. type migration func(*xorm.Engine) error
  10. // The version table. Should have only one row with id==1
  11. type Version struct {
  12. Id int64
  13. Version int64
  14. }
  15. // This is a sequence of migrations. Add new migrations to the bottom of the list.
  16. // If you want to "retire" a migration, replace it with "expiredMigration"
  17. var migrations = []migration{
  18. accessToCollaboration,
  19. accessRefactor,
  20. }
  21. // Migrate database to current version
  22. func Migrate(x *xorm.Engine) error {
  23. if err := x.Sync(new(Version)); err != nil {
  24. return err
  25. }
  26. currentVersion := &Version{Id: 1}
  27. has, err := x.Get(currentVersion)
  28. if err != nil {
  29. return err
  30. } else if !has {
  31. needsMigration, err := x.IsTableExist("user")
  32. if err != nil {
  33. return err
  34. }
  35. if needsMigration {
  36. isEmpty, err := x.IsTableEmpty("user")
  37. if err != nil {
  38. return err
  39. }
  40. needsMigration = !isEmpty
  41. }
  42. if !needsMigration {
  43. currentVersion.Version = int64(len(migrations))
  44. }
  45. if _, err = x.InsertOne(currentVersion); err != nil {
  46. return err
  47. }
  48. }
  49. v := currentVersion.Version
  50. for i, migration := range migrations[v:] {
  51. if err = migration(x); err != nil {
  52. return err
  53. }
  54. currentVersion.Version = v + int64(i) + 1
  55. if _, err = x.Id(1).Update(currentVersion); err != nil {
  56. return err
  57. }
  58. }
  59. return nil
  60. }
  61. func expiredMigration(x *xorm.Engine) error {
  62. return errors.New("You are migrating from a too old gogs version")
  63. }
  64. func mustParseInt64(in []byte) int64 {
  65. i, err := strconv.ParseInt(string(in), 10, 64)
  66. if err != nil {
  67. i = 0
  68. }
  69. return i
  70. }
  71. func accessToCollaboration(x *xorm.Engine) error {
  72. type Collaboration struct {
  73. ID int64 `xorm:"pk autoincr"`
  74. RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
  75. UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
  76. Created time.Time `xorm:"CREATED"`
  77. }
  78. x.Sync(new(Collaboration))
  79. sql := `SELECT u.id AS uid, a.repo_name AS repo, a.mode AS mode, a.created as created FROM access a JOIN user u ON a.user_name=u.lower_name`
  80. results, err := x.Query(sql)
  81. if err != nil {
  82. return err
  83. }
  84. for _, result := range results {
  85. userID := mustParseInt64(result["uid"])
  86. repoRefName := string(result["repo"])
  87. mode := mustParseInt64(result["mode"])
  88. created := result["created"]
  89. //Collaborators must have write access
  90. if mode < 2 {
  91. continue
  92. }
  93. // find owner of repository
  94. parts := strings.SplitN(repoRefName, "/", 2)
  95. ownerName := parts[0]
  96. repoName := parts[1]
  97. sql = `SELECT u.id as uid, ou.uid as memberid FROM user u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?`
  98. results, err := x.Query(sql, ownerName)
  99. if err != nil {
  100. return err
  101. }
  102. if len(results) < 1 {
  103. continue
  104. }
  105. ownerID := mustParseInt64(results[0]["uid"])
  106. if ownerID == userID {
  107. continue
  108. }
  109. // test if user is member of owning organization
  110. isMember := false
  111. for _, member := range results {
  112. memberID := mustParseInt64(member["memberid"])
  113. // We can skip all cases that a user is member of the owning organization
  114. if memberID == userID {
  115. isMember = true
  116. }
  117. }
  118. if isMember {
  119. continue
  120. }
  121. sql = `SELECT id FROM repository WHERE owner_id=? AND lower_name=?`
  122. results, err = x.Query(sql, ownerID, repoName)
  123. if err != nil {
  124. return err
  125. }
  126. if len(results) < 1 {
  127. continue
  128. }
  129. repoID := results[0]["id"]
  130. sql = `INSERT INTO collaboration (user_id, repo_id, created) VALUES (?,?,?)`
  131. _, err = x.Exec(sql, userID, repoID, created)
  132. if err != nil {
  133. return err
  134. }
  135. }
  136. return nil
  137. }
  138. func accessRefactor(x *xorm.Engine) error {
  139. //TODO
  140. return nil
  141. }