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 11 kB

11 years ago
11 years ago
11 years ago
2 years ago
11 years ago
10 years ago
3 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
Better logging (#6038) (#6095) * Panic don't fatal on create new logger Fixes #5854 Signed-off-by: Andrew Thornton <art27@cantab.net> * partial broken * Update the logging infrastrcture Signed-off-by: Andrew Thornton <art27@cantab.net> * Reset the skip levels for Fatal and Error Signed-off-by: Andrew Thornton <art27@cantab.net> * broken ncsa * More log.Error fixes Signed-off-by: Andrew Thornton <art27@cantab.net> * Remove nal * set log-levels to lowercase * Make console_test test all levels * switch to lowercased levels * OK now working * Fix vetting issues * Fix lint * Fix tests * change default logging to match current gitea * Improve log testing Signed-off-by: Andrew Thornton <art27@cantab.net> * reset error skip levels to 0 * Update documentation and access logger configuration * Redirect the router log back to gitea if redirect macaron log but also allow setting the log level - i.e. TRACE * Fix broken level caching * Refactor the router log * Add Router logger * Add colorizing options * Adjust router colors * Only create logger if they will be used * update app.ini.sample * rename Attribute ColorAttribute * Change from white to green for function * Set fatal/error levels * Restore initial trace logger * Fix Trace arguments in modules/auth/auth.go * Properly handle XORMLogger * Improve admin/config page * fix fmt * Add auto-compression of old logs * Update error log levels * Remove the unnecessary skip argument from Error, Fatal and Critical * Add stacktrace support * Fix tests * Remove x/sync from vendors? * Add stderr option to console logger * Use filepath.ToSlash to protect against Windows in tests * Remove prefixed underscores from names in colors.go * Remove not implemented database logger This was removed from Gogs on 4 Mar 2016 but left in the configuration since then. * Ensure that log paths are relative to ROOT_PATH * use path.Join * rename jsonConfig to logConfig * Rename "config" to "jsonConfig" to make it clearer * Requested changes * Requested changes: XormLogger * Try to color the windows terminal If successful default to colorizing the console logs * fixup * Colorize initially too * update vendor * Colorize logs on default and remove if this is not a colorizing logger * Fix documentation * fix test * Use go-isatty to detect if on windows we are on msys or cygwin * Fix spelling mistake * Add missing vendors * More changes * Rationalise the ANSI writer protection * Adjust colors on advice from @0x5c * Make Flags a comma separated list * Move to use the windows constant for ENABLE_VIRTUAL_TERMINAL_PROCESSING * Ensure matching is done on the non-colored message - to simpify EXPRESSION
6 years ago
10 years ago
9 years ago
Add lang specific font stacks for CJK (#6007) * Add lang specific font stacks * Force font changes Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix icons Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix octicons and icons Signed-off-by: Andrew Thornton <art27@cantab.net> * Just override the semantic ui fonts only Signed-off-by: Andrew Thornton <art27@cantab.net> * Missed the headers... override them too * Missed some more semantic ui stuff * Fix PT Sans Signed-off-by: Andrew Thornton <art27@cantab.net> * More changes Signed-off-by: Andrew Thornton <art27@cantab.net> * Squashed commit of the following: commit 7d1679e9079541359869c9e677ba7412bfcc59f3 Author: Mike L <cl.jeremy@qq.com> Date: Wed Mar 13 13:53:49 2019 +0100 Remove missed YaHei leftover from _home.less commit 0079121ea91860a323ed4e5cc1a9c0d490d9cefd Author: Mike L <cl.jeremy@qq.com> Date: Wed Mar 13 12:03:54 2019 +0100 Fix overdone fixes (inherit, :lang) commit 62c919915928ec1db4731d547e95885f91a0618d Author: Mike L <cl.jeremy@qq.com> Date: Wed Mar 13 02:29:10 2019 +0100 Fix elements w/ explicit lang (language chooser) commit b3117587aa2eb8570d60bed583a11ee5565418be Author: Mike L <cl.jeremy@qq.com> Date: Tue Mar 12 20:17:26 2019 +0100 Fix textarea also (to match body) commit 81cedf2c3012c4dd05a7680782b4a98e1b947f67 Author: Mike L <cl.jeremy@qq.com> Date: Tue Mar 12 19:41:39 2019 +0100 Revert css temporarily to fix conflict commit 80ff82797f3203cbeaf866f22e961334e137df89 Author: Mike L <cl.jeremy@qq.com> Date: Tue Mar 12 19:15:30 2019 +0100 Tweak CJK, fix Yu Gothic, more monospace inherits commit 581dceb9a869646c2c486dabb925c88c2680d70c Author: Mike L <cl.jeremy@qq.com> Date: Mon Mar 11 13:09:26 2019 +0100 Add Lato for latin extd. & cyrillic, improve CJK * update stylesheet
6 years ago
11 years ago
10 years ago
11 years ago
3 years ago
11 years ago
11 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2020 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package context
  6. import (
  7. "html"
  8. "html/template"
  9. "io"
  10. "net/http"
  11. "net/url"
  12. "path"
  13. "strings"
  14. "time"
  15. "code.gitea.io/gitea/routers/notice"
  16. "code.gitea.io/gitea/models"
  17. "code.gitea.io/gitea/modules/auth"
  18. "code.gitea.io/gitea/modules/base"
  19. "code.gitea.io/gitea/modules/log"
  20. "code.gitea.io/gitea/modules/setting"
  21. "code.gitea.io/gitea/modules/util"
  22. "gitea.com/macaron/cache"
  23. "gitea.com/macaron/csrf"
  24. "gitea.com/macaron/i18n"
  25. "gitea.com/macaron/macaron"
  26. "gitea.com/macaron/session"
  27. "github.com/unknwon/com"
  28. )
  29. // Context represents context of a request.
  30. type Context struct {
  31. *macaron.Context
  32. Cache cache.Cache
  33. csrf csrf.CSRF
  34. Flash *session.Flash
  35. Session session.Store
  36. Link string // current request URL
  37. EscapedLink string
  38. User *models.User
  39. IsSigned bool
  40. IsBasicAuth bool
  41. Repo *Repository
  42. Org *Organization
  43. Cloudbrain *models.Cloudbrain
  44. }
  45. // IsUserSiteAdmin returns true if current user is a site admin
  46. func (ctx *Context) IsUserSiteAdmin() bool {
  47. return ctx.IsSigned && ctx.User.IsAdmin
  48. }
  49. // IsUserRepoOwner returns true if current user owns current repo
  50. func (ctx *Context) IsUserRepoOwner() bool {
  51. return ctx.Repo.IsOwner()
  52. }
  53. // IsUserRepoAdmin returns true if current user is admin in current repo
  54. func (ctx *Context) IsUserRepoAdmin() bool {
  55. return ctx.Repo.IsAdmin()
  56. }
  57. // IsUserRepoWriter returns true if current user has write privilege in current repo
  58. func (ctx *Context) IsUserRepoWriter(unitTypes []models.UnitType) bool {
  59. for _, unitType := range unitTypes {
  60. if ctx.Repo.CanWrite(unitType) {
  61. return true
  62. }
  63. }
  64. return false
  65. }
  66. // IsUserRepoReaderSpecific returns true if current user can read current repo's specific part
  67. func (ctx *Context) IsUserRepoReaderSpecific(unitType models.UnitType) bool {
  68. return ctx.Repo.CanRead(unitType)
  69. }
  70. // IsUserRepoReaderAny returns true if current user can read any part of current repo
  71. func (ctx *Context) IsUserRepoReaderAny() bool {
  72. return ctx.Repo.HasAccess()
  73. }
  74. // HasAPIError returns true if error occurs in form validation.
  75. func (ctx *Context) HasAPIError() bool {
  76. hasErr, ok := ctx.Data["HasError"]
  77. if !ok {
  78. return false
  79. }
  80. return hasErr.(bool)
  81. }
  82. // GetErrMsg returns error message
  83. func (ctx *Context) GetErrMsg() string {
  84. return ctx.Data["ErrorMsg"].(string)
  85. }
  86. // HasError returns true if error occurs in form validation.
  87. func (ctx *Context) HasError() bool {
  88. hasErr, ok := ctx.Data["HasError"]
  89. if !ok {
  90. return false
  91. }
  92. ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
  93. ctx.Data["Flash"] = ctx.Flash
  94. return hasErr.(bool)
  95. }
  96. // HasValue returns true if value of given name exists.
  97. func (ctx *Context) HasValue(name string) bool {
  98. _, ok := ctx.Data[name]
  99. return ok
  100. }
  101. // RedirectToFirst redirects to first not empty URL
  102. func (ctx *Context) RedirectToFirst(location ...string) {
  103. for _, loc := range location {
  104. if len(loc) == 0 {
  105. continue
  106. }
  107. u, err := url.Parse(loc)
  108. if err != nil || ((u.Scheme != "" || u.Host != "") && !strings.HasPrefix(strings.ToLower(loc), strings.ToLower(setting.AppURL))) {
  109. continue
  110. }
  111. ctx.Redirect(loc)
  112. return
  113. }
  114. ctx.Redirect(setting.AppSubURL + "/")
  115. }
  116. // HTML calls Context.HTML and converts template name to string.
  117. func (ctx *Context) HTML(status int, name base.TplName) {
  118. log.Debug("Template: %s", name)
  119. ctx.Context.HTML(status, string(name))
  120. }
  121. // RenderWithErr used for page has form validation but need to prompt error to users.
  122. func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
  123. if form != nil {
  124. auth.AssignForm(form, ctx.Data)
  125. }
  126. ctx.Flash.ErrorMsg = msg
  127. ctx.Data["Flash"] = ctx.Flash
  128. ctx.HTML(200, tpl)
  129. }
  130. // NotFound displays a 404 (Not Found) page and prints the given error, if any.
  131. func (ctx *Context) NotFound(title string, err error) {
  132. ctx.notFoundInternal(title, err)
  133. }
  134. func (ctx *Context) notFoundInternal(title string, err error) {
  135. if err != nil {
  136. log.ErrorWithSkip(2, "%s: %v", title, err)
  137. if macaron.Env != macaron.PROD {
  138. ctx.Data["ErrorMsg"] = err
  139. }
  140. }
  141. ctx.Data["IsRepo"] = ctx.Repo.Repository != nil
  142. ctx.Data["Title"] = "Page Not Found"
  143. ctx.HTML(http.StatusNotFound, base.TplName("status/404"))
  144. }
  145. // ServerError displays a 500 (Internal Server Error) page and prints the given
  146. // error, if any.
  147. func (ctx *Context) ServerError(title string, err error) {
  148. ctx.serverErrorInternal(title, err)
  149. }
  150. func (ctx *Context) serverErrorInternal(title string, err error) {
  151. if err != nil {
  152. log.ErrorWithSkip(2, "%s: %v", title, err)
  153. if macaron.Env != macaron.PROD {
  154. ctx.Data["ErrorMsg"] = err
  155. }
  156. }
  157. ctx.Data["Title"] = "Internal Server Error"
  158. ctx.HTML(http.StatusInternalServerError, base.TplName("status/500"))
  159. }
  160. // NotFoundOrServerError use error check function to determine if the error
  161. // is about not found. It responses with 404 status code for not found error,
  162. // or error context description for logging purpose of 500 server error.
  163. func (ctx *Context) NotFoundOrServerError(title string, errck func(error) bool, err error) {
  164. if errck(err) {
  165. ctx.notFoundInternal(title, err)
  166. return
  167. }
  168. ctx.serverErrorInternal(title, err)
  169. }
  170. // HandleText handles HTTP status code
  171. func (ctx *Context) HandleText(status int, title string) {
  172. if (status/100 == 4) || (status/100 == 5) {
  173. log.Error("%s", title)
  174. }
  175. ctx.PlainText(status, []byte(title))
  176. }
  177. // ServeContent serves content to http request
  178. func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
  179. modtime := time.Now()
  180. for _, p := range params {
  181. switch v := p.(type) {
  182. case time.Time:
  183. modtime = v
  184. }
  185. }
  186. ctx.Resp.Header().Set("Content-Description", "File Transfer")
  187. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  188. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
  189. ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
  190. ctx.Resp.Header().Set("Expires", "0")
  191. ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
  192. ctx.Resp.Header().Set("Pragma", "public")
  193. http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
  194. }
  195. // Contexter initializes a classic context for a request.
  196. func Contexter() macaron.Handler {
  197. return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
  198. ctx := &Context{
  199. Context: c,
  200. Cache: cache,
  201. csrf: x,
  202. Flash: f,
  203. Session: sess,
  204. Link: setting.AppSubURL + strings.TrimSuffix(c.Req.URL.EscapedPath(), "/"),
  205. Repo: &Repository{
  206. PullRequest: &PullRequest{},
  207. },
  208. Org: &Organization{},
  209. }
  210. ctx.Data["Language"] = ctx.Locale.Language()
  211. c.Data["Link"] = ctx.Link
  212. ctx.Data["PageStartTime"] = time.Now()
  213. // Quick responses appropriate go-get meta with status 200
  214. // regardless of if user have access to the repository,
  215. // or the repository does not exist at all.
  216. // This is particular a workaround for "go get" command which does not respect
  217. // .netrc file.
  218. if ctx.Query("go-get") == "1" {
  219. ownerName := c.Params(":username")
  220. repoName := c.Params(":reponame")
  221. trimmedRepoName := strings.TrimSuffix(repoName, ".git")
  222. if ownerName == "" || trimmedRepoName == "" {
  223. _, _ = c.Write([]byte(`<!doctype html>
  224. <html>
  225. <body>
  226. invalid import path
  227. </body>
  228. </html>
  229. `))
  230. c.WriteHeader(400)
  231. return
  232. }
  233. branchName := "master"
  234. repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
  235. if err == nil && len(repo.DefaultBranch) > 0 {
  236. branchName = repo.DefaultBranch
  237. }
  238. prefix := setting.AppURL + path.Join(url.PathEscape(ownerName), url.PathEscape(repoName), "src", "branch", util.PathEscapeSegments(branchName))
  239. appURL, _ := url.Parse(setting.AppURL)
  240. insecure := ""
  241. if appURL.Scheme == string(setting.HTTP) {
  242. insecure = "--insecure "
  243. }
  244. c.Header().Set("Content-Type", "text/html")
  245. c.WriteHeader(http.StatusOK)
  246. _, _ = c.Write([]byte(com.Expand(`<!doctype html>
  247. <html>
  248. <head>
  249. <meta name="go-import" content="{GoGetImport} git {CloneLink}">
  250. <meta name="go-source" content="{GoGetImport} _ {GoDocDirectory} {GoDocFile}">
  251. </head>
  252. <body>
  253. go get {Insecure}{GoGetImport}
  254. </body>
  255. </html>
  256. `, map[string]string{
  257. "GoGetImport": ComposeGoGetImport(ownerName, trimmedRepoName),
  258. "CloneLink": models.ComposeHTTPSCloneURL(ownerName, repoName),
  259. "GoDocDirectory": prefix + "{/dir}",
  260. "GoDocFile": prefix + "{/dir}/{file}#L{line}",
  261. "Insecure": insecure,
  262. })))
  263. return
  264. }
  265. // Get user from session if logged in.
  266. ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)
  267. if ctx.User != nil {
  268. ctx.IsSigned = true
  269. ctx.Data["IsSigned"] = ctx.IsSigned
  270. ctx.Data["SignedUser"] = ctx.User
  271. ctx.Data["SignedUserID"] = ctx.User.ID
  272. ctx.Data["SignedUserName"] = ctx.User.Name
  273. ctx.Data["IsAdmin"] = ctx.User.IsAdmin
  274. ctx.Data["IsOperator"] = ctx.User.IsOperator
  275. c.Data["SignedUserName"] = ctx.User.Name
  276. } else {
  277. ctx.Data["SignedUserID"] = int64(0)
  278. ctx.Data["SignedUserName"] = ""
  279. c.Data["SignedUserName"] = ""
  280. }
  281. // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
  282. if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
  283. if err := ctx.Req.ParseMultipartForm(setting.Attachment.MaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
  284. ctx.ServerError("ParseMultipartForm", err)
  285. return
  286. }
  287. }
  288. //ctx.Resp.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)
  289. ctx.Data["CsrfToken"] = html.EscapeString(x.GetToken())
  290. ctx.Data["CsrfTokenHtml"] = template.HTML(`<input type="hidden" name="_csrf" value="` + ctx.Data["CsrfToken"].(string) + `">`)
  291. log.Debug("Session ID: %s", sess.ID())
  292. log.Debug("CSRF Token: %v", ctx.Data["CsrfToken"])
  293. ctx.Data["IsLandingPageHome"] = setting.LandingPageURL == setting.LandingPageHome
  294. ctx.Data["IsLandingPageExplore"] = setting.LandingPageURL == setting.LandingPageExplore
  295. ctx.Data["IsLandingPageOrganizations"] = setting.LandingPageURL == setting.LandingPageOrganizations
  296. ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
  297. ctx.Data["ShowMilestonesDashboardPage"] = setting.Service.ShowMilestonesDashboardPage
  298. ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
  299. ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion
  300. ctx.Data["EnableSwagger"] = setting.API.EnableSwagger
  301. ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn
  302. notices, _ := notice.GetNewestNotice()
  303. if notices != nil {
  304. ctx.Data["notices"] = notices
  305. }
  306. c.Map(ctx)
  307. }
  308. }
  309. // CheckWechatBind
  310. func (ctx *Context) CheckWechatBind() {
  311. if !setting.WechatAuthSwitch || ctx.User.IsBindWechat() {
  312. return
  313. }
  314. redirectUrl := ctx.Query("redirect_to")
  315. if redirectUrl == "" {
  316. redirectUrl = ctx.Req.URL.RequestURI()
  317. }
  318. ctx.SetCookie("redirect_to", setting.AppSubURL+redirectUrl, 0, setting.AppSubURL)
  319. ctx.JSON(200, map[string]string{
  320. "WechatRedirectUrl": setting.AppSubURL + "/authentication/wechat/bind",
  321. })
  322. }