You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

context.go 5.0 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package middleware
  5. import (
  6. "fmt"
  7. "html/template"
  8. "net/http"
  9. "time"
  10. "github.com/codegangsta/martini"
  11. "github.com/gogits/cache"
  12. "github.com/gogits/session"
  13. "github.com/gogits/gogs/models"
  14. "github.com/gogits/gogs/modules/auth"
  15. "github.com/gogits/gogs/modules/base"
  16. "github.com/gogits/gogs/modules/log"
  17. )
  18. // Context represents context of a request.
  19. type Context struct {
  20. *Render
  21. c martini.Context
  22. p martini.Params
  23. Req *http.Request
  24. Res http.ResponseWriter
  25. Session session.SessionStore
  26. Cache cache.Cache
  27. User *models.User
  28. IsSigned bool
  29. csrfToken string
  30. Repo struct {
  31. IsValid bool
  32. IsOwner bool
  33. IsWatching bool
  34. Repository *models.Repository
  35. Owner *models.User
  36. CloneLink struct {
  37. SSH string
  38. HTTPS string
  39. Git string
  40. }
  41. }
  42. }
  43. // Query querys form parameter.
  44. func (ctx *Context) Query(name string) string {
  45. ctx.Req.ParseForm()
  46. return ctx.Req.Form.Get(name)
  47. }
  48. // func (ctx *Context) Param(name string) string {
  49. // return ctx.p[name]
  50. // }
  51. // HasError returns true if error occurs in form validation.
  52. func (ctx *Context) HasError() bool {
  53. hasErr, ok := ctx.Data["HasError"]
  54. if !ok {
  55. return false
  56. }
  57. return hasErr.(bool)
  58. }
  59. // HTML calls render.HTML underlying but reduce one argument.
  60. func (ctx *Context) HTML(status int, name string, htmlOpt ...HTMLOptions) {
  61. ctx.Render.HTML(status, name, ctx.Data, htmlOpt...)
  62. }
  63. // RenderWithErr used for page has form validation but need to prompt error to users.
  64. func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) {
  65. ctx.Data["HasError"] = true
  66. ctx.Data["ErrorMsg"] = msg
  67. auth.AssignForm(form, ctx.Data)
  68. ctx.HTML(200, tpl)
  69. }
  70. // Handle handles and logs error by given status.
  71. func (ctx *Context) Handle(status int, title string, err error) {
  72. log.Error("%s: %v", title, err)
  73. if martini.Dev == martini.Prod {
  74. ctx.HTML(500, "status/500")
  75. return
  76. }
  77. ctx.Data["ErrorMsg"] = err
  78. ctx.HTML(status, fmt.Sprintf("status/%d", status))
  79. }
  80. func (ctx *Context) GetCookie(name string) string {
  81. cookie, err := ctx.Req.Cookie(name)
  82. if err != nil {
  83. return ""
  84. }
  85. return cookie.Value
  86. }
  87. func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
  88. cookie := http.Cookie{}
  89. cookie.Name = name
  90. cookie.Value = value
  91. if len(others) > 0 {
  92. switch v := others[0].(type) {
  93. case int:
  94. cookie.MaxAge = v
  95. case int64:
  96. cookie.MaxAge = int(v)
  97. case int32:
  98. cookie.MaxAge = int(v)
  99. }
  100. }
  101. // default "/"
  102. if len(others) > 1 {
  103. if v, ok := others[1].(string); ok && len(v) > 0 {
  104. cookie.Path = v
  105. }
  106. } else {
  107. cookie.Path = "/"
  108. }
  109. // default empty
  110. if len(others) > 2 {
  111. if v, ok := others[2].(string); ok && len(v) > 0 {
  112. cookie.Domain = v
  113. }
  114. }
  115. // default empty
  116. if len(others) > 3 {
  117. switch v := others[3].(type) {
  118. case bool:
  119. cookie.Secure = v
  120. default:
  121. if others[3] != nil {
  122. cookie.Secure = true
  123. }
  124. }
  125. }
  126. // default false. for session cookie default true
  127. if len(others) > 4 {
  128. if v, ok := others[4].(bool); ok && v {
  129. cookie.HttpOnly = true
  130. }
  131. }
  132. ctx.Res.Header().Add("Set-Cookie", cookie.String())
  133. }
  134. func (ctx *Context) CsrfToken() string {
  135. if len(ctx.csrfToken) > 0 {
  136. return ctx.csrfToken
  137. }
  138. token := ctx.GetCookie("_csrf")
  139. if len(token) == 0 {
  140. token = base.GetRandomString(30)
  141. ctx.SetCookie("_csrf", token)
  142. }
  143. ctx.csrfToken = token
  144. return token
  145. }
  146. func (ctx *Context) CsrfTokenValid() bool {
  147. token := ctx.Query("_csrf")
  148. if token == "" {
  149. token = ctx.Req.Header.Get("X-Csrf-Token")
  150. }
  151. if token == "" {
  152. return false
  153. } else if ctx.csrfToken != token {
  154. return false
  155. }
  156. return true
  157. }
  158. // InitContext initializes a classic context for a request.
  159. func InitContext() martini.Handler {
  160. return func(res http.ResponseWriter, r *http.Request, c martini.Context, rd *Render) {
  161. ctx := &Context{
  162. c: c,
  163. // p: p,
  164. Req: r,
  165. Res: res,
  166. Cache: base.Cache,
  167. Render: rd,
  168. }
  169. ctx.Data["PageStartTime"] = time.Now()
  170. // start session
  171. ctx.Session = base.SessionManager.SessionStart(res, r)
  172. rw := res.(martini.ResponseWriter)
  173. rw.Before(func(martini.ResponseWriter) {
  174. ctx.Session.SessionRelease(res)
  175. })
  176. // Get user from session if logined.
  177. user := auth.SignedInUser(ctx.Session)
  178. ctx.User = user
  179. ctx.IsSigned = user != nil
  180. ctx.Data["IsSigned"] = ctx.IsSigned
  181. if user != nil {
  182. ctx.Data["SignedUser"] = user
  183. ctx.Data["SignedUserId"] = user.Id
  184. ctx.Data["SignedUserName"] = user.LowerName
  185. ctx.Data["IsAdmin"] = ctx.User.IsAdmin
  186. if ctx.User.IsAdmin {
  187. ctx.Data["PageIsAdmin"] = true
  188. }
  189. }
  190. // get or create csrf token
  191. ctx.Data["CsrfToken"] = ctx.CsrfToken()
  192. ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.csrfToken + `">`)
  193. c.Map(ctx)
  194. c.Next()
  195. }
  196. }