From f9c07c4186b61a1548d9a908fe6228bd130f4f92 Mon Sep 17 00:00:00 2001 From: slene Date: Sat, 22 Mar 2014 20:49:53 +0800 Subject: update session --- routers/user/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'routers/user/user.go') diff --git a/routers/user/user.go b/routers/user/user.go index d38eb1ce..22446977 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -88,7 +88,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { user, err := models.LoginUserPlain(form.UserName, form.Password) if err != nil { - if err.Error() == models.ErrUserNotExist.Error() { + if err == models.ErrUserNotExist { ctx.RenderWithErr("Username or password is not correct", "user/signin", &form) return } -- cgit v1.2.3 From cb52f6d07d62925a31185fedf591d0241ee2bf63 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 22 Mar 2014 16:40:09 -0400 Subject: Add auto-login --- conf/app.ini | 4 ++++ modules/auth/auth.go | 1 + modules/base/conf.go | 8 ++++++++ modules/middleware/context.go | 43 +++++++++++++++++++++++++++++++++++++++++++ routers/user/user.go | 42 +++++++++++++++++++++++++++++++++++++++++- templates/user/signin.tmpl | 11 +++++++++++ 6 files changed, 108 insertions(+), 1 deletion(-) (limited to 'routers/user/user.go') diff --git a/conf/app.ini b/conf/app.ini index ec5fcb23..7f283012 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -34,6 +34,10 @@ PATH = data/gogs.db [security] ; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! SECRET_KEY = !#@FDEWREWR&*( +; Auto-login remember days +LOGIN_REMEMBER_DAYS = 7 +COOKIE_USERNAME = gogs_awesome +COOKIE_REMEMBER_NAME = gogs_incredible [service] ACTIVE_CODE_LIVE_MINUTES = 180 diff --git a/modules/auth/auth.go b/modules/auth/auth.go index 0e871688..2e0555f6 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -61,6 +61,7 @@ func (f *RegisterForm) Validate(errors *binding.Errors, req *http.Request, conte type LogInForm struct { UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"` Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` + Remember string `form:"remember"` } func (f *LogInForm) Name(field string) string { diff --git a/modules/base/conf.go b/modules/base/conf.go index 7c8ed936..cdbe2b36 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -38,6 +38,10 @@ var ( RunUser string RepoRootPath string + LogInRememberDays int + CookieUserName string + CookieRememberName string + Cfg *goconfig.ConfigFile MailService *Mailer @@ -252,6 +256,10 @@ func NewConfigContext() { SecretKey = Cfg.MustValue("security", "SECRET_KEY") RunUser = Cfg.MustValue("", "RUN_USER") + LogInRememberDays = Cfg.MustInt("security", "LOGIN_REMEMBER_DAYS") + CookieUserName = Cfg.MustValue("security", "COOKIE_USERNAME") + CookieRememberName = Cfg.MustValue("security", "COOKIE_REMEMBER_NAME") + PictureService = Cfg.MustValue("picture", "SERVICE") PictureRootPath = Cfg.MustValue("picture", "PATH") diff --git a/modules/middleware/context.go b/modules/middleware/context.go index 5727b4f0..d81ab999 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -5,9 +5,14 @@ package middleware import ( + "crypto/hmac" + "crypto/sha1" + "encoding/base64" "fmt" "html/template" "net/http" + "strconv" + "strings" "time" "github.com/codegangsta/martini" @@ -155,6 +160,44 @@ func (ctx *Context) SetCookie(name string, value string, others ...interface{}) ctx.Res.Header().Add("Set-Cookie", cookie.String()) } +// Get secure cookie from request by a given key. +func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) { + val := ctx.GetCookie(key) + if val == "" { + return "", false + } + + parts := strings.SplitN(val, "|", 3) + + if len(parts) != 3 { + return "", false + } + + vs := parts[0] + timestamp := parts[1] + sig := parts[2] + + h := hmac.New(sha1.New, []byte(Secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + + if fmt.Sprintf("%02x", h.Sum(nil)) != sig { + return "", false + } + res, _ := base64.URLEncoding.DecodeString(vs) + return string(res), true +} + +// Set Secure cookie for response. +func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) { + vs := base64.URLEncoding.EncodeToString([]byte(value)) + timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) + h := hmac.New(sha1.New, []byte(Secret)) + fmt.Fprintf(h, "%s%s", vs, timestamp) + sig := fmt.Sprintf("%02x", h.Sum(nil)) + cookie := strings.Join([]string{vs, timestamp, sig}, "|") + ctx.SetCookie(name, cookie, others...) +} + func (ctx *Context) CsrfToken() string { if len(ctx.csrfToken) > 0 { return ctx.csrfToken diff --git a/routers/user/user.go b/routers/user/user.go index 22446977..56bc5f8e 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -77,7 +77,39 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { ctx.Data["Title"] = "Log In" if ctx.Req.Method == "GET" { - ctx.HTML(200, "user/signin") + // Check auto-login. + userName := ctx.GetCookie(base.CookieUserName) + if len(userName) == 0 { + ctx.HTML(200, "user/signin") + return + } + + isSucceed := false + defer func() { + if !isSucceed { + log.Trace("%s auto-login cookie cleared: %s", ctx.Req.RequestURI, userName) + ctx.SetCookie(base.CookieUserName, "", -1) + ctx.SetCookie(base.CookieRememberName, "", -1) + } + }() + + user, err := models.GetUserByName(userName) + if err != nil { + ctx.HTML(200, "user/signin") + return + } + + secret := base.EncodeMd5(user.Rands + user.Passwd) + value, _ := ctx.GetSecureCookie(secret, base.CookieRememberName) + if value != user.Name { + ctx.HTML(200, "user/signin") + return + } + + isSucceed = true + ctx.Session.Set("userId", user.Id) + ctx.Session.Set("userName", user.Name) + ctx.Redirect("/") return } @@ -89,6 +121,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { user, err := models.LoginUserPlain(form.UserName, form.Password) if err != nil { if err == models.ErrUserNotExist { + log.Trace("%s Log in failed: %s/%s", ctx.Req.RequestURI, form.UserName, form.Password) ctx.RenderWithErr("Username or password is not correct", "user/signin", &form) return } @@ -97,6 +130,13 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { return } + if form.Remember == "on" { + secret := base.EncodeMd5(user.Rands + user.Passwd) + days := 86400 * base.LogInRememberDays + ctx.SetCookie(base.CookieUserName, user.Name, days) + ctx.SetSecureCookie(secret, base.CookieRememberName, user.Name, days) + } + ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) ctx.Redirect("/") diff --git a/templates/user/signin.tmpl b/templates/user/signin.tmpl index 8dc7292f..1cd3275c 100644 --- a/templates/user/signin.tmpl +++ b/templates/user/signin.tmpl @@ -19,6 +19,17 @@ +
+
+
+ +
+
+
+
-- cgit v1.2.3 From 7356153ba3c19ff49f3ecfa28bac0b8bb38eccb9 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 22 Mar 2014 17:59:22 -0400 Subject: Batch updates --- README.md | 4 ++-- conf/app.ini | 10 ++++++++-- modules/base/conf.go | 4 ++++ modules/middleware/auth.go | 3 +++ routers/admin/user.go | 2 +- routers/repo/issue.go | 2 +- routers/repo/repo.go | 8 ++++---- routers/user/user.go | 21 ++++++++++++++++++--- 8 files changed, 41 insertions(+), 13 deletions(-) (limited to 'routers/user/user.go') diff --git a/README.md b/README.md index 89a346d6..325c3a97 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ There are two ways to install Gogs: ## Acknowledgments - Logo is inspired by [martini](https://github.com/martini-contrib). -- Mail Service is based on [WeTalk](https://github.com/beego/wetalk). -- System Monitor Status is based on [GoBlog](https://github.com/fuxiaohei/goblog). +- Mail Service, modules design is inspired by [WeTalk](https://github.com/beego/wetalk). +- System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog). ## Contributors diff --git a/conf/app.ini b/conf/app.ini index 7f283012..b051557f 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -107,7 +107,7 @@ SERVICE = server PATH = data/pictures [log] -; Either "console", "file", "conn" or "smtp", default is "console" +; Either "console", "file", "conn", "smtp" or "database", default is "console" MODE = console ; Buffer length of channel, keep it as it is if you don't know what it is. BUFFER_LEN = 10000 @@ -156,4 +156,10 @@ HOST = USER = PASSWD = ; Receivers, can be one or more, e.g. ["1@example.com","2@example.com"] -RECEIVERS = \ No newline at end of file +RECEIVERS = + +; For "database" mode only +[log.database] +LEVEL = +Driver = +CONN = \ No newline at end of file diff --git a/modules/base/conf.go b/modules/base/conf.go index cdbe2b36..19f58707 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -143,6 +143,10 @@ func newLogService() { Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"), Cfg.MustValue(modeSec, "RECEIVERS", "[]"), Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve")) + case "database": + LogConfig = fmt.Sprintf(`{"level":%s,"driver":%s,"conn":%s}`, level, + Cfg.MustValue(modeSec, "Driver"), + Cfg.MustValue(modeSec, "CONN")) } log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), LogMode, LogConfig) diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go index 3224b3df..82c3367c 100644 --- a/modules/middleware/auth.go +++ b/modules/middleware/auth.go @@ -5,6 +5,8 @@ package middleware import ( + "net/url" + "github.com/codegangsta/martini" "github.com/gogits/gogs/modules/base" @@ -35,6 +37,7 @@ func Toggle(options *ToggleOptions) martini.Handler { if options.SignInRequire { if !ctx.IsSigned { + ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI)) ctx.Redirect("/user/login") return } else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm { diff --git a/routers/admin/user.go b/routers/admin/user.go index fa27d116..7f66c552 100644 --- a/routers/admin/user.go +++ b/routers/admin/user.go @@ -140,5 +140,5 @@ func DeleteUser(ctx *middleware.Context, params martini.Params) { log.Trace("%s User deleted by admin(%s): %s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.User.LowerName) - ctx.Redirect("/admin/users", 302) + ctx.Redirect("/admin/users") } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 154e8308..4cc007e9 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -56,7 +56,7 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat form.IssueName, form.Labels, form.Content, false) if err == nil { log.Trace("%s Issue created: %d", form.RepoId, issue.Id) - ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", params["username"], params["reponame"], issue.Index), 302) + ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", params["username"], params["reponame"], issue.Index)) return } ctx.Handle(200, "issue.CreateIssue", err) diff --git a/routers/repo/repo.go b/routers/repo/repo.go index c436d387..4782d64f 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -40,7 +40,7 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) { form.Language, form.License, form.Visibility == "private", form.InitReadme == "on") if err == nil { log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName) - ctx.Redirect("/"+ctx.User.Name+"/"+form.RepoName, 302) + ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName) return } else if err == models.ErrRepoAlreadyExist { ctx.RenderWithErr("Repository name has already been used", "repo/create", &form) @@ -73,7 +73,7 @@ func SettingPost(ctx *middleware.Context) { } log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName) - ctx.Redirect("/", 302) + ctx.Redirect("/") } func Branches(ctx *middleware.Context, params martini.Params) { @@ -113,8 +113,8 @@ func Single(ctx *middleware.Context, params martini.Params) { treename := params["_1"] if len(treename) > 0 && treename[len(treename)-1] == '/' { - ctx.Redirect("/"+ctx.Repo.Owner.LowerName+"/"+ - ctx.Repo.Repository.Name+"/src/"+params["branchname"]+"/"+treename[:len(treename)-1], 302) + ctx.Redirect("/" + ctx.Repo.Owner.LowerName + "/" + + ctx.Repo.Repository.Name + "/src/" + params["branchname"] + "/" + treename[:len(treename)-1]) return } diff --git a/routers/user/user.go b/routers/user/user.go index 56bc5f8e..c34b529e 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -6,6 +6,7 @@ package user import ( "fmt" + "net/url" "strings" "github.com/codegangsta/martini" @@ -109,7 +110,13 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { isSucceed = true ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) - ctx.Redirect("/") + redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")) + if len(redirectTo) > 0 { + ctx.SetCookie("redirect_to", "", -1) + ctx.Redirect(redirectTo) + } else { + ctx.Redirect("/") + } return } @@ -139,12 +146,20 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) - ctx.Redirect("/") + redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")) + if len(redirectTo) > 0 { + ctx.SetCookie("redirect_to", "", -1) + ctx.Redirect(redirectTo) + } else { + ctx.Redirect("/") + } } func SignOut(ctx *middleware.Context) { ctx.Session.Delete("userId") ctx.Session.Delete("userName") + ctx.SetCookie(base.CookieUserName, "", -1) + ctx.SetCookie(base.CookieRememberName, "", -1) ctx.Redirect("/") } @@ -314,7 +329,7 @@ func Activate(ctx *middleware.Context) { ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) - ctx.Redirect("/", 302) + ctx.Redirect("/") return } -- cgit v1.2.3 From 47493a0191f3de8aa4e80bce1911f14623cfa46a Mon Sep 17 00:00:00 2001 From: FuXiaoHei Date: Sun, 23 Mar 2014 13:12:55 +0800 Subject: use ctx.Handle to handle 404 page --- routers/repo/issue.go | 6 +++--- routers/repo/repo.go | 32 ++++++++++++++++---------------- routers/user/user.go | 2 +- templates/status/404.tmpl | 7 +++++++ templates/status/500.tmpl | 7 +++++++ 5 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 templates/status/404.tmpl create mode 100644 templates/status/500.tmpl (limited to 'routers/user/user.go') diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 4cc007e9..78fe4b25 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -36,7 +36,7 @@ func Issues(ctx *middleware.Context, params martini.Params) { func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) { if !ctx.Repo.IsOwner { - ctx.Error(404) + ctx.Handle(404, "issue.CreateIssue", nil) return } @@ -65,14 +65,14 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat func ViewIssue(ctx *middleware.Context, params martini.Params) { issueid, err := base.StrTo(params["issueid"]).Int() if err != nil { - ctx.Error(404) + ctx.Handle(404, "issue.ViewIssue", err) return } issue, err := models.GetIssueById(int64(issueid)) if err != nil { if err == models.ErrIssueNotExist { - ctx.Error(404) + ctx.Handle(404, "issue.ViewIssue", err) } else { ctx.Handle(200, "issue.ViewIssue", err) } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 4782d64f..0f1ea312 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -86,7 +86,7 @@ func Branches(ctx *middleware.Context, params martini.Params) { ctx.Handle(200, "repo.Branches", err) return } else if len(brs) == 0 { - ctx.Error(404) + ctx.Handle(404, "repo.Branches", nil) return } @@ -123,8 +123,8 @@ func Single(ctx *middleware.Context, params martini.Params) { // Branches. brs, err := models.GetBranches(params["username"], params["reponame"]) if err != nil { - log.Error("repo.Single(GetBranches): %v", err) - ctx.Error(404) + //log.Error("repo.Single(GetBranches): %v", err) + ctx.Handle(404, "repo.Single(GetBranches)", err) return } else if ctx.Repo.Repository.IsBare { ctx.Data["IsBareRepo"] = true @@ -138,15 +138,15 @@ func Single(ctx *middleware.Context, params martini.Params) { params["branchname"], params["commitid"], treename) if err != nil && err != models.ErrRepoFileNotExist { - log.Error("repo.Single(GetTargetFile): %v", err) - ctx.Error(404) + //log.Error("repo.Single(GetTargetFile): %v", err) + ctx.Handle(404, "repo.Single(GetTargetFile)", err) return } branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"] if len(treename) != 0 && repoFile == nil { - ctx.Error(404) + ctx.Handle(404, "repo.Single", nil) return } @@ -154,8 +154,8 @@ func Single(ctx *middleware.Context, params martini.Params) { if repoFile.Size > 1024*1024 || repoFile.Filemode != git.FileModeBlob { ctx.Data["FileIsLarge"] = true } else if blob, err := repoFile.LookupBlob(); err != nil { - log.Error("repo.Single(repoFile.LookupBlob): %v", err) - ctx.Error(404) + //log.Error("repo.Single(repoFile.LookupBlob): %v", err) + ctx.Handle(404, "repo.Single(repoFile.LookupBlob)", err) } else { ctx.Data["IsFile"] = true ctx.Data["FileName"] = repoFile.Name @@ -179,8 +179,8 @@ func Single(ctx *middleware.Context, params martini.Params) { files, err := models.GetReposFiles(params["username"], params["reponame"], params["branchname"], params["commitid"], treename) if err != nil { - log.Error("repo.Single(GetReposFiles): %v", err) - ctx.Error(404) + //log.Error("repo.Single(GetReposFiles): %v", err) + ctx.Handle(404, "repo.Single(GetReposFiles)", err) return } @@ -203,8 +203,8 @@ func Single(ctx *middleware.Context, params martini.Params) { if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob { ctx.Data["FileIsLarge"] = true } else if blob, err := readmeFile.LookupBlob(); err != nil { - log.Error("repo.Single(readmeFile.LookupBlob): %v", err) - ctx.Error(404) + //log.Error("repo.Single(readmeFile.LookupBlob): %v", err) + ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err) return } else { // current repo branch link @@ -239,7 +239,7 @@ func Single(ctx *middleware.Context, params martini.Params) { params["branchname"], params["commitid"]) if err != nil { log.Error("repo.Single(GetCommit): %v", err) - ctx.Error(404) + ctx.Handle(404, "repo.Single(GetCommit)", err) return } ctx.Data["LastCommit"] = commit @@ -275,7 +275,7 @@ func Http(ctx *middleware.Context, params martini.Params) { func Setting(ctx *middleware.Context, params martini.Params) { if !ctx.Repo.IsOwner { - ctx.Error(404) + ctx.Handle(404, "repo.Setting", nil) return } @@ -307,7 +307,7 @@ func Commits(ctx *middleware.Context, params martini.Params) { ctx.Handle(200, "repo.Commits", err) return } else if len(brs) == 0 { - ctx.Error(404) + ctx.Handle(404, "repo.Commits", nil) return } @@ -315,7 +315,7 @@ func Commits(ctx *middleware.Context, params martini.Params) { commits, err := models.GetCommits(params["username"], params["reponame"], params["branchname"]) if err != nil { - ctx.Error(404) + ctx.Handle(404, "repo.Commits", nil) return } ctx.Data["Username"] = params["username"] diff --git a/routers/user/user.go b/routers/user/user.go index c34b529e..a0321f18 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -301,7 +301,7 @@ func Activate(ctx *middleware.Context) { if len(code) == 0 { ctx.Data["IsActivatePage"] = true if ctx.User.IsActive { - ctx.Error(404) + ctx.Handle(404, "user.Activate", nil) return } // Resend confirmation e-mail. diff --git a/templates/status/404.tmpl b/templates/status/404.tmpl new file mode 100644 index 00000000..4e836b22 --- /dev/null +++ b/templates/status/404.tmpl @@ -0,0 +1,7 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+

This page is not found !

+

Application Version: {{AppVer}}

+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/status/500.tmpl b/templates/status/500.tmpl new file mode 100644 index 00000000..9a00eb1f --- /dev/null +++ b/templates/status/500.tmpl @@ -0,0 +1,7 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+

An error is occurred : {{.ErrorMsg}}

+

Application Version: {{AppVer}}

+
+{{template "base/footer" .}} \ No newline at end of file -- cgit v1.2.3