Refactor error system (#33610)

This commit is contained in:
wxiaoguang 2025-02-17 14:13:17 +08:00 committed by GitHub
parent 69de5a65c2
commit f35850f48e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
184 changed files with 2100 additions and 2106 deletions

View file

@ -116,9 +116,9 @@ func sudo() func(ctx *context.APIContext) {
user, err := user_model.GetUserByName(ctx, sudo)
if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.NotFound()
ctx.APIErrorNotFound()
} else {
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
ctx.APIError(http.StatusInternalServerError, err)
}
return
}
@ -154,12 +154,12 @@ func repoAssignment() func(ctx *context.APIContext) {
if redirectUserID, err := user_model.LookupUserRedirect(ctx, userName); err == nil {
context.RedirectToUser(ctx.Base, userName, redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.NotFound("GetUserByName", err)
ctx.APIErrorNotFound("GetUserByName", err)
} else {
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
ctx.APIError(http.StatusInternalServerError, err)
}
} else {
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
ctx.APIError(http.StatusInternalServerError, err)
}
return
}
@ -175,12 +175,12 @@ func repoAssignment() func(ctx *context.APIContext) {
if err == nil {
context.RedirectToRepo(ctx.Base, redirectRepoID)
} else if repo_model.IsErrRedirectNotExist(err) {
ctx.NotFound()
ctx.APIErrorNotFound()
} else {
ctx.Error(http.StatusInternalServerError, "LookupRepoRedirect", err)
ctx.APIError(http.StatusInternalServerError, err)
}
} else {
ctx.Error(http.StatusInternalServerError, "GetRepositoryByName", err)
ctx.APIError(http.StatusInternalServerError, err)
}
return
}
@ -192,11 +192,11 @@ func repoAssignment() func(ctx *context.APIContext) {
taskID := ctx.Data["ActionsTaskID"].(int64)
task, err := actions_model.GetTaskByID(ctx, taskID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "actions_model.GetTaskByID", err)
ctx.APIError(http.StatusInternalServerError, err)
return
}
if task.RepoID != repo.ID {
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
@ -207,20 +207,20 @@ func repoAssignment() func(ctx *context.APIContext) {
}
if err := ctx.Repo.Repository.LoadUnits(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadUnits", err)
ctx.APIError(http.StatusInternalServerError, err)
return
}
ctx.Repo.Permission.SetUnitsWithDefaultAccessMode(ctx.Repo.Repository.Units, ctx.Repo.Permission.AccessMode)
} else {
ctx.Repo.Permission, err = access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
ctx.APIError(http.StatusInternalServerError, err)
return
}
}
if !ctx.Repo.Permission.HasAnyUnitAccess() {
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
@ -229,7 +229,7 @@ func repoAssignment() func(ctx *context.APIContext) {
func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if ctx.Package.AccessMode < accessMode && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqPackageAccess", "user should have specific permission or be a site admin")
ctx.APIError(http.StatusForbidden, "user should have specific permission or be a site admin")
return
}
}
@ -250,41 +250,41 @@ func checkTokenPublicOnly() func(ctx *context.APIContext) {
switch {
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public repos")
ctx.APIError(http.StatusForbidden, "token scope is limited to public repos")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryIssue):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public issues")
ctx.APIError(http.StatusForbidden, "token scope is limited to public issues")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryOrganization):
if ctx.Org.Organization != nil && ctx.Org.Organization.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
ctx.APIError(http.StatusForbidden, "token scope is limited to public orgs")
return
}
if ctx.ContextUser != nil && ctx.ContextUser.IsOrganization() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
ctx.APIError(http.StatusForbidden, "token scope is limited to public orgs")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryUser):
if ctx.ContextUser != nil && ctx.ContextUser.IsTokenAccessAllowed() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public users")
ctx.APIError(http.StatusForbidden, "token scope is limited to public users")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryActivityPub):
if ctx.ContextUser != nil && ctx.ContextUser.IsTokenAccessAllowed() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public activitypub")
ctx.APIError(http.StatusForbidden, "token scope is limited to public activitypub")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryNotification):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public notifications")
ctx.APIError(http.StatusForbidden, "token scope is limited to public notifications")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryPackage):
if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public packages")
ctx.APIError(http.StatusForbidden, "token scope is limited to public packages")
return
}
}
@ -316,12 +316,12 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
requiredScopes := auth_model.GetRequiredScopes(requiredScopeLevel, requiredScopeCategories...)
allow, err := scope.HasScope(requiredScopes...)
if err != nil {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
ctx.APIError(http.StatusForbidden, "checking scope failed: "+err.Error())
return
}
if !allow {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s), required=%v, token scope=%v", requiredScopes, scope))
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
}
@ -330,7 +330,7 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
// check if scope only applies to public resources
publicOnly, err := scope.PublicOnly()
if err != nil {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "parsing public resource scope failed: "+err.Error())
ctx.APIError(http.StatusForbidden, "parsing public resource scope failed: "+err.Error())
return
}
@ -350,14 +350,14 @@ func reqToken() func(ctx *context.APIContext) {
if ctx.IsSigned {
return
}
ctx.Error(http.StatusUnauthorized, "reqToken", "token is required")
ctx.APIError(http.StatusUnauthorized, "token is required")
}
}
func reqExploreSignIn() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if (setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView) && !ctx.IsSigned {
ctx.Error(http.StatusUnauthorized, "reqExploreSignIn", "you must be signed in to search for users")
ctx.APIError(http.StatusUnauthorized, "you must be signed in to search for users")
}
}
}
@ -365,7 +365,7 @@ func reqExploreSignIn() func(ctx *context.APIContext) {
func reqUsersExploreEnabled() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if setting.Service.Explore.DisableUsersPage {
ctx.NotFound()
ctx.APIErrorNotFound()
}
}
}
@ -376,7 +376,7 @@ func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
return
}
if !ctx.IsBasicAuth {
ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required")
ctx.APIError(http.StatusUnauthorized, "auth required")
return
}
}
@ -386,7 +386,7 @@ func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
func reqSiteAdmin() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqSiteAdmin", "user should be the site admin")
ctx.APIError(http.StatusForbidden, "user should be the site admin")
return
}
}
@ -396,7 +396,7 @@ func reqSiteAdmin() func(ctx *context.APIContext) {
func reqOwner() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.Repo.IsOwner() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo")
ctx.APIError(http.StatusForbidden, "user should be the owner of the repo")
return
}
}
@ -406,7 +406,7 @@ func reqOwner() func(ctx *context.APIContext) {
func reqSelfOrAdmin() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserSiteAdmin() && ctx.ContextUser != ctx.Doer {
ctx.Error(http.StatusForbidden, "reqSelfOrAdmin", "doer should be the site admin or be same as the contextUser")
ctx.APIError(http.StatusForbidden, "doer should be the site admin or be same as the contextUser")
return
}
}
@ -416,7 +416,7 @@ func reqSelfOrAdmin() func(ctx *context.APIContext) {
func reqAdmin() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqAdmin", "user should be an owner or a collaborator with admin write of a repository")
ctx.APIError(http.StatusForbidden, "user should be an owner or a collaborator with admin write of a repository")
return
}
}
@ -426,7 +426,7 @@ func reqAdmin() func(ctx *context.APIContext) {
func reqRepoWriter(unitTypes ...unit.Type) func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserRepoWriter(unitTypes) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqRepoWriter", "user should have a permission to write to a repo")
ctx.APIError(http.StatusForbidden, "user should have a permission to write to a repo")
return
}
}
@ -436,7 +436,7 @@ func reqRepoWriter(unitTypes ...unit.Type) func(ctx *context.APIContext) {
func reqRepoBranchWriter(ctx *context.APIContext) {
options, ok := web.GetForm(ctx).(api.FileOptionInterface)
if !ok || (!ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, options.Branch()) && !ctx.IsUserSiteAdmin()) {
ctx.Error(http.StatusForbidden, "reqRepoBranchWriter", "user should have a permission to write to this branch")
ctx.APIError(http.StatusForbidden, "user should have a permission to write to this branch")
return
}
}
@ -445,7 +445,7 @@ func reqRepoBranchWriter(ctx *context.APIContext) {
func reqRepoReader(unitType unit.Type) func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.Repo.CanRead(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqRepoReader", "user should have specific read permission or be a repo admin or a site admin")
ctx.APIError(http.StatusForbidden, "user should have specific read permission or be a repo admin or a site admin")
return
}
}
@ -455,7 +455,7 @@ func reqRepoReader(unitType unit.Type) func(ctx *context.APIContext) {
func reqAnyRepoReader() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.Repo.Permission.HasAnyUnitAccess() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqAnyRepoReader", "user should have any permission to read repository or permissions of site admin")
ctx.APIError(http.StatusForbidden, "user should have any permission to read repository or permissions of site admin")
return
}
}
@ -474,19 +474,19 @@ func reqOrgOwnership() func(ctx *context.APIContext) {
} else if ctx.Org.Team != nil {
orgID = ctx.Org.Team.OrgID
} else {
ctx.Error(http.StatusInternalServerError, "", "reqOrgOwnership: unprepared context")
ctx.APIError(http.StatusInternalServerError, "reqOrgOwnership: unprepared context")
return
}
isOwner, err := organization.IsOrganizationOwner(ctx, orgID, ctx.Doer.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
ctx.APIError(http.StatusInternalServerError, err)
return
} else if !isOwner {
if ctx.Org.Organization != nil {
ctx.Error(http.StatusForbidden, "", "Must be an organization owner")
ctx.APIError(http.StatusForbidden, "Must be an organization owner")
} else {
ctx.NotFound()
ctx.APIErrorNotFound()
}
return
}
@ -500,30 +500,30 @@ func reqTeamMembership() func(ctx *context.APIContext) {
return
}
if ctx.Org.Team == nil {
ctx.Error(http.StatusInternalServerError, "", "reqTeamMembership: unprepared context")
ctx.APIError(http.StatusInternalServerError, "reqTeamMembership: unprepared context")
return
}
orgID := ctx.Org.Team.OrgID
isOwner, err := organization.IsOrganizationOwner(ctx, orgID, ctx.Doer.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
ctx.APIError(http.StatusInternalServerError, err)
return
} else if isOwner {
return
}
if isTeamMember, err := organization.IsTeamMember(ctx, orgID, ctx.Org.Team.ID, ctx.Doer.ID); err != nil {
ctx.Error(http.StatusInternalServerError, "IsTeamMember", err)
ctx.APIError(http.StatusInternalServerError, err)
return
} else if !isTeamMember {
isOrgMember, err := organization.IsOrganizationMember(ctx, orgID, ctx.Doer.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
ctx.APIError(http.StatusInternalServerError, err)
} else if isOrgMember {
ctx.Error(http.StatusForbidden, "", "Must be a team member")
ctx.APIError(http.StatusForbidden, "Must be a team member")
} else {
ctx.NotFound()
ctx.APIErrorNotFound()
}
return
}
@ -543,18 +543,18 @@ func reqOrgMembership() func(ctx *context.APIContext) {
} else if ctx.Org.Team != nil {
orgID = ctx.Org.Team.OrgID
} else {
ctx.Error(http.StatusInternalServerError, "", "reqOrgMembership: unprepared context")
ctx.APIError(http.StatusInternalServerError, "reqOrgMembership: unprepared context")
return
}
if isMember, err := organization.IsOrganizationMember(ctx, orgID, ctx.Doer.ID); err != nil {
ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
ctx.APIError(http.StatusInternalServerError, err)
return
} else if !isMember {
if ctx.Org.Organization != nil {
ctx.Error(http.StatusForbidden, "", "Must be an organization member")
ctx.APIError(http.StatusForbidden, "Must be an organization member")
} else {
ctx.NotFound()
ctx.APIErrorNotFound()
}
return
}
@ -564,7 +564,7 @@ func reqOrgMembership() func(ctx *context.APIContext) {
func reqGitHook() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.Doer.CanEditGitHook() {
ctx.Error(http.StatusForbidden, "", "must be allowed to edit Git hooks")
ctx.APIError(http.StatusForbidden, "must be allowed to edit Git hooks")
return
}
}
@ -574,7 +574,7 @@ func reqGitHook() func(ctx *context.APIContext) {
func reqWebhooksEnabled() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if setting.DisableWebhooks {
ctx.Error(http.StatusForbidden, "", "webhooks disabled by administrator")
ctx.APIError(http.StatusForbidden, "webhooks disabled by administrator")
return
}
}
@ -584,7 +584,7 @@ func reqWebhooksEnabled() func(ctx *context.APIContext) {
func reqStarsEnabled() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if setting.Repository.DisableStars {
ctx.Error(http.StatusForbidden, "", "stars disabled by administrator")
ctx.APIError(http.StatusForbidden, "stars disabled by administrator")
return
}
}
@ -613,12 +613,12 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
if err == nil {
context.RedirectToUser(ctx.Base, ctx.PathParam("org"), redirectUserID)
} else if user_model.IsErrUserRedirectNotExist(err) {
ctx.NotFound("GetOrgByName", err)
ctx.APIErrorNotFound("GetOrgByName", err)
} else {
ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
ctx.APIError(http.StatusInternalServerError, err)
}
} else {
ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
ctx.APIError(http.StatusInternalServerError, err)
}
return
}
@ -629,9 +629,9 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
ctx.Org.Team, err = organization.GetTeamByID(ctx, ctx.PathParamInt64("teamid"))
if err != nil {
if organization.IsErrTeamNotExist(err) {
ctx.NotFound()
ctx.APIErrorNotFound()
} else {
ctx.Error(http.StatusInternalServerError, "GetTeamById", err)
ctx.APIError(http.StatusInternalServerError, err)
}
return
}
@ -657,7 +657,7 @@ func mustEnableIssues(ctx *context.APIContext) {
ctx.Repo.Permission)
}
}
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
@ -680,7 +680,7 @@ func mustAllowPulls(ctx *context.APIContext) {
ctx.Repo.Permission)
}
}
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
@ -706,28 +706,28 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) {
ctx.Repo.Permission)
}
}
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
func mustEnableWiki(ctx *context.APIContext) {
if !(ctx.Repo.CanRead(unit.TypeWiki)) {
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
func mustNotBeArchived(ctx *context.APIContext) {
if ctx.Repo.Repository.IsArchived {
ctx.Error(http.StatusLocked, "RepoArchived", fmt.Errorf("%s is archived", ctx.Repo.Repository.LogString()))
ctx.APIError(http.StatusLocked, fmt.Errorf("%s is archived", ctx.Repo.Repository.LogString()))
return
}
}
func mustEnableAttachments(ctx *context.APIContext) {
if !setting.Attachment.Enabled {
ctx.NotFound()
ctx.APIErrorNotFound()
return
}
}
@ -738,7 +738,7 @@ func bind[T any](_ T) any {
theObj := new(T) // create a new form obj for every request but not use obj directly
errs := binding.Bind(ctx.Req, theObj)
if len(errs) > 0 {
ctx.Error(http.StatusUnprocessableEntity, "validationError", fmt.Sprintf("%s: %s", errs[0].FieldNames, errs[0].Error()))
ctx.APIError(http.StatusUnprocessableEntity, fmt.Sprintf("%s: %s", errs[0].FieldNames, errs[0].Error()))
return
}
web.SetForm(ctx, theObj)
@ -766,7 +766,7 @@ func apiAuth(authMethod auth.Method) func(*context.APIContext) {
return func(ctx *context.APIContext) {
ar, err := common.AuthShared(ctx.Base, nil, authMethod)
if err != nil {
ctx.Error(http.StatusUnauthorized, "APIAuth", err)
ctx.APIError(http.StatusUnauthorized, err)
return
}
ctx.Doer = ar.Doer
@ -843,12 +843,12 @@ func individualPermsChecker(ctx *context.APIContext) {
switch {
case ctx.ContextUser.Visibility == api.VisibleTypePrivate:
if ctx.Doer == nil || (ctx.ContextUser.ID != ctx.Doer.ID && !ctx.Doer.IsAdmin) {
ctx.NotFound("Visit Project", nil)
ctx.APIErrorNotFound("Visit Project", nil)
return
}
case ctx.ContextUser.Visibility == api.VisibleTypeLimited:
if ctx.Doer == nil {
ctx.NotFound("Visit Project", nil)
ctx.APIErrorNotFound("Visit Project", nil)
return
}
}