migrations.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2015 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. "errors"
  7. "fmt"
  8. "strings"
  9. "time"
  10. "github.com/Unknwon/com"
  11. "github.com/go-xorm/xorm"
  12. "github.com/gogits/gogs/modules/setting"
  13. )
  14. const _DB_VER = 1
  15. type migration func(*xorm.Engine) error
  16. // The version table. Should have only one row with id==1
  17. type Version struct {
  18. Id int64
  19. Version int64
  20. }
  21. // This is a sequence of migrations. Add new migrations to the bottom of the list.
  22. // If you want to "retire" a migration, replace it with "expiredMigration"
  23. var migrations = []migration{
  24. accessToCollaboration,
  25. }
  26. // Migrate database to current version
  27. func Migrate(x *xorm.Engine) error {
  28. if err := x.Sync(new(Version)); err != nil {
  29. return fmt.Errorf("sync: %v", err)
  30. }
  31. currentVersion := &Version{Id: 1}
  32. has, err := x.Get(currentVersion)
  33. if err != nil {
  34. return fmt.Errorf("get: %v", err)
  35. } else if !has {
  36. needsMigration, err := x.IsTableExist("user")
  37. if err != nil {
  38. return err
  39. }
  40. // if needsMigration {
  41. // isEmpty, err := x.IsTableEmpty("user")
  42. // if err != nil {
  43. // return err
  44. // }
  45. // needsMigration = !isEmpty
  46. // }
  47. if !needsMigration {
  48. currentVersion.Version = int64(len(migrations))
  49. }
  50. if _, err = x.InsertOne(currentVersion); err != nil {
  51. return fmt.Errorf("insert: %v", err)
  52. }
  53. }
  54. v := currentVersion.Version
  55. for i, migration := range migrations[v:] {
  56. if err = migration(x); err != nil {
  57. return fmt.Errorf("run migration: %v", err)
  58. }
  59. currentVersion.Version = v + int64(i) + 1
  60. if _, err = x.Id(1).Update(currentVersion); err != nil {
  61. return err
  62. }
  63. }
  64. return nil
  65. }
  66. func expiredMigration(x *xorm.Engine) error {
  67. return errors.New("You are migrating from a too old gogs version")
  68. }
  69. func accessToCollaboration(x *xorm.Engine) error {
  70. type Collaboration struct {
  71. ID int64 `xorm:"pk autoincr"`
  72. RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
  73. UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
  74. Created time.Time
  75. }
  76. x.Sync(new(Collaboration))
  77. results, err := x.Query("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")
  78. if err != nil {
  79. return err
  80. }
  81. offset := strings.Split(time.Now().String(), " ")[2]
  82. for _, result := range results {
  83. mode := com.StrTo(result["mode"]).MustInt64()
  84. // Collaborators must have write access.
  85. if mode < 2 {
  86. continue
  87. }
  88. userID := com.StrTo(result["uid"]).MustInt64()
  89. repoRefName := string(result["repo"])
  90. var created time.Time
  91. switch {
  92. case setting.UseSQLite3:
  93. created, _ = time.Parse(time.RFC3339, string(result["created"]))
  94. case setting.UseMySQL:
  95. created, _ = time.Parse("2006-01-02 15:04:05-0700", string(result["created"])+offset)
  96. case setting.UsePostgreSQL:
  97. created, _ = time.Parse("2006-01-02T15:04:05Z-0700", string(result["created"])+offset)
  98. }
  99. // find owner of repository
  100. parts := strings.SplitN(repoRefName, "/", 2)
  101. ownerName := parts[0]
  102. repoName := parts[1]
  103. results, err := x.Query("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=?", ownerName)
  104. if err != nil {
  105. return err
  106. }
  107. if len(results) < 1 {
  108. continue
  109. }
  110. ownerID := com.StrTo(results[0]["uid"]).MustInt64()
  111. if ownerID == userID {
  112. continue
  113. }
  114. // test if user is member of owning organization
  115. isMember := false
  116. for _, member := range results {
  117. memberID := com.StrTo(member["memberid"]).MustInt64()
  118. // We can skip all cases that a user is member of the owning organization
  119. if memberID == userID {
  120. isMember = true
  121. }
  122. }
  123. if isMember {
  124. continue
  125. }
  126. results, err = x.Query("SELECT id FROM `repository` WHERE owner_id=? AND lower_name=?", ownerID, repoName)
  127. if err != nil {
  128. return err
  129. }
  130. if len(results) < 1 {
  131. continue
  132. }
  133. if _, err = x.InsertOne(&Collaboration{
  134. UserID: userID,
  135. RepoID: com.StrTo(results[0]["id"]).MustInt64(),
  136. Created: created,
  137. }); err != nil {
  138. return err
  139. }
  140. }
  141. return nil
  142. }