gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "fmt"
  6. "net/http"
  7. "code.gitea.io/gitea/models/organization"
  8. "code.gitea.io/gitea/services/context"
  9. "code.gitea.io/gitea/services/convert"
  10. repo_service "code.gitea.io/gitea/services/repository"
  11. )
  12. // ListTeams list a repository's teams
  13. func ListTeams(ctx *context.APIContext) {
  14. // swagger:operation GET /repos/{owner}/{repo}/teams repository repoListTeams
  15. // ---
  16. // summary: List a repository's teams
  17. // produces:
  18. // - application/json
  19. // parameters:
  20. // - name: owner
  21. // in: path
  22. // description: owner of the repo
  23. // type: string
  24. // required: true
  25. // - name: repo
  26. // in: path
  27. // description: name of the repo
  28. // type: string
  29. // required: true
  30. // responses:
  31. // "200":
  32. // "$ref": "#/responses/TeamList"
  33. // "404":
  34. // "$ref": "#/responses/notFound"
  35. if !ctx.Repo.Owner.IsOrganization() {
  36. ctx.APIError(http.StatusMethodNotAllowed, "repo is not owned by an organization")
  37. return
  38. }
  39. teams, err := organization.GetRepoTeams(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
  40. if err != nil {
  41. ctx.APIErrorInternal(err)
  42. return
  43. }
  44. apiTeams, err := convert.ToTeams(ctx, teams, false)
  45. if err != nil {
  46. ctx.APIErrorInternal(err)
  47. return
  48. }
  49. ctx.JSON(http.StatusOK, apiTeams)
  50. }
  51. // IsTeam check if a team is assigned to a repository
  52. func IsTeam(ctx *context.APIContext) {
  53. // swagger:operation GET /repos/{owner}/{repo}/teams/{team} repository repoCheckTeam
  54. // ---
  55. // summary: Check if a team is assigned to a repository
  56. // produces:
  57. // - application/json
  58. // parameters:
  59. // - name: owner
  60. // in: path
  61. // description: owner of the repo
  62. // type: string
  63. // required: true
  64. // - name: repo
  65. // in: path
  66. // description: name of the repo
  67. // type: string
  68. // required: true
  69. // - name: team
  70. // in: path
  71. // description: team name
  72. // type: string
  73. // required: true
  74. // responses:
  75. // "200":
  76. // "$ref": "#/responses/Team"
  77. // "404":
  78. // "$ref": "#/responses/notFound"
  79. // "405":
  80. // "$ref": "#/responses/error"
  81. if !ctx.Repo.Owner.IsOrganization() {
  82. ctx.APIError(http.StatusMethodNotAllowed, "repo is not owned by an organization")
  83. return
  84. }
  85. team := getTeamByParam(ctx)
  86. if team == nil {
  87. return
  88. }
  89. if repo_service.HasRepository(ctx, team, ctx.Repo.Repository.ID) {
  90. apiTeam, err := convert.ToTeam(ctx, team)
  91. if err != nil {
  92. ctx.APIErrorInternal(err)
  93. return
  94. }
  95. ctx.JSON(http.StatusOK, apiTeam)
  96. return
  97. }
  98. ctx.APIErrorNotFound()
  99. }
  100. // AddTeam add a team to a repository
  101. func AddTeam(ctx *context.APIContext) {
  102. // swagger:operation PUT /repos/{owner}/{repo}/teams/{team} repository repoAddTeam
  103. // ---
  104. // summary: Add a team to a repository
  105. // produces:
  106. // - application/json
  107. // parameters:
  108. // - name: owner
  109. // in: path
  110. // description: owner of the repo
  111. // type: string
  112. // required: true
  113. // - name: repo
  114. // in: path
  115. // description: name of the repo
  116. // type: string
  117. // required: true
  118. // - name: team
  119. // in: path
  120. // description: team name
  121. // type: string
  122. // required: true
  123. // responses:
  124. // "204":
  125. // "$ref": "#/responses/empty"
  126. // "422":
  127. // "$ref": "#/responses/validationError"
  128. // "405":
  129. // "$ref": "#/responses/error"
  130. // "404":
  131. // "$ref": "#/responses/notFound"
  132. changeRepoTeam(ctx, true)
  133. }
  134. // DeleteTeam delete a team from a repository
  135. func DeleteTeam(ctx *context.APIContext) {
  136. // swagger:operation DELETE /repos/{owner}/{repo}/teams/{team} repository repoDeleteTeam
  137. // ---
  138. // summary: Delete a team from a repository
  139. // produces:
  140. // - application/json
  141. // parameters:
  142. // - name: owner
  143. // in: path
  144. // description: owner of the repo
  145. // type: string
  146. // required: true
  147. // - name: repo
  148. // in: path
  149. // description: name of the repo
  150. // type: string
  151. // required: true
  152. // - name: team
  153. // in: path
  154. // description: team name
  155. // type: string
  156. // required: true
  157. // responses:
  158. // "204":
  159. // "$ref": "#/responses/empty"
  160. // "422":
  161. // "$ref": "#/responses/validationError"
  162. // "405":
  163. // "$ref": "#/responses/error"
  164. // "404":
  165. // "$ref": "#/responses/notFound"
  166. changeRepoTeam(ctx, false)
  167. }
  168. func changeRepoTeam(ctx *context.APIContext, add bool) {
  169. if !ctx.Repo.Owner.IsOrganization() {
  170. ctx.APIError(http.StatusMethodNotAllowed, "repo is not owned by an organization")
  171. }
  172. if !ctx.Repo.Owner.RepoAdminChangeTeamAccess && !ctx.Repo.IsOwner() {
  173. ctx.APIError(http.StatusForbidden, "user is nor repo admin nor owner")
  174. return
  175. }
  176. team := getTeamByParam(ctx)
  177. if team == nil {
  178. return
  179. }
  180. repoHasTeam := repo_service.HasRepository(ctx, team, ctx.Repo.Repository.ID)
  181. var err error
  182. if add {
  183. if repoHasTeam {
  184. ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("team '%s' is already added to repo", team.Name))
  185. return
  186. }
  187. err = repo_service.TeamAddRepository(ctx, team, ctx.Repo.Repository)
  188. } else {
  189. if !repoHasTeam {
  190. ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("team '%s' was not added to repo", team.Name))
  191. return
  192. }
  193. err = repo_service.RemoveRepositoryFromTeam(ctx, team, ctx.Repo.Repository.ID)
  194. }
  195. if err != nil {
  196. ctx.APIErrorInternal(err)
  197. return
  198. }
  199. ctx.Status(http.StatusNoContent)
  200. }
  201. func getTeamByParam(ctx *context.APIContext) *organization.Team {
  202. team, err := organization.GetTeam(ctx, ctx.Repo.Owner.ID, ctx.PathParam("team"))
  203. if err != nil {
  204. if organization.IsErrTeamNotExist(err) {
  205. ctx.APIError(http.StatusNotFound, err)
  206. return nil
  207. }
  208. ctx.APIErrorInternal(err)
  209. return nil
  210. }
  211. return team
  212. }