2014-08-14 14:12:21 +08:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2020-01-24 19:00:29 +00:00
// Copyright 2020 The Gitea Authors.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2014-08-14 14:12:21 +08:00
2016-03-11 11:56:52 -05:00
package context
2014-08-14 14:12:21 +08:00
import (
2016-01-31 13:28:42 +00:00
"strings"
2022-03-29 14:29:02 +08:00
"code.gitea.io/gitea/models/organization"
2021-11-28 19:58:28 +08:00
"code.gitea.io/gitea/models/perm"
2023-01-20 19:42:33 +08:00
"code.gitea.io/gitea/models/unit"
2021-11-11 15:03:30 +08:00
user_model "code.gitea.io/gitea/models/user"
2024-02-23 01:24:57 +01:00
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
2022-04-01 01:31:53 +08:00
"code.gitea.io/gitea/modules/setting"
2022-07-15 22:21:54 +08:00
"code.gitea.io/gitea/modules/structs"
2014-08-14 14:12:21 +08:00
)
2016-11-25 14:51:01 +08:00
// Organization contains organization context
2016-03-13 17:37:44 -04:00
type Organization struct {
2019-11-20 12:27:49 +01:00
IsOwner bool
IsMember bool
IsTeamMember bool // Is member of team.
IsTeamAdmin bool // In owner team or team that has admin permission level.
2022-03-29 14:29:02 +08:00
Organization * organization . Organization
2019-11-20 12:27:49 +01:00
OrgLink string
CanCreateOrgRepo bool
2016-03-13 17:37:44 -04:00
2022-03-29 14:29:02 +08:00
Team * organization . Team
Teams [ ] * organization . Team
2016-03-13 17:37:44 -04:00
}
2023-01-20 19:42:33 +08:00
func ( org * Organization ) CanWriteUnit ( ctx * Context , unitType unit . Type ) bool {
2023-03-11 00:18:20 +09:00
return org . Organization . UnitPermission ( ctx , ctx . Doer , unitType ) >= perm . AccessModeWrite
2023-01-20 19:42:33 +08:00
}
2023-03-11 00:18:20 +09:00
func ( org * Organization ) CanReadUnit ( ctx * Context , unitType unit . Type ) bool {
return org . Organization . UnitPermission ( ctx , ctx . Doer , unitType ) >= perm . AccessModeRead
}
2023-01-20 19:42:33 +08:00
2023-03-11 00:18:20 +09:00
func GetOrganizationByParams ( ctx * Context ) {
2024-06-19 06:32:45 +08:00
orgName := ctx . PathParam ( ":org" )
2023-03-11 00:18:20 +09:00
var err error
2023-01-20 19:42:33 +08:00
2023-03-11 00:18:20 +09:00
ctx . Org . Organization , err = organization . GetOrgByName ( ctx , orgName )
if err != nil {
if organization . IsErrOrgNotExist ( err ) {
2023-09-25 15:17:37 +02:00
redirectUserID , err := user_model . LookupUserRedirect ( ctx , orgName )
2023-03-11 00:18:20 +09:00
if err == nil {
2023-05-21 09:50:53 +08:00
RedirectToUser ( ctx . Base , orgName , redirectUserID )
2023-03-11 00:18:20 +09:00
} else if user_model . IsErrUserRedirectNotExist ( err ) {
ctx . NotFound ( "GetUserByName" , err )
} else {
ctx . ServerError ( "LookupUserRedirect" , err )
}
} else {
ctx . ServerError ( "GetUserByName" , err )
}
return
}
2023-01-20 19:42:33 +08:00
}
2016-11-25 14:51:01 +08:00
// HandleOrgAssignment handles organization assignment
2015-11-24 19:14:00 -05:00
func HandleOrgAssignment ( ctx * Context , args ... bool ) {
var (
2016-01-31 13:28:42 +00:00
requireMember bool
requireOwner bool
requireTeamMember bool
2016-01-31 15:18:28 +00:00
requireTeamAdmin bool
2015-11-24 19:14:00 -05:00
)
if len ( args ) >= 1 {
requireMember = args [ 0 ]
}
if len ( args ) >= 2 {
requireOwner = args [ 1 ]
}
if len ( args ) >= 3 {
2016-01-31 13:28:42 +00:00
requireTeamMember = args [ 2 ]
}
if len ( args ) >= 4 {
2016-01-31 15:18:28 +00:00
requireTeamAdmin = args [ 3 ]
2015-11-24 19:14:00 -05:00
}
2014-08-14 14:12:21 +08:00
2015-11-24 19:14:00 -05:00
var err error
2023-03-11 00:18:20 +09:00
if ctx . ContextUser == nil {
// if Organization is not defined, get it from params
if ctx . Org . Organization == nil {
GetOrganizationByParams ( ctx )
if ctx . Written ( ) {
return
2021-01-24 10:23:05 -05:00
}
2014-08-14 14:12:21 +08:00
}
2023-03-11 00:18:20 +09:00
} else if ctx . ContextUser . IsOrganization ( ) {
if ctx . Org == nil {
ctx . Org = & Organization { }
}
ctx . Org . Organization = ( * organization . Organization ) ( ctx . ContextUser )
} else {
// ContextUser is an individual User
2015-11-24 19:14:00 -05:00
return
}
2023-03-11 00:18:20 +09:00
2015-11-24 19:14:00 -05:00
org := ctx . Org . Organization
2022-07-15 22:21:54 +08:00
// Handle Visibility
if org . Visibility != structs . VisibleTypePublic && ! ctx . IsSigned {
// We must be signed in to see limited or private organizations
ctx . NotFound ( "OrgAssignment" , err )
return
}
if org . Visibility == structs . VisibleTypePrivate {
requireMember = true
} else if ctx . IsSigned && ctx . Doer . IsRestricted {
requireMember = true
}
2022-03-26 10:04:22 +01:00
ctx . ContextUser = org . AsUser ( )
2015-11-24 19:14:00 -05:00
ctx . Data [ "Org" ] = org
2014-08-14 14:12:21 +08:00
2015-11-28 22:31:06 +01:00
// Admin has super access.
2022-03-22 08:03:22 +01:00
if ctx . IsSigned && ctx . Doer . IsAdmin {
2015-11-28 22:31:06 +01:00
ctx . Org . IsOwner = true
ctx . Org . IsMember = true
2016-01-31 13:28:42 +00:00
ctx . Org . IsTeamMember = true
2016-01-31 15:18:28 +00:00
ctx . Org . IsTeamAdmin = true
2019-11-20 12:27:49 +01:00
ctx . Org . CanCreateOrgRepo = true
2015-11-28 22:31:06 +01:00
} else if ctx . IsSigned {
2023-10-03 12:30:41 +02:00
ctx . Org . IsOwner , err = org . IsOwnedBy ( ctx , ctx . Doer . ID )
2017-12-20 23:43:26 -08:00
if err != nil {
2018-01-10 22:34:17 +01:00
ctx . ServerError ( "IsOwnedBy" , err )
2017-12-20 23:43:26 -08:00
return
}
2015-11-24 19:14:00 -05:00
if ctx . Org . IsOwner {
ctx . Org . IsMember = true
2016-01-31 13:28:42 +00:00
ctx . Org . IsTeamMember = true
2016-01-31 15:18:28 +00:00
ctx . Org . IsTeamAdmin = true
2019-11-20 12:27:49 +01:00
ctx . Org . CanCreateOrgRepo = true
2015-11-24 19:14:00 -05:00
} else {
2023-10-03 12:30:41 +02:00
ctx . Org . IsMember , err = org . IsOrgMember ( ctx , ctx . Doer . ID )
2017-12-20 23:43:26 -08:00
if err != nil {
2018-01-10 22:34:17 +01:00
ctx . ServerError ( "IsOrgMember" , err )
2017-12-20 23:43:26 -08:00
return
2014-08-14 14:12:21 +08:00
}
2023-10-03 12:30:41 +02:00
ctx . Org . CanCreateOrgRepo , err = org . CanCreateOrgRepo ( ctx , ctx . Doer . ID )
2019-11-20 12:27:49 +01:00
if err != nil {
ctx . ServerError ( "CanCreateOrgRepo" , err )
return
}
2014-08-14 14:12:21 +08:00
}
2015-11-24 19:14:00 -05:00
} else {
// Fake data.
2021-11-24 17:49:20 +08:00
ctx . Data [ "SignedUser" ] = & user_model . User { }
2015-11-24 19:14:00 -05:00
}
if ( requireMember && ! ctx . Org . IsMember ) ||
( requireOwner && ! ctx . Org . IsOwner ) {
2018-01-10 22:34:17 +01:00
ctx . NotFound ( "OrgAssignment" , err )
2015-11-24 19:14:00 -05:00
return
}
ctx . Data [ "IsOrganizationOwner" ] = ctx . Org . IsOwner
2015-11-28 22:31:06 +01:00
ctx . Data [ "IsOrganizationMember" ] = ctx . Org . IsMember
2022-04-01 01:31:53 +08:00
ctx . Data [ "IsPackageEnabled" ] = setting . Packages . Enabled
2022-10-11 02:12:03 +03:00
ctx . Data [ "IsRepoIndexerEnabled" ] = setting . Indexer . RepoIndexerEnabled
2021-11-22 23:21:55 +08:00
ctx . Data [ "IsPublicMember" ] = func ( uid int64 ) bool {
2023-10-03 12:30:41 +02:00
is , _ := organization . IsPublicMembership ( ctx , ctx . Org . Organization . ID , uid )
2021-11-22 23:21:55 +08:00
return is
}
2019-11-20 12:27:49 +01:00
ctx . Data [ "CanCreateOrgRepo" ] = ctx . Org . CanCreateOrgRepo
2014-08-15 18:29:41 +08:00
2021-11-19 19:41:40 +08:00
ctx . Org . OrgLink = org . AsUser ( ) . OrganisationLink ( )
2015-11-24 19:14:00 -05:00
ctx . Data [ "OrgLink" ] = ctx . Org . OrgLink
2014-08-16 16:21:17 +08:00
2023-08-15 23:00:35 +09:00
// Member
opts := & organization . FindOrgMembersOpts {
2024-11-11 01:38:30 +01:00
Doer : ctx . Doer ,
OrgID : org . ID ,
IsDoerMember : ctx . Org . IsMember ,
2023-08-15 23:00:35 +09:00
}
2023-10-03 12:30:41 +02:00
ctx . Data [ "NumMembers" ] , err = organization . CountOrgMembers ( ctx , opts )
2023-08-15 23:00:35 +09:00
if err != nil {
ctx . ServerError ( "CountOrgMembers" , err )
return
}
2015-11-24 19:14:00 -05:00
// Team.
2016-01-31 13:28:42 +00:00
if ctx . Org . IsMember {
2022-02-26 20:12:01 +00:00
shouldSeeAllTeams := false
2016-01-31 16:13:31 +00:00
if ctx . Org . IsOwner {
2022-02-26 20:12:01 +00:00
shouldSeeAllTeams = true
} else {
2023-10-03 12:30:41 +02:00
teams , err := org . GetUserTeams ( ctx , ctx . Doer . ID )
2022-02-26 20:12:01 +00:00
if err != nil {
ctx . ServerError ( "GetUserTeams" , err )
return
}
for _ , team := range teams {
if team . IncludesAllRepositories && team . AccessMode >= perm . AccessModeAdmin {
shouldSeeAllTeams = true
break
}
}
}
if shouldSeeAllTeams {
2023-10-03 12:30:41 +02:00
ctx . Org . Teams , err = org . LoadTeams ( ctx )
2021-11-19 19:41:40 +08:00
if err != nil {
2021-08-12 14:43:08 +02:00
ctx . ServerError ( "LoadTeams" , err )
2016-01-31 16:13:31 +00:00
return
}
} else {
2023-10-03 12:30:41 +02:00
ctx . Org . Teams , err = org . GetUserTeams ( ctx , ctx . Doer . ID )
2016-07-24 18:09:45 +08:00
if err != nil {
2018-01-10 22:34:17 +01:00
ctx . ServerError ( "GetUserTeams" , err )
2016-01-31 16:13:31 +00:00
return
}
2016-01-31 13:28:42 +00:00
}
2023-08-15 23:00:35 +09:00
ctx . Data [ "NumTeams" ] = len ( ctx . Org . Teams )
2016-01-31 13:28:42 +00:00
}
2024-06-19 06:32:45 +08:00
teamName := ctx . PathParam ( ":team" )
2015-11-24 19:14:00 -05:00
if len ( teamName ) > 0 {
2016-01-31 13:28:42 +00:00
teamExists := false
2021-11-19 19:41:40 +08:00
for _ , team := range ctx . Org . Teams {
2016-02-04 13:03:34 -05:00
if team . LowerName == strings . ToLower ( teamName ) {
2016-01-31 13:28:42 +00:00
teamExists = true
ctx . Org . Team = team
ctx . Org . IsTeamMember = true
ctx . Data [ "Team" ] = ctx . Org . Team
break
2014-08-16 16:21:17 +08:00
}
2016-01-31 13:28:42 +00:00
}
if ! teamExists {
2018-01-10 22:34:17 +01:00
ctx . NotFound ( "OrgAssignment" , err )
2016-01-31 13:28:42 +00:00
return
}
ctx . Data [ "IsTeamMember" ] = ctx . Org . IsTeamMember
if requireTeamMember && ! ctx . Org . IsTeamMember {
2018-01-10 22:34:17 +01:00
ctx . NotFound ( "OrgAssignment" , err )
2014-08-24 21:09:05 +08:00
return
2014-08-16 16:21:17 +08:00
}
2016-01-31 13:28:42 +00:00
2022-01-05 11:37:00 +08:00
ctx . Org . IsTeamAdmin = ctx . Org . Team . IsOwnerTeam ( ) || ctx . Org . Team . AccessMode >= perm . AccessModeAdmin
2016-01-31 15:18:28 +00:00
ctx . Data [ "IsTeamAdmin" ] = ctx . Org . IsTeamAdmin
if requireTeamAdmin && ! ctx . Org . IsTeamAdmin {
2018-01-10 22:34:17 +01:00
ctx . NotFound ( "OrgAssignment" , err )
2016-01-31 13:28:42 +00:00
return
}
2015-11-24 19:14:00 -05:00
}
2023-09-06 15:38:14 +09:00
ctx . Data [ "ContextUser" ] = ctx . ContextUser
2023-03-11 00:18:20 +09:00
ctx . Data [ "CanReadProjects" ] = ctx . Org . CanReadUnit ( ctx , unit . TypeProjects )
ctx . Data [ "CanReadPackages" ] = ctx . Org . CanReadUnit ( ctx , unit . TypePackages )
ctx . Data [ "CanReadCode" ] = ctx . Org . CanReadUnit ( ctx , unit . TypeCode )
2024-02-23 01:24:57 +01:00
ctx . Data [ "IsFollowing" ] = ctx . Doer != nil && user_model . IsFollowing ( ctx , ctx . Doer . ID , ctx . ContextUser . ID )
if len ( ctx . ContextUser . Description ) != 0 {
content , err := markdown . RenderString ( & markup . RenderContext {
Metas : map [ string ] string { "mode" : "document" } ,
Ctx : ctx ,
} , ctx . ContextUser . Description )
if err != nil {
ctx . ServerError ( "RenderString" , err )
return
}
ctx . Data [ "RenderedDescription" ] = content
}
2015-11-24 19:14:00 -05:00
}
2021-01-29 23:35:30 +08:00
// OrgAssignment returns a middleware to handle organization assignment
2021-01-26 23:36:53 +08:00
func OrgAssignment ( args ... bool ) func ( ctx * Context ) {
2015-11-24 19:14:00 -05:00
return func ( ctx * Context ) {
HandleOrgAssignment ( ctx , args ... )
2014-08-14 14:12:21 +08:00
}
}