Bläddra i källkod

Lots of api refactoring for org routes, #2014

Torkel Ödegaard 10 år sedan
förälder
incheckning
788e7fd36d

+ 23 - 12
pkg/api/api.go

@@ -13,7 +13,7 @@ func Register(r *macaron.Macaron) {
 	reqSignedIn := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true})
 	reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
 	reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
-	reqAccountAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
+	regOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
 	bind := binding.Bind
 
 	// not logged in views
@@ -71,23 +71,34 @@ func Register(r *macaron.Macaron) {
 			r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
 		}, reqGrafanaAdmin)
 
-		// account
+		// current org
 		r.Group("/org", func() {
-			r.Get("/", GetOrg)
-			r.Post("/", bind(m.CreateOrgCommand{}), CreateOrg)
-			r.Put("/", bind(m.UpdateOrgCommand{}), UpdateOrg)
-			r.Post("/users", bind(m.AddOrgUserCommand{}), AddOrgUser)
-			r.Get("/users", GetOrgUsers)
-			r.Patch("/users/:id", bind(m.UpdateOrgUserCommand{}), UpdateOrgUser)
-			r.Delete("/users/:id", RemoveOrgUser)
-		}, reqAccountAdmin)
+			r.Get("/", wrap(GetOrgCurrent))
+			r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrgCurrent))
+			r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUserToCurrentOrg))
+			r.Get("/users", wrap(GetOrgUsersForCurrentOrg))
+			r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUserForCurrentOrg))
+			r.Delete("/users/:userId", wrap(RemoveOrgUserForCurrentOrg))
+		}, regOrgAdmin)
+
+		// create new org
+		r.Post("/orgs", bind(m.CreateOrgCommand{}), wrap(CreateOrg))
+
+		// orgs (admin routes)
+		r.Group("/orgs/:orgId", func() {
+			r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrg))
+			r.Get("/users", wrap(GetOrgUsers))
+			r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))
+			r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUser))
+			r.Delete("/users/:userId", wrap(RemoveOrgUser))
+		}, reqGrafanaAdmin)
 
 		// auth api keys
 		r.Group("/auth/keys", func() {
 			r.Get("/", wrap(GetApiKeys))
 			r.Post("/", bind(m.AddApiKeyCommand{}), wrap(AddApiKey))
 			r.Delete("/:id", wrap(DeleteApiKey))
-		}, reqAccountAdmin)
+		}, regOrgAdmin)
 
 		// Data sources
 		r.Group("/datasources", func() {
@@ -98,7 +109,7 @@ func Register(r *macaron.Macaron) {
 			r.Delete("/:id", DeleteDataSource)
 			r.Get("/:id", GetDataSourceById)
 			r.Get("/plugins", GetDataSourcePlugins)
-		}, reqAccountAdmin)
+		}, regOrgAdmin)
 
 		r.Get("/frontend/settings/", GetFrontendSettings)
 		r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)

+ 33 - 17
pkg/api/org.go

@@ -8,17 +8,25 @@ import (
 	"github.com/grafana/grafana/pkg/setting"
 )
 
-func GetOrg(c *middleware.Context) {
-	query := m.GetOrgByIdQuery{Id: c.OrgId}
+// GET /api/org
+func GetOrgCurrent(c *middleware.Context) Response {
+	return getOrgHelper(c.OrgId)
+}
+
+// GET /api/orgs/:orgId
+func GetOrgById(c *middleware.Context) Response {
+	return getOrgHelper(c.ParamsInt64(":orgId"))
+}
+
+func getOrgHelper(orgId int64) Response {
+	query := m.GetOrgByIdQuery{Id: orgId}
 
 	if err := bus.Dispatch(&query); err != nil {
 		if err == m.ErrOrgNotFound {
-			c.JsonApiErr(404, "Organization not found", err)
-			return
+			return ApiError(404, "Organization not found", err)
 		}
 
-		c.JsonApiErr(500, "Failed to get organization", err)
-		return
+		return ApiError(500, "Failed to get organization", err)
 	}
 
 	org := m.OrgDTO{
@@ -26,33 +34,41 @@ func GetOrg(c *middleware.Context) {
 		Name: query.Result.Name,
 	}
 
-	c.JSON(200, &org)
+	return Json(200, &org)
 }
 
-func CreateOrg(c *middleware.Context, cmd m.CreateOrgCommand) {
+// POST /api/orgs
+func CreateOrg(c *middleware.Context, cmd m.CreateOrgCommand) Response {
 	if !setting.AllowUserOrgCreate && !c.IsGrafanaAdmin {
-		c.JsonApiErr(401, "Access denied", nil)
-		return
+		return ApiError(401, "Access denied", nil)
 	}
 
 	cmd.UserId = c.UserId
 	if err := bus.Dispatch(&cmd); err != nil {
-		c.JsonApiErr(500, "Failed to create organization", err)
-		return
+		return ApiError(500, "Failed to create organization", err)
 	}
 
 	metrics.M_Api_Org_Create.Inc(1)
 
-	c.JsonOK("Organization created")
+	return ApiSuccess("Organization created")
 }
 
-func UpdateOrg(c *middleware.Context, cmd m.UpdateOrgCommand) {
+// PUT /api/org
+func UpdateOrgCurrent(c *middleware.Context, cmd m.UpdateOrgCommand) Response {
 	cmd.OrgId = c.OrgId
+	return updateOrgHelper(cmd)
+}
+
+// PUT /api/orgs/:orgId
+func UpdateOrg(c *middleware.Context, cmd m.UpdateOrgCommand) Response {
+	cmd.OrgId = c.ParamsInt64(":orgId")
+	return updateOrgHelper(cmd)
+}
 
+func updateOrgHelper(cmd m.UpdateOrgCommand) Response {
 	if err := bus.Dispatch(&cmd); err != nil {
-		c.JsonApiErr(500, "Failed to update organization", err)
-		return
+		return ApiError(500, "Failed to update organization", err)
 	}
 
-	c.JsonOK("Organization updated")
+	return ApiSuccess("Organization updated")
 }

+ 69 - 34
pkg/api/org_users.go

@@ -6,77 +6,112 @@ import (
 	m "github.com/grafana/grafana/pkg/models"
 )
 
-func AddOrgUser(c *middleware.Context, cmd m.AddOrgUserCommand) {
+// POST /api/org/users
+func AddOrgUserToCurrentOrg(c *middleware.Context, cmd m.AddOrgUserCommand) Response {
+	cmd.OrgId = c.OrgId
+	return addOrgUserHelper(cmd)
+}
+
+// POST /api/orgs/:orgId/users
+func AddOrgUser(c *middleware.Context, cmd m.AddOrgUserCommand) Response {
+	cmd.OrgId = c.ParamsInt64(":orgId")
+	return addOrgUserHelper(cmd)
+}
+
+func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
 	if !cmd.Role.IsValid() {
-		c.JsonApiErr(400, "Invalid role specified", nil)
-		return
+		return ApiError(400, "Invalid role specified", nil)
 	}
 
 	userQuery := m.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail}
 	err := bus.Dispatch(&userQuery)
 	if err != nil {
-		c.JsonApiErr(404, "User not found", nil)
-		return
+		return ApiError(404, "User not found", nil)
 	}
 
 	userToAdd := userQuery.Result
 
-	if userToAdd.Id == c.UserId {
-		c.JsonApiErr(400, "Cannot add yourself as user", nil)
-		return
-	}
+	// if userToAdd.Id == c.UserId {
+	// 	return ApiError(400, "Cannot add yourself as user", nil)
+	// }
 
-	cmd.OrgId = c.OrgId
 	cmd.UserId = userToAdd.Id
 
 	if err := bus.Dispatch(&cmd); err != nil {
-		c.JsonApiErr(500, "Could not add user to organization", err)
-		return
+		return ApiError(500, "Could not add user to organization", err)
 	}
 
-	c.JsonOK("User added to organization")
+	return ApiSuccess("User added to organization")
+}
+
+// GET /api/org/users
+func GetOrgUsersForCurrentOrg(c *middleware.Context) Response {
+	return getOrgUsersHelper(c.OrgId)
+}
+
+// GET /api/orgs/:orgId/users
+func GetOrgUsers(c *middleware.Context) Response {
+	return getOrgUsersHelper(c.ParamsInt64(":orgId"))
 }
 
-func GetOrgUsers(c *middleware.Context) {
-	query := m.GetOrgUsersQuery{OrgId: c.OrgId}
+func getOrgUsersHelper(orgId int64) Response {
+	query := m.GetOrgUsersQuery{OrgId: orgId}
 
 	if err := bus.Dispatch(&query); err != nil {
-		c.JsonApiErr(500, "Failed to get account user", err)
-		return
+		return ApiError(500, "Failed to get account user", err)
 	}
 
-	c.JSON(200, query.Result)
+	return Json(200, query.Result)
 }
 
-func UpdateOrgUser(c *middleware.Context, cmd m.UpdateOrgUserCommand) {
+// PATCH /api/org/users/:userId
+func UpdateOrgUserForCurrentOrg(c *middleware.Context, cmd m.UpdateOrgUserCommand) Response {
+	cmd.OrgId = c.OrgId
+	cmd.UserId = c.ParamsInt64(":userId")
+	return updateOrgUserHelper(cmd)
+}
+
+// PATCH /api/orgs/:orgId/users/:userId
+func UpdateOrgUser(c *middleware.Context, cmd m.UpdateOrgUserCommand) Response {
+	cmd.OrgId = c.ParamsInt64(":orgId")
+	cmd.UserId = c.ParamsInt64(":userId")
+	return updateOrgUserHelper(cmd)
+}
+
+func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
 	if !cmd.Role.IsValid() {
-		c.JsonApiErr(400, "Invalid role specified", nil)
-		return
+		return ApiError(400, "Invalid role specified", nil)
 	}
 
-	cmd.UserId = c.ParamsInt64(":id")
-	cmd.OrgId = c.OrgId
-
 	if err := bus.Dispatch(&cmd); err != nil {
-		c.JsonApiErr(500, "Failed update org user", err)
-		return
+		return ApiError(500, "Failed update org user", err)
 	}
 
-	c.JsonOK("Organization user updated")
+	return ApiSuccess("Organization user updated")
 }
 
-func RemoveOrgUser(c *middleware.Context) {
-	userId := c.ParamsInt64(":id")
+// DELETE /api/org/users/:userId
+func RemoveOrgUserForCurrentOrg(c *middleware.Context) Response {
+	userId := c.ParamsInt64(":userId")
+	return removeOrgUserHelper(c.OrgId, userId)
+}
+
+// DELETE /api/orgs/:orgId/users/:userId
+func RemoveOrgUser(c *middleware.Context) Response {
+	userId := c.ParamsInt64(":userId")
+	orgId := c.ParamsInt64(":orgId")
+	return removeOrgUserHelper(orgId, userId)
+}
 
-	cmd := m.RemoveOrgUserCommand{OrgId: c.OrgId, UserId: userId}
+func removeOrgUserHelper(orgId int64, userId int64) Response {
+	cmd := m.RemoveOrgUserCommand{OrgId: orgId, UserId: userId}
 
 	if err := bus.Dispatch(&cmd); err != nil {
 		if err == m.ErrLastOrgAdmin {
-			c.JsonApiErr(400, "Cannot remove last organization admin", nil)
-			return
+			return ApiError(400, "Cannot remove last organization admin", nil)
 		}
-		c.JsonApiErr(500, "Failed to remove user from organization", err)
+		return ApiError(500, "Failed to remove user from organization", err)
 	}
 
-	c.JsonOK("User removed from organization")
+	return ApiSuccess("User removed from organization")
 }

+ 1 - 0
pkg/models/user.go

@@ -133,6 +133,7 @@ type UserProfileDTO struct {
 	Name           string `json:"name"`
 	Login          string `json:"login"`
 	Theme          string `json:"theme"`
+	OrgId          int64  `json:"orgId"`
 	IsGrafanaAdmin bool   `json:"isGrafanaAdmin"`
 }
 

+ 1 - 0
pkg/services/sqlstore/user.go

@@ -236,6 +236,7 @@ func GetUserProfile(query *m.GetUserProfileQuery) error {
 		Login:          user.Login,
 		Theme:          user.Theme,
 		IsGrafanaAdmin: user.IsAdmin,
+		OrgId:          user.OrgId,
 	}
 
 	return err

+ 17 - 8
public/app/features/admin/partials/edit_user.html

@@ -98,17 +98,26 @@
 			Organizations
 		</h2>
 
-		<table class="grafana-options-table">
+		<table class="grafana-options-table form-inline">
+			<tr>
+				<th>Name</th>
+				<th>Role</th>
+				<th></th>
+			</tr>
 			<tr ng-repeat="org in orgs">
-				<td style="width: 98%"><strong>Name: </strong> {{org.name}}</td>
-				<td><strong>Role: </strong> {{org.role}}</td>
-				<td class="nobg max-width-btns">
-					<span class="label label-info" ng-show="org.orgId === user.orgId">
-						Current
-					</span>
+				<td>
+					{{org.name}} <span class="label label-info" ng-show="org.orgId === user.orgId">Current</span>
+				</td>
+				<td>
+					<select type="text" ng-model="org.role" class="input-small" ng-options="f for f in ['Viewer', 'Editor', 'Admin']" ng-change="updateOrgRole(org)">
+					</select>
+				</td>
+				<td style="width: 1%">
+					<a ng-click="removeUser(user)" class="btn btn-danger btn-mini">
+						<i class="fa fa-remove"></i>
+					</a>
 				</td>
 			</tr>
 		</table>
-
 	</div>
 </div>

+ 1 - 1
public/app/features/admin/partials/users.html

@@ -1,4 +1,4 @@
-<topnav icon="fa fa-fw fa-user" title="Global users" subnav="true">
+<topnav icon="fa fa-fw fa-user" title="Global Users" subnav="true">
 	<ul class="nav">
 		<li class="active"><a href="admin/users">Overview</a></li>
 		<li><a href="admin/users/create">Create user</a></li>

+ 1 - 1
public/app/features/org/newOrgCtrl.js

@@ -11,7 +11,7 @@ function (angular) {
     $scope.newOrg = {name: ''};
 
     $scope.createOrg = function() {
-      backendSrv.post('/api/org/', $scope.newOrg).then($scope.getUserOrgs);
+      backendSrv.post('/api/orgs/', $scope.newOrg).then($scope.getUserOrgs);
     };
 
   });

+ 1 - 1
public/app/features/org/partials/orgUsers.html

@@ -7,7 +7,7 @@
 <div class="page-container">
 	<div class="page">
 
-		<h2>Account users</h2>
+		<h2>Organization users</h2>
 
 		<form name="form">
 			<div class="tight-form">

+ 0 - 2
public/app/plugins/datasource/influxdb/queryBuilder.js

@@ -57,8 +57,6 @@ function (_) {
   p._buildQuery = function() {
     var target = this.target;
 
-    console.log('Build Query: target = ', target);
-
     if (!target.measurement) {
       throw "Metric measurement is missing";
     }

+ 7 - 8
public/test/specs/influx09-querybuilder-specs.js

@@ -48,15 +48,14 @@ define([
     });
 
     describe('series with groupByTag', function() {
-      var builder = new InfluxQueryBuilder({
-        measurement: 'cpu',
-        tags: [],
-        groupByTags: ["host"]
-      });
-
-      var query = builder.build();
-
       it('should generate correct query', function() {
+        var builder = new InfluxQueryBuilder({
+          measurement: 'cpu',
+          tags: [],
+          groupByTags: ["host"]
+        });
+
+        var query = builder.build();
         expect(query).to.be('SELECT mean(value) FROM "cpu" WHERE $timeFilter ' +
           'GROUP BY time($interval), host ORDER BY asc');
       });