code.gitea.io/gitea@v1.19.3/modules/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.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 []interface{} 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 // RequireRepoScopedToken check whether personal access token has repo scope 115 func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository) { 116 if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true { 117 return 118 } 119 120 var err error 121 scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope) 122 if ok { // it's a personal access token but not oauth2 token 123 var scopeMatched bool 124 scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeRepo) 125 if err != nil { 126 ctx.ServerError("HasScope", err) 127 return 128 } 129 if !scopeMatched && !repo.IsPrivate { 130 scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopePublicRepo) 131 if err != nil { 132 ctx.ServerError("HasScope", err) 133 return 134 } 135 } 136 if !scopeMatched { 137 ctx.Error(http.StatusForbidden) 138 return 139 } 140 } 141 }