diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/context/permission.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'services/context/permission.go')
-rw-r--r-- | services/context/permission.go | 149 |
1 files changed, 149 insertions, 0 deletions
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 + } + } +} |