From 667f68ebc87b23d5b46c4c41666153f285bf5b49 Mon Sep 17 00:00:00 2001
From: yp05327 <576951401@qq.com>
Date: Tue, 21 Feb 2023 15:44:49 +0900
Subject: [PATCH] add org team permission check
---
models/organization/org.go | 26 +++++++++++++++++++++++
models/user/user.go | 5 +++++
modules/context/org.go | 30 ++++++++-------------------
routers/web/org/home.go | 3 ++-
routers/web/shared/user/header.go | 2 ++
routers/web/user/code.go | 1 +
routers/web/user/profile.go | 1 +
routers/web/web.go | 32 ++++++++++++++++++++++++++---
templates/org/menu.tmpl | 6 ++++--
templates/user/overview/header.tmpl | 6 ++++--
10 files changed, 82 insertions(+), 30 deletions(-)
diff --git a/models/organization/org.go b/models/organization/org.go
index f05027be729d4..269b3e83288dc 100644
--- a/models/organization/org.go
+++ b/models/organization/org.go
@@ -239,6 +239,32 @@ func (org *Organization) CustomAvatarRelativePath() string {
return org.Avatar
}
+// UnitPermission returns unit permission
+func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.User, unitType unit.Type) perm.AccessMode {
+ if doer != nil {
+ teams, err := GetUserOrgTeams(ctx, org.ID, doer.ID)
+ if err != nil {
+ log.Error("GetUserOrgTeams: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if err := teams.LoadUnits(ctx); err != nil {
+ log.Error("LoadUnits: %v", err)
+ return perm.AccessModeNone
+ }
+
+ if len(teams) > 0 {
+ return teams.UnitMaxAccess(unitType)
+ }
+ }
+
+ if org.Visibility.IsPublic() {
+ return perm.AccessModeRead
+ }
+
+ return perm.AccessModeNone
+}
+
// CreateOrganization creates record of a new organization.
func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
if !owner.CanCreateOrganization() {
diff --git a/models/user/user.go b/models/user/user.go
index f6fafe64f3915..454779b9ea361 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -393,6 +393,11 @@ func (u *User) IsOrganization() bool {
return u.Type == UserTypeOrganization
}
+// IsIndividual returns true if user is actually a individual user.
+func (u *User) IsIndividual() bool {
+ return u.Type == UserTypeIndividual
+}
+
// DisplayName returns full name if it's not empty,
// returns username otherwise.
func (u *User) DisplayName() string {
diff --git a/modules/context/org.go b/modules/context/org.go
index 50c9f6f757760..61491eedf2334 100644
--- a/modules/context/org.go
+++ b/modules/context/org.go
@@ -11,7 +11,6 @@ import (
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
)
@@ -31,29 +30,11 @@ type Organization struct {
}
func (org *Organization) CanWriteUnit(ctx *Context, unitType unit.Type) bool {
- if ctx.Doer == nil {
- return false
- }
- return org.UnitPermission(ctx, ctx.Doer.ID, unitType) >= perm.AccessModeWrite
+ return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeWrite
}
-func (org *Organization) UnitPermission(ctx *Context, doerID int64, unitType unit.Type) perm.AccessMode {
- if doerID > 0 {
- teams, err := organization.GetUserOrgTeams(ctx, org.Organization.ID, doerID)
- if err != nil {
- log.Error("GetUserOrgTeams: %v", err)
- return perm.AccessModeNone
- }
- if len(teams) > 0 {
- return teams.UnitMaxAccess(unitType)
- }
- }
-
- if org.Organization.Visibility == structs.VisibleTypePublic {
- return perm.AccessModeRead
- }
-
- return perm.AccessModeNone
+func (org *Organization) CanReadUnit(ctx *Context, unitType unit.Type) bool {
+ return org.Organization.UnitPermission(ctx, ctx.Doer, unitType) >= perm.AccessModeRead
}
func GetOrganizationByParams(ctx *Context) {
@@ -170,6 +151,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
}
ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["IsPublicMember"] = func(uid int64) bool {
@@ -245,6 +227,10 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
return
}
}
+
+ 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)
}
// OrgAssignment returns a middleware to handle organization assignment
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index 4cc364acd3a01..61eaa1bb933bf 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -156,6 +156,7 @@ func Home(ctx *context.Context) {
pager.SetDefaultParams(ctx)
pager.AddParam(ctx, "language", "Language")
ctx.Data["Page"] = pager
-
+ ctx.Data["ContextUser"] = ctx.ContextUser
+
ctx.HTML(http.StatusOK, tplOrgHome)
}
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index 94e59e2a490fd..05e45f999eed9 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -9,6 +9,8 @@ import (
)
func RenderUserHeader(ctx *context.Context) {
+ ctx.Data["IsProjectEnabled"] = true
+ ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["ContextUser"] = ctx.ContextUser
}
diff --git a/routers/web/user/code.go b/routers/web/user/code.go
index 81e3e65b4b67a..b3adbcb8d3a8f 100644
--- a/routers/web/user/code.go
+++ b/routers/web/user/code.go
@@ -24,6 +24,7 @@ func CodeSearch(ctx *context.Context) {
return
}
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["Title"] = ctx.Tr("explore.code")
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 4f0a816569bb9..0a215e920344e 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -288,6 +288,7 @@ func Profile(ctx *context.Context) {
pager.AddParam(ctx, "language", "Language")
}
ctx.Data["Page"] = pager
+ ctx.Data["IsProjectEnabled"] = true
ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
diff --git a/routers/web/web.go b/routers/web/web.go
index 88e27ad678992..36986cff63793 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -869,8 +869,21 @@ func RegisterRoutes(m *web.Route) {
}
m.Group("/projects", func() {
- m.Get("", org.Projects)
- m.Get("/{id}", org.ViewProject)
+ m.Group("", func() {
+ m.Get("", org.Projects)
+ m.Get("/{id}", org.ViewProject)
+ }, func(ctx *context.Context) {
+ if ctx.ContextUser == nil {
+ ctx.NotFound("Project", nil)
+ return
+ }
+ if ctx.ContextUser.IsOrganization() {
+ if !ctx.Org.CanReadUnit(ctx, unit.TypeProjects) {
+ ctx.NotFound("Project", nil)
+ return
+ }
+ }
+ })
m.Group("", func() { //nolint:dupl
m.Get("/new", org.NewProject)
m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
@@ -907,7 +920,20 @@ func RegisterRoutes(m *web.Route) {
})
}, repo.MustEnableProjects)
- m.Get("/code", user.CodeSearch)
+ m.Group("", func() {
+ m.Get("/code", user.CodeSearch)
+ }, func(ctx *context.Context) {
+ if ctx.ContextUser == nil {
+ ctx.NotFound("Code", nil)
+ return
+ }
+ if ctx.ContextUser.IsOrganization() {
+ if !ctx.Org.CanReadUnit(ctx, unit.TypeCode) {
+ ctx.NotFound("Code", nil)
+ return
+ }
+ }
+ })
}, context_service.UserAssignmentWeb())
// ***** Release Attachment Download without Signin
diff --git a/templates/org/menu.tmpl b/templates/org/menu.tmpl
index 4c6000603f268..d4bea05f9d6c7 100644
--- a/templates/org/menu.tmpl
+++ b/templates/org/menu.tmpl
@@ -3,15 +3,17 @@
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
+ {{if and .IsProjectEnabled (and .ContextUser.IsOrganization .CanReadProjects)}}
{{svg "octicon-project"}} {{.locale.Tr "user.projects"}}
- {{if .IsPackageEnabled}}
+ {{end}}
+ {{if and .IsPackageEnabled (and .ContextUser.IsOrganization .CanReadPackages)}}
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
{{end}}
- {{if .IsRepoIndexerEnabled}}
+ {{if and .IsRepoIndexerEnabled (and .ContextUser.IsOrganization .CanReadCode)}}
{{svg "octicon-code"}} {{$.locale.Tr "org.code"}}
diff --git a/templates/user/overview/header.tmpl b/templates/user/overview/header.tmpl
index 9b32886891dfe..f0537f3d1a453 100644
--- a/templates/user/overview/header.tmpl
+++ b/templates/user/overview/header.tmpl
@@ -22,15 +22,17 @@
{{svg "octicon-repo"}} {{.locale.Tr "user.repositories"}}
+ {{if and .IsProjectEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadProjects))}}
{{svg "octicon-project"}} {{.locale.Tr "user.projects"}}
- {{if .IsPackageEnabled}}
+ {{end}}
+ {{if and .IsPackageEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadPackages))}}
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
{{end}}
- {{if .IsRepoIndexerEnabled}}
+ {{if and .IsRepoIndexerEnabled (or .ContextUser.IsIndividual (and .ContextUser.IsOrganization .CanReadCode))}}
{{svg "octicon-code"}} {{.locale.Tr "user.code"}}