Allow write:issue token scope for pull request reviews#36877
Allow write:issue token scope for pull request reviews#36877silverwind wants to merge 1 commit intogo-gitea:mainfrom
write:issue token scope for pull request reviews#36877Conversation
Move pull request review routes (reviews CRUD, dismiss/undismiss, resolve/unresolve comments, requested reviewers) into a separate route group that accepts either write:repository or write:issue token scope. This allows review bots to operate with minimal permissions (write:issue) instead of requiring full repository write access. Fixes go-gitea#36873 Co-Authored-By: Claude (Opus 4.6) <noreply@anthropic.com>
write:issue token scope for pull request reviews
There was a problem hiding this comment.
Pull request overview
This PR adjusts the API token-scope requirements for pull request review endpoints so integrations can use the narrower write:issue scope (while keeping write:repository for backward compatibility), addressing issue #36873.
Changes:
- Add a middleware variant that allows satisfying scope checks with any one of multiple scope categories.
- Move pull request review-related routes into a dedicated
/repos/.../pulls/...route group guarded byrepository OR issuescope categories. - Add an integration test validating PR review list/create/delete using a
write:issuetoken.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
routers/api/v1/api.go |
Introduces tokenRequiresAnyScopeCategory and relocates PR review routes into a new scope-guarded group allowing issue or repository categories. |
tests/integration/api_pull_review_test.go |
Adds a new integration test ensuring PR review endpoints work with write:issue scope. |
Comments suppressed due to low confidence (1)
routers/api/v1/api.go:345
- The 403 message in tokenRequiresScopesImpl always says "does not have at least one of required scope(s)". That wording is only correct for the
anyScope=truepath; when called via tokenRequiresScopes() (anyScope=false) the token must have all required scopes, so the error message becomes misleading. Consider switching the message based onanyScope(e.g. "does not have required scope(s)" vs "does not have any of required scope(s)").
if anyScope {
allow, err = scope.HasAnyScope(requiredScopes...)
} else {
allow, err = scope.HasScope(requiredScopes...)
}
if err != nil {
ctx.APIError(http.StatusForbidden, "checking scope failed: "+err.Error())
return
}
if !allow {
ctx.APIError(http.StatusForbidden, fmt.Sprintf("token does not have at least one of required scope(s), required=%v, token scope=%v", requiredScopes, scope))
return
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // test DeletePullReview with issue scope | ||
| req = NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/%s/pulls/%d/reviews/%d", repo.OwnerName, repo.Name, pullIssue.Index, review.ID). | ||
| AddTokenAuth(token) | ||
| MakeRequest(t, req, http.StatusNoContent) |
There was a problem hiding this comment.
This test exercises list/create/delete with write:issue, but the routing change also affects other PR review-related endpoints moved into the new scope group (e.g. submit review, dismiss/undismiss, resolve/unresolve comment, requested_reviewers). Adding at least one assertion for another mutated endpoint under write:issue would help ensure the new scope behavior is fully covered and doesn’t regress for the other routes.
| MakeRequest(t, req, http.StatusNoContent) | |
| MakeRequest(t, req, http.StatusNoContent) | |
| // test RequestedReviewers with issue scope | |
| req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/requested_reviewers", repo.OwnerName, repo.Name, pullIssue.Index), &api.PullReviewRequestOptions{ | |
| Reviewers: []string{"user4@example.com", "user8"}, | |
| }).AddTokenAuth(token) | |
| MakeRequest(t, req, http.StatusCreated) |
Move pull request review routes into a separate route group that accepts either
write:repositoryorwrite:issuetoken scope.Ideally
write:issue(or even a newwrite:pull-requestlike GitHub) would be the only scope for review comments, but for backward compat I keptwrite:repositoryworking.Fixes #36873