Browse Source

dashfolders: new admin permission needed to view/change acl

Daniel Lee 8 years ago
parent
commit
1d43bfbf3f
3 changed files with 66 additions and 19 deletions
  1. 3 3
      pkg/api/dashboard_acl.go
  2. 59 16
      pkg/api/dashboard_acl_test.go
  3. 4 0
      pkg/services/guardian/guardian.go

+ 3 - 3
pkg/api/dashboard_acl.go

@@ -16,7 +16,7 @@ func GetDashboardAclList(c *middleware.Context) Response {
 
 	guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
 
-	if canView, err := guardian.CanView(); err != nil || !canView {
+	if canAdmin, err := guardian.CanAdmin(); err != nil || !canAdmin {
 		return dashboardGuardianResponse(err)
 	}
 
@@ -33,7 +33,7 @@ func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCom
 	dashId := c.ParamsInt64(":dashboardId")
 
 	guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
-	if canSave, err := guardian.CanSave(); err != nil || !canSave {
+	if canAdmin, err := guardian.CanAdmin(); err != nil || !canAdmin {
 		return dashboardGuardianResponse(err)
 	}
 
@@ -69,7 +69,7 @@ func DeleteDashboardAcl(c *middleware.Context) Response {
 	aclId := c.ParamsInt64(":aclId")
 
 	guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
-	if canSave, err := guardian.CanSave(); err != nil || !canSave {
+	if canAdmin, err := guardian.CanAdmin(); err != nil || !canAdmin {
 		return dashboardGuardianResponse(err)
 	}
 

+ 59 - 16
pkg/api/dashboard_acl_test.go

@@ -13,17 +13,13 @@ import (
 func TestDashboardAclApiEndpoint(t *testing.T) {
 	Convey("Given a dashboard acl", t, func() {
 		mockResult := []*models.DashboardAcl{
-			{Id: 1, OrgId: 1, DashboardId: 1, UserId: 2, Permission: models.PERMISSION_EDIT},
-			{Id: 2, OrgId: 1, DashboardId: 1, UserId: 3, Permission: models.PERMISSION_VIEW},
-			{Id: 3, OrgId: 1, DashboardId: 1, UserGroupId: 1, Permission: models.PERMISSION_EDIT},
-			{Id: 4, OrgId: 1, DashboardId: 1, UserGroupId: 2, Permission: models.PERMISSION_READ_ONLY_EDIT},
-		}
-		dtoRes := []*models.DashboardAclInfoDTO{
-			{Id: 1, OrgId: 1, DashboardId: 1, UserId: 2, Permission: models.PERMISSION_EDIT},
-			{Id: 2, OrgId: 1, DashboardId: 1, UserId: 3, Permission: models.PERMISSION_VIEW},
-			{Id: 3, OrgId: 1, DashboardId: 1, UserGroupId: 1, Permission: models.PERMISSION_EDIT},
-			{Id: 4, OrgId: 1, DashboardId: 1, UserGroupId: 2, Permission: models.PERMISSION_READ_ONLY_EDIT},
+			{Id: 1, OrgId: 1, DashboardId: 1, UserId: 2, Permission: models.PERMISSION_VIEW},
+			{Id: 2, OrgId: 1, DashboardId: 1, UserId: 3, Permission: models.PERMISSION_EDIT},
+			{Id: 3, OrgId: 1, DashboardId: 1, UserId: 4, Permission: models.PERMISSION_ADMIN},
+			{Id: 4, OrgId: 1, DashboardId: 1, UserGroupId: 1, Permission: models.PERMISSION_VIEW},
+			{Id: 5, OrgId: 1, DashboardId: 1, UserGroupId: 2, Permission: models.PERMISSION_ADMIN},
 		}
+		dtoRes := transformDashboardAclsToDTOs(mockResult)
 
 		bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error {
 			query.Result = dtoRes
@@ -51,15 +47,16 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
 
 					respJSON, err := simplejson.NewJson(sc.resp.Body.Bytes())
 					So(err, ShouldBeNil)
+					So(len(respJSON.MustArray()), ShouldEqual, 5)
 					So(respJSON.GetIndex(0).Get("userId").MustInt(), ShouldEqual, 2)
-					So(respJSON.GetIndex(0).Get("permissions").MustInt(), ShouldEqual, models.PERMISSION_EDIT)
+					So(respJSON.GetIndex(0).Get("permission").MustInt(), ShouldEqual, models.PERMISSION_VIEW)
 				})
 			})
 		})
 
-		Convey("When user is editor and in the ACL", func() {
+		Convey("When user is editor and has admin permission in the ACL", func() {
 			loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardId/acl", models.ROLE_EDITOR, func(sc *scenarioContext) {
-				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_EDIT})
+				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_ADMIN})
 
 				Convey("Should be able to access ACL", func() {
 					sc.handlerFunc = GetDashboardAclList
@@ -70,7 +67,7 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
 			})
 
 			loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardId/acl/:aclId", models.ROLE_EDITOR, func(sc *scenarioContext) {
-				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_EDIT})
+				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_ADMIN})
 
 				bus.AddHandler("test3", func(cmd *models.RemoveDashboardAclCommand) error {
 					return nil
@@ -84,9 +81,9 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
 				})
 			})
 
