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.

member.go 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package org
  4. import (
  5. "net/http"
  6. "net/url"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/models/organization"
  9. "code.gitea.io/gitea/modules/setting"
  10. api "code.gitea.io/gitea/modules/structs"
  11. "code.gitea.io/gitea/routers/api/v1/user"
  12. "code.gitea.io/gitea/routers/api/v1/utils"
  13. "code.gitea.io/gitea/services/context"
  14. "code.gitea.io/gitea/services/convert"
  15. )
  16. // listMembers list an organization's members
  17. func listMembers(ctx *context.APIContext, publicOnly bool) {
  18. opts := &organization.FindOrgMembersOpts{
  19. OrgID: ctx.Org.Organization.ID,
  20. PublicOnly: publicOnly,
  21. ListOptions: utils.GetListOptions(ctx),
  22. }
  23. count, err := organization.CountOrgMembers(ctx, opts)
  24. if err != nil {
  25. ctx.InternalServerError(err)
  26. return
  27. }
  28. members, _, err := organization.FindOrgMembers(ctx, opts)
  29. if err != nil {
  30. ctx.InternalServerError(err)
  31. return
  32. }
  33. apiMembers := make([]*api.User, len(members))
  34. for i, member := range members {
  35. apiMembers[i] = convert.ToUser(ctx, member, ctx.Doer)
  36. }
  37. ctx.SetTotalCountHeader(count)
  38. ctx.JSON(http.StatusOK, apiMembers)
  39. }
  40. // ListMembers list an organization's members
  41. func ListMembers(ctx *context.APIContext) {
  42. // swagger:operation GET /orgs/{org}/members organization orgListMembers
  43. // ---
  44. // summary: List an organization's members
  45. // produces:
  46. // - application/json
  47. // parameters:
  48. // - name: org
  49. // in: path
  50. // description: name of the organization
  51. // type: string
  52. // required: true
  53. // - name: page
  54. // in: query
  55. // description: page number of results to return (1-based)
  56. // type: integer
  57. // - name: limit
  58. // in: query
  59. // description: page size of results
  60. // type: integer
  61. // responses:
  62. // "200":
  63. // "$ref": "#/responses/UserList"
  64. // "404":
  65. // "$ref": "#/responses/notFound"
  66. publicOnly := true
  67. if ctx.Doer != nil {
  68. isMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID)
  69. if err != nil {
  70. ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
  71. return
  72. }
  73. publicOnly = !isMember && !ctx.Doer.IsAdmin
  74. }
  75. listMembers(ctx, publicOnly)
  76. }
  77. // ListPublicMembers list an organization's public members
  78. func ListPublicMembers(ctx *context.APIContext) {
  79. // swagger:operation GET /orgs/{org}/public_members organization orgListPublicMembers
  80. // ---
  81. // summary: List an organization's public members
  82. // parameters:
  83. // - name: org
  84. // in: path
  85. // description: name of the organization
  86. // type: string
  87. // required: true
  88. // - name: page
  89. // in: query
  90. // description: page number of results to return (1-based)
  91. // type: integer
  92. // - name: limit
  93. // in: query
  94. // description: page size of results
  95. // type: integer
  96. // produces:
  97. // - application/json
  98. // responses:
  99. // "200":
  100. // "$ref": "#/responses/UserList"
  101. // "404":
  102. // "$ref": "#/responses/notFound"
  103. listMembers(ctx, true)
  104. }
  105. // IsMember check if a user is a member of an organization
  106. func IsMember(ctx *context.APIContext) {
  107. // swagger:operation GET /orgs/{org}/members/{username} organization orgIsMember
  108. // ---
  109. // summary: Check if a user is a member of an organization
  110. // parameters:
  111. // - name: org
  112. // in: path
  113. // description: name of the organization
  114. // type: string
  115. // required: true
  116. // - name: username
  117. // in: path
  118. // description: username of the user
  119. // type: string
  120. // required: true
  121. // responses:
  122. // "204":
  123. // description: user is a member
  124. // "303":
  125. // description: redirection to /orgs/{org}/public_members/{username}
  126. // "404":
  127. // description: user is not a member
  128. userToCheck := user.GetUserByParams(ctx)
  129. if ctx.Written() {
  130. return
  131. }
  132. if ctx.Doer != nil {
  133. userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID)
  134. if err != nil {
  135. ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
  136. return
  137. } else if userIsMember || ctx.Doer.IsAdmin {
  138. userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(ctx, userToCheck.ID)
  139. if err != nil {
  140. ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
  141. } else if userToCheckIsMember {
  142. ctx.Status(http.StatusNoContent)
  143. } else {
  144. ctx.NotFound()
  145. }
  146. return
  147. } else if ctx.Doer.ID == userToCheck.ID {
  148. ctx.NotFound()
  149. return
  150. }
  151. }
  152. redirectURL := setting.AppSubURL + "/api/v1/orgs/" + url.PathEscape(ctx.Org.Organization.Name) + "/public_members/" + url.PathEscape(userToCheck.Name)
  153. ctx.Redirect(redirectURL)
  154. }
  155. // IsPublicMember check if a user is a public member of an organization
  156. func IsPublicMember(ctx *context.APIContext) {
  157. // swagger:operation GET /orgs/{org}/public_members/{username} organization orgIsPublicMember
  158. // ---
  159. // summary: Check if a user is a public member of an organization
  160. // parameters:
  161. // - name: org
  162. // in: path
  163. // description: name of the organization
  164. // type: string
  165. // required: true
  166. // - name: username
  167. // in: path
  168. // description: username of the user
  169. // type: string
  170. // required: true
  171. // responses:
  172. // "204":
  173. // description: user is a public member
  174. // "404":
  175. // description: user is not a public member
  176. userToCheck := user.GetUserByParams(ctx)
  177. if ctx.Written() {
  178. return
  179. }
  180. is, err := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, userToCheck.ID)
  181. if err != nil {
  182. ctx.Error(http.StatusInternalServerError, "IsPublicMembership", err)
  183. return
  184. }
  185. if is {
  186. ctx.Status(http.StatusNoContent)
  187. } else {
  188. ctx.NotFound()
  189. }
  190. }
  191. // PublicizeMember make a member's membership public
  192. func PublicizeMember(ctx *context.APIContext) {
  193. // swagger:operation PUT /orgs/{org}/public_members/{username} organization orgPublicizeMember
  194. // ---
  195. // summary: Publicize a user's membership
  196. // produces:
  197. // - application/json
  198. // parameters:
  199. // - name: org
  200. // in: path
  201. // description: name of the organization
  202. // type: string
  203. // required: true
  204. // - name: username
  205. // in: path
  206. // description: username of the user
  207. // type: string
  208. // required: true
  209. // responses:
  210. // "204":
  211. // description: membership publicized
  212. // "403":
  213. // "$ref": "#/responses/forbidden"
  214. // "404":
  215. // "$ref": "#/responses/notFound"
  216. userToPublicize := user.GetUserByParams(ctx)
  217. if ctx.Written() {
  218. return
  219. }
  220. if userToPublicize.ID != ctx.Doer.ID {
  221. ctx.Error(http.StatusForbidden, "", "Cannot publicize another member")
  222. return
  223. }
  224. err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToPublicize.ID, true)
  225. if err != nil {
  226. ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
  227. return
  228. }
  229. ctx.Status(http.StatusNoContent)
  230. }
  231. // ConcealMember make a member's membership not public
  232. func ConcealMember(ctx *context.APIContext) {
  233. // swagger:operation DELETE /orgs/{org}/public_members/{username} organization orgConcealMember
  234. // ---
  235. // summary: Conceal a user's membership
  236. // produces:
  237. // - application/json
  238. // parameters:
  239. // - name: org
  240. // in: path
  241. // description: name of the organization
  242. // type: string
  243. // required: true
  244. // - name: username
  245. // in: path
  246. // description: username of the user
  247. // type: string
  248. // required: true
  249. // responses:
  250. // "204":
  251. // "$ref": "#/responses/empty"
  252. // "403":
  253. // "$ref": "#/responses/forbidden"
  254. // "404":
  255. // "$ref": "#/responses/notFound"
  256. userToConceal := user.GetUserByParams(ctx)
  257. if ctx.Written() {
  258. return
  259. }
  260. if userToConceal.ID != ctx.Doer.ID {
  261. ctx.Error(http.StatusForbidden, "", "Cannot conceal another member")
  262. return
  263. }
  264. err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToConceal.ID, false)
  265. if err != nil {
  266. ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err)
  267. return
  268. }
  269. ctx.Status(http.StatusNoContent)
  270. }
  271. // DeleteMember remove a member from an organization
  272. func DeleteMember(ctx *context.APIContext) {
  273. // swagger:operation DELETE /orgs/{org}/members/{username} organization orgDeleteMember
  274. // ---
  275. // summary: Remove a member from an organization
  276. // produces:
  277. // - application/json
  278. // parameters:
  279. // - name: org
  280. // in: path
  281. // description: name of the organization
  282. // type: string
  283. // required: true
  284. // - name: username
  285. // in: path
  286. // description: username of the user
  287. // type: string
  288. // required: true
  289. // responses:
  290. // "204":
  291. // description: member removed
  292. // "404":
  293. // "$ref": "#/responses/notFound"
  294. member := user.GetUserByParams(ctx)
  295. if ctx.Written() {
  296. return
  297. }
  298. if err := models.RemoveOrgUser(ctx, ctx.Org.Organization, member); err != nil {
  299. ctx.Error(http.StatusInternalServerError, "RemoveOrgUser", err)
  300. }
  301. ctx.Status(http.StatusNoContent)
  302. }