diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2021-01-26 23:36:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-26 16:36:53 +0100 |
commit | 6433ba0ec3dfde67f45267aa12bd713c4a44c740 (patch) | |
tree | 8813388f7e58ff23ad24af9ccbdb5f0350cb3a09 /modules/context/auth.go | |
parent | 3adbbb4255c42cde04d59b6ebf5ead7e3edda3e7 (diff) | |
download | gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.tar.gz gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.zip |
Move macaron to chi (#14293)
Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR.
- [x] Define `context.ResponseWriter` interface with an implementation `context.Response`.
- [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before.
- [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic .
- [x] Use https://github.com/unrolled/render instead of macaron's internal render
- [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip
- [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK**
- [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha
- [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache
- [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding
- [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors
- [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation`
- [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle.
- [x] Removed macaron log service because it's not need any more. **BREAK**
- [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition.
- [x] Move Git HTTP protocol implementation to use routers directly.
- [x] Fix the problem that chi routes don't support trailing slash but macaron did.
- [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render.
Notices:
- Chi router don't support request with trailing slash
- Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI.
Co-authored-by: 6543 <6543@obermui.de>
Diffstat (limited to 'modules/context/auth.go')
-rw-r--r-- | modules/context/auth.go | 129 |
1 files changed, 80 insertions, 49 deletions
diff --git a/modules/context/auth.go b/modules/context/auth.go index 02248384e1..8be6ed1907 100644 --- a/modules/context/auth.go +++ b/modules/context/auth.go @@ -7,12 +7,8 @@ package context import ( "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - - "gitea.com/macaron/csrf" - "gitea.com/macaron/macaron" ) // ToggleOptions contains required or check options @@ -24,42 +20,23 @@ type ToggleOptions struct { } // Toggle returns toggle options as middleware -func Toggle(options *ToggleOptions) macaron.Handler { +func Toggle(options *ToggleOptions) func(ctx *Context) { return func(ctx *Context) { - isAPIPath := auth.IsAPIPath(ctx.Req.URL.Path) - // Check prohibit login users. if ctx.IsSigned { if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { ctx.Data["Title"] = ctx.Tr("auth.active_your_account") - if isAPIPath { - ctx.JSON(403, map[string]string{ - "message": "This account is not activated.", - }) - return - } ctx.HTML(200, "user/auth/activate") return - } else if !ctx.User.IsActive || ctx.User.ProhibitLogin { + } + if !ctx.User.IsActive || ctx.User.ProhibitLogin { log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr()) ctx.Data["Title"] = ctx.Tr("auth.prohibit_login") - if isAPIPath { - ctx.JSON(403, map[string]string{ - "message": "This account is prohibited from signing in, please contact your site administrator.", - }) - return - } ctx.HTML(200, "user/auth/prohibit_login") return } if ctx.User.MustChangePassword { - if isAPIPath { - ctx.JSON(403, map[string]string{ - "message": "You must change your password. Change it at: " + setting.AppURL + "/user/change_password", - }) - return - } if ctx.Req.URL.Path != "/user/settings/change_password" { ctx.Data["Title"] = ctx.Tr("auth.must_change_password") ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password" @@ -82,8 +59,8 @@ func Toggle(options *ToggleOptions) macaron.Handler { return } - if !options.SignOutRequired && !options.DisableCSRF && ctx.Req.Method == "POST" && !auth.IsAPIPath(ctx.Req.URL.Path) { - csrf.Validate(ctx.Context, ctx.csrf) + if !options.SignOutRequired && !options.DisableCSRF && ctx.Req.Method == "POST" { + Validate(ctx, ctx.csrf) if ctx.Written() { return } @@ -91,13 +68,6 @@ func Toggle(options *ToggleOptions) macaron.Handler { if options.SignInRequired { if !ctx.IsSigned { - // Restrict API calls with error message. - if isAPIPath { - ctx.JSON(403, map[string]string{ - "message": "Only signed in user is allowed to call APIs.", - }) - return - } if ctx.Req.URL.Path != "/user/events" { ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL) } @@ -108,19 +78,88 @@ func Toggle(options *ToggleOptions) macaron.Handler { ctx.HTML(200, "user/auth/activate") return } - if ctx.IsSigned && isAPIPath && ctx.IsBasicAuth { + } + + // Redirect to log in page if auto-signin info is provided and has not signed in. + if !options.SignOutRequired && !ctx.IsSigned && + len(ctx.GetCookie(setting.CookieUserName)) > 0 { + if ctx.Req.URL.Path != "/user/events" { + ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL) + } + ctx.Redirect(setting.AppSubURL + "/user/login") + return + } + + if options.AdminRequired { + if !ctx.User.IsAdmin { + ctx.Error(403) + return + } + ctx.Data["PageIsAdmin"] = true + } + } +} + +// ToggleAPI returns toggle options as middleware +func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) { + return func(ctx *APIContext) { + // Check prohibit login users. + if ctx.IsSigned { + if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { + ctx.Data["Title"] = ctx.Tr("auth.active_your_account") + ctx.JSON(403, map[string]string{ + "message": "This account is not activated.", + }) + return + } + if !ctx.User.IsActive || ctx.User.ProhibitLogin { + log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr()) + ctx.Data["Title"] = ctx.Tr("auth.prohibit_login") + ctx.JSON(403, map[string]string{ + "message": "This account is prohibited from signing in, please contact your site administrator.", + }) + return + } + + if ctx.User.MustChangePassword { + ctx.JSON(403, map[string]string{ + "message": "You must change your password. Change it at: " + setting.AppURL + "/user/change_password", + }) + return + } + } + + // Redirect to dashboard if user tries to visit any non-login page. + if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" { + ctx.Redirect(setting.AppSubURL + "/") + return + } + + if options.SignInRequired { + if !ctx.IsSigned { + // Restrict API calls with error message. + ctx.JSON(403, map[string]string{ + "message": "Only signed in user is allowed to call APIs.", + }) + return + } else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { + ctx.Data["Title"] = ctx.Tr("auth.active_your_account") + ctx.HTML(200, "user/auth/activate") + return + } + if ctx.IsSigned && ctx.IsBasicAuth { twofa, err := models.GetTwoFactorByUID(ctx.User.ID) if err != nil { if models.IsErrTwoFactorNotEnrolled(err) { return // No 2FA enrollment for this user } - ctx.Error(500) + ctx.InternalServerError(err) return } otpHeader := ctx.Req.Header.Get("X-Gitea-OTP") ok, err := twofa.ValidateTOTP(otpHeader) if err != nil { - ctx.Error(500) + ctx.InternalServerError(err) return } if !ok { @@ -132,19 +171,11 @@ func Toggle(options *ToggleOptions) macaron.Handler { } } - // Redirect to log in page if auto-signin info is provided and has not signed in. - if !options.SignOutRequired && !ctx.IsSigned && !isAPIPath && - len(ctx.GetCookie(setting.CookieUserName)) > 0 { - if ctx.Req.URL.Path != "/user/events" { - ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL) - } - ctx.Redirect(setting.AppSubURL + "/user/login") - return - } - if options.AdminRequired { if !ctx.User.IsAdmin { - ctx.Error(403) + ctx.JSON(403, map[string]string{ + "message": "You have no permission to request for this.", + }) return } ctx.Data["PageIsAdmin"] = true |