瀏覽代碼

dashboard acl work

Torkel Ödegaard 8 年之前
父節點
當前提交
2257c1f874

+ 1 - 1
pkg/api/api.go

@@ -250,7 +250,7 @@ func (hs *HttpServer) registerRoutes() {
 
 				r.Group("/acl", func() {
 					r.Get("/", wrap(GetDashboardAclList))
-					r.Post("/", bind(m.SetDashboardAclCommand{}), wrap(PostDashboardAcl))
+					r.Post("/", bind(dtos.UpdateDashboardAclCommand{}), wrap(UpdateDashboardAcl))
 					r.Delete("/:aclId", wrap(DeleteDashboardAcl))
 				})
 			}, reqSignedIn)

+ 20 - 9
pkg/api/dashboard_acl.go

@@ -1,12 +1,14 @@
 package api
 
 import (
+	"time"
+
+	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/middleware"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/guardian"
-	"github.com/grafana/grafana/pkg/util"
 )
 
 func GetDashboardAclList(c *middleware.Context) Response {
@@ -27,7 +29,7 @@ func GetDashboardAclList(c *middleware.Context) Response {
 	return Json(200, list)
 }
 
-func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Response {
+func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCommand) Response {
 	dashId := c.ParamsInt64(":dashboardId")
 
 	guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
@@ -35,9 +37,22 @@ func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Respo
 		return dashboardGuardianResponse(err)
 	}
 
-	cmd.OrgId = c.OrgId
+	cmd := m.UpdateDashboardAclCommand{}
 	cmd.DashboardId = dashId
 
+	for _, item := range apiCmd.Items {
+		cmd.Items = append(cmd.Items, &m.DashboardAcl{
+			OrgId:       c.OrgId,
+			DashboardId: dashId,
+			UserId:      item.UserId,
+			UserGroupId: item.UserGroupId,
+			Role:        item.Role,
+			Permission:  item.Permission,
+			Created:     time.Now(),
+			Updated:     time.Now(),
+		})
+	}
+
 	if err := bus.Dispatch(&cmd); err != nil {
 		if err == m.ErrDashboardAclInfoMissing || err == m.ErrDashboardPermissionDashboardEmpty {
 			return ApiError(409, err.Error(), err)
@@ -45,12 +60,8 @@ func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Respo
 		return ApiError(500, "Failed to create permission", err)
 	}
 
-	metrics.M_Api_Dashboard_Acl_Create.Inc(1)
-
-	return Json(200, &util.DynMap{
-		"permissionId": cmd.Result.Id,
-		"message":      "Permission created",
-	})
+	metrics.M_Api_Dashboard_Acl_Update.Inc(1)
+	return ApiSuccess("Dashboard acl updated")
 }
 
 func DeleteDashboardAcl(c *middleware.Context) Response {

+ 16 - 0
pkg/api/dtos/acl.go

@@ -0,0 +1,16 @@
+package dtos
+
+import (
+	m "github.com/grafana/grafana/pkg/models"
+)
+
+type UpdateDashboardAclCommand struct {
+	Items []DashboardAclUpdateItem `json:"items"`
+}
+
+type DashboardAclUpdateItem struct {
+	UserId      int64            `json:"userId"`
+	UserGroupId int64            `json:"userGroupId"`
+	Role        m.RoleType       `json:"role"`
+	Permission  m.PermissionType `json:"permission"`
+}

+ 2 - 2
pkg/metrics/metrics.go

@@ -36,7 +36,7 @@ var (
 	M_Api_Dashboard_Snapshot_External      Counter
 	M_Api_Dashboard_Snapshot_Get           Counter
 	M_Api_UserGroup_Create                 Counter
-	M_Api_Dashboard_Acl_Create             Counter
+	M_Api_Dashboard_Acl_Update             Counter
 	M_Models_Dashboard_Insert              Counter
 	M_Alerting_Result_State_Alerting       Counter
 	M_Alerting_Result_State_Ok             Counter
@@ -95,7 +95,7 @@ func initMetricVars(settings *MetricSettings) {
 	M_Api_User_SignUpInvite = RegCounter("api.user.signup_invite")
 
 	M_Api_UserGroup_Create = RegCounter("api.usergroup.create")
-	M_Api_Dashboard_Acl_Create = RegCounter("api.dashboard.acl.create")
+	M_Api_Dashboard_Acl_Update = RegCounter("api.dashboard.acl.update")
 
 	M_Api_Dashboard_Save = RegTimer("api.dashboard.save")
 	M_Api_Dashboard_Get = RegTimer("api.dashboard.get")

+ 12 - 6
pkg/models/dashboard_acl.go

@@ -36,6 +36,7 @@ type DashboardAcl struct {
 
 	UserId      int64
 	UserGroupId int64
+	Role        RoleType
 	Permission  PermissionType
 
 	Created time.Time
@@ -64,14 +65,19 @@ type DashboardAclInfoDTO struct {
 // COMMANDS
 //
 
+type UpdateDashboardAclCommand struct {
+	DashboardId int64
+	Items       []*DashboardAcl
+}
+
 type SetDashboardAclCommand struct {
-	DashboardId int64          `json:"-"`
-	OrgId       int64          `json:"-"`
-	UserId      int64          `json:"userId"`
-	UserGroupId int64          `json:"userGroupId"`
-	Permission  PermissionType `json:"permission" binding:"Required"`
+	DashboardId int64
+	OrgId       int64
+	UserId      int64
+	UserGroupId int64
+	Permission  PermissionType
 
-	Result DashboardAcl `json:"-"`
+	Result DashboardAcl
 }
 
 type RemoveDashboardAclCommand struct {

+ 33 - 0
pkg/services/sqlstore/dashboard_acl.go

@@ -9,11 +9,44 @@ import (
 
 func init() {
 	bus.AddHandler("sql", SetDashboardAcl)
+	bus.AddHandler("sql", UpdateDashboardAcl)
 	bus.AddHandler("sql", RemoveDashboardAcl)
 	bus.AddHandler("sql", GetDashboardAclInfoList)
 	bus.AddHandler("sql", GetInheritedDashboardAcl)
 }
 
+func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
+	return inTransaction(func(sess *DBSession) error {
+		// delete existing items
+		_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", cmd.DashboardId)
+		if err != nil {
+			return err
+		}
+
+		for _, item := range cmd.Items {
+			if item.UserId == 0 && item.UserGroupId == 0 && !item.Role.IsValid() {
+				return m.ErrDashboardAclInfoMissing
+			}
+
+			if item.DashboardId == 0 {
+				return m.ErrDashboardPermissionDashboardEmpty
+			}
+
+			sess.Nullable("user_id", "user_group_id")
+			if _, err := sess.Insert(item); err != nil {
+				return err
+			}
+		}
+
+		// Update dashboard HasAcl flag
+		dashboard := m.Dashboard{HasAcl: true}
+		if _, err := sess.Cols("has_acl").Where("id=? OR parent_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil {
+			return err
+		}
+		return nil
+	})
+}
+
 func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
 	return inTransaction(func(sess *DBSession) error {
 		if cmd.UserId == 0 && cmd.UserGroupId == 0 {

+ 1 - 1
public/app/features/dashboard/acl/acl.html

@@ -12,7 +12,7 @@
 
   <div class="modal-content">
     <table class="filter-table gf-form-group">
-      <tr ng-repeat="acl in ctrl.aclItems">
+      <tr ng-repeat="acl in ctrl.items">
         <td style="width: 100%;">
           <i class="{{acl.icon}}"></i>
           <span ng-bind-html="acl.nameHtml"></span>

+ 11 - 8
public/app/features/dashboard/acl/acl.ts

@@ -6,7 +6,7 @@ import _ from 'lodash';
 
 export class AclCtrl {
   dashboard: any;
-  aclItems: DashboardAcl[];
+  items: DashboardAcl[];
   permissionOptions = [
     {value: 1, text: 'View'},
     {value: 2, text: 'Edit'},
@@ -19,12 +19,13 @@ export class AclCtrl {
     {value: 'Editor', text: 'Everyone With Editor Role'}
   ];
 
+  dismiss: () => void;
   newType: string;
   canUpdate: boolean;
 
   /** @ngInject */
   constructor(private backendSrv, private dashboardSrv, private $sce, private $scope) {
-    this.aclItems = [];
+    this.items = [];
     this.resetNewType();
     this.dashboard = dashboardSrv.getCurrent();
     this.get(this.dashboard.id);
@@ -37,7 +38,7 @@ export class AclCtrl {
   get(dashboardId: number) {
     return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`)
       .then(result => {
-        this.aclItems = _.map(result, this.prepareViewModel.bind(this));
+        this.items = _.map(result, this.prepareViewModel.bind(this));
       });
   }
 
@@ -58,7 +59,7 @@ export class AclCtrl {
 
   update() {
     return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, {
-      acl: this.aclItems.map(item => {
+      items: this.items.map(item => {
         return {
           id: item.id,
           userId: item.userId,
@@ -67,12 +68,14 @@ export class AclCtrl {
           permission: item.permission,
         };
       })
+    }).then(() => {
+      this.dismiss();
     });
   }
 
   typeChanged() {
     if (this.newType === 'Viewer' || this.newType === 'Editor') {
-      this.aclItems.push(this.prepareViewModel({
+      this.items.push(this.prepareViewModel({
         permission: 1,
         role: this.newType
       }));
@@ -87,7 +90,7 @@ export class AclCtrl {
   }
 
   userPicked(user) {
-    this.aclItems.push(this.prepareViewModel({
+    this.items.push(this.prepareViewModel({
       userId: user.id,
       userLogin: user.login,
       permission: 1,
@@ -99,7 +102,7 @@ export class AclCtrl {
 
   groupPicked(group) {
     console.log(group);
-    this.aclItems.push(this.prepareViewModel({
+    this.items.push(this.prepareViewModel({
       userGroupId: group.id,
       userGroup: group.name,
       permission: 1,
@@ -110,7 +113,7 @@ export class AclCtrl {
   }
 
   removeItem(index) {
-    this.aclItems.splice(index, 1);
+    this.items.splice(index, 1);
     this.canUpdate = true;
   }
 }