Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

transfer.go 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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 repository
  5. import (
  6. "fmt"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/models/db"
  9. "code.gitea.io/gitea/models/perm"
  10. repo_model "code.gitea.io/gitea/models/repo"
  11. user_model "code.gitea.io/gitea/models/user"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/notification"
  14. "code.gitea.io/gitea/modules/sync"
  15. )
  16. // repoWorkingPool represents a working pool to order the parallel changes to the same repository
  17. var repoWorkingPool = sync.NewExclusivePool()
  18. // TransferOwnership transfers all corresponding setting from old user to new one.
  19. func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*models.Team) error {
  20. if err := repo.GetOwner(db.DefaultContext); err != nil {
  21. return err
  22. }
  23. for _, team := range teams {
  24. if newOwner.ID != team.OrgID {
  25. return fmt.Errorf("team %d does not belong to organization", team.ID)
  26. }
  27. }
  28. oldOwner := repo.Owner
  29. repoWorkingPool.CheckIn(fmt.Sprint(repo.ID))
  30. if err := models.TransferOwnership(doer, newOwner.Name, repo); err != nil {
  31. repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
  32. return err
  33. }
  34. repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
  35. newRepo, err := repo_model.GetRepositoryByID(repo.ID)
  36. if err != nil {
  37. return err
  38. }
  39. for _, team := range teams {
  40. if err := team.AddRepository(newRepo); err != nil {
  41. return err
  42. }
  43. }
  44. notification.NotifyTransferRepository(doer, repo, oldOwner.Name)
  45. return nil
  46. }
  47. // ChangeRepositoryName changes all corresponding setting from old repository name to new one.
  48. func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, newRepoName string) error {
  49. log.Trace("ChangeRepositoryName: %s/%s -> %s", doer.Name, repo.Name, newRepoName)
  50. oldRepoName := repo.Name
  51. // Change repository directory name. We must lock the local copy of the
  52. // repo so that we can atomically rename the repo path and updates the
  53. // local copy's origin accordingly.
  54. repoWorkingPool.CheckIn(fmt.Sprint(repo.ID))
  55. if err := repo_model.ChangeRepositoryName(doer, repo, newRepoName); err != nil {
  56. repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
  57. return err
  58. }
  59. repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
  60. repo.Name = newRepoName
  61. notification.NotifyRenameRepository(doer, repo, oldRepoName)
  62. return nil
  63. }
  64. // StartRepositoryTransfer transfer a repo from one owner to a new one.
  65. // it make repository into pending transfer state, if doer can not create repo for new owner.
  66. func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*models.Team) error {
  67. if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
  68. return err
  69. }
  70. // Admin is always allowed to transfer || user transfer repo back to his account
  71. if doer.IsAdmin || doer.ID == newOwner.ID {
  72. return TransferOwnership(doer, newOwner, repo, teams)
  73. }
  74. // If new owner is an org and user can create repos he can transfer directly too
  75. if newOwner.IsOrganization() {
  76. allowed, err := models.CanCreateOrgRepo(newOwner.ID, doer.ID)
  77. if err != nil {
  78. return err
  79. }
  80. if allowed {
  81. return TransferOwnership(doer, newOwner, repo, teams)
  82. }
  83. }
  84. // In case the new owner would not have sufficient access to the repo, give access rights for read
  85. hasAccess, err := models.HasAccess(newOwner.ID, repo)
  86. if err != nil {
  87. return err
  88. }
  89. if !hasAccess {
  90. if err := models.AddCollaborator(repo, newOwner); err != nil {
  91. return err
  92. }
  93. if err := models.ChangeCollaborationAccessMode(repo, newOwner.ID, perm.AccessModeRead); err != nil {
  94. return err
  95. }
  96. }
  97. // Make repo as pending for transfer
  98. repo.Status = repo_model.RepositoryPendingTransfer
  99. if err := models.CreatePendingRepositoryTransfer(doer, newOwner, repo.ID, teams); err != nil {
  100. return err
  101. }
  102. // notify users who are able to accept / reject transfer
  103. notification.NotifyRepoPendingTransfer(doer, newOwner, repo)
  104. return nil
  105. }