mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-02 13:44:16 +09:00
feat: add commitstatus access token scope (#40144)
Add `read:commitstatus` and `write:commitstatus` token scopes, so CI and
other integrations can report commit statuses without a token that
grants full repository access.
- The commit status endpoints (`/statuses/{sha}`,
`/commits/{ref}/status` and `/commits/{ref}/statuses`) accept the new
scopes, and the repository scopes keep working as they include them
- Creating a status still requires code write permission on the
repository, the scope only narrows what the token may do
- `public-only` tokens still cannot reach private repositories
- `PathGroup` middlewares now run only for a matched path, so unrelated
methods and paths that fall back to the group are not rejected by its
scope check
Fixes: https://github.com/go-gitea/gitea/issues/32625
Ref: https://github.com/go-gitea/gitea/pull/35383
Docs: https://gitea.com/gitea/docs/pulls/622
Signed-off-by: Norbert Szulc <norbert@not7cd.net>
Co-authored-by: Aiden Scandella <git@sca.ndella.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
11 files changed
+87
-28
No files matched your search
@@ -313,7 +313,7 @@ func (r *Router) Combo(pattern string, h ...any) *Combo {
|
||||
// It is only designed to resolve some special cases which chi router can't handle.
|
||||
// For most cases, it shouldn't be used because it needs to iterate all rules to find the matched one (inefficient).
|
||||
func (r *Router) PathGroup(pattern string, fn func(g *RouterPathGroup), h ...any) {
|
||||
g := &RouterPathGroup{r: r, pathParam: "*"}
|
||||
g := &RouterPathGroup{r: r, pathParam: "*", middlewares: h} // run h only on a match, unmatched methods and paths also fall back here
|
||||
fn(g)
|
||||
r.Any(pattern, append(h, g.ServeHTTP)...)
|
||||
r.Any(pattern, g.ServeHTTP)
|
||||
}
|
||||
@@ -17,10 +17,11 @@ import (
|
||||
)
|
||||
|
||||
type RouterPathGroup struct {
|
||||
r *Router
|
||||
pathParam string
|
||||
matchers []*routerPathMatcher
|
||||
unescape bool
|
||||
r *Router
|
||||
pathParam string
|
||||
matchers []*routerPathMatcher
|
||||
unescape bool
|
||||
middlewares []any
|
||||
}
|
||||
|
||||
func (g *RouterPathGroup) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
@@ -55,7 +56,7 @@ func (g *RouterPathGroup) MatchPath(methods, pattern string, h ...any) {
|
||||
}
|
||||
|
||||
func (g *RouterPathGroup) MatchPattern(methods string, pattern *RouterPathGroupPattern, h ...any) {
|
||||
g.matchers = append(g.matchers, newRouterPathMatcher(methods, pattern, h...))
|
||||
g.matchers = append(g.matchers, newRouterPathMatcher(methods, pattern, g.middlewares, h...))
|
||||
}
|
||||
|
||||
func (g *RouterPathGroup) UseUnescapedPath() {
|
||||
@@ -127,8 +128,8 @@ func isValidMethod(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func newRouterPathMatcher(methods string, patternRegexp *RouterPathGroupPattern, h ...any) *routerPathMatcher {
|
||||
middlewares, handlerFunc, hasPreMiddlewares := wrapMiddlewareAndHandler(nil, patternRegexp.middlewares, h)
|
||||
func newRouterPathMatcher(methods string, patternRegexp *RouterPathGroupPattern, uses []any, h ...any) *routerPathMatcher {
|
||||
middlewares, handlerFunc, hasPreMiddlewares := wrapMiddlewareAndHandler(uses, patternRegexp.middlewares, h)
|
||||
if hasPreMiddlewares {
|
||||
panic("pre-middlewares are not supported in router path matcher")
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func TestPathProcessor(t *testing.T) {
|
||||
testProcess := func(pattern, uri string, expectedPathParams map[string]string) {
|
||||
chiCtx := chi.NewRouteContext()
|
||||
chiCtx.RouteMethod = "GET"
|
||||
p := newRouterPathMatcher("GET", patternRegexp(pattern), http.NotFound)
|
||||
p := newRouterPathMatcher("GET", patternRegexp(pattern), nil, http.NotFound)
|
||||
shouldProcess := expectedPathParams != nil
|
||||
if unescape {
|
||||
uri, _ = url.PathUnescape(uri)
|
||||
@@ -236,12 +236,12 @@ func TestRouter(t *testing.T) {
|
||||
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches/d1/d2/000", resultStruct{
|
||||
method: "GET",
|
||||
pathParams: map[string]string{"reponame": "the-repo", "username": "the-user", "*": "d1/d2/000"},
|
||||
handlerMarks: []string{"s1", "not-found:/api/v1"},
|
||||
handlerMarks: []string{"not-found:/api/v1"},
|
||||
})
|
||||
|
||||
testRoute(t, "GET /api/v1/repos/the-user/the-repo/branches/d1/d2/fn?stop=s1", resultStruct{
|
||||
method: "GET",
|
||||
pathParams: map[string]string{"username": "the-user", "reponame": "the-repo", "*": "d1/d2/fn"},
|
||||
pathParams: map[string]string{"*": "d1/d2/fn", "dir": "d1/d2", "file": "fn", "reponame": "the-repo", "username": "the-user"},
|
||||
handlerMarks: []string{"s1"},
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user