code.gitea.io/gitea@v1.21.7/routers/api/v1/org/member.go (about)

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