gitea源码

org_list.go 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package organization
  4. import (
  5. "context"
  6. "fmt"
  7. "strings"
  8. "code.gitea.io/gitea/models/db"
  9. "code.gitea.io/gitea/models/perm"
  10. user_model "code.gitea.io/gitea/models/user"
  11. "code.gitea.io/gitea/modules/structs"
  12. "xorm.io/builder"
  13. )
  14. type OrgList []*Organization
  15. func (orgs OrgList) LoadTeams(ctx context.Context) (map[int64]TeamList, error) {
  16. if len(orgs) == 0 {
  17. return map[int64]TeamList{}, nil
  18. }
  19. orgIDs := make([]int64, len(orgs))
  20. for i, org := range orgs {
  21. orgIDs[i] = org.ID
  22. }
  23. teams, err := GetTeamsByOrgIDs(ctx, orgIDs)
  24. if err != nil {
  25. return nil, err
  26. }
  27. teamMap := make(map[int64]TeamList, len(orgs))
  28. for _, team := range teams {
  29. teamMap[team.OrgID] = append(teamMap[team.OrgID], team)
  30. }
  31. return teamMap, nil
  32. }
  33. // SearchOrganizationsOptions options to filter organizations
  34. type SearchOrganizationsOptions struct {
  35. db.ListOptions
  36. All bool
  37. }
  38. // FindOrgOptions finds orgs options
  39. type FindOrgOptions struct {
  40. db.ListOptions
  41. UserID int64
  42. IncludeVisibility structs.VisibleType
  43. }
  44. func queryUserOrgIDs(userID int64, includePrivate bool) *builder.Builder {
  45. cond := builder.Eq{"uid": userID}
  46. if !includePrivate {
  47. cond["is_public"] = true
  48. }
  49. return builder.Select("org_id").From("org_user").Where(cond)
  50. }
  51. func (opts FindOrgOptions) ToConds() builder.Cond {
  52. var cond builder.Cond = builder.Eq{"`user`.`type`": user_model.UserTypeOrganization}
  53. if opts.UserID > 0 {
  54. cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludeVisibility == structs.VisibleTypePrivate)))
  55. }
  56. // public=0, limited=1, private=2
  57. cond = cond.And(builder.Lte{"`user`.visibility": opts.IncludeVisibility})
  58. return cond
  59. }
  60. func (opts FindOrgOptions) ToOrders() string {
  61. return "`user`.lower_name ASC"
  62. }
  63. func DoerViewOtherVisibility(doer, other *user_model.User) structs.VisibleType {
  64. if doer == nil || other == nil {
  65. return structs.VisibleTypePublic
  66. }
  67. if doer.IsAdmin || doer.ID == other.ID {
  68. return structs.VisibleTypePrivate
  69. }
  70. return structs.VisibleTypeLimited
  71. }
  72. // GetOrgsCanCreateRepoByUserID returns a list of organizations where given user ID
  73. // are allowed to create repos.
  74. func GetOrgsCanCreateRepoByUserID(ctx context.Context, userID int64) ([]*Organization, error) {
  75. orgs := make([]*Organization, 0, 10)
  76. return orgs, db.GetEngine(ctx).Where(builder.In("id", builder.Select("`user`.id").From("`user`").
  77. Join("INNER", "`team_user`", "`team_user`.org_id = `user`.id").
  78. Join("INNER", "`team`", "`team`.id = `team_user`.team_id").
  79. Where(builder.Eq{"`team_user`.uid": userID}).
  80. And(builder.Eq{"`team`.authorize": perm.AccessModeOwner}.Or(builder.Eq{"`team`.can_create_org_repo": true})))).
  81. Asc("`user`.name").
  82. Find(&orgs)
  83. }
  84. // MinimalOrg represents a simple organization with only the needed columns
  85. type MinimalOrg = Organization
  86. // GetUserOrgsList returns all organizations the given user has access to
  87. func GetUserOrgsList(ctx context.Context, user *user_model.User) ([]*MinimalOrg, error) {
  88. outputCols := []string{
  89. "id",
  90. "name",
  91. "full_name",
  92. "visibility",
  93. "avatar",
  94. "avatar_email",
  95. "use_custom_avatar",
  96. }
  97. selectColumns := &strings.Builder{}
  98. for i, col := range outputCols {
  99. _, _ = fmt.Fprintf(selectColumns, "`user`.%s", col)
  100. if i < len(outputCols)-1 {
  101. selectColumns.WriteString(", ")
  102. }
  103. }
  104. columnsStr := selectColumns.String()
  105. var orgs []*MinimalOrg
  106. if err := db.GetEngine(ctx).Select(columnsStr).
  107. Table("user").
  108. Where(builder.In("`user`.`id`", queryUserOrgIDs(user.ID, true))).
  109. OrderBy("`user`.lower_name ASC").
  110. Find(&orgs); err != nil {
  111. return nil, err
  112. }
  113. type orgCount struct {
  114. OrgID int64
  115. RepoCount int
  116. }
  117. var orgCounts []orgCount
  118. if err := db.GetEngine(ctx).
  119. Select("owner_id AS org_id, COUNT(DISTINCT(repository.id)) as repo_count").
  120. Table("repository").
  121. Join("INNER", "org_user", "owner_id = org_user.org_id").
  122. Where("org_user.uid = ?", user.ID).
  123. And(builder.Or(
  124. builder.Eq{"repository.is_private": false},
  125. builder.In("repository.id", builder.Select("repo_id").From("team_repo").
  126. InnerJoin("team_user", "team_user.team_id = team_repo.team_id").
  127. Where(builder.Eq{"team_user.uid": user.ID})),
  128. builder.In("repository.id", builder.Select("repo_id").From("collaboration").
  129. Where(builder.Eq{"user_id": user.ID})),
  130. )).
  131. GroupBy("owner_id").Find(&orgCounts); err != nil {
  132. return nil, err
  133. }
  134. orgCountMap := make(map[int64]int, len(orgCounts))
  135. for _, orgCount := range orgCounts {
  136. orgCountMap[orgCount.OrgID] = orgCount.RepoCount
  137. }
  138. for _, org := range orgs {
  139. org.NumRepos = orgCountMap[org.ID]
  140. }
  141. return orgs, nil
  142. }