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 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 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 org
  6. import (
  7. "fmt"
  8. "net/http"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/context"
  11. "code.gitea.io/gitea/modules/convert"
  12. api "code.gitea.io/gitea/modules/structs"
  13. "code.gitea.io/gitea/modules/util"
  14. "code.gitea.io/gitea/modules/web"
  15. "code.gitea.io/gitea/routers/api/v1/user"
  16. "code.gitea.io/gitea/routers/api/v1/utils"
  17. )
  18. func listUserOrgs(ctx *context.APIContext, u *models.User) {
  19. listOptions := utils.GetListOptions(ctx)
  20. showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
  21. orgs, err := models.GetOrgsByUserID(u.ID, showPrivate)
  22. if err != nil {
  23. ctx.Error(http.StatusInternalServerError, "GetOrgsByUserID", err)
  24. return
  25. }
  26. maxResults := len(orgs)
  27. orgs, _ = util.PaginateSlice(orgs, listOptions.Page, listOptions.PageSize).([]*models.User)
  28. apiOrgs := make([]*api.Organization, len(orgs))
  29. for i := range orgs {
  30. apiOrgs[i] = convert.ToOrganization(orgs[i])
  31. }
  32. ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
  33. ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
  34. ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
  35. ctx.JSON(http.StatusOK, &apiOrgs)
  36. }
  37. // ListMyOrgs list all my orgs
  38. func ListMyOrgs(ctx *context.APIContext) {
  39. // swagger:operation GET /user/orgs organization orgListCurrentUserOrgs
  40. // ---
  41. // summary: List the current user's organizations
  42. // produces:
  43. // - application/json
  44. // parameters:
  45. // - name: page
  46. // in: query
  47. // description: page number of results to return (1-based)
  48. // type: integer
  49. // - name: limit
  50. // in: query
  51. // description: page size of results
  52. // type: integer
  53. // responses:
  54. // "200":
  55. // "$ref": "#/responses/OrganizationList"
  56. listUserOrgs(ctx, ctx.User)
  57. }
  58. // ListUserOrgs list user's orgs
  59. func ListUserOrgs(ctx *context.APIContext) {
  60. // swagger:operation GET /users/{username}/orgs organization orgListUserOrgs
  61. // ---
  62. // summary: List a user's organizations
  63. // produces:
  64. // - application/json
  65. // parameters:
  66. // - name: username
  67. // in: path
  68. // description: username of user
  69. // type: string
  70. // required: true
  71. // - name: page
  72. // in: query
  73. // description: page number of results to return (1-based)
  74. // type: integer
  75. // - name: limit
  76. // in: query
  77. // description: page size of results
  78. // type: integer
  79. // responses:
  80. // "200":
  81. // "$ref": "#/responses/OrganizationList"
  82. u := user.GetUserByParams(ctx)
  83. if ctx.Written() {
  84. return
  85. }
  86. listUserOrgs(ctx, u)
  87. }
  88. // GetAll return list of all public organizations
  89. func GetAll(ctx *context.APIContext) {
  90. // swagger:operation Get /orgs organization orgGetAll
  91. // ---
  92. // summary: Get list of organizations
  93. // produces:
  94. // - application/json
  95. // parameters:
  96. // - name: page
  97. // in: query
  98. // description: page number of results to return (1-based)
  99. // type: integer
  100. // - name: limit
  101. // in: query
  102. // description: page size of results
  103. // type: integer
  104. // responses:
  105. // "200":
  106. // "$ref": "#/responses/OrganizationList"
  107. vMode := []api.VisibleType{api.VisibleTypePublic}
  108. if ctx.IsSigned {
  109. vMode = append(vMode, api.VisibleTypeLimited)
  110. if ctx.User.IsAdmin {
  111. vMode = append(vMode, api.VisibleTypePrivate)
  112. }
  113. }
  114. listOptions := utils.GetListOptions(ctx)
  115. publicOrgs, maxResults, err := models.SearchUsers(&models.SearchUserOptions{
  116. ListOptions: listOptions,
  117. Type: models.UserTypeOrganization,
  118. OrderBy: models.SearchOrderByAlphabetically,
  119. Visible: vMode,
  120. })
  121. if err != nil {
  122. ctx.Error(http.StatusInternalServerError, "SearchOrganizations", err)
  123. return
  124. }
  125. orgs := make([]*api.Organization, len(publicOrgs))
  126. for i := range publicOrgs {
  127. orgs[i] = convert.ToOrganization(publicOrgs[i])
  128. }
  129. ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
  130. ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", maxResults))
  131. ctx.Header().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
  132. ctx.JSON(http.StatusOK, &orgs)
  133. }
  134. // Create api for create organization
  135. func Create(ctx *context.APIContext) {
  136. // swagger:operation POST /orgs organization orgCreate
  137. // ---
  138. // summary: Create an organization
  139. // consumes:
  140. // - application/json
  141. // produces:
  142. // - application/json
  143. // parameters:
  144. // - name: organization
  145. // in: body
  146. // required: true
  147. // schema: { "$ref": "#/definitions/CreateOrgOption" }
  148. // responses:
  149. // "201":
  150. // "$ref": "#/responses/Organization"
  151. // "403":
  152. // "$ref": "#/responses/forbidden"
  153. // "422":
  154. // "$ref": "#/responses/validationError"
  155. form := web.GetForm(ctx).(*api.CreateOrgOption)
  156. if !ctx.User.CanCreateOrganization() {
  157. ctx.Error(http.StatusForbidden, "Create organization not allowed", nil)
  158. return
  159. }
  160. visibility := api.VisibleTypePublic
  161. if form.Visibility != "" {
  162. visibility = api.VisibilityModes[form.Visibility]
  163. }
  164. org := &models.User{
  165. Name: form.UserName,
  166. FullName: form.FullName,
  167. Description: form.Description,
  168. Website: form.Website,
  169. Location: form.Location,
  170. IsActive: true,
  171. Type: models.UserTypeOrganization,
  172. Visibility: visibility,
  173. RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
  174. }
  175. if err := models.CreateOrganization(org, ctx.User); err != nil {
  176. if models.IsErrUserAlreadyExist(err) ||
  177. models.IsErrNameReserved(err) ||
  178. models.IsErrNameCharsNotAllowed(err) ||
  179. models.IsErrNamePatternNotAllowed(err) {
  180. ctx.Error(http.StatusUnprocessableEntity, "", err)
  181. } else {
  182. ctx.Error(http.StatusInternalServerError, "CreateOrganization", err)
  183. }
  184. return
  185. }
  186. ctx.JSON(http.StatusCreated, convert.ToOrganization(org))
  187. }
  188. // Get get an organization
  189. func Get(ctx *context.APIContext) {
  190. // swagger:operation GET /orgs/{org} organization orgGet
  191. // ---
  192. // summary: Get an organization
  193. // produces:
  194. // - application/json
  195. // parameters:
  196. // - name: org
  197. // in: path
  198. // description: name of the organization to get
  199. // type: string
  200. // required: true
  201. // responses:
  202. // "200":
  203. // "$ref": "#/responses/Organization"
  204. if !models.HasOrgVisible(ctx.Org.Organization, ctx.User) {
  205. ctx.NotFound("HasOrgVisible", nil)
  206. return
  207. }
  208. ctx.JSON(http.StatusOK, convert.ToOrganization(ctx.Org.Organization))
  209. }
  210. // Edit change an organization's information
  211. func Edit(ctx *context.APIContext) {
  212. // swagger:operation PATCH /orgs/{org} organization orgEdit
  213. // ---
  214. // summary: Edit an organization
  215. // consumes:
  216. // - application/json
  217. // produces:
  218. // - application/json
  219. // parameters:
  220. // - name: org
  221. // in: path
  222. // description: name of the organization to edit
  223. // type: string
  224. // required: true
  225. // - name: body
  226. // in: body
  227. // required: true
  228. // schema:
  229. // "$ref": "#/definitions/EditOrgOption"
  230. // responses:
  231. // "200":
  232. // "$ref": "#/responses/Organization"
  233. form := web.GetForm(ctx).(*api.EditOrgOption)
  234. org := ctx.Org.Organization
  235. org.FullName = form.FullName
  236. org.Description = form.Description
  237. org.Website = form.Website
  238. org.Location = form.Location
  239. if form.Visibility != "" {
  240. org.Visibility = api.VisibilityModes[form.Visibility]
  241. }
  242. if form.RepoAdminChangeTeamAccess != nil {
  243. org.RepoAdminChangeTeamAccess = *form.RepoAdminChangeTeamAccess
  244. }
  245. if err := models.UpdateUserCols(org,
  246. "full_name", "description", "website", "location",
  247. "visibility", "repo_admin_change_team_access",
  248. ); err != nil {
  249. ctx.Error(http.StatusInternalServerError, "EditOrganization", err)
  250. return
  251. }
  252. ctx.JSON(http.StatusOK, convert.ToOrganization(org))
  253. }
  254. //Delete an organization
  255. func Delete(ctx *context.APIContext) {
  256. // swagger:operation DELETE /orgs/{org} organization orgDelete
  257. // ---
  258. // summary: Delete an organization
  259. // produces:
  260. // - application/json
  261. // parameters:
  262. // - name: org
  263. // in: path
  264. // description: organization that is to be deleted
  265. // type: string
  266. // required: true
  267. // responses:
  268. // "204":
  269. // "$ref": "#/responses/empty"
  270. if err := models.DeleteOrganization(ctx.Org.Organization); err != nil {
  271. ctx.Error(http.StatusInternalServerError, "DeleteOrganization", err)
  272. return
  273. }
  274. ctx.Status(http.StatusNoContent)
  275. }