diff --git a/pkg/api/dashboard_acl.go b/pkg/api/dashboard_acl.go index b0e1dde1683..8feb464ca5e 100644 --- a/pkg/api/dashboard_acl.go +++ b/pkg/api/dashboard_acl.go @@ -20,13 +20,12 @@ func GetDashboardAclList(c *middleware.Context) Response { return dashboardGuardianResponse(err) } - query := m.GetDashboardAclInfoListQuery{DashboardId: dashId} - if err := bus.Dispatch(&query); err != nil { - return ApiError(500, "Failed to get Dashboard ACL", err) + acl, err := guardian.GetAcl() + if err != nil { + return ApiError(500, "Failed to get dashboard acl", err) } - list := query.Result - return Json(200, list) + return Json(200, acl) } func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCommand) Response { diff --git a/pkg/api/dashboard_acl_test.go b/pkg/api/dashboard_acl_test.go index b48916a2343..3780018026b 100644 --- a/pkg/api/dashboard_acl_test.go +++ b/pkg/api/dashboard_acl_test.go @@ -30,7 +30,7 @@ func TestDashboardAclApiEndpoint(t *testing.T) { return nil }) - bus.AddHandler("test", func(query *models.GetInheritedDashboardAclQuery) error { + bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error { query.Result = mockResult return nil }) diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index 2611dbb5ae6..66681f4b686 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -31,7 +31,7 @@ func TestDashboardApiEndpoint(t *testing.T) { }) aclMockResp := []*models.DashboardAcl{} - bus.AddHandler("test", func(query *models.GetInheritedDashboardAclQuery) error { + bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error { query.Result = aclMockResp return nil }) @@ -179,7 +179,7 @@ func TestDashboardApiEndpoint(t *testing.T) { }, } - bus.AddHandler("test", func(query *models.GetInheritedDashboardAclQuery) error { + bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error { query.Result = aclMockResp return nil }) @@ -276,7 +276,7 @@ func TestDashboardApiEndpoint(t *testing.T) { {Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: models.PERMISSION_EDIT}, } - bus.AddHandler("test", func(query *models.GetInheritedDashboardAclQuery) error { + bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error { query.Result = mockResult return nil }) @@ -318,7 +318,7 @@ func TestDashboardApiEndpoint(t *testing.T) { {Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: models.PERMISSION_VIEW}, } - bus.AddHandler("test", func(query *models.GetInheritedDashboardAclQuery) error { + bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error { query.Result = mockResult return nil }) diff --git a/pkg/api/dtos/acl.go b/pkg/api/dtos/acl.go index df9b05cbd10..41f560e794b 100644 --- a/pkg/api/dtos/acl.go +++ b/pkg/api/dtos/acl.go @@ -11,6 +11,6 @@ type UpdateDashboardAclCommand struct { type DashboardAclUpdateItem struct { UserId int64 `json:"userId"` UserGroupId int64 `json:"userGroupId"` - Role m.RoleType `json:"role"` + Role *m.RoleType `json:"role,omitempty"` Permission m.PermissionType `json:"permission"` } diff --git a/pkg/models/dashboard_acl.go b/pkg/models/dashboard_acl.go index ff9db8ae612..9b65ec8eb33 100644 --- a/pkg/models/dashboard_acl.go +++ b/pkg/models/dashboard_acl.go @@ -36,7 +36,7 @@ type DashboardAcl struct { UserId int64 UserGroupId int64 - Role RoleType + Role *RoleType // pointer to be nullable Permission PermissionType Created time.Time @@ -56,7 +56,7 @@ type DashboardAclInfoDTO struct { UserEmail string `json:"userEmail"` UserGroupId int64 `json:"userGroupId"` UserGroup string `json:"userGroup"` - Role RoleType `json:"role"` + Role *RoleType `json:"role,omitempty"` Permission PermissionType `json:"permission"` PermissionName string `json:"permissionName"` } @@ -90,12 +90,6 @@ type RemoveDashboardAclCommand struct { // type GetDashboardAclInfoListQuery struct { DashboardId int64 + OrgId int64 Result []*DashboardAclInfoDTO } - -// Returns dashboard acl list items and parent folder items -type GetInheritedDashboardAclQuery struct { - DashboardId int64 - OrgId int64 - Result []*DashboardAcl -} diff --git a/pkg/services/guardian/guardian.go b/pkg/services/guardian/guardian.go index 4a2c32f32ab..85f528c5f76 100644 --- a/pkg/services/guardian/guardian.go +++ b/pkg/services/guardian/guardian.go @@ -10,7 +10,7 @@ type DashboardGuardian struct { user *m.SignedInUser dashId int64 orgId int64 - acl []*m.DashboardAcl + acl []*m.DashboardAclInfoDTO groups []*m.UserGroup log log.Logger } @@ -41,7 +41,7 @@ func (g *DashboardGuardian) HasPermission(permission m.PermissionType) (bool, er return true, nil } - acl, err := g.getAcl() + acl, err := g.GetAcl() if err != nil { return false, err } @@ -62,8 +62,8 @@ func (g *DashboardGuardian) HasPermission(permission m.PermissionType) (bool, er } } - if p.Role.IsValid() { - if p.Role == g.user.OrgRole && p.Permission >= permission { + if p.Role != nil { + if *p.Role == g.user.OrgRole && p.Permission >= permission { return true, nil } } @@ -73,12 +73,12 @@ func (g *DashboardGuardian) HasPermission(permission m.PermissionType) (bool, er } // Returns dashboard acl -func (g *DashboardGuardian) getAcl() ([]*m.DashboardAcl, error) { +func (g *DashboardGuardian) GetAcl() ([]*m.DashboardAclInfoDTO, error) { if g.acl != nil { return g.acl, nil } - query := m.GetInheritedDashboardAclQuery{DashboardId: g.dashId, OrgId: g.orgId} + query := m.GetDashboardAclInfoListQuery{DashboardId: g.dashId, OrgId: g.orgId} if err := bus.Dispatch(&query); err != nil { return nil, err } diff --git a/pkg/services/sqlstore/dashboard_acl.go b/pkg/services/sqlstore/dashboard_acl.go index 9912511c432..dbe6ac9f23a 100644 --- a/pkg/services/sqlstore/dashboard_acl.go +++ b/pkg/services/sqlstore/dashboard_acl.go @@ -13,7 +13,6 @@ func init() { bus.AddHandler("sql", UpdateDashboardAcl) bus.AddHandler("sql", RemoveDashboardAcl) bus.AddHandler("sql", GetDashboardAclInfoList) - bus.AddHandler("sql", GetInheritedDashboardAcl) } func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error { @@ -126,31 +125,9 @@ func RemoveDashboardAcl(cmd *m.RemoveDashboardAclCommand) error { }) } -func GetInheritedDashboardAcl(query *m.GetInheritedDashboardAclQuery) error { - rawSQL := `SELECT - da.id, - da.org_id, - da.dashboard_id, - da.user_id, - da.user_group_id, - da.role, - da.permission, - da.created, - da.updated - FROM dashboard_acl as da - WHERE da.dashboard_id IN ( - SELECT id FROM dashboard where id = ? - UNION - SELECT parent_id from dashboard where id = ? - ) AND org_id = ?` - - query.Result = make([]*m.DashboardAcl, 0) - return x.SQL(rawSQL, query.DashboardId, query.DashboardId, query.OrgId).Find(&query.Result) -} - func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error { dashboardFilter := fmt.Sprintf(`IN ( - SELECT id FROM dashboard where id = %d + SELECT %d UNION SELECT parent_id from dashboard where id = %d )`, query.DashboardId, query.DashboardId) @@ -172,7 +149,7 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error { FROM` + dialect.Quote("dashboard_acl") + ` as da LEFT OUTER JOIN ` + dialect.Quote("user") + ` AS u ON u.id = da.user_id LEFT OUTER JOIN user_group ug on ug.id = da.user_group_id - WHERE dashboard_id ` + dashboardFilter + ` + WHERE dashboard_id ` + dashboardFilter + ` AND da.org_id = ? -- Also include default permission if has_acl = 0 @@ -195,7 +172,7 @@ func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error { ` query.Result = make([]*m.DashboardAclInfoDTO, 0) - err := x.SQL(rawSQL, query.DashboardId).Find(&query.Result) + err := x.SQL(rawSQL, query.OrgId, query.DashboardId).Find(&query.Result) for _, p := range query.Result { p.PermissionName = p.Permission.String() diff --git a/pkg/services/sqlstore/dashboard_acl_test.go b/pkg/services/sqlstore/dashboard_acl_test.go index 1b4a06a1cd8..252d85368a3 100644 --- a/pkg/services/sqlstore/dashboard_acl_test.go +++ b/pkg/services/sqlstore/dashboard_acl_test.go @@ -35,9 +35,9 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) Convey("When reading dashboard acl should include acl for parent folder", func() { - query := m.GetInheritedDashboardAclQuery{OrgId: 1, DashboardId: childDash.Id} + query := m.GetDashboardAclInfoListQuery{DashboardId: childDash.Id, OrgId: 1} - err := GetInheritedDashboardAcl(&query) + err := GetDashboardAclInfoList(&query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 1) @@ -54,9 +54,9 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) Convey("When reading dashboard acl should include acl for parent folder and child", func() { - query := m.GetInheritedDashboardAclQuery{OrgId: 1, DashboardId: childDash.Id} + query := m.GetDashboardAclInfoListQuery{OrgId: 1, DashboardId: childDash.Id} - err := GetInheritedDashboardAcl(&query) + err := GetDashboardAclInfoList(&query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 2) @@ -79,7 +79,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(setDashAclCmd.Result.Id, ShouldEqual, 3) - q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q1) So(err, ShouldBeNil) @@ -109,7 +109,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) - q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 1) @@ -127,7 +127,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) - q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 0) @@ -150,7 +150,7 @@ func TestDashboardAclDataAccess(t *testing.T) { err := SetDashboardAcl(&setDashAclCmd) So(err, ShouldBeNil) - q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q1) So(err, ShouldBeNil) So(q1.Result[0].DashboardId, ShouldEqual, savedFolder.Id) @@ -164,7 +164,7 @@ func TestDashboardAclDataAccess(t *testing.T) { }) So(err, ShouldBeNil) - q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 0) @@ -180,7 +180,7 @@ func TestDashboardAclDataAccess(t *testing.T) { }) So(err, ShouldBeNil) - q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id} + q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1} err = GetDashboardAclInfoList(q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 1) diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index ea3b02a3551..59d96c4f8ca 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -169,7 +169,7 @@ func TestAccountDataAccess(t *testing.T) { err = AddOrgUser(&orgUserCmd) So(err, ShouldBeNil) - query := m.GetOrgUsersQuery{OrgId: orgUserCmd.OrgId} + query := m.GetOrgUsersQuery{OrgId: ac1.OrgId} err = GetOrgUsers(&query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 3) @@ -181,12 +181,12 @@ func TestAccountDataAccess(t *testing.T) { So(err, ShouldBeNil) Convey("When org user is deleted", func() { - cmdRemove := m.RemoveOrgUserCommand{OrgId: orgUserCmd.OrgId, UserId: ac3.Id} + cmdRemove := m.RemoveOrgUserCommand{OrgId: ac1.OrgId, UserId: ac3.Id} err := RemoveOrgUser(&cmdRemove) So(err, ShouldBeNil) Convey("Should remove dependent permissions for deleted org user", func() { - permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1} + permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: ac1.OrgId} err = GetDashboardAclInfoList(permQuery) So(err, ShouldBeNil) @@ -194,10 +194,11 @@ func TestAccountDataAccess(t *testing.T) { }) Convey("Should not remove dashboard permissions for same user in another org", func() { - permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 2} + permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 2, OrgId: ac3.OrgId} err = GetDashboardAclInfoList(permQuery) So(err, ShouldBeNil) + So(len(permQuery.Result), ShouldEqual, 1) So(permQuery.Result[0].OrgId, ShouldEqual, ac3.OrgId) So(permQuery.Result[0].UserId, ShouldEqual, ac3.Id) }) diff --git a/pkg/services/sqlstore/user_group_test.go b/pkg/services/sqlstore/user_group_test.go index 9a8d02d9a95..76056f98837 100644 --- a/pkg/services/sqlstore/user_group_test.go +++ b/pkg/services/sqlstore/user_group_test.go @@ -103,7 +103,7 @@ func TestUserGroupCommandsAndQueries(t *testing.T) { err = GetUserGroupById(query) So(err, ShouldEqual, m.ErrUserGroupNotFound) - permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1} + permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: 1} err = GetDashboardAclInfoList(permQuery) So(err, ShouldBeNil) diff --git a/pkg/services/sqlstore/user_test.go b/pkg/services/sqlstore/user_test.go index 4f99d2f550f..a65b7226eb6 100644 --- a/pkg/services/sqlstore/user_test.go +++ b/pkg/services/sqlstore/user_test.go @@ -116,7 +116,7 @@ func TestUserDataAccess(t *testing.T) { So(len(query.Result), ShouldEqual, 1) - permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1} + permQuery := &m.GetDashboardAclInfoListQuery{DashboardId: 1, OrgId: 1} err = GetDashboardAclInfoList(permQuery) So(err, ShouldBeNil) diff --git a/public/app/features/dashboard/acl/acl.ts b/public/app/features/dashboard/acl/acl.ts index 94ebeab205b..e9bcf660193 100644 --- a/public/app/features/dashboard/acl/acl.ts +++ b/public/app/features/dashboard/acl/acl.ts @@ -106,11 +106,7 @@ export class AclCtrl { typeChanged() { if (this.newType === 'Viewer' || this.newType === 'Editor') { - this.items.push(this.prepareViewModel({ - permission: 1, - role: this.newType - })); - + this.addNewItem({permission: 1, role: this.newType}); this.canUpdate = true; this.resetNewType(); } diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index b10bbffa7d3..e9e41a16b02 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -21,6 +21,10 @@ $gf-form-margin: 0.25rem; .gf-form-disabled { color: $text-color-weak; + .gf-form-select-wrapper::after { + color: $text-color-weak; + } + a, .gf-form-input { color: $text-color-weak;