gitea源码

org_user.go 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package organization
  4. import (
  5. "context"
  6. "fmt"
  7. "code.gitea.io/gitea/models/db"
  8. "code.gitea.io/gitea/models/perm"
  9. "code.gitea.io/gitea/models/unit"
  10. user_model "code.gitea.io/gitea/models/user"
  11. "code.gitea.io/gitea/modules/container"
  12. "code.gitea.io/gitea/modules/log"
  13. "xorm.io/builder"
  14. )
  15. // ________ ____ ___
  16. // \_____ \_______ ____ | | \______ ___________
  17. // / | \_ __ \/ ___\| | / ___// __ \_ __ \
  18. // / | \ | \/ /_/ > | /\___ \\ ___/| | \/
  19. // \_______ /__| \___ /|______//____ >\___ >__|
  20. // \/ /_____/ \/ \/
  21. // OrgUser represents an organization-user relation.
  22. type OrgUser struct {
  23. ID int64 `xorm:"pk autoincr"`
  24. UID int64 `xorm:"INDEX UNIQUE(s)"`
  25. OrgID int64 `xorm:"INDEX UNIQUE(s)"`
  26. IsPublic bool `xorm:"INDEX"`
  27. }
  28. func init() {
  29. db.RegisterModel(new(OrgUser))
  30. }
  31. // ErrUserHasOrgs represents a "UserHasOrgs" kind of error.
  32. type ErrUserHasOrgs struct {
  33. UID int64
  34. }
  35. // IsErrUserHasOrgs checks if an error is a ErrUserHasOrgs.
  36. func IsErrUserHasOrgs(err error) bool {
  37. _, ok := err.(ErrUserHasOrgs)
  38. return ok
  39. }
  40. func (err ErrUserHasOrgs) Error() string {
  41. return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
  42. }
  43. // GetOrganizationCount returns count of membership of organization of the user.
  44. func GetOrganizationCount(ctx context.Context, u *user_model.User) (int64, error) {
  45. return db.GetEngine(ctx).
  46. Where("uid=?", u.ID).
  47. Count(new(OrgUser))
  48. }
  49. // IsOrganizationOwner returns true if given user is in the owner team.
  50. func IsOrganizationOwner(ctx context.Context, orgID, uid int64) (bool, error) {
  51. ownerTeam, err := GetOwnerTeam(ctx, orgID)
  52. if err != nil {
  53. if IsErrTeamNotExist(err) {
  54. log.Error("Organization does not have owner team: %d", orgID)
  55. return false, nil
  56. }
  57. return false, err
  58. }
  59. return IsTeamMember(ctx, orgID, ownerTeam.ID, uid)
  60. }
  61. // IsOrganizationAdmin returns true if given user is in the owner team or an admin team.
  62. func IsOrganizationAdmin(ctx context.Context, orgID, uid int64) (bool, error) {
  63. teams, err := GetUserOrgTeams(ctx, orgID, uid)
  64. if err != nil {
  65. return false, err
  66. }
  67. for _, t := range teams {
  68. if t.HasAdminAccess() {
  69. return true, nil
  70. }
  71. }
  72. return false, nil
  73. }
  74. // IsOrganizationMember returns true if given user is member of organization.
  75. func IsOrganizationMember(ctx context.Context, orgID, uid int64) (bool, error) {
  76. return db.GetEngine(ctx).
  77. Where("uid=?", uid).
  78. And("org_id=?", orgID).
  79. Table("org_user").
  80. Exist()
  81. }
  82. // IsPublicMembership returns true if the given user's membership of given org is public.
  83. func IsPublicMembership(ctx context.Context, orgID, uid int64) (bool, error) {
  84. return db.GetEngine(ctx).
  85. Where("uid=?", uid).
  86. And("org_id=?", orgID).
  87. And("is_public=?", true).
  88. Table("org_user").
  89. Exist()
  90. }
  91. // CanCreateOrgRepo returns true if user can create repo in organization
  92. func CanCreateOrgRepo(ctx context.Context, orgID, uid int64) (bool, error) {
  93. return db.GetEngine(ctx).
  94. Where(builder.Eq{"team.can_create_org_repo": true}).
  95. Join("INNER", "team_user", "team_user.team_id = team.id").
  96. And("team_user.uid = ?", uid).
  97. And("team_user.org_id = ?", orgID).
  98. Exist(new(Team))
  99. }
  100. // IsUserOrgOwner returns true if user is in the owner team of given organization.
  101. func IsUserOrgOwner(ctx context.Context, users user_model.UserList, orgID int64) map[int64]bool {
  102. results := make(map[int64]bool, len(users))
  103. for _, user := range users {
  104. results[user.ID] = false // Set default to false
  105. }
  106. ownerMaps, err := loadOrganizationOwners(ctx, users, orgID)
  107. if err == nil {
  108. for _, owner := range ownerMaps {
  109. results[owner.UID] = true
  110. }
  111. }
  112. return results
  113. }
  114. // GetOrgAssignees returns all users that have write access and can be assigned to issues
  115. // of the any repository in the organization.
  116. func GetOrgAssignees(ctx context.Context, orgID int64) (_ []*user_model.User, err error) {
  117. e := db.GetEngine(ctx)
  118. userIDs := make([]int64, 0, 10)
  119. if err = e.Table("access").
  120. Join("INNER", "repository", "`repository`.id = `access`.repo_id").
  121. Where("`repository`.owner_id = ? AND `access`.mode >= ?", orgID, perm.AccessModeWrite).
  122. Select("user_id").
  123. Find(&userIDs); err != nil {
  124. return nil, err
  125. }
  126. additionalUserIDs := make([]int64, 0, 10)
  127. if err = e.Table("team_user").
  128. Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
  129. Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
  130. Join("INNER", "repository", "`repository`.id = `team_repo`.repo_id").
  131. Where("`repository`.owner_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
  132. orgID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
  133. Distinct("`team_user`.uid").
  134. Select("`team_user`.uid").
  135. Find(&additionalUserIDs); err != nil {
  136. return nil, err
  137. }
  138. uniqueUserIDs := make(container.Set[int64])
  139. uniqueUserIDs.AddMultiple(userIDs...)
  140. uniqueUserIDs.AddMultiple(additionalUserIDs...)
  141. users := make([]*user_model.User, 0, len(uniqueUserIDs))
  142. if len(userIDs) > 0 {
  143. if err = e.In("id", uniqueUserIDs.Values()).
  144. Where(builder.Eq{"`user`.is_active": true}).
  145. OrderBy(user_model.GetOrderByName()).
  146. Find(&users); err != nil {
  147. return nil, err
  148. }
  149. }
  150. return users, nil
  151. }
  152. func loadOrganizationOwners(ctx context.Context, users user_model.UserList, orgID int64) (map[int64]*TeamUser, error) {
  153. if len(users) == 0 {
  154. return nil, nil
  155. }
  156. ownerTeam, err := GetOwnerTeam(ctx, orgID)
  157. if err != nil {
  158. if IsErrTeamNotExist(err) {
  159. log.Error("Organization does not have owner team: %d", orgID)
  160. return nil, nil
  161. }
  162. return nil, err
  163. }
  164. userIDs := users.GetUserIDs()
  165. ownerMaps := make(map[int64]*TeamUser)
  166. err = db.GetEngine(ctx).In("uid", userIDs).
  167. And("org_id=?", orgID).
  168. And("team_id=?", ownerTeam.ID).
  169. Find(&ownerMaps)
  170. if err != nil {
  171. return nil, fmt.Errorf("find team users: %w", err)
  172. }
  173. return ownerMaps, nil
  174. }