diff options
Diffstat (limited to 'modules/context/context.go')
-rw-r--r-- | modules/context/context.go | 100 |
1 files changed, 35 insertions, 65 deletions
diff --git a/modules/context/context.go b/modules/context/context.go index e2e120ba38..cee533e42a 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -45,6 +45,8 @@ import ( "golang.org/x/crypto/pbkdf2" ) +const CookieNameFlash = "gitea_flash" + // Render represents a template render type Render interface { TemplateLookup(tmpl string) (*template.Template, error) @@ -60,7 +62,7 @@ type Context struct { Render Render translation.Locale Cache cache.Cache - csrf CSRFProtector + Csrf CSRFProtector Flash *middleware.Flash Session session.Store @@ -478,38 +480,26 @@ func (ctx *Context) Redirect(location string, status ...int) { http.Redirect(ctx.Resp, ctx.Req, location, code) } -// SetCookie convenience function to set most cookies consistently +// SetSiteCookie convenience function to set most cookies consistently // CSRF and a few others are the exception here -func (ctx *Context) SetCookie(name, value string, expiry int) { - middleware.SetCookie(ctx.Resp, name, value, - expiry, - setting.AppSubURL, - setting.SessionConfig.Domain, - setting.SessionConfig.Secure, - true, - middleware.SameSite(setting.SessionConfig.SameSite)) +func (ctx *Context) SetSiteCookie(name, value string, maxAge int) { + middleware.SetSiteCookie(ctx.Resp, name, value, maxAge) } -// DeleteCookie convenience function to delete most cookies consistently +// DeleteSiteCookie convenience function to delete most cookies consistently // CSRF and a few others are the exception here -func (ctx *Context) DeleteCookie(name string) { - middleware.SetCookie(ctx.Resp, name, "", - -1, - setting.AppSubURL, - setting.SessionConfig.Domain, - setting.SessionConfig.Secure, - true, - middleware.SameSite(setting.SessionConfig.SameSite)) +func (ctx *Context) DeleteSiteCookie(name string) { + middleware.SetSiteCookie(ctx.Resp, name, "", -1) } -// GetCookie returns given cookie value from request header. -func (ctx *Context) GetCookie(name string) string { - return middleware.GetCookie(ctx.Req, name) +// GetSiteCookie returns given cookie value from request header. +func (ctx *Context) GetSiteCookie(name string) string { + return middleware.GetSiteCookie(ctx.Req, name) } // GetSuperSecureCookie returns given cookie value from request header with secret string. func (ctx *Context) GetSuperSecureCookie(secret, name string) (string, bool) { - val := ctx.GetCookie(name) + val := ctx.GetSiteCookie(name) return ctx.CookieDecrypt(secret, val) } @@ -530,10 +520,9 @@ func (ctx *Context) CookieDecrypt(secret, val string) (string, bool) { } // SetSuperSecureCookie sets given cookie value to response header with secret string. -func (ctx *Context) SetSuperSecureCookie(secret, name, value string, expiry int) { +func (ctx *Context) SetSuperSecureCookie(secret, name, value string, maxAge int) { text := ctx.CookieEncrypt(secret, value) - - ctx.SetCookie(name, text, expiry) + ctx.SetSiteCookie(name, text, maxAge) } // CookieEncrypt encrypts a given value using the provided secret @@ -549,19 +538,19 @@ func (ctx *Context) CookieEncrypt(secret, value string) string { // GetCookieInt returns cookie result in int type. func (ctx *Context) GetCookieInt(name string) int { - r, _ := strconv.Atoi(ctx.GetCookie(name)) + r, _ := strconv.Atoi(ctx.GetSiteCookie(name)) return r } // GetCookieInt64 returns cookie result in int64 type. func (ctx *Context) GetCookieInt64(name string) int64 { - r, _ := strconv.ParseInt(ctx.GetCookie(name), 10, 64) + r, _ := strconv.ParseInt(ctx.GetSiteCookie(name), 10, 64) return r } // GetCookieFloat64 returns cookie result in float64 type. func (ctx *Context) GetCookieFloat64(name string) float64 { - v, _ := strconv.ParseFloat(ctx.GetCookie(name), 64) + v, _ := strconv.ParseFloat(ctx.GetSiteCookie(name), 64) return v } @@ -659,7 +648,10 @@ func WithContext(req *http.Request, ctx *Context) *http.Request { // GetContext retrieves install context from request func GetContext(req *http.Request) *Context { - return req.Context().Value(contextKey).(*Context) + if ctx, ok := req.Context().Value(contextKey).(*Context); ok { + return ctx + } + return nil } // GetContextUser returns context user @@ -726,13 +718,13 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler { ctx.Data["Context"] = &ctx ctx.Req = WithContext(req, &ctx) - ctx.csrf = PrepareCSRFProtector(csrfOpts, &ctx) + ctx.Csrf = PrepareCSRFProtector(csrfOpts, &ctx) - // Get flash. - flashCookie := ctx.GetCookie("macaron_flash") - vals, _ := url.ParseQuery(flashCookie) - if len(vals) > 0 { - f := &middleware.Flash{ + // Get the last flash message from cookie + lastFlashCookie := middleware.GetSiteCookie(ctx.Req, CookieNameFlash) + if vals, _ := url.ParseQuery(lastFlashCookie); len(vals) > 0 { + // store last Flash message into the template data, to render it + ctx.Data["Flash"] = &middleware.Flash{ DataStore: &ctx, Values: vals, ErrorMsg: vals.Get("error"), @@ -740,40 +732,18 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler { InfoMsg: vals.Get("info"), WarningMsg: vals.Get("warning"), } - ctx.Data["Flash"] = f } - f := &middleware.Flash{ - DataStore: &ctx, - Values: url.Values{}, - ErrorMsg: "", - WarningMsg: "", - InfoMsg: "", - SuccessMsg: "", - } + // prepare an empty Flash message for current request + ctx.Flash = &middleware.Flash{DataStore: &ctx, Values: url.Values{}} ctx.Resp.Before(func(resp ResponseWriter) { - if flash := f.Encode(); len(flash) > 0 { - middleware.SetCookie(resp, "macaron_flash", flash, 0, - setting.SessionConfig.CookiePath, - middleware.Domain(setting.SessionConfig.Domain), - middleware.HTTPOnly(true), - middleware.Secure(setting.SessionConfig.Secure), - middleware.SameSite(setting.SessionConfig.SameSite), - ) - return + if val := ctx.Flash.Encode(); val != "" { + middleware.SetSiteCookie(ctx.Resp, CookieNameFlash, val, 0) + } else if lastFlashCookie != "" { + middleware.SetSiteCookie(ctx.Resp, CookieNameFlash, "", -1) } - - middleware.SetCookie(ctx.Resp, "macaron_flash", "", -1, - setting.SessionConfig.CookiePath, - middleware.Domain(setting.SessionConfig.Domain), - middleware.HTTPOnly(true), - middleware.Secure(setting.SessionConfig.Secure), - middleware.SameSite(setting.SessionConfig.SameSite), - ) }) - ctx.Flash = f - // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid. if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") { if err := ctx.Req.ParseMultipartForm(setting.Attachment.MaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size @@ -785,7 +755,7 @@ func Contexter(ctx context.Context) func(next http.Handler) http.Handler { httpcache.SetCacheControlInHeader(ctx.Resp.Header(), 0, "no-transform") ctx.Resp.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions) - ctx.Data["CsrfToken"] = ctx.csrf.GetToken() + ctx.Data["CsrfToken"] = ctx.Csrf.GetToken() ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.Data["CsrfToken"].(string) + `">`) // FIXME: do we really always need these setting? There should be someway to have to avoid having to always set these |