-			Convey("When user is a member of a user group in the ACL with edit permission", func() {
+			Convey("When user is a member of a user group in the ACL with admin permission", func() {
 				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardsId/acl/:aclId", models.ROLE_EDITOR, func(sc *scenarioContext) {
-					userGroupResp = append(userGroupResp, &models.UserGroup{Id: 1, OrgId: 1, Name: "UG1"})
+					userGroupResp = append(userGroupResp, &models.UserGroup{Id: 2, OrgId: 1, Name: "UG2"})
 
 					bus.AddHandler("test3", func(cmd *models.RemoveDashboardAclCommand) error {
 						return nil
@@ -102,6 +99,34 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
 			})
 		})
 
+		Convey("When user is editor and has edit permission in the ACL", func() {
+			loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardId/acl", models.ROLE_EDITOR, func(sc *scenarioContext) {
+				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_EDIT})
+
+				Convey("Should not be able to access ACL", func() {
+					sc.handlerFunc = GetDashboardAclList
+					sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
+
+					So(sc.resp.Code, ShouldEqual, 403)
+				})
+			})
+
+			loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardId/acl/:aclId", models.ROLE_EDITOR, func(sc *scenarioContext) {
+				mockResult = append(mockResult, &models.DashboardAcl{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: models.PERMISSION_EDIT})
+
+				bus.AddHandler("test3", func(cmd *models.RemoveDashboardAclCommand) error {
+					return nil
+				})
+
+				Convey("Should be not be able to delete permission", func() {
+					sc.handlerFunc = DeleteDashboardAcl
+					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
+
+					So(sc.resp.Code, ShouldEqual, 403)
+				})
+			})
+		})
+
 		Convey("When user is editor and not in the ACL", func() {
 			loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardsId/acl", models.ROLE_EDITOR, func(sc *scenarioContext) {
 
@@ -129,3 +154,21 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
 		})
 	})
 }
+
+func transformDashboardAclsToDTOs(acls []*models.DashboardAcl) []*models.DashboardAclInfoDTO {
+	dtos := make([]*models.DashboardAclInfoDTO, 0)
+
+	for _, acl := range acls {
+		dto := &models.DashboardAclInfoDTO{
+			Id:          acl.Id,
+			OrgId:       acl.OrgId,
+			DashboardId: acl.DashboardId,
+			Permission:  acl.Permission,
+			UserId:      acl.UserId,
+			UserGroupId: acl.UserGroupId,
+		}
+		dtos = append(dtos, dto)
+	}
+
+	return dtos
+}

+ 4 - 0
pkg/services/guardian/guardian.go

@@ -36,6 +36,10 @@ func (g *DashboardGuardian) CanView() (bool, error) {
 	return g.HasPermission(m.PERMISSION_VIEW)
 }
 
+func (g *DashboardGuardian) CanAdmin() (bool, error) {
+	return g.HasPermission(m.PERMISSION_ADMIN)
+}
+
 func (g *DashboardGuardian) HasPermission(permission m.PermissionType) (bool, error) {
 	if g.user.OrgRole == m.ROLE_ADMIN {
 		return true, nil