Commit 47c6c6e1 by Torkel Ödegaard

Added change password feature, Closes #1455

parent afc52f57
......@@ -50,6 +50,7 @@ func Register(r *macaron.Macaron) {
r.Get("/accounts", GetUserAccounts)
r.Post("/stars/dashboard/:id", StarDashboard)
r.Delete("/stars/dashboard/:id", UnstarDashboard)
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), ChangeUserPassword)
})
// account
......
......@@ -4,6 +4,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/middleware"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util"
)
func GetUser(c *middleware.Context) {
......@@ -84,3 +85,33 @@ func SetUsingAccount(c *middleware.Context) {
c.JsonOK("Active account changed")
}
func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) {
userQuery := m.GetUserByIdQuery{Id: c.UserId}
if err := bus.Dispatch(&userQuery); err != nil {
c.JsonApiErr(500, "Could not read user from database", err)
return
}
passwordHashed := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt)
if passwordHashed != userQuery.Result.Password {
c.JsonApiErr(401, "Invalid old password", nil)
return
}
if len(cmd.NewPassword) < 4 {
c.JsonApiErr(400, "New password too short", nil)
return
}
cmd.UserId = c.UserId
cmd.NewPassword = util.EncodePassword(cmd.NewPassword, userQuery.Result.Salt)
if err := bus.Dispatch(&cmd); err != nil {
c.JsonApiErr(500, "Failed to change user password", err)
return
}
c.JsonOK("User password changed")
}
......@@ -52,6 +52,13 @@ type UpdateUserCommand struct {
UserId int64 `json:"-"`
}
type ChangeUserPasswordCommand struct {
OldPassword string `json:"oldPassword"`
NewPassword string `json:"newPassword"`
UserId int64 `json:"-"`
}
type DeleteUserCommand struct {
UserId int64
}
......
......@@ -18,6 +18,7 @@ func init() {
bus.AddHandler("sql", CreateUser)
bus.AddHandler("sql", GetUserById)
bus.AddHandler("sql", UpdateUser)
bus.AddHandler("sql", ChangeUserPassword)
bus.AddHandler("sql", GetUserByLogin)
bus.AddHandler("sql", SetUsingAccount)
bus.AddHandler("sql", GetUserInfo)
......@@ -181,6 +182,22 @@ func UpdateUser(cmd *m.UpdateUserCommand) error {
})
}
func ChangeUserPassword(cmd *m.ChangeUserPasswordCommand) error {
return inTransaction2(func(sess *session) error {
user := m.User{
Password: cmd.NewPassword,
Updated: time.Now(),
}
if _, err := sess.Id(cmd.UserId).Update(&user); err != nil {
return err
}
return nil
})
}
func SetUsingAccount(cmd *m.SetUsingAccountCommand) error {
return inTransaction(func(sess *xorm.Session) error {
user := m.User{}
......
......@@ -9,6 +9,7 @@ define([
'./dashboard/all',
'./panel/all',
'./profile/profileCtrl',
'./profile/changePasswordCtrl',
'./account/all',
'./admin/all',
'./grafanaDatasource/datasource',
......
......@@ -120,7 +120,7 @@ function (angular, _, kbn) {
}
function convertTargetToQuery(target) {
if (!target.metric) {
if (!target.metric || target.hide) {
return null;
}
......
define([
'angular',
'config',
],
function (angular) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('ChangePasswordCtrl', function($scope, backendSrv, $location) {
$scope.command = {};
$scope.changePassword = function() {
if (!$scope.userForm.$valid) { return; }
if ($scope.command.newPassword !== $scope.command.confirmNew) {
$scope.appEvent('alert-warning', ['New passwords do not match', '']);
return;
}
backendSrv.put('/api/user/password', $scope.command).then(function() {
$location.path("profile");
});
};
});
});
<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fa-user" subnav="true">
<ul class="nav">
<li><a href="profile">Overview</a></li>
<li class="active"><a href="profile/password">Change password</a></li>
</ul>
</topnav>
<div class="page-container">
<div class="page">
<h2>Change password</h2>
<form name="userForm">
<div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
<strong>Old Password</strong>
</li>
<li>
<input type="password" required ng-model="command.oldPassword" class="input-xxlarge tight-form-input last" >
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form" style="margin-top: 5px">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
<strong>New Password</strong>
</li>
<li>
<input type="password" required ng-model="command.newPassword" ng-minlength="4" class="input-xxlarge tight-form-input last" >
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form" style="margin-top: 5px">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
<strong>Confirm New</strong>
</li>
<li>
<input type="password" required ng-model="command.confirmNew" ng-minlength="4" class="input-xxlarge tight-form-input last" >
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<br>
<button type="submit" class="pull-right btn btn-success" ng-click="changePassword()">Change Password</button>
</form>
</div>
</div>
<topnav title="{{contextSrv.user.name}}"
section="Profile"
icon="fa fa-user">
<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fa-user" subnav="true">
<ul class="nav">
<li class="active"><a href="profile">Overview</a></li>
<li><a href="profile/password">Change password</a></li>
</ul>
</topnav>
<div class="page-container">
......
......@@ -7,7 +7,7 @@ function (angular, config) {
var module = angular.module('grafana.controllers');
module.controller('ProfileCtrl', function($scope, $http, backendSrv) {
module.controller('ProfileCtrl', function($scope, backendSrv) {
$scope.newAccount = {name: ''};
......
......@@ -62,6 +62,10 @@ define([
templateUrl: 'app/features/profile/partials/profile.html',
controller : 'ProfileCtrl',
})
.when('/profile/password', {
templateUrl: 'app/features/profile/partials/password.html',
controller : 'ChangePasswordCtrl',
})
.when('/admin/settings', {
templateUrl: 'app/features/admin/partials/settings.html',
controller : 'AdminSettingsCtrl',
......
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