func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) Response { userQuery := m.GetUserByIdQuery{Id: c.UserId} if err := bus.Dispatch(&userQuery); err != nil { return ApiError(500, "Could not read user from database", err) } passwordHashed := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt) if passwordHashed != userQuery.Result.Password { return ApiError(401, "Invalid old password", nil) } if len(cmd.NewPassword) < 4 { return ApiError(400, "New password too short", nil) } cmd.UserId = c.UserId cmd.NewPassword = util.EncodePassword(cmd.NewPassword, userQuery.Result.Salt) if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Failed to change user password", err) } return ApiSuccess("User password changed") }
func AdminUpdateUserPassword(c *middleware.Context, form dtos.AdminUpdateUserPasswordForm) { userId := c.ParamsInt64(":id") if len(form.Password) < 4 { c.JsonApiErr(400, "New password too short", nil) return } userQuery := m.GetUserByIdQuery{Id: userId} if err := bus.Dispatch(&userQuery); err != nil { c.JsonApiErr(500, "Could not read user from database", err) return } passwordHashed := util.EncodePassword(form.Password, userQuery.Result.Salt) cmd := m.ChangeUserPasswordCommand{ UserId: userId, NewPassword: passwordHashed, } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to update user password", err) return } c.JsonOK("User password updated") }
func New(orgId int64, name string) KeyGenResult { jsonKey := ApiKeyJson{} jsonKey.OrgId = orgId jsonKey.Name = name jsonKey.Key = util.GetRandomString(16) result := KeyGenResult{} result.HashedKey = util.EncodePassword(jsonKey.Key, name) jsonString, _ := json.Marshal(jsonKey) result.ClientSecret = base64.StdEncoding.EncodeToString([]byte(jsonString)) return result }
func TestApiKeyGen(t *testing.T) { Convey("When generating new api key", t, func() { result := New(12, "Cool key") So(result.ClientSecret, ShouldNotBeEmpty) So(result.HashedKey, ShouldNotBeEmpty) Convey("can decode key", func() { keyInfo, err := Decode(result.ClientSecret) So(err, ShouldBeNil) keyHashed := util.EncodePassword(keyInfo.Key, keyInfo.Name) So(keyHashed, ShouldEqual, result.HashedKey) }) }) }
func loginUsingGrafanaDB(query *LoginUserQuery) error { userQuery := m.GetUserByLoginQuery{LoginOrEmail: query.Username} if err := bus.Dispatch(&userQuery); err != nil { if err == m.ErrUserNotFound { return ErrInvalidCredentials } return err } user := userQuery.Result passwordHashed := util.EncodePassword(query.Password, user.Salt) if passwordHashed != user.Password { return ErrInvalidCredentials } query.User = user return nil }
func initContextWithBasicAuth(ctx *Context) bool { if !setting.BasicAuthEnabled { return false } header := ctx.Req.Header.Get("Authorization") if header == "" { return false } username, password, err := util.DecodeBasicAuthHeader(header) if err != nil { ctx.JsonApiErr(401, "Invalid Basic Auth Header", err) return true } loginQuery := m.GetUserByLoginQuery{LoginOrEmail: username} if err := bus.Dispatch(&loginQuery); err != nil { ctx.JsonApiErr(401, "Basic auth failed", err) return true } user := loginQuery.Result // validate password if util.EncodePassword(password, user.Salt) != user.Password { ctx.JsonApiErr(401, "Invalid username or password", nil) return true } query := m.GetSignedInUserQuery{UserId: user.Id} if err := bus.Dispatch(&query); err != nil { ctx.JsonApiErr(401, "Authentication error", err) return true } else { ctx.SignedInUser = query.Result ctx.IsSignedIn = true return true } }
func ResetPassword(c *middleware.Context, form dtos.ResetUserPasswordForm) Response { query := m.ValidateResetPasswordCodeQuery{Code: form.Code} if err := bus.Dispatch(&query); err != nil { if err == m.ErrInvalidEmailCode { return ApiError(400, "Invalid or expired reset password code", nil) } return ApiError(500, "Unknown error validating email code", err) } if form.NewPassword != form.ConfirmPassword { return ApiError(400, "Passwords do not match", nil) } cmd := m.ChangeUserPasswordCommand{} cmd.UserId = query.Result.Id cmd.NewPassword = util.EncodePassword(form.NewPassword, query.Result.Salt) if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Failed to change user password", err) } return ApiSuccess("User password changed") }
func CreateUser(cmd *m.CreateUserCommand) error { return inTransaction2(func(sess *session) error { orgId, err := getOrgIdForNewUser(cmd, sess) if err != nil { return err } if cmd.Email == "" { cmd.Email = cmd.Login } // create user user := m.User{ Email: cmd.Email, Name: cmd.Name, Login: cmd.Login, IsAdmin: cmd.IsAdmin, OrgId: orgId, EmailVerified: cmd.EmailVerified, Theme: "light", Created: time.Now(), Updated: time.Now(), } if len(cmd.Password) > 0 { user.Salt = util.GetRandomString(10) user.Rands = util.GetRandomString(10) user.Password = util.EncodePassword(cmd.Password, user.Salt) } sess.UseBool("is_admin") if _, err := sess.Insert(&user); err != nil { return err } sess.publishAfterCommit(&events.UserCreated{ Timestamp: user.Created, Id: user.Id, Name: user.Name, Login: user.Login, Email: user.Email, }) cmd.Result = user // create org user link if !cmd.SkipOrgSetup { orgUser := m.OrgUser{ OrgId: orgId, UserId: user.Id, Role: m.ROLE_ADMIN, Created: time.Now(), Updated: time.Now(), } if setting.AutoAssignOrg && !user.IsAdmin { orgUser.Role = m.RoleType(setting.AutoAssignOrgRole) } if _, err = sess.Insert(&orgUser); err != nil { return err } } return nil }) }
func TestMiddlewareContext(t *testing.T) { Convey("Given the grafana middleware", t, func() { middlewareScenario("middleware should add context to injector", func(sc *scenarioContext) { sc.fakeReq("GET", "/").exec() So(sc.context, ShouldNotBeNil) }) middlewareScenario("Default middleware should allow get request", func(sc *scenarioContext) { sc.fakeReq("GET", "/").exec() So(sc.resp.Code, ShouldEqual, 200) }) middlewareScenario("Non api request should init session", func(sc *scenarioContext) { sc.fakeReq("GET", "/").exec() So(sc.resp.Header().Get("Set-Cookie"), ShouldContainSubstring, "grafana_sess") }) middlewareScenario("Invalid api key", func(sc *scenarioContext) { sc.apiKey = "invalid_key_test" sc.fakeReq("GET", "/").exec() Convey("Should not init session", func() { So(sc.resp.Header().Get("Set-Cookie"), ShouldBeEmpty) }) Convey("Should return 401", func() { So(sc.resp.Code, ShouldEqual, 401) So(sc.respJson["message"], ShouldEqual, "Invalid API key") }) }) middlewareScenario("Using basic auth", func(sc *scenarioContext) { bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error { query.Result = &m.User{ Password: util.EncodePassword("myPass", "salt"), Salt: "salt", } return nil }) bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { query.Result = &m.SignedInUser{OrgId: 2, UserId: 12} return nil }) setting.BasicAuthEnabled = true authHeader := util.GetBasicAuthHeader("myUser", "myPass") sc.fakeReq("GET", "/").withAuthoriziationHeader(authHeader).exec() Convey("Should init middleware context with user", func() { So(sc.context.IsSignedIn, ShouldEqual, true) So(sc.context.OrgId, ShouldEqual, 2) So(sc.context.UserId, ShouldEqual, 12) }) }) middlewareScenario("Valid api key", func(sc *scenarioContext) { keyhash := util.EncodePassword("v5nAwpMafFP6znaS4urhdWDLS5511M42", "asd") bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error { query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash} return nil }) sc.fakeReq("GET", "/").withValidApiKey().exec() Convey("Should return 200", func() { So(sc.resp.Code, ShouldEqual, 200) }) Convey("Should init middleware context", func() { So(sc.context.IsSignedIn, ShouldEqual, true) So(sc.context.OrgId, ShouldEqual, 12) So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR) }) }) middlewareScenario("Valid api key, but does not match db hash", func(sc *scenarioContext) { keyhash := "something_not_matching" bus.AddHandler("test", func(query *m.GetApiKeyByNameQuery) error { query.Result = &m.ApiKey{OrgId: 12, Role: m.ROLE_EDITOR, Key: keyhash} return nil }) sc.fakeReq("GET", "/").withValidApiKey().exec() Convey("Should return api key invalid", func() { So(sc.resp.Code, ShouldEqual, 401) So(sc.respJson["message"], ShouldEqual, "Invalid API key") }) }) middlewareScenario("UserId in session", func(sc *scenarioContext) { sc.fakeReq("GET", "/").handler(func(c *Context) { c.Session.Set(SESS_KEY_USERID, int64(12)) }).exec() bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { query.Result = &m.SignedInUser{OrgId: 2, UserId: 12} return nil }) sc.fakeReq("GET", "/").exec() Convey("should init context with user info", func() { So(sc.context.IsSignedIn, ShouldBeTrue) So(sc.context.UserId, ShouldEqual, 12) }) }) middlewareScenario("When anonymous access is enabled", func(sc *scenarioContext) { setting.AnonymousEnabled = true setting.AnonymousOrgName = "test" setting.AnonymousOrgRole = string(m.ROLE_EDITOR) bus.AddHandler("test", func(query *m.GetOrgByNameQuery) error { So(query.Name, ShouldEqual, "test") query.Result = &m.Org{Id: 2, Name: "test"} return nil }) sc.fakeReq("GET", "/").exec() Convey("should init context with org info", func() { So(sc.context.UserId, ShouldEqual, 0) So(sc.context.OrgId, ShouldEqual, 2) So(sc.context.OrgRole, ShouldEqual, m.ROLE_EDITOR) }) Convey("context signed in should be false", func() { So(sc.context.IsSignedIn, ShouldBeFalse) }) }) middlewareScenario("When auth_proxy is enabled enabled and user exists", func(sc *scenarioContext) { setting.AuthProxyEnabled = true setting.AuthProxyHeaderName = "X-WEBAUTH-USER" setting.AuthProxyHeaderProperty = "username" bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { query.Result = &m.SignedInUser{OrgId: 2, UserId: 12} return nil }) sc.fakeReq("GET", "/") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.exec() Convey("should init context with user info", func() { So(sc.context.IsSignedIn, ShouldBeTrue) So(sc.context.UserId, ShouldEqual, 12) So(sc.context.OrgId, ShouldEqual, 2) }) }) middlewareScenario("When auth_proxy is enabled enabled and user does not exists", func(sc *scenarioContext) { setting.AuthProxyEnabled = true setting.AuthProxyHeaderName = "X-WEBAUTH-USER" setting.AuthProxyHeaderProperty = "username" setting.AuthProxyAutoSignUp = true bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { if query.UserId > 0 { query.Result = &m.SignedInUser{OrgId: 4, UserId: 33} return nil } else { return m.ErrUserNotFound } }) var createUserCmd *m.CreateUserCommand bus.AddHandler("test", func(cmd *m.CreateUserCommand) error { createUserCmd = cmd cmd.Result = m.User{Id: 33} return nil }) sc.fakeReq("GET", "/") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.exec() Convey("Should create user if auto sign up is enabled", func() { So(sc.context.IsSignedIn, ShouldBeTrue) So(sc.context.UserId, ShouldEqual, 33) So(sc.context.OrgId, ShouldEqual, 4) }) }) }) }
func IsValid(key *ApiKeyJson, hashedKey string) bool { check := util.EncodePassword(key.Key, key.Name) return check == hashedKey }