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.

repo_collaboration.go 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright 2016 The Gogs Authors. All rights reserved.
  2. // Copyright 2020 The Gitea Authors.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package models
  6. import (
  7. "context"
  8. "fmt"
  9. "code.gitea.io/gitea/models/db"
  10. "code.gitea.io/gitea/models/organization"
  11. "code.gitea.io/gitea/models/perm"
  12. access_model "code.gitea.io/gitea/models/perm/access"
  13. repo_model "code.gitea.io/gitea/models/repo"
  14. "code.gitea.io/gitea/models/unit"
  15. user_model "code.gitea.io/gitea/models/user"
  16. "xorm.io/builder"
  17. )
  18. func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
  19. collaboration := &repo_model.Collaboration{
  20. RepoID: repo.ID,
  21. UserID: u.ID,
  22. }
  23. e := db.GetEngine(ctx)
  24. has, err := e.Get(collaboration)
  25. if err != nil {
  26. return err
  27. } else if has {
  28. return nil
  29. }
  30. collaboration.Mode = perm.AccessModeWrite
  31. if _, err = e.InsertOne(collaboration); err != nil {
  32. return err
  33. }
  34. return access_model.RecalculateUserAccess(ctx, repo, u.ID)
  35. }
  36. // AddCollaborator adds new collaboration to a repository with default access mode.
  37. func AddCollaborator(repo *repo_model.Repository, u *user_model.User) error {
  38. ctx, committer, err := db.TxContext()
  39. if err != nil {
  40. return err
  41. }
  42. defer committer.Close()
  43. if err := addCollaborator(ctx, repo, u); err != nil {
  44. return err
  45. }
  46. return committer.Commit()
  47. }
  48. // DeleteCollaboration removes collaboration relation between the user and repository.
  49. func DeleteCollaboration(repo *repo_model.Repository, uid int64) (err error) {
  50. collaboration := &repo_model.Collaboration{
  51. RepoID: repo.ID,
  52. UserID: uid,
  53. }
  54. ctx, committer, err := db.TxContext()
  55. if err != nil {
  56. return err
  57. }
  58. defer committer.Close()
  59. if has, err := db.GetEngine(ctx).Delete(collaboration); err != nil || has == 0 {
  60. return err
  61. } else if err = access_model.RecalculateAccesses(ctx, repo); err != nil {
  62. return err
  63. }
  64. if err = repo_model.WatchRepo(ctx, uid, repo.ID, false); err != nil {
  65. return err
  66. }
  67. if err = reconsiderWatches(ctx, repo, uid); err != nil {
  68. return err
  69. }
  70. // Unassign a user from any issue (s)he has been assigned to in the repository
  71. if err := reconsiderRepoIssuesAssignee(ctx, repo, uid); err != nil {
  72. return err
  73. }
  74. return committer.Commit()
  75. }
  76. func reconsiderRepoIssuesAssignee(ctx context.Context, repo *repo_model.Repository, uid int64) error {
  77. user, err := user_model.GetUserByIDCtx(ctx, uid)
  78. if err != nil {
  79. return err
  80. }
  81. if canAssigned, err := access_model.CanBeAssigned(ctx, user, repo, true); err != nil || canAssigned {
  82. return err
  83. }
  84. if _, err := db.GetEngine(ctx).Where(builder.Eq{"assignee_id": uid}).
  85. In("issue_id", builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repo.ID})).
  86. Delete(&IssueAssignees{}); err != nil {
  87. return fmt.Errorf("Could not delete assignee[%d] %v", uid, err)
  88. }
  89. return nil
  90. }
  91. func reconsiderWatches(ctx context.Context, repo *repo_model.Repository, uid int64) error {
  92. if has, err := access_model.HasAccess(ctx, uid, repo); err != nil || has {
  93. return err
  94. }
  95. if err := repo_model.WatchRepo(ctx, uid, repo.ID, false); err != nil {
  96. return err
  97. }
  98. // Remove all IssueWatches a user has subscribed to in the repository
  99. return removeIssueWatchersByRepoID(ctx, uid, repo.ID)
  100. }
  101. // IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository
  102. func IsOwnerMemberCollaborator(repo *repo_model.Repository, userID int64) (bool, error) {
  103. if repo.OwnerID == userID {
  104. return true, nil
  105. }
  106. teamMember, err := db.GetEngine(db.DefaultContext).Join("INNER", "team_repo", "team_repo.team_id = team_user.team_id").
  107. Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id").
  108. Where("team_repo.repo_id = ?", repo.ID).
  109. And("team_unit.`type` = ?", unit.TypeCode).
  110. And("team_user.uid = ?", userID).Table("team_user").Exist(&organization.TeamUser{})
  111. if err != nil {
  112. return false, err
  113. }
  114. if teamMember {
  115. return true, nil
  116. }
  117. return db.GetEngine(db.DefaultContext).Get(&repo_model.Collaboration{RepoID: repo.ID, UserID: userID})
  118. }