mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Permissions: Fix inherited folder permissions can prevent new permissions being added to a dashboard (#33329)
In the case permissions has been added on dashboard(s). Later permissions for the parent folder of the dashboard is edited in such a way that dashboard in that folder has a permission that is a duplicate of an inherited one. This PR changes so that duplicate permissions are now filtered out from /api/dashboards/id/<dashboard id>/permissions. Duplicate permission are not filtered out if the permission on dashboard is higher than on the inherited folder. Fixes #33296 Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
parent
6d95f2f1db
commit
7e6db1ee7e
@ -24,7 +24,7 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.
|
|||||||
return dashboardGuardianResponse(err)
|
return dashboardGuardianResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
acl, err := g.GetAcl()
|
acl, err := g.GetACLWithoutDuplicates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Error(500, "Failed to get dashboard permissions", err)
|
return response.Error(500, "Failed to get dashboard permissions", err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,14 @@ type DashboardGuardian interface {
|
|||||||
CanAdmin() (bool, error)
|
CanAdmin() (bool, error)
|
||||||
HasPermission(permission models.PermissionType) (bool, error)
|
HasPermission(permission models.PermissionType) (bool, error)
|
||||||
CheckPermissionBeforeUpdate(permission models.PermissionType, updatePermissions []*models.DashboardAcl) (bool, error)
|
CheckPermissionBeforeUpdate(permission models.PermissionType, updatePermissions []*models.DashboardAcl) (bool, error)
|
||||||
|
|
||||||
|
// GetAcl returns ACL.
|
||||||
GetAcl() ([]*models.DashboardAclInfoDTO, error)
|
GetAcl() ([]*models.DashboardAclInfoDTO, error)
|
||||||
|
|
||||||
|
// GetACLWithoutDuplicates returns ACL and strips any permission
|
||||||
|
// that already has an inherited permission with higher or equal
|
||||||
|
// permission.
|
||||||
|
GetACLWithoutDuplicates() ([]*models.DashboardAclInfoDTO, error)
|
||||||
GetHiddenACL(*setting.Cfg) ([]*models.DashboardAcl, error)
|
GetHiddenACL(*setting.Cfg) ([]*models.DashboardAcl, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,6 +209,42 @@ func (g *dashboardGuardianImpl) GetAcl() ([]*models.DashboardAclInfoDTO, error)
|
|||||||
return g.acl, nil
|
return g.acl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *dashboardGuardianImpl) GetACLWithoutDuplicates() ([]*models.DashboardAclInfoDTO, error) {
|
||||||
|
acl, err := g.GetAcl()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonInherited := []*models.DashboardAclInfoDTO{}
|
||||||
|
inherited := []*models.DashboardAclInfoDTO{}
|
||||||
|
for _, aclItem := range acl {
|
||||||
|
if aclItem.Inherited {
|
||||||
|
inherited = append(inherited, aclItem)
|
||||||
|
} else {
|
||||||
|
nonInherited = append(nonInherited, aclItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []*models.DashboardAclInfoDTO{}
|
||||||
|
for _, nonInheritedAclItem := range nonInherited {
|
||||||
|
duplicate := false
|
||||||
|
for _, inheritedAclItem := range inherited {
|
||||||
|
if nonInheritedAclItem.IsDuplicateOf(inheritedAclItem) && nonInheritedAclItem.Permission <= inheritedAclItem.Permission {
|
||||||
|
duplicate = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !duplicate {
|
||||||
|
result = append(result, nonInheritedAclItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(inherited, result...)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *dashboardGuardianImpl) getTeams() ([]*models.TeamDTO, error) {
|
func (g *dashboardGuardianImpl) getTeams() ([]*models.TeamDTO, error) {
|
||||||
if g.teams != nil {
|
if g.teams != nil {
|
||||||
return g.teams, nil
|
return g.teams, nil
|
||||||
@ -290,6 +333,10 @@ func (g *FakeDashboardGuardian) GetAcl() ([]*models.DashboardAclInfoDTO, error)
|
|||||||
return g.GetAclValue, nil
|
return g.GetAclValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *FakeDashboardGuardian) GetACLWithoutDuplicates() ([]*models.DashboardAclInfoDTO, error) {
|
||||||
|
return g.GetAcl()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *FakeDashboardGuardian) GetHiddenACL(cfg *setting.Cfg) ([]*models.DashboardAcl, error) {
|
func (g *FakeDashboardGuardian) GetHiddenACL(cfg *setting.Cfg) ([]*models.DashboardAcl, error) {
|
||||||
return g.GetHiddenAclValue, nil
|
return g.GetHiddenAclValue, nil
|
||||||
}
|
}
|
||||||
|
@ -726,3 +726,45 @@ func TestGuardianGetHiddenACL(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGuardianGetAclWithoutDuplicates(t *testing.T) {
|
||||||
|
t.Run("Get hidden ACL tests", func(t *testing.T) {
|
||||||
|
t.Cleanup(bus.ClearBusHandlers)
|
||||||
|
|
||||||
|
bus.AddHandler("test", func(query *models.GetDashboardAclInfoListQuery) error {
|
||||||
|
query.Result = []*models.DashboardAclInfoDTO{
|
||||||
|
{Inherited: true, UserId: 3, UserLogin: "user3", Permission: models.PERMISSION_EDIT},
|
||||||
|
{Inherited: false, UserId: 3, UserLogin: "user3", Permission: models.PERMISSION_VIEW},
|
||||||
|
{Inherited: false, UserId: 2, UserLogin: "user2", Permission: models.PERMISSION_ADMIN},
|
||||||
|
{Inherited: true, UserId: 4, UserLogin: "user4", Permission: models.PERMISSION_ADMIN},
|
||||||
|
{Inherited: false, UserId: 4, UserLogin: "user4", Permission: models.PERMISSION_ADMIN},
|
||||||
|
{Inherited: false, UserId: 5, UserLogin: "user5", Permission: models.PERMISSION_EDIT},
|
||||||
|
{Inherited: true, UserId: 6, UserLogin: "user6", Permission: models.PERMISSION_VIEW},
|
||||||
|
{Inherited: false, UserId: 6, UserLogin: "user6", Permission: models.PERMISSION_EDIT},
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should get acl without duplicates", func(t *testing.T) {
|
||||||
|
user := &models.SignedInUser{
|
||||||
|
OrgId: orgID,
|
||||||
|
UserId: 1,
|
||||||
|
Login: "user1",
|
||||||
|
}
|
||||||
|
g := New(dashboardID, orgID, user)
|
||||||
|
|
||||||
|
acl, err := g.GetACLWithoutDuplicates()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, acl)
|
||||||
|
require.Len(t, acl, 6)
|
||||||
|
require.ElementsMatch(t, []*models.DashboardAclInfoDTO{
|
||||||
|
{Inherited: true, UserId: 3, UserLogin: "user3", Permission: models.PERMISSION_EDIT},
|
||||||
|
{Inherited: true, UserId: 4, UserLogin: "user4", Permission: models.PERMISSION_ADMIN},
|
||||||
|
{Inherited: true, UserId: 6, UserLogin: "user6", Permission: models.PERMISSION_VIEW},
|
||||||
|
{Inherited: false, UserId: 2, UserLogin: "user2", Permission: models.PERMISSION_ADMIN},
|
||||||
|
{Inherited: false, UserId: 5, UserLogin: "user5", Permission: models.PERMISSION_EDIT},
|
||||||
|
{Inherited: false, UserId: 6, UserLogin: "user6", Permission: models.PERMISSION_EDIT},
|
||||||
|
}, acl)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user