From e68b9d00a6e05b3a941f63ffb696f91e554ac5ec Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 18 Oct 2024 20:33:49 +0200 Subject: Adding upstream version 9.0.3. Signed-off-by: Daniel Baumann --- services/context/permission.go | 149 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 services/context/permission.go (limited to 'services/context/permission.go') diff --git a/services/context/permission.go b/services/context/permission.go new file mode 100644 index 0000000..14a9801 --- /dev/null +++ b/services/context/permission.go @@ -0,0 +1,149 @@ +// Copyright 2018 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package context + +import ( + "net/http" + + auth_model "code.gitea.io/gitea/models/auth" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/modules/log" +) + +// RequireRepoAdmin returns a middleware for requiring repository admin permission +func RequireRepoAdmin() func(ctx *Context) { + return func(ctx *Context) { + if !ctx.IsSigned || !ctx.Repo.IsAdmin() { + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + } +} + +// RequireRepoWriter returns a middleware for requiring repository write to the specify unitType +func RequireRepoWriter(unitType unit.Type) func(ctx *Context) { + return func(ctx *Context) { + if !ctx.Repo.CanWrite(unitType) { + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + } +} + +// CanEnableEditor checks if the user is allowed to write to the branch of the repo +func CanEnableEditor() func(ctx *Context) { + return func(ctx *Context) { + if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { + ctx.NotFound("CanWriteToBranch denies permission", nil) + return + } + } +} + +// RequireRepoWriterOr returns a middleware for requiring repository write to one of the unit permission +func RequireRepoWriterOr(unitTypes ...unit.Type) func(ctx *Context) { + return func(ctx *Context) { + for _, unitType := range unitTypes { + if ctx.Repo.CanWrite(unitType) { + return + } + } + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + } +} + +// RequireRepoReader returns a middleware for requiring repository read to the specify unitType +func RequireRepoReader(unitType unit.Type) func(ctx *Context) { + return func(ctx *Context) { + if !ctx.Repo.CanRead(unitType) { + if log.IsTrace() { + if ctx.IsSigned { + log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+ + "User in Repo has Permissions: %-+v", + ctx.Doer, + unitType, + ctx.Repo.Repository, + ctx.Repo.Permission) + } else { + log.Trace("Permission Denied: Anonymous user cannot read %-v in Repo %-v\n"+ + "Anonymous user in Repo has Permissions: %-+v", + unitType, + ctx.Repo.Repository, + ctx.Repo.Permission) + } + } + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + } +} + +// RequireRepoReaderOr returns a middleware for requiring repository write to one of the unit permission +func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) { + return func(ctx *Context) { + for _, unitType := range unitTypes { + if ctx.Repo.CanRead(unitType) { + return + } + } + if log.IsTrace() { + var format string + var args []any + if ctx.IsSigned { + format = "Permission Denied: User %-v cannot read [" + args = append(args, ctx.Doer) + } else { + format = "Permission Denied: Anonymous user cannot read [" + } + for _, unit := range unitTypes { + format += "%-v, " + args = append(args, unit) + } + + format = format[:len(format)-2] + "] in Repo %-v\n" + + "User in Repo has Permissions: %-+v" + args = append(args, ctx.Repo.Repository, ctx.Repo.Permission) + log.Trace(format, args...) + } + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + } +} + +// CheckRepoScopedToken check whether personal access token has repo scope +func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository, level auth_model.AccessTokenScopeLevel) { + if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true { + return + } + + scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) + if ok { // it's a personal access token but not oauth2 token + var scopeMatched bool + + requiredScopes := auth_model.GetRequiredScopes(level, auth_model.AccessTokenScopeCategoryRepository) + + // check if scope only applies to public resources + publicOnly, err := scope.PublicOnly() + if err != nil { + ctx.ServerError("HasScope", err) + return + } + + if publicOnly && repo.IsPrivate { + ctx.Error(http.StatusForbidden) + return + } + + scopeMatched, err = scope.HasScope(requiredScopes...) + if err != nil { + ctx.ServerError("HasScope", err) + return + } + + if !scopeMatched { + ctx.Error(http.StatusForbidden) + return + } + } +} -- cgit v1.2.3