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.

org.go 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  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. "strings"
  10. "code.gitea.io/gitea/models/db"
  11. "code.gitea.io/gitea/models/organization"
  12. access_model "code.gitea.io/gitea/models/perm/access"
  13. repo_model "code.gitea.io/gitea/models/repo"
  14. user_model "code.gitea.io/gitea/models/user"
  15. "xorm.io/builder"
  16. )
  17. // MinimalOrg represents a simple orgnization with only needed columns
  18. type MinimalOrg = organization.Organization
  19. // GetUserOrgsList returns one user's all orgs list
  20. func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {
  21. schema, err := db.TableInfo(new(user_model.User))
  22. if err != nil {
  23. return nil, err
  24. }
  25. outputCols := []string{
  26. "id",
  27. "name",
  28. "full_name",
  29. "visibility",
  30. "avatar",
  31. "avatar_email",
  32. "use_custom_avatar",
  33. }
  34. groupByCols := &strings.Builder{}
  35. for _, col := range outputCols {
  36. fmt.Fprintf(groupByCols, "`%s`.%s,", schema.Name, col)
  37. }
  38. groupByStr := groupByCols.String()
  39. groupByStr = groupByStr[0 : len(groupByStr)-1]
  40. sess := db.GetEngine(db.DefaultContext)
  41. sess = sess.Select(groupByStr+", count(distinct repo_id) as org_count").
  42. Table("user").
  43. Join("INNER", "team", "`team`.org_id = `user`.id").
  44. Join("INNER", "team_user", "`team`.id = `team_user`.team_id").
  45. Join("LEFT", builder.
  46. Select("id as repo_id, owner_id as repo_owner_id").
  47. From("repository").
  48. Where(accessibleRepositoryCondition(user)), "`repository`.repo_owner_id = `team`.org_id").
  49. Where("`team_user`.uid = ?", user.ID).
  50. GroupBy(groupByStr)
  51. type OrgCount struct {
  52. organization.Organization `xorm:"extends"`
  53. OrgCount int
  54. }
  55. orgCounts := make([]*OrgCount, 0, 10)
  56. if err := sess.
  57. Asc("`user`.name").
  58. Find(&orgCounts); err != nil {
  59. return nil, err
  60. }
  61. orgs := make([]*MinimalOrg, len(orgCounts))
  62. for i, orgCount := range orgCounts {
  63. orgCount.Organization.NumRepos = orgCount.OrgCount
  64. orgs[i] = &orgCount.Organization
  65. }
  66. return orgs, nil
  67. }
  68. func removeOrgUser(ctx context.Context, orgID, userID int64) error {
  69. ou := new(organization.OrgUser)
  70. sess := db.GetEngine(ctx)
  71. has, err := sess.
  72. Where("uid=?", userID).
  73. And("org_id=?", orgID).
  74. Get(ou)
  75. if err != nil {
  76. return fmt.Errorf("get org-user: %v", err)
  77. } else if !has {
  78. return nil
  79. }
  80. org, err := organization.GetOrgByIDCtx(ctx, orgID)
  81. if err != nil {
  82. return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
  83. }
  84. // Check if the user to delete is the last member in owner team.
  85. if isOwner, err := organization.IsOrganizationOwner(ctx, orgID, userID); err != nil {
  86. return err
  87. } else if isOwner {
  88. t, err := organization.GetOwnerTeam(ctx, org.ID)
  89. if err != nil {
  90. return err
  91. }
  92. if t.NumMembers == 1 {
  93. if err := t.GetMembersCtx(ctx); err != nil {
  94. return err
  95. }
  96. if t.Members[0].ID == userID {
  97. return organization.ErrLastOrgOwner{UID: userID}
  98. }
  99. }
  100. }
  101. if _, err := sess.ID(ou.ID).Delete(ou); err != nil {
  102. return err
  103. } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgID); err != nil {
  104. return err
  105. }
  106. // Delete all repository accesses and unwatch them.
  107. env, err := organization.AccessibleReposEnv(ctx, org, userID)
  108. if err != nil {
  109. return fmt.Errorf("AccessibleReposEnv: %v", err)
  110. }
  111. repoIDs, err := env.RepoIDs(1, org.NumRepos)
  112. if err != nil {
  113. return fmt.Errorf("GetUserRepositories [%d]: %v", userID, err)
  114. }
  115. for _, repoID := range repoIDs {
  116. if err = repo_model.WatchRepoCtx(ctx, userID, repoID, false); err != nil {
  117. return err
  118. }
  119. }
  120. if len(repoIDs) > 0 {
  121. if _, err = sess.
  122. Where("user_id = ?", userID).
  123. In("repo_id", repoIDs).
  124. Delete(new(access_model.Access)); err != nil {
  125. return err
  126. }
  127. }
  128. // Delete member in his/her teams.
  129. teams, err := organization.GetUserOrgTeams(ctx, org.ID, userID)
  130. if err != nil {
  131. return err
  132. }
  133. for _, t := range teams {
  134. if err = removeTeamMember(ctx, t, userID); err != nil {
  135. return err
  136. }
  137. }
  138. return nil
  139. }
  140. // RemoveOrgUser removes user from given organization.
  141. func RemoveOrgUser(orgID, userID int64) error {
  142. ctx, committer, err := db.TxContext()
  143. if err != nil {
  144. return err
  145. }
  146. defer committer.Close()
  147. if err := removeOrgUser(ctx, orgID, userID); err != nil {
  148. return err
  149. }
  150. return committer.Commit()
  151. }