diff --git a/pkg/api/admin_users.go b/pkg/api/admin_users.go index b202c5ce2a8..0ffe0612ac0 100644 --- a/pkg/api/admin_users.go +++ b/pkg/api/admin_users.go @@ -1,6 +1,7 @@ package api import ( + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" @@ -12,9 +13,83 @@ func AdminSearchUsers(c *middleware.Context) { query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 20} if err := bus.Dispatch(&query); err != nil { - c.JsonApiErr(500, "Failed to fetch collaboratos", err) + c.JsonApiErr(500, "Failed to fetch users", err) return } c.JSON(200, query.Result) } + +func AdminGetUser(c *middleware.Context) { + userId := c.ParamsInt64(":id") + + query := m.GetUserByIdQuery{Id: userId} + + if err := bus.Dispatch(&query); err != nil { + c.JsonApiErr(500, "Failed to fetch user", err) + return + } + + result := m.UserDTO{ + Name: query.Result.Name, + Email: query.Result.Email, + Login: query.Result.Login, + } + + c.JSON(200, result) +} + +func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) { + cmd := m.CreateUserCommand{ + Login: form.Login, + Email: form.Email, + Password: form.Password, + Name: form.Name, + } + + if len(cmd.Login) == 0 { + cmd.Login = cmd.Email + if len(cmd.Login) == 0 { + c.JsonApiErr(400, "Validation error, need specify either username or email", nil) + return + } + } + + if len(cmd.Password) < 4 { + c.JsonApiErr(400, "Password is missing or too short", nil) + return + } + + if err := bus.Dispatch(&cmd); err != nil { + c.JsonApiErr(500, "failed to create user", err) + return + } + + c.JsonOK("User created") +} + +func AdminUpdateUser(c *middleware.Context, form dtos.AdminUpdateUserForm) { + userId := c.ParamsInt64(":id") + + cmd := m.UpdateUserCommand{ + UserId: userId, + Login: form.Login, + Email: form.Email, + Name: form.Name, + } + + if len(cmd.Login) == 0 { + cmd.Login = cmd.Email + if len(cmd.Login) == 0 { + c.JsonApiErr(400, "Validation error, need specify either username or email", nil) + return + } + } + + if err := bus.Dispatch(&cmd); err != nil { + c.JsonApiErr(500, "failed to update user", err) + return + } + + c.JsonOK("User updated") +} diff --git a/pkg/api/api.go b/pkg/api/api.go index 02994d1047f..4595869ab0b 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -93,6 +93,9 @@ func Register(r *macaron.Macaron) { // admin api r.Group("/api/admin", func() { r.Get("/users", AdminSearchUsers) + r.Get("/users/:id", AdminGetUser) + r.Post("/users", bind(dtos.AdminCreateUserForm{}), AdminCreateUser) + r.Put("/users/:id", bind(dtos.AdminUpdateUserForm{}), AdminUpdateUser) }, reqGrafanaAdmin) // rendering diff --git a/pkg/api/dtos/user.go b/pkg/api/dtos/user.go new file mode 100644 index 00000000000..69fc3797029 --- /dev/null +++ b/pkg/api/dtos/user.go @@ -0,0 +1,14 @@ +package dtos + +type AdminCreateUserForm struct { + Email string `json:"email"` + Login string `json:"login"` + Name string `json:"name"` + Password string `json:"password" binding:"Required"` +} + +type AdminUpdateUserForm struct { + Email string `json:"email"` + Login string `json:"login"` + Name string `json:"name"` +} diff --git a/pkg/models/user.go b/pkg/models/user.go index 0a3de0c9a4d..b63ded299c7 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -63,6 +63,11 @@ type GetUserByLoginQuery struct { Result *User } +type GetUserByIdQuery struct { + Id int64 + Result *User +} + type GetSignedInUserQuery struct { UserId int64 Result *SignedInUser diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index f56a64c8c0e..ac7286af77c 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -15,6 +15,7 @@ import ( func init() { bus.AddHandler("sql", CreateUser) + bus.AddHandler("sql", GetUserById) bus.AddHandler("sql", UpdateUser) bus.AddHandler("sql", GetUserByLogin) bus.AddHandler("sql", SetUsingAccount) @@ -112,9 +113,24 @@ func CreateUser(cmd *m.CreateUserCommand) error { }) } +func GetUserById(query *m.GetUserByIdQuery) error { + user := new(m.User) + has, err := x.Id(query.Id).Get(user) + + if err != nil { + return err + } else if has == false { + return m.ErrUserNotFound + } + + query.Result = user + + return nil +} + func GetUserByLogin(query *m.GetUserByLoginQuery) error { if query.LoginOrEmail == "" { - return m.ErrAccountNotFound + return m.ErrUserNotFound } user := new(m.User) diff --git a/src/app/features/admin/adminEditUserCtrl.js b/src/app/features/admin/adminEditUserCtrl.js new file mode 100644 index 00000000000..d01d5d8559d --- /dev/null +++ b/src/app/features/admin/adminEditUserCtrl.js @@ -0,0 +1,40 @@ +define([ + 'angular', +], +function (angular) { + 'use strict'; + + var module = angular.module('grafana.controllers'); + + module.controller('AdminEditUserCtrl', function($scope, $routeParams, backendSrv) { + $scope.user = {}; + + $scope.init = function() { + if ($routeParams.id) { + $scope.createMode = false; + $scope.getUser($routeParams.id); + } else { + $scope.createMode = true; + } + }; + + $scope.getUser = function(id) { + backendSrv.get('/api/admin/users/' + id).then(function(user) { + $scope.user = user; + $scope.user_id = id; + }); + }; + + $scope.update = function() { + if (!$scope.userForm.$valid) { return; } + if ($scope.createMode) { + backendSrv.post('/api/admin/users', $scope.user); + } else { + backendSrv.put('/api/admin/users/' + $scope.user_id, $scope.user); + } + }; + + $scope.init(); + + }); +}); diff --git a/src/app/features/admin/partials/edit_user.html b/src/app/features/admin/partials/edit_user.html new file mode 100644 index 00000000000..4209b280d5b --- /dev/null +++ b/src/app/features/admin/partials/edit_user.html @@ -0,0 +1,74 @@ + + + + +
+
+

+ Create a new user +

+ +

+ Edit user +

+ +
+
+
+
    +
  • + Name +
  • +
  • + +
  • +
+
+
+
+
    +
  • + Email +
  • +
  • + +
  • +
+
+
+
+
    +
  • + Username +
  • +
  • + +
  • +
+
+
+ +
+
    +
  • + Password +
  • +
  • + +
  • +
+
+
+
+ +
+ + +
+
+
diff --git a/src/app/features/admin/partials/users.html b/src/app/features/admin/partials/users.html index ebc31919457..fb59f6ee514 100644 --- a/src/app/features/admin/partials/users.html +++ b/src/app/features/admin/partials/users.html @@ -2,30 +2,33 @@
-

Users

+

+ Users +

+ - + -
IdName Login EmailName Admin
{{user.id}}{{user.name}} {{user.login}} {{user.email}}{{user.name}} {{user.isAdmin}} - + Edit diff --git a/src/app/features/all.js b/src/app/features/all.js index a262a57b5ba..6ebabafcbad 100644 --- a/src/app/features/all.js +++ b/src/app/features/all.js @@ -16,5 +16,6 @@ define([ './account/accountCtrl', './admin/adminUsersCtrl', './admin/adminCtrl', + './admin/adminEditUserCtrl', './grafanaDatasource/datasource', ], function () {}); diff --git a/src/app/features/profile/partials/profile.html b/src/app/features/profile/partials/profile.html index 2a839db6e10..db9d9b52702 100644 --- a/src/app/features/profile/partials/profile.html +++ b/src/app/features/profile/partials/profile.html @@ -27,7 +27,7 @@ Email
  • - +
  • diff --git a/src/app/routes/backend/all.js b/src/app/routes/backend/all.js index 2ffd773ea82..e9d5d8ac95d 100644 --- a/src/app/routes/backend/all.js +++ b/src/app/routes/backend/all.js @@ -62,6 +62,14 @@ define([ templateUrl: 'app/features/admin/partials/users.html', controller : 'AdminUsersCtrl', }) + .when('/admin/users/create', { + templateUrl: 'app/features/admin/partials/edit_user.html', + controller : 'AdminEditUserCtrl', + }) + .when('/admin/users/edit/:id', { + templateUrl: 'app/features/admin/partials/edit_user.html', + controller : 'AdminEditUserCtrl', + }) .when('/login', { templateUrl: 'app/partials/login.html', controller : 'LoginCtrl',