Commit 25751949 by Torkel Ödegaard

Worked on login remember cookie, and redirect after login

parent 6e5ef561
Subproject commit 11b74baf7920bcd4e39b5e77bfb49e6b08752dc2 Subproject commit 4572747bd60c688f7cc2cbf8a2303b9c95ad7b9d
package api package api
import ( import (
"net/url"
"github.com/torkelo/grafana-pro/pkg/api/dtos" "github.com/torkelo/grafana-pro/pkg/api/dtos"
"github.com/torkelo/grafana-pro/pkg/bus" "github.com/torkelo/grafana-pro/pkg/bus"
"github.com/torkelo/grafana-pro/pkg/log" "github.com/torkelo/grafana-pro/pkg/log"
"github.com/torkelo/grafana-pro/pkg/middleware" "github.com/torkelo/grafana-pro/pkg/middleware"
m "github.com/torkelo/grafana-pro/pkg/models" m "github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/setting"
"github.com/torkelo/grafana-pro/pkg/util" "github.com/torkelo/grafana-pro/pkg/util"
) )
const (
VIEW_INDEX = "index"
)
func LoginView(c *middleware.Context) { func LoginView(c *middleware.Context) {
if err := setIndexViewData(c); err != nil { if err := setIndexViewData(c); err != nil {
c.Handle(500, "Failed to get settings", err) c.Handle(500, "Failed to get settings", err)
return return
} }
c.HTML(200, "index") // Check auto-login.
uname := c.GetCookie(setting.CookieUserName)
if len(uname) == 0 {
c.HTML(200, VIEW_INDEX)
return
}
isSucceed := false
defer func() {
if !isSucceed {
log.Trace("auto-login cookie cleared: %s", uname)
c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/")
c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/")
return
}
}()
userQuery := m.GetUserByLoginQuery{LoginOrEmail: uname}
if err := bus.Dispatch(&userQuery); err != nil {
if err != m.ErrUserNotFound {
c.Handle(500, "GetUserByLoginQuery", err)
} else {
c.HTML(200, VIEW_INDEX)
}
return
}
user := userQuery.Result
if val, _ := c.GetSuperSecureCookie(
util.EncodeMd5(user.Rands+user.Password), setting.CookieRememberName); val != user.Login {
c.HTML(200, VIEW_INDEX)
return
}
isSucceed = true
loginUserWithUser(user, c)
if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 {
c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/")
c.Redirect(redirectTo)
return
}
c.Redirect(setting.AppSubUrl + "/")
} }
func LoginPost(c *middleware.Context, cmd dtos.LoginCommand) { func LoginPost(c *middleware.Context, cmd dtos.LoginCommand) {
...@@ -36,9 +87,27 @@ func LoginPost(c *middleware.Context, cmd dtos.LoginCommand) { ...@@ -36,9 +87,27 @@ func LoginPost(c *middleware.Context, cmd dtos.LoginCommand) {
return return
} }
// default to true here for now
cmd.Remember = true
if cmd.Remember {
days := 86400 * setting.LogInRememberDays
c.SetCookie(setting.CookieUserName, user.Login, days, setting.AppSubUrl+"/")
c.SetSuperSecureCookie(util.EncodeMd5(user.Rands+user.Password), setting.CookieRememberName, user.Login, days, setting.AppSubUrl+"/")
}
loginUserWithUser(user, c) loginUserWithUser(user, c)
c.JsonOK("User logged in") result := map[string]interface{}{
"message": "Logged in",
}
if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 {
result["redirectUrl"] = redirectTo
c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/")
}
c.JSON(200, result)
} }
func loginUserWithUser(user *m.User, c *middleware.Context) { func loginUserWithUser(user *m.User, c *middleware.Context) {
...@@ -50,6 +119,8 @@ func loginUserWithUser(user *m.User, c *middleware.Context) { ...@@ -50,6 +119,8 @@ func loginUserWithUser(user *m.User, c *middleware.Context) {
} }
func LogoutPost(c *middleware.Context) { func LogoutPost(c *middleware.Context) {
c.Session.Delete("userId") c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/")
c.JSON(200, util.DynMap{"status": "logged out"}) c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/")
c.Session.Destory(c.Context)
c.JsonOK("logged out")
} }
...@@ -12,6 +12,7 @@ func SignUp(c *middleware.Context, cmd m.CreateUserCommand) { ...@@ -12,6 +12,7 @@ func SignUp(c *middleware.Context, cmd m.CreateUserCommand) {
cmd.Login = cmd.Email cmd.Login = cmd.Email
cmd.Salt = util.GetRandomString(10) cmd.Salt = util.GetRandomString(10)
cmd.Rands = util.GetRandomString(10)
cmd.Password = util.EncodePassword(cmd.Password, cmd.Salt) cmd.Password = util.EncodePassword(cmd.Password, cmd.Salt)
if err := bus.Dispatch(&cmd); err != nil { if err := bus.Dispatch(&cmd); err != nil {
......
package middleware package middleware
import ( import (
"net/url"
"strings" "strings"
"github.com/Unknwon/macaron" "github.com/Unknwon/macaron"
"github.com/torkelo/grafana-pro/pkg/log"
m "github.com/torkelo/grafana-pro/pkg/models" m "github.com/torkelo/grafana-pro/pkg/models"
"github.com/torkelo/grafana-pro/pkg/setting" "github.com/torkelo/grafana-pro/pkg/setting"
) )
...@@ -45,6 +47,7 @@ func getApiKey(c *Context) string { ...@@ -45,6 +47,7 @@ func getApiKey(c *Context) string {
func authDenied(c *Context) { func authDenied(c *Context) {
if c.IsApiRequest() { if c.IsApiRequest() {
c.JsonApiErr(401, "Access denied", nil) c.JsonApiErr(401, "Access denied", nil)
return
} }
c.Redirect(setting.AppSubUrl + "/login") c.Redirect(setting.AppSubUrl + "/login")
...@@ -69,6 +72,8 @@ func Auth(options *AuthOptions) macaron.Handler { ...@@ -69,6 +72,8 @@ func Auth(options *AuthOptions) macaron.Handler {
return func(c *Context) { return func(c *Context) {
if !c.IsSignedIn && options.ReqSignedIn { if !c.IsSignedIn && options.ReqSignedIn {
log.Info("AppSubUrl: %v", setting.AppSubUrl)
c.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+c.Req.RequestURI), 0, setting.AppSubUrl+"/")
authDenied(c) authDenied(c)
return return
} }
......
...@@ -17,6 +17,7 @@ type User struct { ...@@ -17,6 +17,7 @@ type User struct {
Login string Login string
Password string Password string
Salt string Salt string
Rands string
Company string Company string
IsAdmin bool IsAdmin bool
...@@ -36,6 +37,7 @@ type CreateUserCommand struct { ...@@ -36,6 +37,7 @@ type CreateUserCommand struct {
Company string `json:"compay"` Company string `json:"compay"`
Password string `json:"password" binding:"Required"` Password string `json:"password" binding:"Required"`
Salt string `json:"-"` Salt string `json:"-"`
Rands string `json:"-"`
IsAdmin bool `json:"-"` IsAdmin bool `json:"-"`
Result User `json:"-"` Result User `json:"-"`
......
...@@ -50,6 +50,9 @@ func addUserMigrations(mg *Migrator) { ...@@ -50,6 +50,9 @@ func addUserMigrations(mg *Migrator) {
Table("user").Columns("login").Unique()) Table("user").Columns("login").Unique())
mg.AddMigration("add unique index user.email", new(AddIndexMigration). mg.AddMigration("add unique index user.email", new(AddIndexMigration).
Table("user").Columns("email").Unique()) Table("user").Columns("email").Unique())
mg.AddMigration("add column user.rands", new(AddColumnMigration).
Table("user").Column(&Column{Name: "rands", Type: DB_NVarchar, Length: 255, Nullable: true}))
} }
func addAccountMigrations(mg *Migrator) { func addAccountMigrations(mg *Migrator) {
......
...@@ -41,6 +41,7 @@ func EnsureAdminUser() { ...@@ -41,6 +41,7 @@ func EnsureAdminUser() {
cmd.Login = setting.AdminUser cmd.Login = setting.AdminUser
cmd.Email = setting.AdminUser + "@localhost" cmd.Email = setting.AdminUser + "@localhost"
cmd.Salt = util.GetRandomString(10) cmd.Salt = util.GetRandomString(10)
cmd.Rands = util.GetRandomString(10)
cmd.Password = util.EncodePassword(setting.AdminPassword, cmd.Salt) cmd.Password = util.EncodePassword(setting.AdminPassword, cmd.Salt)
cmd.IsAdmin = true cmd.IsAdmin = true
......
...@@ -43,6 +43,7 @@ func CreateUser(cmd *m.CreateUserCommand) error { ...@@ -43,6 +43,7 @@ func CreateUser(cmd *m.CreateUserCommand) error {
Login: cmd.Login, Login: cmd.Login,
Company: cmd.Company, Company: cmd.Company,
Salt: cmd.Salt, Salt: cmd.Salt,
Rands: cmd.Rands,
IsAdmin: cmd.IsAdmin, IsAdmin: cmd.IsAdmin,
AccountId: account.Id, AccountId: account.Id,
Created: time.Now(), Created: time.Now(),
......
...@@ -2,8 +2,10 @@ package util ...@@ -2,8 +2,10 @@ package util
import ( import (
"crypto/hmac" "crypto/hmac"
"crypto/md5"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"encoding/hex"
"fmt" "fmt"
"hash" "hash"
) )
...@@ -28,6 +30,13 @@ func EncodePassword(password string, salt string) string { ...@@ -28,6 +30,13 @@ func EncodePassword(password string, salt string) string {
return fmt.Sprintf("%x", newPasswd) return fmt.Sprintf("%x", newPasswd)
} }
// Encode string to md5 hex value.
func EncodeMd5(str string) string {
m := md5.New()
m.Write([]byte(str))
return hex.EncodeToString(m.Sum(nil))
}
// http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto // http://code.google.com/p/go/source/browse/pbkdf2/pbkdf2.go?repo=crypto
func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
prf := hmac.New(h, password) prf := hmac.New(h, password)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment