mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboard acl query fixes (#10909)
* initial fixes for dashboard permission acl list query, fixes #10864 * permissions: refactoring of acl api and query
This commit is contained in:
@@ -269,7 +269,6 @@ func (hs *HttpServer) registerRoutes() {
|
||||
dashIdRoute.Group("/acl", func(aclRoute RouteRegister) {
|
||||
aclRoute.Get("/", wrap(GetDashboardAclList))
|
||||
aclRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), wrap(UpdateDashboardAcl))
|
||||
aclRoute.Delete("/:aclId", wrap(DeleteDashboardAcl))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -84,33 +84,3 @@ func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCom
|
||||
|
||||
return ApiSuccess("Dashboard acl updated")
|
||||
}
|
||||
|
||||
func DeleteDashboardAcl(c *middleware.Context) Response {
|
||||
dashId := c.ParamsInt64(":dashboardId")
|
||||
aclId := c.ParamsInt64(":aclId")
|
||||
|
||||
_, rsp := getDashboardHelper(c.OrgId, "", dashId, "")
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
|
||||
if canAdmin, err := guardian.CanAdmin(); err != nil || !canAdmin {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
if okToDelete, err := guardian.CheckPermissionBeforeRemove(m.PERMISSION_ADMIN, aclId); err != nil || !okToDelete {
|
||||
if err != nil {
|
||||
return ApiError(500, "Error while checking dashboard permissions", err)
|
||||
}
|
||||
|
||||
return ApiError(403, "Cannot remove own admin permission for a folder", nil)
|
||||
}
|
||||
|
||||
cmd := m.RemoveDashboardAclCommand{OrgId: c.OrgId, AclId: aclId}
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return ApiError(500, "Failed to delete permission for user", err)
|
||||
}
|
||||
|
||||
return Json(200, "")
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ import (
|
||||
func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
Convey("Given a dashboard acl", t, func() {
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 1, UserId: 2, Permission: m.PERMISSION_VIEW},
|
||||
{Id: 2, OrgId: 1, DashboardId: 1, UserId: 3, Permission: m.PERMISSION_EDIT},
|
||||
{Id: 3, OrgId: 1, DashboardId: 1, UserId: 4, Permission: m.PERMISSION_ADMIN},
|
||||
{Id: 4, OrgId: 1, DashboardId: 1, TeamId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{Id: 5, OrgId: 1, DashboardId: 1, TeamId: 2, Permission: m.PERMISSION_ADMIN},
|
||||
{OrgId: 1, DashboardId: 1, UserId: 2, Permission: m.PERMISSION_VIEW},
|
||||
{OrgId: 1, DashboardId: 1, UserId: 3, Permission: m.PERMISSION_EDIT},
|
||||
{OrgId: 1, DashboardId: 1, UserId: 4, Permission: m.PERMISSION_ADMIN},
|
||||
{OrgId: 1, DashboardId: 1, TeamId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{OrgId: 1, DashboardId: 1, TeamId: 2, Permission: m.PERMISSION_ADMIN},
|
||||
}
|
||||
dtoRes := transformDashboardAclsToDTOs(mockResult)
|
||||
|
||||
@@ -92,21 +92,11 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
So(sc.resp.Code, ShouldEqual, 404)
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/2/acl/6", "/api/dashboards/id/:dashboardId/acl/:aclId", m.ROLE_ADMIN, func(sc *scenarioContext) {
|
||||
getDashboardNotFoundError = m.ErrDashboardNotFound
|
||||
sc.handlerFunc = DeleteDashboardAcl
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
|
||||
Convey("Should not be able to delete non-existing dashboard", func() {
|
||||
So(sc.resp.Code, ShouldEqual, 404)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is org 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", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 6, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
|
||||
Convey("Should be able to access ACL", func() {
|
||||
sc.handlerFunc = GetDashboardAclList
|
||||
@@ -116,36 +106,6 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardId/acl/:aclId", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 6, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
|
||||
bus.AddHandler("test3", func(cmd *m.RemoveDashboardAclCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("Should be able to delete permission", func() {
|
||||
sc.handlerFunc = DeleteDashboardAcl
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/6", "/api/dashboards/id/:dashboardId/acl/:aclId", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 6, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
|
||||
bus.AddHandler("test3", func(cmd *m.RemoveDashboardAclCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("Should not be able to delete their own Admin permission", func() {
|
||||
sc.handlerFunc = DeleteDashboardAcl
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should not be able to downgrade their own Admin permission", func() {
|
||||
cmd := dtos.UpdateDashboardAclCommand{
|
||||
Items: []dtos.DashboardAclUpdateItem{
|
||||
@@ -154,7 +114,7 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
postAclScenario("When calling POST on", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardId/acl", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 6, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
|
||||
CallPostAcl(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
@@ -170,34 +130,18 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
postAclScenario("When calling POST on", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardId/acl", m.ROLE_EDITOR, cmd, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 6, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_ADMIN})
|
||||
|
||||
CallPostAcl(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is a member of a team 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", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
teamResp = append(teamResp, &m.Team{Id: 2, OrgId: 1, Name: "UG2"})
|
||||
|
||||
bus.AddHandler("test3", func(cmd *m.RemoveDashboardAclCommand) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
Convey("Should be able to delete permission", func() {
|
||||
sc.handlerFunc = DeleteDashboardAcl
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
|
||||
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is org viewer and has edit permission in the ACL", func() {
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/1/acl", "/api/dashboards/id/:dashboardId/acl", m.ROLE_VIEWER, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_EDIT})
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_EDIT})
|
||||
|
||||
// Getting the permissions is an Admin permission
|
||||
Convey("Should not be able to get list of permissions from ACL", func() {
|
||||
@@ -207,21 +151,6 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardId/acl/:aclId", m.ROLE_VIEWER, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_EDIT})
|
||||
|
||||
bus.AddHandler("test3", func(cmd *m.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 org editor and not in the ACL", func() {
|
||||
@@ -234,20 +163,6 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
So(sc.resp.Code, ShouldEqual, 403)
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/user/1", "/api/dashboards/id/:dashboardsId/acl/user/:userId", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
mockResult = append(mockResult, &m.DashboardAclInfoDTO{Id: 1, OrgId: 1, DashboardId: 1, UserId: 1, Permission: m.PERMISSION_VIEW})
|
||||
bus.AddHandler("test3", func(cmd *m.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)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -257,7 +172,6 @@ func transformDashboardAclsToDTOs(acls []*m.DashboardAclInfoDTO) []*m.DashboardA
|
||||
|
||||
for _, acl := range acls {
|
||||
dto := &m.DashboardAclInfoDTO{
|
||||
Id: acl.Id,
|
||||
OrgId: acl.OrgId,
|
||||
DashboardId: acl.DashboardId,
|
||||
Permission: acl.Permission,
|
||||
|
||||
@@ -431,7 +431,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
role := m.ROLE_VIEWER
|
||||
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_EDIT},
|
||||
{OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_EDIT},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
@@ -505,7 +505,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
setting.ViewersCanEdit = true
|
||||
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_VIEW},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
@@ -564,7 +564,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
role := m.ROLE_VIEWER
|
||||
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_ADMIN},
|
||||
{OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_ADMIN},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
@@ -637,7 +637,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
role := m.ROLE_EDITOR
|
||||
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_VIEW},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
|
||||
Reference in New Issue
Block a user