Restrict scope for some APIs

This commit is contained in:
harryzcy 2022-09-06 16:27:04 -04:00
parent ad3ff542f7
commit 6c5dd10100
No known key found for this signature in database
GPG key ID: CC2953E050C19686
4 changed files with 134 additions and 111 deletions

View file

@ -71,6 +71,7 @@ import (
"reflect" "reflect"
"strings" "strings"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access" access_model "code.gitea.io/gitea/models/perm/access"
@ -208,9 +209,22 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
} }
// Contexter middleware already checks token for user sign in process. // Contexter middleware already checks token for user sign in process.
func reqToken() func(ctx *context.APIContext) { func reqToken(requiredScope string) func(ctx *context.APIContext) {
return func(ctx *context.APIContext) { return func(ctx *context.APIContext) {
if true == ctx.Data["IsApiToken"] { if true == ctx.Data["IsApiToken"] {
if requiredScope == "" {
return
}
scope := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
allow, err := scope.HasScope(requiredScope)
if err != nil {
ctx.Error(http.StatusUnauthorized, "reqToken", "parsing token failed")
return
}
if !allow {
ctx.Error(http.StatusUnauthorized, "reqToken", "token does not have required scope")
return
}
return return
} }
if ctx.Context.IsBasicAuth { if ctx.Context.IsBasicAuth {
@ -662,7 +676,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/repository", settings.GetGeneralRepoSettings) m.Get("/repository", settings.GetGeneralRepoSettings)
}) })
// Notifications // Notifications (requires 'notification' scope)
m.Group("/notifications", func() { m.Group("/notifications", func() {
m.Combo(""). m.Combo("").
Get(notify.ListNotifications). Get(notify.ListNotifications).
@ -671,9 +685,9 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Combo("/threads/{id}"). m.Combo("/threads/{id}").
Get(notify.GetThread). Get(notify.GetThread).
Patch(notify.ReadThread) Patch(notify.ReadThread)
}, reqToken()) }, reqToken(auth_model.AccessTokenScopeNotification))
// Users // Users (public information, no scope required)
m.Group("/users", func() { m.Group("/users", func() {
m.Get("/search", reqExploreSignIn(), user.Search) m.Get("/search", reqExploreSignIn(), user.Search)
@ -689,10 +703,11 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Combo("").Get(user.ListAccessTokens). m.Combo("").Get(user.ListAccessTokens).
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
m.Combo("/{id}").Delete(user.DeleteAccessToken) m.Combo("/{id}").Delete(user.DeleteAccessToken)
}, reqBasicOrRevProxyAuth()) }, reqBasicOrRevProxyAuth()) // basic auth or reverse proxy auth required
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
}) })
// (public information, no scope required)
m.Group("/users", func() { m.Group("/users", func() {
m.Group("/{username}", func() { m.Group("/{username}", func() {
m.Get("/keys", user.ListPublicKeys) m.Get("/keys", user.ListPublicKeys)
@ -708,25 +723,25 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/subscriptions", user.GetWatchedRepos) m.Get("/subscriptions", user.GetWatchedRepos)
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
}, reqToken()) }, reqToken(""))
m.Group("/user", func() { m.Group("/user", func() {
m.Get("", user.GetAuthenticatedUser) m.Get("", user.GetAuthenticatedUser)
m.Group("/settings", func() { m.Group("/settings", func() {
m.Get("", user.GetUserSettings) m.Get("", reqToken(auth_model.AccessTokenScopeReadUser), user.GetUserSettings) // requires 'read:user' scope
m.Patch("", bind(api.UserSettingsOptions{}), user.UpdateUserSettings) m.Patch("", reqToken(auth_model.AccessTokenScopeReadUser), bind(api.UserSettingsOptions{}), user.UpdateUserSettings) // requires 'read:user' scope
}, reqToken()) }, reqToken(""))
m.Combo("/emails").Get(user.ListEmails). m.Combo("/emails").Get(reqToken(auth_model.AccessTokenScopeReadUser), user.ListEmails). // requires 'read:user' scope
Post(bind(api.CreateEmailOption{}), user.AddEmail). Post(reqToken(auth_model.AccessTokenScopeUser), bind(api.CreateEmailOption{}), user.AddEmail). // requires 'user' scope
Delete(bind(api.DeleteEmailOption{}), user.DeleteEmail) Delete(reqToken(auth_model.AccessTokenScopeUser), bind(api.DeleteEmailOption{}), user.DeleteEmail) // requires 'user' scope
m.Get("/followers", user.ListMyFollowers) m.Get("/followers", user.ListMyFollowers)
m.Group("/following", func() { m.Group("/following", func() {
m.Get("", user.ListMyFollowing) m.Get("", user.ListMyFollowing)
m.Group("/{username}", func() { m.Group("/{username}", func() {
m.Get("", user.CheckMyFollowing) m.Get("", user.CheckMyFollowing)
m.Put("", user.Follow) m.Put("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Follow) // requires 'user:follow' scope
m.Delete("", user.Unfollow) m.Delete("", reqToken(auth_model.AccessTokenScopeUserFollow), user.Unfollow) // requires 'user:follow' scope
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
}) })
@ -744,7 +759,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Delete(user.DeleteOauth2Application). Delete(user.DeleteOauth2Application).
Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application). Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application).
Get(user.GetOauth2Application) Get(user.GetOauth2Application)
}, reqToken()) }, reqToken(""))
m.Group("/gpg_keys", func() { m.Group("/gpg_keys", func() {
m.Combo("").Get(user.ListMyGPGKeys). m.Combo("").Get(user.ListMyGPGKeys).
@ -774,31 +789,31 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/subscriptions", user.GetMyWatchedRepos) m.Get("/subscriptions", user.GetMyWatchedRepos)
m.Get("/teams", org.ListUserTeams) m.Get("/teams", org.ListUserTeams)
}, reqToken()) }, reqToken(""))
// Repositories // Repositories
m.Post("/org/{org}/repos", reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated) m.Post("/org/{org}/repos", reqToken(""), bind(api.CreateRepoOption{}), repo.CreateOrgRepoDeprecated)
m.Combo("/repositories/{id}", reqToken()).Get(repo.GetByID) m.Combo("/repositories/{id}", reqToken("")).Get(repo.GetByID)
m.Group("/repos", func() { m.Group("/repos", func() {
m.Get("/search", repo.Search) m.Get("/search", repo.Search)
m.Get("/issues/search", repo.SearchIssues) m.Get("/issues/search", repo.SearchIssues)
m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate) m.Post("/migrate", reqToken(""), bind(api.MigrateRepoOptions{}), repo.Migrate)
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Combo("").Get(reqAnyRepoReader(), repo.Get). m.Combo("").Get(reqAnyRepoReader(), repo.Get).
Delete(reqToken(), reqOwner(), repo.Delete). Delete(reqToken(auth_model.AccessTokenScopeDeleteRepo), reqOwner(), repo.Delete).
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit) Patch(reqToken(auth_model.AccessTokenScopeRepo), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
m.Post("/generate", reqToken(), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate) m.Post("/generate", reqToken(""), reqRepoReader(unit.TypeCode), bind(api.GenerateRepoOption{}), repo.Generate)
m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer) m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
m.Post("/transfer/accept", reqToken(), repo.AcceptTransfer) m.Post("/transfer/accept", reqToken(""), repo.AcceptTransfer)
m.Post("/transfer/reject", reqToken(), repo.RejectTransfer) m.Post("/transfer/reject", reqToken(""), repo.RejectTransfer)
m.Combo("/notifications"). m.Combo("/notifications", reqToken(auth_model.AccessTokenScopeNotification)).
Get(reqToken(), notify.ListRepoNotifications). Get(reqToken(""), notify.ListRepoNotifications).
Put(reqToken(), notify.ReadRepoNotifications) Put(reqToken(""), notify.ReadRepoNotifications)
m.Group("/hooks/git", func() { m.Group("/hooks/git", func() {
m.Combo("").Get(repo.ListGitHooks) m.Combo("").Get(repo.ListGitHooks)
m.Group("/{id}", func() { m.Group("/{id}", func() {
@ -806,7 +821,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Patch(bind(api.EditGitHookOption{}), repo.EditGitHook). Patch(bind(api.EditGitHookOption{}), repo.EditGitHook).
Delete(repo.DeleteGitHook) Delete(repo.DeleteGitHook)
}) })
}, reqToken(), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true)) }, reqToken(""), reqAdmin(), reqGitHook(), context.ReferencesGitRepo(true))
m.Group("/hooks", func() { m.Group("/hooks", func() {
m.Combo("").Get(repo.ListHooks). m.Combo("").Get(repo.ListHooks).
Post(bind(api.CreateHookOption{}), repo.CreateHook) Post(bind(api.CreateHookOption{}), repo.CreateHook)
@ -816,7 +831,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Delete(repo.DeleteHook) Delete(repo.DeleteHook)
m.Post("/tests", context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook) m.Post("/tests", context.ReferencesGitRepo(), context.RepoRefForAPI, repo.TestHook)
}) })
}, reqToken(), reqAdmin(), reqWebhooksEnabled()) }, reqToken(""), reqAdmin(), reqWebhooksEnabled())
m.Group("/collaborators", func() { m.Group("/collaborators", func() {
m.Get("", reqAnyRepoReader(), repo.ListCollaborators) m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
m.Group("/{collaborator}", func() { m.Group("/{collaborator}", func() {
@ -824,21 +839,21 @@ func Routes(ctx gocontext.Context) *web.Route {
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator). Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
Delete(reqAdmin(), repo.DeleteCollaborator) Delete(reqAdmin(), repo.DeleteCollaborator)
m.Get("/permission", repo.GetRepoPermissions) m.Get("/permission", repo.GetRepoPermissions)
}, reqToken()) }, reqToken(""))
}, reqToken()) }, reqToken(""))
m.Get("/assignees", reqToken(), reqAnyRepoReader(), repo.GetAssignees) m.Get("/assignees", reqToken(""), reqAnyRepoReader(), repo.GetAssignees)
m.Get("/reviewers", reqToken(), reqAnyRepoReader(), repo.GetReviewers) m.Get("/reviewers", reqToken(""), reqAnyRepoReader(), repo.GetReviewers)
m.Group("/teams", func() { m.Group("/teams", func() {
m.Get("", reqAnyRepoReader(), repo.ListTeams) m.Get("", reqAnyRepoReader(), repo.ListTeams)
m.Combo("/{team}").Get(reqAnyRepoReader(), repo.IsTeam). m.Combo("/{team}").Get(reqAnyRepoReader(), repo.IsTeam).
Put(reqAdmin(), repo.AddTeam). Put(reqAdmin(), repo.AddTeam).
Delete(reqAdmin(), repo.DeleteTeam) Delete(reqAdmin(), repo.DeleteTeam)
}, reqToken()) }, reqToken(""))
m.Get("/raw/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFile) m.Get("/raw/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFile)
m.Get("/media/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFileOrLFS) m.Get("/media/*", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetRawFileOrLFS)
m.Get("/archive/*", reqRepoReader(unit.TypeCode), repo.GetArchive) m.Get("/archive/*", reqRepoReader(unit.TypeCode), repo.GetArchive)
m.Combo("/forks").Get(repo.ListForks). m.Combo("/forks").Get(repo.ListForks).
Post(reqToken(), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork) Post(reqToken(""), reqRepoReader(unit.TypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
m.Group("/branches", func() { m.Group("/branches", func() {
m.Get("", repo.ListBranches) m.Get("", repo.ListBranches)
m.Get("/*", repo.GetBranch) m.Get("/*", repo.GetBranch)
@ -853,7 +868,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection) m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
m.Delete("", repo.DeleteBranchProtection) m.Delete("", repo.DeleteBranchProtection)
}) })
}, reqToken(), reqAdmin()) }, reqToken(""), reqAdmin())
m.Group("/tags", func() { m.Group("/tags", func() {
m.Get("", repo.ListTags) m.Get("", repo.ListTags)
m.Get("/*", repo.GetTag) m.Get("/*", repo.GetTag)
@ -865,11 +880,11 @@ func Routes(ctx gocontext.Context) *web.Route {
Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey) Post(bind(api.CreateKeyOption{}), repo.CreateDeployKey)
m.Combo("/{id}").Get(repo.GetDeployKey). m.Combo("/{id}").Get(repo.GetDeployKey).
Delete(repo.DeleteDeploykey) Delete(repo.DeleteDeploykey)
}, reqToken(), reqAdmin()) }, reqToken(""), reqAdmin())
m.Group("/times", func() { m.Group("/times", func() {
m.Combo("").Get(repo.ListTrackedTimesByRepository) m.Combo("").Get(repo.ListTrackedTimesByRepository)
m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser) m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser)
}, mustEnableIssues, reqToken()) }, mustEnableIssues, reqToken(""))
m.Group("/wiki", func() { m.Group("/wiki", func() {
m.Combo("/page/{pageName}"). m.Combo("/page/{pageName}").
Get(repo.GetWikiPage). Get(repo.GetWikiPage).
@ -881,37 +896,37 @@ func Routes(ctx gocontext.Context) *web.Route {
}, mustEnableWiki) }, mustEnableWiki)
m.Group("/issues", func() { m.Group("/issues", func() {
m.Combo("").Get(repo.ListIssues). m.Combo("").Get(repo.ListIssues).
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue) Post(reqToken(""), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
m.Group("/comments", func() { m.Group("/comments", func() {
m.Get("", repo.ListRepoIssueComments) m.Get("", repo.ListRepoIssueComments)
m.Group("/{id}", func() { m.Group("/{id}", func() {
m.Combo(""). m.Combo("").
Get(repo.GetIssueComment). Get(repo.GetIssueComment).
Patch(mustNotBeArchived, reqToken(), bind(api.EditIssueCommentOption{}), repo.EditIssueComment). Patch(mustNotBeArchived, reqToken(""), bind(api.EditIssueCommentOption{}), repo.EditIssueComment).
Delete(reqToken(), repo.DeleteIssueComment) Delete(reqToken(""), repo.DeleteIssueComment)
m.Combo("/reactions"). m.Combo("/reactions").
Get(repo.GetIssueCommentReactions). Get(repo.GetIssueCommentReactions).
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction). Post(reqToken(""), bind(api.EditReactionOption{}), repo.PostIssueCommentReaction).
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction) Delete(reqToken(""), bind(api.EditReactionOption{}), repo.DeleteIssueCommentReaction)
}) })
}) })
m.Group("/{index}", func() { m.Group("/{index}", func() {
m.Combo("").Get(repo.GetIssue). m.Combo("").Get(repo.GetIssue).
Patch(reqToken(), bind(api.EditIssueOption{}), repo.EditIssue). Patch(reqToken(""), bind(api.EditIssueOption{}), repo.EditIssue).
Delete(reqToken(), reqAdmin(), repo.DeleteIssue) Delete(reqToken(""), reqAdmin(), repo.DeleteIssue)
m.Group("/comments", func() { m.Group("/comments", func() {
m.Combo("").Get(repo.ListIssueComments). m.Combo("").Get(repo.ListIssueComments).
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment) Post(reqToken(""), mustNotBeArchived, bind(api.CreateIssueCommentOption{}), repo.CreateIssueComment)
m.Combo("/{id}", reqToken()).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated). m.Combo("/{id}", reqToken("")).Patch(bind(api.EditIssueCommentOption{}), repo.EditIssueCommentDeprecated).
Delete(repo.DeleteIssueCommentDeprecated) Delete(repo.DeleteIssueCommentDeprecated)
}) })
m.Get("/timeline", repo.ListIssueCommentsAndTimeline) m.Get("/timeline", repo.ListIssueCommentsAndTimeline)
m.Group("/labels", func() { m.Group("/labels", func() {
m.Combo("").Get(repo.ListIssueLabels). m.Combo("").Get(repo.ListIssueLabels).
Post(reqToken(), bind(api.IssueLabelsOption{}), repo.AddIssueLabels). Post(reqToken(""), bind(api.IssueLabelsOption{}), repo.AddIssueLabels).
Put(reqToken(), bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels). Put(reqToken(""), bind(api.IssueLabelsOption{}), repo.ReplaceIssueLabels).
Delete(reqToken(), repo.ClearIssueLabels) Delete(reqToken(""), repo.ClearIssueLabels)
m.Delete("/{id}", reqToken(), repo.DeleteIssueLabel) m.Delete("/{id}", reqToken(""), repo.DeleteIssueLabel)
}) })
m.Group("/times", func() { m.Group("/times", func() {
m.Combo(""). m.Combo("").
@ -919,70 +934,70 @@ func Routes(ctx gocontext.Context) *web.Route {
Post(bind(api.AddTimeOption{}), repo.AddTime). Post(bind(api.AddTimeOption{}), repo.AddTime).
Delete(repo.ResetIssueTime) Delete(repo.ResetIssueTime)
m.Delete("/{id}", repo.DeleteTime) m.Delete("/{id}", repo.DeleteTime)
}, reqToken()) }, reqToken(""))
m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline) m.Combo("/deadline").Post(reqToken(""), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
m.Group("/stopwatch", func() { m.Group("/stopwatch", func() {
m.Post("/start", reqToken(), repo.StartIssueStopwatch) m.Post("/start", reqToken(""), repo.StartIssueStopwatch)
m.Post("/stop", reqToken(), repo.StopIssueStopwatch) m.Post("/stop", reqToken(""), repo.StopIssueStopwatch)
m.Delete("/delete", reqToken(), repo.DeleteIssueStopwatch) m.Delete("/delete", reqToken(""), repo.DeleteIssueStopwatch)
}) })
m.Group("/subscriptions", func() { m.Group("/subscriptions", func() {
m.Get("", repo.GetIssueSubscribers) m.Get("", repo.GetIssueSubscribers)
m.Get("/check", reqToken(), repo.CheckIssueSubscription) m.Get("/check", reqToken(""), repo.CheckIssueSubscription)
m.Put("/{user}", reqToken(), repo.AddIssueSubscription) m.Put("/{user}", reqToken(""), repo.AddIssueSubscription)
m.Delete("/{user}", reqToken(), repo.DelIssueSubscription) m.Delete("/{user}", reqToken(""), repo.DelIssueSubscription)
}) })
m.Combo("/reactions"). m.Combo("/reactions").
Get(repo.GetIssueReactions). Get(repo.GetIssueReactions).
Post(reqToken(), bind(api.EditReactionOption{}), repo.PostIssueReaction). Post(reqToken(""), bind(api.EditReactionOption{}), repo.PostIssueReaction).
Delete(reqToken(), bind(api.EditReactionOption{}), repo.DeleteIssueReaction) Delete(reqToken(""), bind(api.EditReactionOption{}), repo.DeleteIssueReaction)
}) })
}, mustEnableIssuesOrPulls) }, mustEnableIssuesOrPulls)
m.Group("/labels", func() { m.Group("/labels", func() {
m.Combo("").Get(repo.ListLabels). m.Combo("").Get(repo.ListLabels).
Post(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel) Post(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateLabelOption{}), repo.CreateLabel)
m.Combo("/{id}").Get(repo.GetLabel). m.Combo("/{id}").Get(repo.GetLabel).
Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel). Patch(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditLabelOption{}), repo.EditLabel).
Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteLabel) Delete(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteLabel)
}) })
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown) m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
m.Post("/markdown/raw", misc.MarkdownRaw) m.Post("/markdown/raw", misc.MarkdownRaw)
m.Group("/milestones", func() { m.Group("/milestones", func() {
m.Combo("").Get(repo.ListMilestones). m.Combo("").Get(repo.ListMilestones).
Post(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone) Post(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.CreateMilestoneOption{}), repo.CreateMilestone)
m.Combo("/{id}").Get(repo.GetMilestone). m.Combo("/{id}").Get(repo.GetMilestone).
Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone). Patch(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone).
Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone) Delete(reqToken(""), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone)
}) })
m.Get("/stargazers", repo.ListStargazers) m.Get("/stargazers", repo.ListStargazers)
m.Get("/subscribers", repo.ListSubscribers) m.Get("/subscribers", repo.ListSubscribers)
m.Group("/subscription", func() { m.Group("/subscription", func() {
m.Get("", user.IsWatching) m.Get("", user.IsWatching)
m.Put("", reqToken(), user.Watch) m.Put("", reqToken(""), user.Watch)
m.Delete("", reqToken(), user.Unwatch) m.Delete("", reqToken(""), user.Unwatch)
}) })
m.Group("/releases", func() { m.Group("/releases", func() {
m.Combo("").Get(repo.ListReleases). m.Combo("").Get(repo.ListReleases).
Post(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease) Post(reqToken(""), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.CreateReleaseOption{}), repo.CreateRelease)
m.Group("/{id}", func() { m.Group("/{id}", func() {
m.Combo("").Get(repo.GetRelease). m.Combo("").Get(repo.GetRelease).
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease). Patch(reqToken(""), reqRepoWriter(unit.TypeReleases), context.ReferencesGitRepo(), bind(api.EditReleaseOption{}), repo.EditRelease).
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease) Delete(reqToken(""), reqRepoWriter(unit.TypeReleases), repo.DeleteRelease)
m.Group("/assets", func() { m.Group("/assets", func() {
m.Combo("").Get(repo.ListReleaseAttachments). m.Combo("").Get(repo.ListReleaseAttachments).
Post(reqToken(), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment) Post(reqToken(""), reqRepoWriter(unit.TypeReleases), repo.CreateReleaseAttachment)
m.Combo("/{asset}").Get(repo.GetReleaseAttachment). m.Combo("/{asset}").Get(repo.GetReleaseAttachment).
Patch(reqToken(), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment). Patch(reqToken(""), reqRepoWriter(unit.TypeReleases), bind(api.EditAttachmentOptions{}), repo.EditReleaseAttachment).
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment) Delete(reqToken(""), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseAttachment)
}) })
}) })
m.Group("/tags", func() { m.Group("/tags", func() {
m.Combo("/{tag}"). m.Combo("/{tag}").
Get(repo.GetReleaseByTag). Get(repo.GetReleaseByTag).
Delete(reqToken(), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag) Delete(reqToken(""), reqRepoWriter(unit.TypeReleases), repo.DeleteReleaseByTag)
}) })
}, reqRepoReader(unit.TypeReleases)) }, reqRepoReader(unit.TypeReleases))
m.Post("/mirror-sync", reqToken(), reqRepoWriter(unit.TypeCode), repo.MirrorSync) m.Post("/mirror-sync", reqToken(""), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
m.Post("/push_mirrors-sync", reqAdmin(), repo.PushMirrorSync) m.Post("/push_mirrors-sync", reqAdmin(), repo.PushMirrorSync)
m.Group("/push_mirrors", func() { m.Group("/push_mirrors", func() {
m.Combo("").Get(repo.ListPushMirrors). m.Combo("").Get(repo.ListPushMirrors).
@ -995,39 +1010,39 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig) m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
m.Group("/pulls", func() { m.Group("/pulls", func() {
m.Combo("").Get(repo.ListPullRequests). m.Combo("").Get(repo.ListPullRequests).
Post(reqToken(), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest) Post(reqToken(""), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest)
m.Group("/{index}", func() { m.Group("/{index}", func() {
m.Combo("").Get(repo.GetPullRequest). m.Combo("").Get(repo.GetPullRequest).
Patch(reqToken(), bind(api.EditPullRequestOption{}), repo.EditPullRequest) Patch(reqToken(""), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch) m.Get(".{diffType:diff|patch}", repo.DownloadPullDiffOrPatch)
m.Post("/update", reqToken(), repo.UpdatePullRequest) m.Post("/update", reqToken(""), repo.UpdatePullRequest)
m.Get("/commits", repo.GetPullRequestCommits) m.Get("/commits", repo.GetPullRequestCommits)
m.Combo("/merge").Get(repo.IsPullRequestMerged). m.Combo("/merge").Get(repo.IsPullRequestMerged).
Post(reqToken(), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest). Post(reqToken(""), mustNotBeArchived, bind(forms.MergePullRequestForm{}), repo.MergePullRequest).
Delete(reqToken(), mustNotBeArchived, repo.CancelScheduledAutoMerge) Delete(reqToken(""), mustNotBeArchived, repo.CancelScheduledAutoMerge)
m.Group("/reviews", func() { m.Group("/reviews", func() {
m.Combo(""). m.Combo("").
Get(repo.ListPullReviews). Get(repo.ListPullReviews).
Post(reqToken(), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview) Post(reqToken(""), bind(api.CreatePullReviewOptions{}), repo.CreatePullReview)
m.Group("/{id}", func() { m.Group("/{id}", func() {
m.Combo(""). m.Combo("").
Get(repo.GetPullReview). Get(repo.GetPullReview).
Delete(reqToken(), repo.DeletePullReview). Delete(reqToken(""), repo.DeletePullReview).
Post(reqToken(), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview) Post(reqToken(""), bind(api.SubmitPullReviewOptions{}), repo.SubmitPullReview)
m.Combo("/comments"). m.Combo("/comments").
Get(repo.GetPullReviewComments) Get(repo.GetPullReviewComments)
m.Post("/dismissals", reqToken(), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview) m.Post("/dismissals", reqToken(""), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
m.Post("/undismissals", reqToken(), repo.UnDismissPullReview) m.Post("/undismissals", reqToken(""), repo.UnDismissPullReview)
}) })
}) })
m.Combo("/requested_reviewers"). m.Combo("/requested_reviewers").
Delete(reqToken(), bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests). Delete(reqToken(""), bind(api.PullReviewRequestOptions{}), repo.DeleteReviewRequests).
Post(reqToken(), bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests) Post(reqToken(""), bind(api.PullReviewRequestOptions{}), repo.CreateReviewRequests)
}) })
}, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo()) }, mustAllowPulls, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
m.Group("/statuses", func() { m.Group("/statuses", func() {
m.Combo("/{sha}").Get(repo.GetCommitStatuses). m.Combo("/{sha}").Get(repo.GetCommitStatuses).
Post(reqToken(), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus) Post(reqToken(""), reqRepoWriter(unit.TypeCode), bind(api.CreateStatusOption{}), repo.NewCommitStatus)
}, reqRepoReader(unit.TypeCode)) }, reqRepoReader(unit.TypeCode))
m.Group("/commits", func() { m.Group("/commits", func() {
m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits) m.Get("", context.ReferencesGitRepo(), repo.GetAllCommits)
@ -1048,7 +1063,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/tags/{sha}", repo.GetAnnotatedTag) m.Get("/tags/{sha}", repo.GetAnnotatedTag)
m.Get("/notes/{sha}", repo.GetNote) m.Get("/notes/{sha}", repo.GetNote)
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode)) }, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch) m.Post("/diffpatch", reqRepoWriter(unit.TypeCode), reqToken(""), bind(api.ApplyDiffPatchFileOptions{}), repo.ApplyDiffPatch)
m.Group("/contents", func() { m.Group("/contents", func() {
m.Get("", repo.GetContentsList) m.Get("", repo.GetContentsList)
m.Get("/*", repo.GetContents) m.Get("/*", repo.GetContents)
@ -1056,15 +1071,15 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Post("", bind(api.CreateFileOptions{}), reqRepoBranchWriter, repo.CreateFile) m.Post("", bind(api.CreateFileOptions{}), reqRepoBranchWriter, repo.CreateFile)
m.Put("", bind(api.UpdateFileOptions{}), reqRepoBranchWriter, repo.UpdateFile) m.Put("", bind(api.UpdateFileOptions{}), reqRepoBranchWriter, repo.UpdateFile)
m.Delete("", bind(api.DeleteFileOptions{}), reqRepoBranchWriter, repo.DeleteFile) m.Delete("", bind(api.DeleteFileOptions{}), reqRepoBranchWriter, repo.DeleteFile)
}, reqToken()) }, reqToken(""))
}, reqRepoReader(unit.TypeCode)) }, reqRepoReader(unit.TypeCode))
m.Get("/signing-key.gpg", misc.SigningKey) m.Get("/signing-key.gpg", misc.SigningKey)
m.Group("/topics", func() { m.Group("/topics", func() {
m.Combo("").Get(repo.ListTopics). m.Combo("").Get(repo.ListTopics).
Put(reqToken(), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics) Put(reqToken(""), reqAdmin(), bind(api.RepoTopicOptions{}), repo.UpdateTopics)
m.Group("/{topic}", func() { m.Group("/{topic}", func() {
m.Combo("").Put(reqToken(), repo.AddTopic). m.Combo("").Put(reqToken(""), repo.AddTopic).
Delete(reqToken(), repo.DeleteTopic) Delete(reqToken(""), repo.DeleteTopic)
}, reqAdmin()) }, reqAdmin())
}, reqAnyRepoReader()) }, reqAnyRepoReader())
m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates) m.Get("/issue_templates", context.ReferencesGitRepo(), repo.GetIssueTemplates)
@ -1082,41 +1097,41 @@ func Routes(ctx gocontext.Context) *web.Route {
}, context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead)) }, context_service.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
// Organizations // Organizations
m.Get("/user/orgs", reqToken(), org.ListMyOrgs) m.Get("/user/orgs", reqToken(""), org.ListMyOrgs)
m.Group("/users/{username}/orgs", func() { m.Group("/users/{username}/orgs", func() {
m.Get("", org.ListUserOrgs) m.Get("", org.ListUserOrgs)
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions) m.Get("/{org}/permissions", reqToken(""), org.GetUserOrgsPermissions)
}, context_service.UserAssignmentAPI()) }, context_service.UserAssignmentAPI())
m.Post("/orgs", reqToken(), bind(api.CreateOrgOption{}), org.Create) m.Post("/orgs", reqToken(""), bind(api.CreateOrgOption{}), org.Create)
m.Get("/orgs", org.GetAll) m.Get("/orgs", org.GetAll)
m.Group("/orgs/{org}", func() { m.Group("/orgs/{org}", func() {
m.Combo("").Get(org.Get). m.Combo("").Get(org.Get).
Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit). Patch(reqToken(""), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
Delete(reqToken(), reqOrgOwnership(), org.Delete) Delete(reqToken(""), reqOrgOwnership(), org.Delete)
m.Combo("/repos").Get(user.ListOrgRepos). m.Combo("/repos").Get(user.ListOrgRepos).
Post(reqToken(), bind(api.CreateRepoOption{}), repo.CreateOrgRepo) Post(reqToken(""), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
m.Group("/members", func() { m.Group("/members", func() {
m.Get("", org.ListMembers) m.Get("", org.ListMembers)
m.Combo("/{username}").Get(org.IsMember). m.Combo("/{username}").Get(org.IsMember).
Delete(reqToken(), reqOrgOwnership(), org.DeleteMember) Delete(reqToken(""), reqOrgOwnership(), org.DeleteMember)
}) })
m.Group("/public_members", func() { m.Group("/public_members", func() {
m.Get("", org.ListPublicMembers) m.Get("", org.ListPublicMembers)
m.Combo("/{username}").Get(org.IsPublicMember). m.Combo("/{username}").Get(org.IsPublicMember).
Put(reqToken(), reqOrgMembership(), org.PublicizeMember). Put(reqToken(""), reqOrgMembership(), org.PublicizeMember).
Delete(reqToken(), reqOrgMembership(), org.ConcealMember) Delete(reqToken(""), reqOrgMembership(), org.ConcealMember)
}) })
m.Group("/teams", func() { m.Group("/teams", func() {
m.Get("", org.ListTeams) m.Get("", org.ListTeams)
m.Post("", reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam) m.Post("", reqOrgOwnership(), bind(api.CreateTeamOption{}), org.CreateTeam)
m.Get("/search", org.SearchTeam) m.Get("/search", org.SearchTeam)
}, reqToken(), reqOrgMembership()) }, reqToken(""), reqOrgMembership())
m.Group("/labels", func() { m.Group("/labels", func() {
m.Get("", org.ListLabels) m.Get("", org.ListLabels)
m.Post("", reqToken(), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel) m.Post("", reqToken(""), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
m.Combo("/{id}").Get(org.GetLabel). m.Combo("/{id}").Get(org.GetLabel).
Patch(reqToken(), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel). Patch(reqToken(""), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
Delete(reqToken(), reqOrgOwnership(), org.DeleteLabel) Delete(reqToken(""), reqOrgOwnership(), org.DeleteLabel)
}) })
m.Group("/hooks", func() { m.Group("/hooks", func() {
m.Combo("").Get(org.ListHooks). m.Combo("").Get(org.ListHooks).
@ -1124,7 +1139,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Combo("/{id}").Get(org.GetHook). m.Combo("/{id}").Get(org.GetHook).
Patch(bind(api.EditHookOption{}), org.EditHook). Patch(bind(api.EditHookOption{}), org.EditHook).
Delete(org.DeleteHook) Delete(org.DeleteHook)
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled()) }, reqToken(""), reqOrgOwnership(), reqWebhooksEnabled())
}, orgAssignment(true)) }, orgAssignment(true))
m.Group("/teams/{teamid}", func() { m.Group("/teams/{teamid}", func() {
m.Combo("").Get(org.GetTeam). m.Combo("").Get(org.GetTeam).
@ -1144,7 +1159,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Delete(org.RemoveTeamRepository). Delete(org.RemoveTeamRepository).
Get(org.GetTeamRepo) Get(org.GetTeamRepo)
}) })
}, orgAssignment(false, true), reqToken(), reqTeamMembership()) }, orgAssignment(false, true), reqToken(""), reqTeamMembership())
m.Group("/admin", func() { m.Group("/admin", func() {
m.Group("/cron", func() { m.Group("/cron", func() {
@ -1172,7 +1187,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Post("/{username}/{reponame}", admin.AdoptRepository) m.Post("/{username}/{reponame}", admin.AdoptRepository)
m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository) m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository)
}) })
}, reqToken(), reqSiteAdmin()) }, reqToken(""), reqSiteAdmin())
m.Group("/topics", func() { m.Group("/topics", func() {
m.Get("/search", repo.TopicSearch) m.Get("/search", repo.TopicSearch)

View file

@ -82,6 +82,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore
} }
store.GetData()["IsApiToken"] = true store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = auth_model.AccessTokenScopeAll
return u return u
} }
@ -100,6 +101,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore
} }
store.GetData()["IsApiToken"] = true store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = auth_model.AccessTokenScopeAll
return u return u
} else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) { } else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) {
log.Error("GetAccessTokenBySha: %v", err) log.Error("GetAccessTokenBySha: %v", err)

View file

@ -13,6 +13,7 @@ import (
"strings" "strings"
asymkey_model "code.gitea.io/gitea/models/asymkey" asymkey_model "code.gitea.io/gitea/models/asymkey"
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -80,6 +81,7 @@ func (h *HTTPSign) Verify(req *http.Request, w http.ResponseWriter, store DataSt
} }
store.GetData()["IsApiToken"] = true store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = auth_model.AccessTokenScopeAll
log.Trace("HTTP Sign: Logged in user %-v", u) log.Trace("HTTP Sign: Logged in user %-v", u)

View file

@ -60,6 +60,8 @@ func (o *OAuth2) Name() string {
} }
// userIDFromToken returns the user id corresponding to the OAuth token. // userIDFromToken returns the user id corresponding to the OAuth token.
// It will set 'IsApiToken' to true if the token is an API token and
// set 'ApiTokenScope' to the scope of the access token
func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 { func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
_ = req.ParseForm() _ = req.ParseForm()
@ -87,6 +89,7 @@ func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
uid := CheckOAuthAccessToken(tokenSHA) uid := CheckOAuthAccessToken(tokenSHA)
if uid != 0 { if uid != 0 {
store.GetData()["IsApiToken"] = true store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = auth_model.AccessTokenScopeAll // fallback to all
} }
return uid return uid
} }
@ -102,6 +105,7 @@ func (o *OAuth2) userIDFromToken(req *http.Request, store DataStore) int64 {
log.Error("UpdateAccessToken: %v", err) log.Error("UpdateAccessToken: %v", err)
} }
store.GetData()["IsApiToken"] = true store.GetData()["IsApiToken"] = true
store.GetData()["ApiTokenScope"] = t.Scope
return t.UID return t.UID
} }