From 7a1ff8636c01844a501dd9cdca2c436d1b7826b7 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 22 Mar 2014 06:42:19 -0400 Subject: Add config option: Picture cache path --- modules/base/conf.go | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'modules/base/conf.go') diff --git a/modules/base/conf.go b/modules/base/conf.go index 863daca6..8c6ee628 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -44,6 +44,9 @@ var ( CacheAdapter string CacheConfig string + PictureService string + PictureRootPath string + LogMode string LogConfig string ) @@ -52,6 +55,7 @@ var Service struct { RegisterEmailConfirm bool DisenableRegisteration bool RequireSignInView bool + EnableCacheAvatar bool ActiveCodeLives int ResetPwdCodeLives int } @@ -82,6 +86,7 @@ func newService() { Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180) Service.DisenableRegisteration = Cfg.MustBool("service", "DISENABLE_REGISTERATION", false) Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW", false) + Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR", false) } func newLogService() { @@ -214,6 +219,9 @@ func NewConfigContext() { SecretKey = Cfg.MustValue("security", "SECRET_KEY") RunUser = Cfg.MustValue("", "RUN_USER") + PictureService = Cfg.MustValue("picture", "SERVICE") + PictureRootPath = Cfg.MustValue("picture", "PATH") + // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { -- cgit v1.2.3 From f9c07c4186b61a1548d9a908fe6228bd130f4f92 Mon Sep 17 00:00:00 2001 From: slene Date: Sat, 22 Mar 2014 20:49:53 +0800 Subject: update session --- .gitignore | 1 + conf/app.ini | 27 +++++++++++++++++++++++++++ modules/auth/user.go | 11 ++++++----- modules/base/conf.go | 30 ++++++++++++++++++++++++++++++ modules/middleware/context.go | 24 ++++++++++++++---------- routers/user/user.go | 2 +- web.go | 5 ----- 7 files changed, 79 insertions(+), 21 deletions(-) (limited to 'modules/base/conf.go') diff --git a/.gitignore b/.gitignore index ad27cc8b..d201223e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ gogs *.db *.log custom/ +data/ .vendor/ .idea/ *.iml \ No newline at end of file diff --git a/conf/app.ini b/conf/app.ini index cf99c9da..cf2ae31d 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -72,6 +72,33 @@ INTERVAL = 60 ; memcache: "127.0.0.1:11211" HOST = +[session] +; Either "memory", "file", "redis" or "mysql", default is "memory" +PROVIDER = file +; provider config +; memory: not have any config yet +; file: session file path +; e.g. tmp/sessions +; redis: config like redis server addr,poolSize,password +; e.g. 127.0.0.1:6379,100,astaxie +; mysql: go-sql-driver/mysql dsn config string +; e.g. root:password@/session_table +PROVIDER_CONFIG = data/sessions +; session cookie name +COOKIE_NAME = i_like_gogits +; if you use session in https only, default is false +COOKIE_SECURE = false +; enable set cookie, default is true +ENABLE_SET_COOKIE = true +; session gc time interval, default is 86400 +GC_INTERVAL_TIME = 86400 +; session life time, default is 86400 +SESSION_LIFE_TIME = 86400 +; session id hash func, default is sha1 +SESSION_ID_HASHFUNC = sha1 +; session hash key, default is use random string +SESSION_ID_HASHKEY = + [picture] ; The place to picture data, either "server" or "qiniu", default is "server" SERVICE = server diff --git a/modules/auth/user.go b/modules/auth/user.go index f8d8f661..cb8db1b2 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -9,7 +9,8 @@ import ( "reflect" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" + + "github.com/gogits/session" "github.com/gogits/binding" @@ -19,7 +20,7 @@ import ( ) // SignedInId returns the id of signed in user. -func SignedInId(session sessions.Session) int64 { +func SignedInId(session session.SessionStore) int64 { userId := session.Get("userId") if userId == nil { return 0 @@ -34,7 +35,7 @@ func SignedInId(session sessions.Session) int64 { } // SignedInName returns the name of signed in user. -func SignedInName(session sessions.Session) string { +func SignedInName(session session.SessionStore) string { userName := session.Get("userName") if userName == nil { return "" @@ -46,7 +47,7 @@ func SignedInName(session sessions.Session) string { } // SignedInUser returns the user object of signed user. -func SignedInUser(session sessions.Session) *models.User { +func SignedInUser(session session.SessionStore) *models.User { id := SignedInId(session) if id <= 0 { return nil @@ -61,7 +62,7 @@ func SignedInUser(session sessions.Session) *models.User { } // IsSignedIn check if any user has signed in. -func IsSignedIn(session sessions.Session) bool { +func IsSignedIn(session session.SessionStore) bool { return SignedInId(session) > 0 } diff --git a/modules/base/conf.go b/modules/base/conf.go index 8c6ee628..d5e27d04 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -16,6 +16,7 @@ import ( "github.com/Unknwon/goconfig" "github.com/gogits/cache" + "github.com/gogits/session" "github.com/gogits/gogs/modules/log" ) @@ -49,6 +50,10 @@ var ( LogMode string LogConfig string + + SessionProvider string + SessionConfig *session.Config + SessionManager *session.Manager ) var Service struct { @@ -164,6 +169,30 @@ func newCacheService() { log.Info("Cache Service Enabled") } +func newSessionService() { + SessionProvider = Cfg.MustValue("session", "PROVIDER", "memory") + + SessionConfig = new(session.Config) + SessionConfig.ProviderConfig = Cfg.MustValue("session", "PROVIDER_CONFIG") + SessionConfig.CookieName = Cfg.MustValue("session", "COOKIE_NAME", "i_like_gogits") + SessionConfig.CookieSecure = Cfg.MustBool("session", "COOKIE_SECURE") + SessionConfig.EnableSetCookie = Cfg.MustBool("session", "ENABLE_SET_COOKIE", true) + SessionConfig.GcIntervalTime = Cfg.MustInt64("session", "GC_INTERVAL_TIME", 86400) + SessionConfig.SessionLifeTime = Cfg.MustInt64("session", "SESSION_LIFE_TIME", 86400) + SessionConfig.SessionIDHashFunc = Cfg.MustValue("session", "SESSION_ID_HASHFUNC", "sha1") + SessionConfig.SessionIDHashKey = Cfg.MustValue("session", "SESSION_ID_HASHKEY") + + var err error + SessionManager, err = session.NewManager(SessionProvider, *SessionConfig) + if err != nil { + fmt.Printf("Init session system failed, provider: %s, %v\n", + SessionProvider, err) + os.Exit(2) + } + + log.Info("Session Service Enabled") +} + func newMailService() { // Check mailer setting. if Cfg.MustBool("mailer", "ENABLED") { @@ -234,6 +263,7 @@ func NewServices() { newService() newLogService() newCacheService() + newSessionService() newMailService() newRegisterMailService() } diff --git a/modules/middleware/context.go b/modules/middleware/context.go index a25a3dbb..c958c1d6 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -10,9 +10,9 @@ import ( "time" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" "github.com/gogits/cache" + "github.com/gogits/session" "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" @@ -27,7 +27,7 @@ type Context struct { p martini.Params Req *http.Request Res http.ResponseWriter - Session sessions.Session + Session session.SessionStore Cache cache.Cache User *models.User IsSigned bool @@ -92,21 +92,25 @@ func (ctx *Context) Handle(status int, title string, err error) { // InitContext initializes a classic context for a request. func InitContext() martini.Handler { - return func(res http.ResponseWriter, r *http.Request, c martini.Context, - session sessions.Session, rd *Render) { + return func(res http.ResponseWriter, r *http.Request, c martini.Context, rd *Render) { ctx := &Context{ c: c, // p: p, - Req: r, - Res: res, - Session: session, - Cache: base.Cache, - Render: rd, + Req: r, + Res: res, + Cache: base.Cache, + Render: rd, } + // start session + ctx.Session = base.SessionManager.SessionStart(res, r) + defer func() { + ctx.Session.SessionRelease(res) + }() + // Get user from session if logined. - user := auth.SignedInUser(session) + user := auth.SignedInUser(ctx.Session) ctx.User = user ctx.IsSigned = user != nil 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 } diff --git a/web.go b/web.go index 595b8f74..ac5761d7 100644 --- a/web.go +++ b/web.go @@ -12,7 +12,6 @@ import ( "github.com/codegangsta/cli" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" "github.com/gogits/binding" @@ -81,10 +80,6 @@ func runWeb(*cli.Context) { // Middlewares. m.Use(middleware.Renderer(middleware.RenderOptions{Funcs: []template.FuncMap{base.TemplateFuncs}})) - // TODO: should use other store because cookie store is not secure. - store := sessions.NewCookieStore([]byte("secret123")) - m.Use(sessions.Sessions("my_session", store)) - m.Use(middleware.InitContext()) reqSignIn := middleware.SignInRequire(true) -- cgit v1.2.3 From fd1831052c3a79492643b89512282fc66f34dd8d Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 22 Mar 2014 09:21:57 -0400 Subject: Update session --- .gopmfile | 1 - README.md | 2 +- conf/app.ini | 25 ++++++------- gogs.go | 2 +- modules/base/conf.go | 16 +++++--- modules/base/tool.go | 84 +++++++++++++++++++++++++++++++++++++++++- routers/admin/admin.go | 12 +++++- templates/admin/config.tmpl | 19 ++++++++++ templates/admin/dashboard.tmpl | 1 + 9 files changed, 135 insertions(+), 27 deletions(-) (limited to 'modules/base/conf.go') diff --git a/.gopmfile b/.gopmfile index 5b690a06..6e6b59c6 100644 --- a/.gopmfile +++ b/.gopmfile @@ -4,7 +4,6 @@ path=github.com/gogits/gogs [deps] github.com/codegangsta/cli= github.com/codegangsta/martini= -github.com/martini-contrib/sessions= github.com/Unknwon/com= github.com/Unknwon/cae= github.com/Unknwon/goconfig= diff --git a/README.md b/README.md index a9ab7fe4..35044927 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ 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). +- Mail Service is based on [WeTalk](https://github.com/beego/wetalk). - System Monitor Status is based on [GoBlog](https://github.com/fuxiaohei/goblog). ## Contributors diff --git a/conf/app.ini b/conf/app.ini index cf2ae31d..30d6c7d4 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -75,28 +75,25 @@ HOST = [session] ; Either "memory", "file", "redis" or "mysql", default is "memory" PROVIDER = file -; provider config +; Provider config options ; memory: not have any config yet -; file: session file path -; e.g. tmp/sessions -; redis: config like redis server addr,poolSize,password -; e.g. 127.0.0.1:6379,100,astaxie -; mysql: go-sql-driver/mysql dsn config string -; e.g. root:password@/session_table +; file: session file path, e.g. data/sessions +; redis: config like redis server addr, poolSize, password, e.g. 127.0.0.1:6379,100,astaxie +; mysql: go-sql-driver/mysql dsn config string, e.g. root:password@/session_table PROVIDER_CONFIG = data/sessions -; session cookie name +; Session cookie name COOKIE_NAME = i_like_gogits -; if you use session in https only, default is false +; If you use session in https only, default is false COOKIE_SECURE = false -; enable set cookie, default is true +; Enable set cookie, default is true ENABLE_SET_COOKIE = true -; session gc time interval, default is 86400 +; Session GC time interval, default is 86400 GC_INTERVAL_TIME = 86400 -; session life time, default is 86400 +; Session life time, default is 86400 SESSION_LIFE_TIME = 86400 -; session id hash func, default is sha1 +; Session id hash func, default is sha1 SESSION_ID_HASHFUNC = sha1 -; session hash key, default is use random string +; Session hash key, default is use random string SESSION_ID_HASHKEY = [picture] diff --git a/gogs.go b/gogs.go index 8ec4fd42..a6090320 100644 --- a/gogs.go +++ b/gogs.go @@ -20,7 +20,7 @@ import ( // Test that go1.2 tag above is included in builds. main.go refers to this definition. const go12tag = true -const APP_VER = "0.1.5.0322" +const APP_VER = "0.1.5.0322.2" func init() { base.AppVer = APP_VER diff --git a/modules/base/conf.go b/modules/base/conf.go index d5e27d04..7c8ed936 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -41,19 +41,19 @@ var ( Cfg *goconfig.ConfigFile MailService *Mailer + LogMode string + LogConfig string + Cache cache.Cache CacheAdapter string CacheConfig string - PictureService string - PictureRootPath string - - LogMode string - LogConfig string - SessionProvider string SessionConfig *session.Config SessionManager *session.Manager + + PictureService string + PictureRootPath string ) var Service struct { @@ -182,6 +182,10 @@ func newSessionService() { SessionConfig.SessionIDHashFunc = Cfg.MustValue("session", "SESSION_ID_HASHFUNC", "sha1") SessionConfig.SessionIDHashKey = Cfg.MustValue("session", "SESSION_ID_HASHKEY") + if SessionProvider == "file" { + os.MkdirAll(path.Dir(SessionConfig.ProviderConfig), os.ModePerm) + } + var err error SessionManager, err = session.NewManager(SessionProvider, *SessionConfig) if err != nil { diff --git a/modules/base/tool.go b/modules/base/tool.go index 8fabb8c5..4f368aa5 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -111,6 +111,85 @@ const ( Year = 12 * Month ) +func computeTimeDiff(diff int64) (int64, string) { + diffStr := "" + switch { + case diff <= 0: + diff = 0 + diffStr = "now" + case diff < 2: + diff = 0 + diffStr = "1 second" + case diff < 1*Minute: + diffStr = fmt.Sprintf("%d seconds", diff) + diff = 0 + + case diff < 2*Minute: + diff -= 1 * Minute + diffStr = "1 minute" + case diff < 1*Hour: + diffStr = fmt.Sprintf("%d minutes", diff/Minute) + diff -= diff / Minute * Minute + + case diff < 2*Hour: + diff -= 1 * Hour + diffStr = "1 hour" + case diff < 1*Day: + diffStr = fmt.Sprintf("%d hours", diff/Hour) + diff -= diff / Hour * Hour + + case diff < 2*Day: + diff -= 1 * Day + diffStr = "1 day" + case diff < 1*Week: + diffStr = fmt.Sprintf("%d days", diff/Day) + diff -= diff / Day * Day + + case diff < 2*Week: + diff -= 1 * Week + diffStr = "1 week" + case diff < 1*Month: + diffStr = fmt.Sprintf("%d weeks", diff/Week) + diff -= diff / Week * Week + + case diff < 2*Month: + diff -= 1 * Month + diffStr = "1 month" + case diff < 1*Year: + diffStr = fmt.Sprintf("%d months", diff/Month) + diff -= diff / Month * Month + + case diff < 2*Year: + diff -= 1 * Year + diffStr = "1 year" + default: + diffStr = fmt.Sprintf("%d years", diff/Year) + diff = 0 + } + return diff, diffStr +} + +// TimeSincePro calculates the time interval and generate full user-friendly string. +func TimeSincePro(then time.Time) string { + now := time.Now() + diff := now.Unix() - then.Unix() + + if then.After(now) { + return "future" + } + + var timeStr, diffStr string + for { + if diff == 0 { + break + } + + diff, diffStr = computeTimeDiff(diff) + timeStr += ", " + diffStr + } + return strings.TrimPrefix(timeStr, ", ") +} + // TimeSince calculates the time interval and generate user-friendly string. func TimeSince(then time.Time) string { now := time.Now() @@ -123,7 +202,6 @@ func TimeSince(then time.Time) string { } switch { - case diff <= 0: return "now" case diff <= 2: @@ -156,8 +234,10 @@ func TimeSince(then time.Time) string { case diff < 1*Year: return fmt.Sprintf("%d months %s", diff/Month, lbl) - case diff < 18*Month: + case diff < 2*Year: return fmt.Sprintf("1 year %s", lbl) + default: + return fmt.Sprintf("%d years %s", diff/Year, lbl) } return then.String() } diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 57a46d1d..c0f39f71 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -17,7 +17,10 @@ import ( "github.com/gogits/gogs/modules/middleware" ) +var startTime = time.Now() + var sysStatus struct { + Uptime string NumGoroutine int // General statistics. @@ -58,6 +61,8 @@ var sysStatus struct { } func updateSystemStatus() { + sysStatus.Uptime = base.TimeSincePro(startTime) + m := new(runtime.MemStats) runtime.ReadMemStats(m) sysStatus.NumGoroutine = runtime.NumGoroutine() @@ -88,8 +93,8 @@ func updateSystemStatus() { sysStatus.NextGC = base.FileSize(int64(m.NextGC)) sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000) - sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs/1000/1000/1000)) - sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256]/1000/1000/1000)) + sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000) + sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000) sysStatus.NumGC = m.NumGC } @@ -151,6 +156,9 @@ func Config(ctx *middleware.Context) { ctx.Data["CacheAdapter"] = base.CacheAdapter ctx.Data["CacheConfig"] = base.CacheConfig + ctx.Data["SessionProvider"] = base.SessionProvider + ctx.Data["SessionConfig"] = base.SessionConfig + ctx.Data["PictureService"] = base.PictureService ctx.Data["PictureRootPath"] = base.PictureRootPath diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index e3f69ee6..048740e6 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -77,6 +77,25 @@ +
+
+ Session Configuration +
+ +
+
Session Provider: {{.SessionProvider}}
+
Cookie Name: {{.SessionConfig.CookieName}}
+
Enable Set Cookie:
+
GC Interval Time: {{.SessionConfig.GcIntervalTime}} seconds
+
Session Life Time: {{.SessionConfig.SessionLifeTime}} seconds
+
HTTPS Only:
+
Cookie Life Time: {{.SessionConfig.CookieLifeTime}} seconds
+
Session ID Hash Function: {{.SessionConfig.SessionIDHashFunc}}
+
Session ID Hash Key: {{.SessionConfig.SessionIDHashKey}}
+
Provider Config: {{.SessionConfig.ProviderConfig}}
+
+
+
Picture Configuration diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 0bebf831..2a5a161e 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -19,6 +19,7 @@
+
Server Uptime: {{.SysStatus.Uptime}}
Current Goroutines: {{.SysStatus.NumGoroutine}}

Current Memory Usage: {{.SysStatus.MemAllocated}}
-- 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 'modules/base/conf.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 'modules/base/conf.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