code.gitea.io/gitea@v1.22.3/services/context/permission.go (about) 1 // Copyright 2018 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package context 5 6 import ( 7 "net/http" 8 9 auth_model "code.gitea.io/gitea/models/auth" 10 repo_model "code.gitea.io/gitea/models/repo" 11 "code.gitea.io/gitea/models/unit" 12 "code.gitea.io/gitea/modules/log" 13 ) 14 15 // RequireRepoAdmin returns a middleware for requiring repository admin permission 16 func RequireRepoAdmin() func(ctx *Context) { 17 return func(ctx *Context) { 18 if !ctx.IsSigned || !ctx.Repo.IsAdmin() { 19 ctx.NotFound(ctx.Req.URL.RequestURI(), nil) 20 return 21 } 22 } 23 } 24 25 // RequireRepoWriter returns a middleware for requiring repository write to the specify unitType 26 func RequireRepoWriter(unitType unit.Type) func(ctx *Context) { 27 return func(ctx *Context) { 28 if !ctx.Repo.CanWrite(unitType) { 29 ctx.NotFound(ctx.Req.URL.RequestURI(), nil) 30 return 31 } 32 } 33 } 34 35 // CanEnableEditor checks if the user is allowed to write to the branch of the repo 36 func CanEnableEditor() func(ctx *Context) { 37 return func(ctx *Context) { 38 if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) { 39 ctx.NotFound("CanWriteToBranch denies permission", nil) 40 return 41 } 42 } 43 } 44 45 // RequireRepoWriterOr returns a middleware for requiring repository write to one of the unit permission 46 func RequireRepoWriterOr(unitTypes ...unit.Type) func(ctx *Context) { 47 return func(ctx *Context) { 48 for _, unitType := range unitTypes { 49 if ctx.Repo.CanWrite(unitType) { 50 return 51 } 52 } 53 ctx.NotFound(ctx.Req.URL.RequestURI(), nil) 54 } 55 } 56 57 // RequireRepoReader returns a middleware for requiring repository read to the specify unitType 58 func RequireRepoReader(unitType unit.Type) func(ctx *Context) { 59 return func(ctx *Context) { 60 if !ctx.Repo.CanRead(unitType) { 61 if log.IsTrace() { 62 if ctx.IsSigned { 63 log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+ 64 "User in Repo has Permissions: %-+v", 65 ctx.Doer, 66 unitType, 67 ctx.Repo.Repository, 68 ctx.Repo.Permission) 69 } else { 70 log.Trace("Permission Denied: Anonymous user cannot read %-v in Repo %-v\n"+ 71 "Anonymous user in Repo has Permissions: %-+v", 72 unitType, 73 ctx.Repo.Repository, 74 ctx.Repo.Permission) 75 } 76 } 77 ctx.NotFound(ctx.Req.URL.RequestURI(), nil) 78 return 79 } 80 } 81 } 82 83 // RequireRepoReaderOr returns a middleware for requiring repository write to one of the unit permission 84 func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) { 85 return func(ctx *Context) { 86 for _, unitType := range unitTypes { 87 if ctx.Repo.CanRead(unitType) { 88 return 89 } 90 } 91 if log.IsTrace() { 92 var format string 93 var args []any 94 if ctx.IsSigned { 95 format = "Permission Denied: User %-v cannot read [" 96 args = append(args, ctx.Doer) 97 } else { 98 format = "Permission Denied: Anonymous user cannot read [" 99 } 100 for _, unit := range unitTypes { 101 format += "%-v, " 102 args = append(args, unit) 103 } 104 105 format = format[:len(format)-2] + "] in Repo %-v\n" + 106 "User in Repo has Permissions: %-+v" 107 args = append(args, ctx.Repo.Repository, ctx.Repo.Permission) 108 log.Trace(format, args...) 109 } 110 ctx.NotFound(ctx.Req.URL.RequestURI(), nil) 111 } 112 } 113 114 // CheckRepoScopedToken check whether personal access token has repo scope 115 func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository, level auth_model.AccessTokenScopeLevel) { 116 if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true { 117 return 118 } 119 120 scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) 121 if ok { // it's a personal access token but not oauth2 token 122 var scopeMatched bool 123 124 requiredScopes := auth_model.GetRequiredScopes(level, auth_model.AccessTokenScopeCategoryRepository) 125 126 // check if scope only applies to public resources 127 publicOnly, err := scope.PublicOnly() 128 if err != nil { 129 ctx.ServerError("HasScope", err) 130 return 131 } 132 133 if publicOnly && repo.IsPrivate { 134 ctx.Error(http.StatusForbidden) 135 return 136 } 137 138 scopeMatched, err = scope.HasScope(requiredScopes...) 139 if err != nil { 140 ctx.ServerError("HasScope", err) 141 return 142 } 143 144 if !scopeMatched { 145 ctx.Error(http.StatusForbidden) 146 return 147 } 148 } 149 }