Folders: Allow listing folders with write permission (#83527)

* Folders: Allow listing folders with write permission

* Check for subfolder access if parent does not have

* Add test

* GetFolders: fix ordering

* Apply suggestion from code review
This commit is contained in:
Sofia Papagiannaki
2024-03-15 14:05:27 +02:00
committed by GitHub
parent 39232a0776
commit 1208888bb6
9 changed files with 347 additions and 16 deletions
+41 -13
View File
@@ -22,6 +22,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/auth/identity"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/guardian"
@@ -298,12 +299,16 @@ func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) (
return nil, err
}
canView, err := g.CanView()
guardianFunc := g.CanView
if q.Permission == dashboardaccess.PERMISSION_EDIT {
guardianFunc = g.CanEdit
}
hasAccess, err := guardianFunc()
if err != nil {
return nil, err
}
if !canView {
if !hasAccess {
return nil, dashboards.ErrFolderAccessDenied
}
@@ -341,8 +346,19 @@ func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) (
func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
permissions := q.SignedInUser.GetPermissions()
folderPermissions := permissions[dashboards.ActionFoldersRead]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsRead]...)
var folderPermissions []string
if q.Permission == dashboardaccess.PERMISSION_EDIT {
folderPermissions = permissions[dashboards.ActionFoldersWrite]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsWrite]...)
} else {
folderPermissions = permissions[dashboards.ActionFoldersRead]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsRead]...)
}
if len(folderPermissions) == 0 && !q.SignedInUser.GetIsGrafanaAdmin() {
return nil, nil
}
q.FolderUIDs = make([]string, 0, len(folderPermissions))
for _, p := range folderPermissions {
if p == dashboards.ScopeFoldersAll {
@@ -401,12 +417,12 @@ func (s *Service) getRootFolders(ctx context.Context, q *folder.GetChildrenQuery
// GetSharedWithMe returns folders available to user, which cannot be accessed from the root folders
func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
start := time.Now()
availableNonRootFolders, err := s.getAvailableNonRootFolders(ctx, q.OrgID, q.SignedInUser)
availableNonRootFolders, err := s.getAvailableNonRootFolders(ctx, q)
if err != nil {
s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("failure").Observe(time.Since(start).Seconds())
return nil, folder.ErrInternal.Errorf("failed to fetch subfolders to which the user has explicit access: %w", err)
}
rootFolders, err := s.GetChildren(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser})
rootFolders, err := s.GetChildren(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser, Permission: q.Permission})
if err != nil {
s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("failure").Observe(time.Since(start).Seconds())
return nil, folder.ErrInternal.Errorf("failed to fetch root folders to which the user has access: %w", err)
@@ -417,10 +433,21 @@ func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuer
return availableNonRootFolders, nil
}
func (s *Service) getAvailableNonRootFolders(ctx context.Context, orgID int64, user identity.Requester) ([]*folder.Folder, error) {
permissions := user.GetPermissions()
folderPermissions := permissions[dashboards.ActionFoldersRead]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsRead]...)
func (s *Service) getAvailableNonRootFolders(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.Folder, error) {
permissions := q.SignedInUser.GetPermissions()
var folderPermissions []string
if q.Permission == dashboardaccess.PERMISSION_EDIT {
folderPermissions = permissions[dashboards.ActionFoldersWrite]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsWrite]...)
} else {
folderPermissions = permissions[dashboards.ActionFoldersRead]
folderPermissions = append(folderPermissions, permissions[dashboards.ActionDashboardsRead]...)
}
if len(folderPermissions) == 0 {
return nil, nil
}
nonRootFolders := make([]*folder.Folder, 0)
folderUids := make([]string, 0, len(folderPermissions))
for _, p := range folderPermissions {
@@ -437,8 +464,9 @@ func (s *Service) getAvailableNonRootFolders(ctx context.Context, orgID int64, u
dashFolders, err := s.GetFolders(ctx, folder.GetFoldersQuery{
UIDs: folderUids,
OrgID: orgID,
SignedInUser: user,
OrgID: q.OrgID,
SignedInUser: q.SignedInUser,
OrderByTitle: true,
WithFullpathUIDs: true,
})
if err != nil {