瀏覽代碼

Worked on user admin features, can now create and edit users as a grafana admin user, #1446

Torkel Ödegaard 11 年之前
父節點
當前提交
e165e2af95

+ 76 - 1
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")
+}

+ 3 - 0
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

+ 14 - 0
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"`
+}

+ 5 - 0
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

+ 17 - 1
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)

+ 40 - 0
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();
+
+  });
+});

+ 74 - 0
src/app/features/admin/partials/edit_user.html

@@ -0,0 +1,74 @@
+<topnav icon="fa fa-cube" title="Admin" subnav="true">
+	<ul class="nav">
+		<li><a href="admin">Settings</a></li>
+		<li><a href="admin/users">Users</a></li>
+		<li ng-class="{active: createMode}"><a href="admin/users/new">Create user</a></li>
+		<li class="active" ng-show="!createMode"><a href="admin/users/new">Edit user</a></li>
+	</ul>
+</topnav>
+
+<div class="page-container">
+	<div class="page">
+		<h2 ng-show="createMode">
+			Create a new user
+		</h2>
+
+		<h2 ng-show="!createMode">
+			Edit user
+		</h2>
+
+		<form name="userForm">
+			<div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							<strong>Name</strong>
+						</li>
+						<li>
+							<input type="text" required ng-model="user.name" 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>Email</strong>
+						</li>
+						<li>
+							<input type="email" ng-model="user.email" 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>Username</strong>
+						</li>
+						<li>
+							<input type="text" ng-model="user.login" class="input-xxlarge tight-form-input last" >
+						</li>
+					</ul>
+					<div class="clearfix"></div>
+				</div>
+
+				<div class="tight-form" style="margin-top: 5px" ng-if="createMode">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							<strong>Password</strong>
+						</li>
+						<li>
+							<input type="password" required ng-model="user.password" 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="update()" ng-show="createMode">Create</button>
+			<button type="submit" class="pull-right btn btn-success" ng-click="update()" ng-show="!createMode">Update</button>
+		</form>
+	</div>
+</div>

+ 7 - 4
src/app/features/admin/partials/users.html

@@ -2,30 +2,33 @@
 	<ul class="nav">
 		<li><a href="admin">Settings</a></li>
 		<li class="active"><a href="admin/users">Users</a></li>
+		<li><a href="admin/users/create">Create user</a></li>
 	</ul>
 </topnav>
 
 <div class="page-container">
 	<div class="page">
-		<h2>Users</h2>
+		<h2>
+			Users
+		</h2>
 
 		<table class="grafana-options-table">
 			<tr>
 				<th style="text-align:left">Id</th>
+				<th>Name</th>
 				<th>Login</th>
 				<th>Email</th>
-				<th>Name</th>
 				<th>Admin</th>
 				<th></th>
 			</tr>
 			<tr ng-repeat="user in users">
 				<td>{{user.id}}</td>
+				<td>{{user.name}}</td>
 				<td>{{user.login}}</td>
 				<td>{{user.email}}</td>
-				<td>{{user.name}}</td>
 				<td>{{user.isAdmin}}</td>
 				<td style="width: 1%">
-					<a ng-click="edit(variable)" class="btn btn-success btn-small">
+					<a href="admin/users/edit/{{user.id}}" class="btn btn-inverse btn-small">
 						<i class="fa fa-edit"></i>
 						Edit
 					</a>

+ 1 - 0
src/app/features/all.js

@@ -16,5 +16,6 @@ define([
   './account/accountCtrl',
   './admin/adminUsersCtrl',
   './admin/adminCtrl',
+  './admin/adminEditUserCtrl',
   './grafanaDatasource/datasource',
 ], function () {});

+ 1 - 1
src/app/features/profile/partials/profile.html

@@ -27,7 +27,7 @@
 							<strong>Email</strong>
 						</li>
 						<li>
-							<input type="text" required ng-model="user.email" class="input-xxlarge tight-form-input last" >
+							<input type="email" required ng-model="user.email" class="input-xxlarge tight-form-input last" >
 						</li>
 					</ul>
 					<div class="clearfix"></div>

+ 8 - 0
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',