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 }