code.gitea.io/gitea@v1.22.3/services/context/org.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 context
     6  
     7  import (
     8  	"strings"
     9  
    10  	"code.gitea.io/gitea/models/organization"
    11  	"code.gitea.io/gitea/models/perm"
    12  	"code.gitea.io/gitea/models/unit"
    13  	user_model "code.gitea.io/gitea/models/user"
    14  	"code.gitea.io/gitea/modules/markup"
    15  	"code.gitea.io/gitea/modules/markup/markdown"
    16  	"code.gitea.io/gitea/modules/setting"
    17  	"code.gitea.io/gitea/modules/structs"
    18  )
    19  
    20  // Organization contains organization context
    21  type Organization struct {
    22  	IsOwner          bool
    23  	IsMember         bool
    24  	IsTeamMember     bool // Is member of team.
    25  	IsTeamAdmin      bool // In owner team or team that has admin permission level.
    26  	Organization     *organization.Organization
    27  	OrgLink          string
    28  	CanCreateOrgRepo bool
    29  	PublicMemberOnly bool // Only display public members
    30  
    31  	Team  *organization.Team
    32  	Teams []*organization.Team
    33  }
    34  
    35  func (org *Organization) CanWriteUnit(ctx *Context, unitType unit.Type) bool {
    36  	return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeWrite
    37  }
    38  
    39  func (org *Organization) CanReadUnit(ctx *Context, unitType unit.Type) bool {
    40  	return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeRead
    41  }
    42  
    43  func GetOrganizationByParams(ctx *Context) {
    44  	orgName := ctx.Params(":org")
    45  
    46  	var err error
    47  
    48  	ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
    49  	if err != nil {
    50  		if organization.IsErrOrgNotExist(err) {
    51  			redirectUserID, err := user_model.LookupUserRedirect(ctx, orgName)
    52  			if err == nil {
    53  				RedirectToUser(ctx.Base, orgName, redirectUserID)
    54  			} else if user_model.IsErrUserRedirectNotExist(err) {
    55  				ctx.NotFound("GetUserByName", err)
    56  			} else {
    57  				ctx.ServerError("LookupUserRedirect", err)
    58  			}
    59  		} else {
    60  			ctx.ServerError("GetUserByName", err)
    61  		}
    62  		return
    63  	}
    64  }
    65  
    66  // HandleOrgAssignment handles organization assignment
    67  func HandleOrgAssignment(ctx *Context, args ...bool) {
    68  	var (
    69  		requireMember     bool
    70  		requireOwner      bool
    71  		requireTeamMember bool
    72  		requireTeamAdmin  bool
    73  	)
    74  	if len(args) >= 1 {
    75  		requireMember = args[0]
    76  	}
    77  	if len(args) >= 2 {
    78  		requireOwner = args[1]
    79  	}
    80  	if len(args) >= 3 {
    81  		requireTeamMember = args[2]
    82  	}
    83  	if len(args) >= 4 {
    84  		requireTeamAdmin = args[3]
    85  	}
    86  
    87  	var err error
    88  
    89  	if ctx.ContextUser == nil {
    90  		// if Organization is not defined, get it from params
    91  		if ctx.Org.Organization == nil {
    92  			GetOrganizationByParams(ctx)
    93  			if ctx.Written() {
    94  				return
    95  			}
    96  		}
    97  	} else if ctx.ContextUser.IsOrganization() {
    98  		if ctx.Org == nil {
    99  			ctx.Org = &Organization{}
   100  		}
   101  		ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser)
   102  	} else {
   103  		// ContextUser is an individual User
   104  		return
   105  	}
   106  
   107  	org := ctx.Org.Organization
   108  
   109  	// Handle Visibility
   110  	if org.Visibility != structs.VisibleTypePublic && !ctx.IsSigned {
   111  		// We must be signed in to see limited or private organizations
   112  		ctx.NotFound("OrgAssignment", err)
   113  		return
   114  	}
   115  
   116  	if org.Visibility == structs.VisibleTypePrivate {
   117  		requireMember = true
   118  	} else if ctx.IsSigned && ctx.Doer.IsRestricted {
   119  		requireMember = true
   120  	}
   121  
   122  	ctx.ContextUser = org.AsUser()
   123  	ctx.Data["Org"] = org
   124  
   125  	// Admin has super access.
   126  	if ctx.IsSigned && ctx.Doer.IsAdmin {
   127  		ctx.Org.IsOwner = true
   128  		ctx.Org.IsMember = true
   129  		ctx.Org.IsTeamMember = true
   130  		ctx.Org.IsTeamAdmin = true
   131  		ctx.Org.CanCreateOrgRepo = true
   132  	} else if ctx.IsSigned {
   133  		ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID)
   134  		if err != nil {
   135  			ctx.ServerError("IsOwnedBy", err)
   136  			return
   137  		}
   138  
   139  		if ctx.Org.IsOwner {
   140  			ctx.Org.IsMember = true
   141  			ctx.Org.IsTeamMember = true
   142  			ctx.Org.IsTeamAdmin = true
   143  			ctx.Org.CanCreateOrgRepo = true
   144  		} else {
   145  			ctx.Org.IsMember, err = org.IsOrgMember(ctx, ctx.Doer.ID)
   146  			if err != nil {
   147  				ctx.ServerError("IsOrgMember", err)
   148  				return
   149  			}
   150  			ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx, ctx.Doer.ID)
   151  			if err != nil {
   152  				ctx.ServerError("CanCreateOrgRepo", err)
   153  				return
   154  			}
   155  		}
   156  	} else {
   157  		// Fake data.
   158  		ctx.Data["SignedUser"] = &user_model.User{}
   159  	}
   160  	if (requireMember && !ctx.Org.IsMember) ||
   161  		(requireOwner && !ctx.Org.IsOwner) {
   162  		ctx.NotFound("OrgAssignment", err)
   163  		return
   164  	}
   165  	ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
   166  	ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
   167  	ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
   168  	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
   169  	ctx.Data["IsPublicMember"] = func(uid int64) bool {
   170  		is, _ := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, uid)
   171  		return is
   172  	}
   173  	ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo
   174  
   175  	ctx.Org.OrgLink = org.AsUser().OrganisationLink()
   176  	ctx.Data["OrgLink"] = ctx.Org.OrgLink
   177  
   178  	// Member
   179  	ctx.Org.PublicMemberOnly = ctx.Doer == nil || !ctx.Org.IsMember && !ctx.Doer.IsAdmin
   180  	opts := &organization.FindOrgMembersOpts{
   181  		OrgID:      org.ID,
   182  		PublicOnly: ctx.Org.PublicMemberOnly,
   183  	}
   184  	ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts)
   185  	if err != nil {
   186  		ctx.ServerError("CountOrgMembers", err)
   187  		return
   188  	}
   189  
   190  	// Team.
   191  	if ctx.Org.IsMember {
   192  		shouldSeeAllTeams := false
   193  		if ctx.Org.IsOwner {
   194  			shouldSeeAllTeams = true
   195  		} else {
   196  			teams, err := org.GetUserTeams(ctx, ctx.Doer.ID)
   197  			if err != nil {
   198  				ctx.ServerError("GetUserTeams", err)
   199  				return
   200  			}
   201  			for _, team := range teams {
   202  				if team.IncludesAllRepositories && team.AccessMode >= perm.AccessModeAdmin {
   203  					shouldSeeAllTeams = true
   204  					break
   205  				}
   206  			}
   207  		}
   208  		if shouldSeeAllTeams {
   209  			ctx.Org.Teams, err = org.LoadTeams(ctx)
   210  			if err != nil {
   211  				ctx.ServerError("LoadTeams", err)
   212  				return
   213  			}
   214  		} else {
   215  			ctx.Org.Teams, err = org.GetUserTeams(ctx, ctx.Doer.ID)
   216  			if err != nil {
   217  				ctx.ServerError("GetUserTeams", err)
   218  				return
   219  			}
   220  		}
   221  		ctx.Data["NumTeams"] = len(ctx.Org.Teams)
   222  	}
   223  
   224  	teamName := ctx.Params(":team")
   225  	if len(teamName) > 0 {
   226  		teamExists := false
   227  		for _, team := range ctx.Org.Teams {
   228  			if team.LowerName == strings.ToLower(teamName) {
   229  				teamExists = true
   230  				ctx.Org.Team = team
   231  				ctx.Org.IsTeamMember = true
   232  				ctx.Data["Team"] = ctx.Org.Team
   233  				break
   234  			}
   235  		}
   236  
   237  		if !teamExists {
   238  			ctx.NotFound("OrgAssignment", err)
   239  			return
   240  		}
   241  
   242  		ctx.Data["IsTeamMember"] = ctx.Org.IsTeamMember
   243  		if requireTeamMember && !ctx.Org.IsTeamMember {
   244  			ctx.NotFound("OrgAssignment", err)
   245  			return
   246  		}
   247  
   248  		ctx.Org.IsTeamAdmin = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.AccessMode >= perm.AccessModeAdmin
   249  		ctx.Data["IsTeamAdmin"] = ctx.Org.IsTeamAdmin
   250  		if requireTeamAdmin && !ctx.Org.IsTeamAdmin {
   251  			ctx.NotFound("OrgAssignment", err)
   252  			return
   253  		}
   254  	}
   255  	ctx.Data["ContextUser"] = ctx.ContextUser
   256  
   257  	ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects)
   258  	ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages)
   259  	ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode)
   260  
   261  	ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
   262  	if len(ctx.ContextUser.Description) != 0 {
   263  		content, err := markdown.RenderString(&markup.RenderContext{
   264  			Metas: map[string]string{"mode": "document"},
   265  			Ctx:   ctx,
   266  		}, ctx.ContextUser.Description)
   267  		if err != nil {
   268  			ctx.ServerError("RenderString", err)
   269  			return
   270  		}
   271  		ctx.Data["RenderedDescription"] = content
   272  	}
   273  }
   274  
   275  // OrgAssignment returns a middleware to handle organization assignment
   276  func OrgAssignment(args ...bool) func(ctx *Context) {
   277  	return func(ctx *Context) {
   278  		HandleOrgAssignment(ctx, args...)
   279  	}
   280  }