// Copyright 2014 The Gogs Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package middleware import ( "fmt" "html/template" "net/http" "time" "github.com/codegangsta/martini" "github.com/gogits/cache" "github.com/gogits/session" "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" ) // Context represents context of a request. type Context struct { *Render c martini.Context p martini.Params Req *http.Request Res http.ResponseWriter Session session.SessionStore Cache cache.Cache User *models.User IsSigned bool csrfToken string Repo struct { IsValid bool IsOwner bool IsWatching bool Repository *models.Repository Owner *models.User CloneLink struct { SSH string HTTPS string Git string } } } // Query querys form parameter. func (ctx *Context) Query(name string) string { ctx.Req.ParseForm() return ctx.Req.Form.Get(name) } // func (ctx *Context) Param(name string) string { // return ctx.p[name] // } // HasError returns true if error occurs in form validation. func (ctx *Context) HasError() bool { hasErr, ok := ctx.Data["HasError"] if !ok { return false } return hasErr.(bool) } // HTML calls render.HTML underlying but reduce one argument. func (ctx *Context) HTML(status int, name string, htmlOpt ...HTMLOptions) { ctx.Render.HTML(status, name, ctx.Data, htmlOpt...) } // RenderWithErr used for page has form validation but need to prompt error to users. func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) { ctx.Data["HasError"] = true ctx.Data["ErrorMsg"] = msg auth.AssignForm(form, ctx.Data) ctx.HTML(200, tpl) } // Handle handles and logs error by given status. func (ctx *Context) Handle(status int, title string, err error) { log.Error("%s: %v", title, err) if martini.Dev == martini.Prod { ctx.HTML(500, "status/500") return } ctx.Data["ErrorMsg"] = err ctx.HTML(status, fmt.Sprintf("status/%d", status)) } func (ctx *Context) GetCookie(name string) string { cookie, err := ctx.Req.Cookie(name) if err != nil { return "" } return cookie.Value } func (ctx *Context) SetCookie(name string, value string, others ...interface{}) { cookie := http.Cookie{} cookie.Name = name cookie.Value = value if len(others) > 0 { switch v := others[0].(type) { case int: cookie.MaxAge = v case int64: cookie.MaxAge = int(v) case int32: cookie.MaxAge = int(v) } } // default "/" if len(others) > 1 { if v, ok := others[1].(string); ok && len(v) > 0 { cookie.Path = v } } else { cookie.Path = "/" } // default empty if len(others) > 2 { if v, ok := others[2].(string); ok && len(v) > 0 { cookie.Domain = v } } // default empty if len(others) > 3 { switch v := others[3].(type) { case bool: cookie.Secure = v default: if others[3] != nil { cookie.Secure = true } } } // default false. for session cookie default true if len(others) > 4 { if v, ok := others[4].(bool); ok && v { cookie.HttpOnly = true } } ctx.Res.Header().Add("Set-Cookie", cookie.String()) } func (ctx *Context) CsrfToken() string { if len(ctx.csrfToken) > 0 { return ctx.csrfToken } token := ctx.GetCookie("_csrf") if len(token) == 0 { token = base.GetRandomString(30) ctx.SetCookie("_csrf", token) } ctx.csrfToken = token return token } func (ctx *Context) CsrfTokenValid() bool { token := ctx.Query("_csrf") if token == "" { token = ctx.Req.Header.Get("X-Csrf-Token") } if token == "" { return false } else if ctx.csrfToken != token { return false } return true } // InitContext initializes a classic context for a request. func InitContext() martini.Handler { return func(res http.ResponseWriter, r *http.Request, c martini.Context, rd *Render) { ctx := &Context{ c: c, // p: p, Req: r, Res: res, Cache: base.Cache, Render: rd, } ctx.Data["PageStartTime"] = time.Now() // start session ctx.Session = base.SessionManager.SessionStart(res, r) rw := res.(martini.ResponseWriter) rw.Before(func(martini.ResponseWriter) { ctx.Session.SessionRelease(res) }) // Get user from session if logined. user := auth.SignedInUser(ctx.Session) ctx.User = user ctx.IsSigned = user != nil ctx.Data["IsSigned"] = ctx.IsSigned if user != nil { ctx.Data["SignedUser"] = user ctx.Data["SignedUserId"] = user.Id ctx.Data["SignedUserName"] = user.LowerName ctx.Data["IsAdmin"] = ctx.User.IsAdmin if ctx.User.IsAdmin { ctx.Data["PageIsAdmin"] = true } } // get or create csrf token ctx.Data["CsrfToken"] = ctx.CsrfToken() ctx.Data["CsrfTokenHtml"] = template.HTML(``) c.Map(ctx) c.Next() } }