gitea源码

member.go 9.0KB

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