gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2018 The Gitea Authors. All rights reserved.
  2. // Copyright 2016 The Gogs Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package organization
  5. import (
  6. "context"
  7. "fmt"
  8. "strings"
  9. "code.gitea.io/gitea/models/db"
  10. "code.gitea.io/gitea/models/perm"
  11. "code.gitea.io/gitea/models/unit"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/util"
  15. "xorm.io/builder"
  16. )
  17. // ___________
  18. // \__ ___/___ _____ _____
  19. // | |_/ __ \\__ \ / \
  20. // | |\ ___/ / __ \| Y Y \
  21. // |____| \___ >____ /__|_| /
  22. // \/ \/ \/
  23. // ErrTeamAlreadyExist represents a "TeamAlreadyExist" kind of error.
  24. type ErrTeamAlreadyExist struct {
  25. OrgID int64
  26. Name string
  27. }
  28. // IsErrTeamAlreadyExist checks if an error is a ErrTeamAlreadyExist.
  29. func IsErrTeamAlreadyExist(err error) bool {
  30. _, ok := err.(ErrTeamAlreadyExist)
  31. return ok
  32. }
  33. func (err ErrTeamAlreadyExist) Error() string {
  34. return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
  35. }
  36. func (err ErrTeamAlreadyExist) Unwrap() error {
  37. return util.ErrAlreadyExist
  38. }
  39. // ErrTeamNotExist represents a "TeamNotExist" error
  40. type ErrTeamNotExist struct {
  41. OrgID int64
  42. TeamID int64
  43. Name string
  44. }
  45. // IsErrTeamNotExist checks if an error is a ErrTeamNotExist.
  46. func IsErrTeamNotExist(err error) bool {
  47. _, ok := err.(ErrTeamNotExist)
  48. return ok
  49. }
  50. func (err ErrTeamNotExist) Error() string {
  51. return fmt.Sprintf("team does not exist [org_id %d, team_id %d, name: %s]", err.OrgID, err.TeamID, err.Name)
  52. }
  53. func (err ErrTeamNotExist) Unwrap() error {
  54. return util.ErrNotExist
  55. }
  56. // OwnerTeamName return the owner team name
  57. const OwnerTeamName = "Owners"
  58. // Team represents a organization team.
  59. type Team struct {
  60. ID int64 `xorm:"pk autoincr"`
  61. OrgID int64 `xorm:"INDEX"`
  62. LowerName string
  63. Name string
  64. Description string
  65. AccessMode perm.AccessMode `xorm:"'authorize'"`
  66. Members []*user_model.User `xorm:"-"`
  67. NumRepos int
  68. NumMembers int
  69. Units []*TeamUnit `xorm:"-"`
  70. IncludesAllRepositories bool `xorm:"NOT NULL DEFAULT false"`
  71. CanCreateOrgRepo bool `xorm:"NOT NULL DEFAULT false"`
  72. }
  73. func init() {
  74. db.RegisterModel(new(Team))
  75. db.RegisterModel(new(TeamUser))
  76. db.RegisterModel(new(TeamRepo))
  77. db.RegisterModel(new(TeamUnit))
  78. db.RegisterModel(new(TeamInvite))
  79. }
  80. func (t *Team) LogString() string {
  81. if t == nil {
  82. return "<Team nil>"
  83. }
  84. return fmt.Sprintf("<Team %d:%s OrgID=%d AccessMode=%s>", t.ID, t.Name, t.OrgID, t.AccessMode.LogString())
  85. }
  86. // LoadUnits load a list of available units for a team
  87. func (t *Team) LoadUnits(ctx context.Context) (err error) {
  88. if t.Units != nil {
  89. return nil
  90. }
  91. t.Units, err = getUnitsByTeamID(ctx, t.ID)
  92. return err
  93. }
  94. // GetUnitNames returns the team units names
  95. func (t *Team) GetUnitNames() (res []string) {
  96. if t.HasAdminAccess() {
  97. return unit.AllUnitKeyNames()
  98. }
  99. for _, u := range t.Units {
  100. res = append(res, unit.Units[u.Type].NameKey)
  101. }
  102. return res
  103. }
  104. // GetUnitsMap returns the team units permissions
  105. func (t *Team) GetUnitsMap() map[string]string {
  106. m := make(map[string]string)
  107. if t.HasAdminAccess() {
  108. for _, u := range unit.Units {
  109. m[u.NameKey] = t.AccessMode.ToString()
  110. }
  111. } else {
  112. for _, u := range t.Units {
  113. m[u.Unit().NameKey] = u.AccessMode.ToString()
  114. }
  115. }
  116. return m
  117. }
  118. // IsOwnerTeam returns true if team is owner team.
  119. func (t *Team) IsOwnerTeam() bool {
  120. return t.Name == OwnerTeamName
  121. }
  122. // IsMember returns true if given user is a member of team.
  123. func (t *Team) IsMember(ctx context.Context, userID int64) bool {
  124. isMember, err := IsTeamMember(ctx, t.OrgID, t.ID, userID)
  125. if err != nil {
  126. log.Error("IsMember: %v", err)
  127. return false
  128. }
  129. return isMember
  130. }
  131. func (t *Team) HasAdminAccess() bool {
  132. return t.AccessMode >= perm.AccessModeAdmin
  133. }
  134. // LoadMembers returns paginated members in team of organization.
  135. func (t *Team) LoadMembers(ctx context.Context) (err error) {
  136. t.Members, err = GetTeamMembers(ctx, &SearchMembersOptions{
  137. TeamID: t.ID,
  138. })
  139. return err
  140. }
  141. // UnitEnabled returns true if the team has the given unit type enabled
  142. func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool {
  143. return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone
  144. }
  145. // UnitAccessMode returns the access mode for the given unit type, "none" for non-existent units
  146. func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode {
  147. accessMode, _ := t.UnitAccessModeEx(ctx, tp)
  148. return accessMode
  149. }
  150. func (t *Team) UnitAccessModeEx(ctx context.Context, tp unit.Type) (accessMode perm.AccessMode, exist bool) {
  151. if err := t.LoadUnits(ctx); err != nil {
  152. log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
  153. }
  154. for _, u := range t.Units {
  155. if u.Type == tp {
  156. return u.AccessMode, true
  157. }
  158. }
  159. return perm.AccessModeNone, false
  160. }
  161. // IsUsableTeamName tests if a name could be as team name
  162. func IsUsableTeamName(name string) error {
  163. switch name {
  164. case "new":
  165. return db.ErrNameReserved{Name: name}
  166. default:
  167. return nil
  168. }
  169. }
  170. // GetTeam returns team by given team name and organization.
  171. func GetTeam(ctx context.Context, orgID int64, name string) (*Team, error) {
  172. t, exist, err := db.Get[Team](ctx, builder.Eq{"org_id": orgID, "lower_name": strings.ToLower(name)})
  173. if err != nil {
  174. return nil, err
  175. } else if !exist {
  176. return nil, ErrTeamNotExist{orgID, 0, name}
  177. }
  178. return t, nil
  179. }
  180. // GetTeamIDsByNames returns a slice of team ids corresponds to names.
  181. func GetTeamIDsByNames(ctx context.Context, orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) {
  182. ids := make([]int64, 0, len(names))
  183. for _, name := range names {
  184. u, err := GetTeam(ctx, orgID, name)
  185. if err != nil {
  186. if ignoreNonExistent {
  187. continue
  188. }
  189. return nil, err
  190. }
  191. ids = append(ids, u.ID)
  192. }
  193. return ids, nil
  194. }
  195. // GetOwnerTeam returns team by given team name and organization.
  196. func GetOwnerTeam(ctx context.Context, orgID int64) (*Team, error) {
  197. return GetTeam(ctx, orgID, OwnerTeamName)
  198. }
  199. // GetTeamByID returns team by given ID.
  200. func GetTeamByID(ctx context.Context, teamID int64) (*Team, error) {
  201. t := new(Team)
  202. has, err := db.GetEngine(ctx).ID(teamID).Get(t)
  203. if err != nil {
  204. return nil, err
  205. } else if !has {
  206. return nil, ErrTeamNotExist{0, teamID, ""}
  207. }
  208. return t, nil
  209. }
  210. // IncrTeamRepoNum increases the number of repos for the given team by 1
  211. func IncrTeamRepoNum(ctx context.Context, teamID int64) error {
  212. _, err := db.GetEngine(ctx).Incr("num_repos").ID(teamID).Update(new(Team))
  213. return err
  214. }