code.gitea.io/gitea@v1.22.3/routers/web/org/members.go (about)

     1  // Copyright 2014 The Gogs Authors. All rights reserved.
     2  // Copyright 2020 The Gitea Authors.
     3  // SPDX-License-Identifier: MIT
     4  
     5  package org
     6  
     7  import (
     8  	"net/http"
     9  
    10  	"code.gitea.io/gitea/models"
    11  	"code.gitea.io/gitea/models/organization"
    12  	user_model "code.gitea.io/gitea/models/user"
    13  	"code.gitea.io/gitea/modules/base"
    14  	"code.gitea.io/gitea/modules/log"
    15  	"code.gitea.io/gitea/modules/setting"
    16  	shared_user "code.gitea.io/gitea/routers/web/shared/user"
    17  	"code.gitea.io/gitea/services/context"
    18  )
    19  
    20  const (
    21  	// tplMembers template for organization members page
    22  	tplMembers base.TplName = "org/member/members"
    23  )
    24  
    25  // Members render organization users page
    26  func Members(ctx *context.Context) {
    27  	org := ctx.Org.Organization
    28  	ctx.Data["Title"] = org.FullName
    29  	ctx.Data["PageIsOrgMembers"] = true
    30  
    31  	page := ctx.FormInt("page")
    32  	if page <= 1 {
    33  		page = 1
    34  	}
    35  
    36  	opts := &organization.FindOrgMembersOpts{
    37  		OrgID:      org.ID,
    38  		PublicOnly: true,
    39  	}
    40  
    41  	if ctx.Doer != nil {
    42  		isMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID)
    43  		if err != nil {
    44  			ctx.Error(http.StatusInternalServerError, "IsOrgMember")
    45  			return
    46  		}
    47  		opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
    48  	}
    49  	ctx.Data["PublicOnly"] = opts.PublicOnly
    50  
    51  	total, err := organization.CountOrgMembers(ctx, opts)
    52  	if err != nil {
    53  		ctx.Error(http.StatusInternalServerError, "CountOrgMembers")
    54  		return
    55  	}
    56  
    57  	err = shared_user.LoadHeaderCount(ctx)
    58  	if err != nil {
    59  		ctx.ServerError("LoadHeaderCount", err)
    60  		return
    61  	}
    62  
    63  	pager := context.NewPagination(int(total), setting.UI.MembersPagingNum, page, 5)
    64  	opts.ListOptions.Page = page
    65  	opts.ListOptions.PageSize = setting.UI.MembersPagingNum
    66  	members, membersIsPublic, err := organization.FindOrgMembers(ctx, opts)
    67  	if err != nil {
    68  		ctx.ServerError("GetMembers", err)
    69  		return
    70  	}
    71  	ctx.Data["Page"] = pager
    72  	ctx.Data["Members"] = members
    73  	ctx.Data["MembersIsPublicMember"] = membersIsPublic
    74  	ctx.Data["MembersIsUserOrgOwner"] = organization.IsUserOrgOwner(ctx, members, org.ID)
    75  	ctx.Data["MembersTwoFaStatus"] = members.GetTwoFaStatus(ctx)
    76  
    77  	ctx.HTML(http.StatusOK, tplMembers)
    78  }
    79  
    80  // MembersAction response for operation to a member of organization
    81  func MembersAction(ctx *context.Context) {
    82  	member, err := user_model.GetUserByID(ctx, ctx.FormInt64("uid"))
    83  	if err != nil {
    84  		log.Error("GetUserByID: %v", err)
    85  	}
    86  	if member == nil {
    87  		ctx.Redirect(ctx.Org.OrgLink + "/members")
    88  		return
    89  	}
    90  
    91  	org := ctx.Org.Organization
    92  
    93  	switch ctx.Params(":action") {
    94  	case "private":
    95  		if ctx.Doer.ID != member.ID && !ctx.Org.IsOwner {
    96  			ctx.Error(http.StatusNotFound)
    97  			return
    98  		}
    99  		err = organization.ChangeOrgUserStatus(ctx, org.ID, member.ID, false)
   100  	case "public":
   101  		if ctx.Doer.ID != member.ID && !ctx.Org.IsOwner {
   102  			ctx.Error(http.StatusNotFound)
   103  			return
   104  		}
   105  		err = organization.ChangeOrgUserStatus(ctx, org.ID, member.ID, true)
   106  	case "remove":
   107  		if !ctx.Org.IsOwner {
   108  			ctx.Error(http.StatusNotFound)
   109  			return
   110  		}
   111  		err = models.RemoveOrgUser(ctx, org, member)
   112  		if organization.IsErrLastOrgOwner(err) {
   113  			ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
   114  			ctx.JSONRedirect(ctx.Org.OrgLink + "/members")
   115  			return
   116  		}
   117  	case "leave":
   118  		err = models.RemoveOrgUser(ctx, org, ctx.Doer)
   119  		if err == nil {
   120  			ctx.Flash.Success(ctx.Tr("form.organization_leave_success", org.DisplayName()))
   121  			ctx.JSON(http.StatusOK, map[string]any{
   122  				"redirect": "", // keep the user stay on current page, in case they want to do other operations.
   123  			})
   124  		} else if organization.IsErrLastOrgOwner(err) {
   125  			ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
   126  			ctx.JSONRedirect(ctx.Org.OrgLink + "/members")
   127  		} else {
   128  			log.Error("RemoveOrgUser(%d,%d): %v", org.ID, ctx.Doer.ID, err)
   129  		}
   130  		return
   131  	}
   132  
   133  	if err != nil {
   134  		log.Error("Action(%s): %v", ctx.Params(":action"), err)
   135  		ctx.JSON(http.StatusOK, map[string]any{
   136  			"ok":  false,
   137  			"err": err.Error(),
   138  		})
   139  		return
   140  	}
   141  
   142  	redirect := ctx.Org.OrgLink + "/members"
   143  	if ctx.Params(":action") == "leave" {
   144  		redirect = setting.AppSubURL + "/"
   145  	}
   146  
   147  	ctx.JSONRedirect(redirect)
   148  }