diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-05-21 09:50:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-21 09:50:53 +0800 |
commit | 6b33152b7dc81b38e5832a30c52cfad1902e86d0 (patch) | |
tree | 020272cc3b2d0566d286ed01f85ae74a9f48c177 /services/auth | |
parent | 6ba4f897231229c06ac98bf2e067665e3ef0bf23 (diff) | |
download | gitea-6b33152b7dc81b38e5832a30c52cfad1902e86d0.tar.gz gitea-6b33152b7dc81b38e5832a30c52cfad1902e86d0.zip |
Decouple the different contexts from each other (#24786)
Replace #16455
Close #21803
Mixing different Gitea contexts together causes some problems:
1. Unable to respond proper content when error occurs, eg: Web should
respond HTML while API should respond JSON
2. Unclear dependency, eg: it's unclear when Context is used in
APIContext, which fields should be initialized, which methods are
necessary.
To make things clear, this PR introduces a Base context, it only
provides basic Req/Resp/Data features.
This PR mainly moves code. There are still many legacy problems and
TODOs in code, leave unrelated changes to future PRs.
Diffstat (limited to 'services/auth')
-rw-r--r-- | services/auth/middleware.go | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/services/auth/middleware.go b/services/auth/middleware.go index 3b2f883d00..d1955a4c90 100644 --- a/services/auth/middleware.go +++ b/services/auth/middleware.go @@ -8,6 +8,7 @@ import ( "strings" "code.gitea.io/gitea/models/auth" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -17,11 +18,15 @@ import ( // Auth is a middleware to authenticate a web user func Auth(authMethod Method) func(*context.Context) { return func(ctx *context.Context) { - if err := authShared(ctx, authMethod); err != nil { + ar, err := authShared(ctx.Base, ctx.Session, authMethod) + if err != nil { log.Error("Failed to verify user: %v", err) ctx.Error(http.StatusUnauthorized, "Verify") return } + ctx.Doer = ar.Doer + ctx.IsSigned = ar.Doer != nil + ctx.IsBasicAuth = ar.IsBasicAuth if ctx.Doer == nil { // ensure the session uid is deleted _ = ctx.Session.Delete("uid") @@ -32,32 +37,41 @@ func Auth(authMethod Method) func(*context.Context) { // APIAuth is a middleware to authenticate an api user func APIAuth(authMethod Method) func(*context.APIContext) { return func(ctx *context.APIContext) { - if err := authShared(ctx.Context, authMethod); err != nil { + ar, err := authShared(ctx.Base, nil, authMethod) + if err != nil { ctx.Error(http.StatusUnauthorized, "APIAuth", err) + return } + ctx.Doer = ar.Doer + ctx.IsSigned = ar.Doer != nil + ctx.IsBasicAuth = ar.IsBasicAuth } } -func authShared(ctx *context.Context, authMethod Method) error { - var err error - ctx.Doer, err = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) +type authResult struct { + Doer *user_model.User + IsBasicAuth bool +} + +func authShared(ctx *context.Base, sessionStore SessionStore, authMethod Method) (ar authResult, err error) { + ar.Doer, err = authMethod.Verify(ctx.Req, ctx.Resp, ctx, sessionStore) if err != nil { - return err + return ar, err } - if ctx.Doer != nil { - if ctx.Locale.Language() != ctx.Doer.Language { + if ar.Doer != nil { + if ctx.Locale.Language() != ar.Doer.Language { ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req) } - ctx.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == BasicMethodName - ctx.IsSigned = true - ctx.Data["IsSigned"] = ctx.IsSigned - ctx.Data[middleware.ContextDataKeySignedUser] = ctx.Doer - ctx.Data["SignedUserID"] = ctx.Doer.ID - ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin + ar.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == BasicMethodName + + ctx.Data["IsSigned"] = true + ctx.Data[middleware.ContextDataKeySignedUser] = ar.Doer + ctx.Data["SignedUserID"] = ar.Doer.ID + ctx.Data["IsAdmin"] = ar.Doer.IsAdmin } else { ctx.Data["SignedUserID"] = int64(0) } - return nil + return ar, nil } // VerifyOptions contains required or check options @@ -68,7 +82,7 @@ type VerifyOptions struct { DisableCSRF bool } -// Checks authentication according to options +// VerifyAuthWithOptions checks authentication according to options func VerifyAuthWithOptions(options *VerifyOptions) func(ctx *context.Context) { return func(ctx *context.Context) { // Check prohibit login users. @@ -153,7 +167,7 @@ func VerifyAuthWithOptions(options *VerifyOptions) func(ctx *context.Context) { } } -// Checks authentication according to options +// VerifyAuthWithOptionsAPI checks authentication according to options func VerifyAuthWithOptionsAPI(options *VerifyOptions) func(ctx *context.APIContext) { return func(ctx *context.APIContext) { // Check prohibit login users. @@ -197,7 +211,9 @@ func VerifyAuthWithOptionsAPI(options *VerifyOptions) func(ctx *context.APIConte return } else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm { ctx.Data["Title"] = ctx.Tr("auth.active_your_account") - ctx.HTML(http.StatusOK, "user/auth/activate") + ctx.JSON(http.StatusForbidden, map[string]string{ + "message": "This account is not activated.", + }) return } if ctx.IsSigned && ctx.IsBasicAuth { |