mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
959ebf82da
* Folders: Show folders user has access to at the root level * Refactor * Refactor * Hide parent folders user has no access to * Skip expensive computation if possible * Fix tests * Fix potential nil access * Fix duplicated folders * Fix linter error * Fix querying folders if no managed permissions set * Update benchmark * Add special shared with me folder and fetch available non-root folders on demand * Fix parents query * Improve db query for folders * Reset benchmark changes * Fix permissions for shared with me folder * Simplify dedup * Add option to include shared folder permission to user's permissions * Fix nil UID * Remove duplicated folders from shared list * Folders: Fix fetching empty folder * Nested folders: Show dashboards with directly assigned permissions * Fix slow dashboards fetch * Refactor * Fix cycle dependencies * Move shared folder to models * Fix shared folder links * Refactor * Use feature flag for permissions * Use feature flag * Review comments * Expose shared folder UID through frontend settings * Add frontend type for sharedWithMeFolderUID option * Refactor: apply review suggestions * Fix parent uid for shared folder * Fix listing shared dashboards for users with access to all folders * Prevent creating folder with "shared" UID * Add tests for shared folders * Add test for shared dashboards * Fix linter * Add metrics for shared with me folder * Add metrics for shared with me dashboards * Fix tests * Tests: add metrics as a dependency * Fix access control metadata for shared with me folder * Use constant for shared with me * Optimize parent folders access check, fetch all folders in one query. * Use labels for metrics
126 lines
4.1 KiB
Go
126 lines
4.1 KiB
Go
package guardian
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
|
|
"github.com/grafana/grafana/pkg/services/auth/identity"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
"github.com/grafana/grafana/pkg/util/errutil"
|
|
)
|
|
|
|
var (
|
|
ErrGuardianGetDashboardFailure = errutil.Internal("guardian.getDashboardFailure", errutil.WithPublicMessage("Failed to get dashboard"))
|
|
ErrGuardianDashboardNotFound = errutil.NotFound("guardian.dashboardNotFound")
|
|
ErrGuardianFolderNotFound = errutil.NotFound("guardian.folderNotFound")
|
|
)
|
|
|
|
// DashboardGuardian to be used for guard against operations without access on dashboard and acl
|
|
type DashboardGuardian interface {
|
|
CanSave() (bool, error)
|
|
CanEdit() (bool, error)
|
|
CanView() (bool, error)
|
|
CanAdmin() (bool, error)
|
|
CanDelete() (bool, error)
|
|
CanCreate(folderID int64, isFolder bool) (bool, error)
|
|
}
|
|
|
|
// New factory for creating a new dashboard guardian instance
|
|
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
|
var New = func(ctx context.Context, dashId int64, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
panic("no guardian factory implementation provided")
|
|
}
|
|
|
|
// NewByUID factory for creating a new dashboard guardian instance
|
|
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
|
var NewByUID = func(ctx context.Context, dashUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
panic("no guardian factory implementation provided")
|
|
}
|
|
|
|
// NewByDashboard factory for creating a new dashboard guardian instance
|
|
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
|
var NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
panic("no guardian factory implementation provided")
|
|
}
|
|
|
|
// NewByFolder factory for creating a new folder guardian instance
|
|
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
|
var NewByFolder = func(ctx context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
panic("no guardian factory implementation provided")
|
|
}
|
|
|
|
// nolint:unused
|
|
type FakeDashboardGuardian struct {
|
|
DashID int64
|
|
DashUID string
|
|
OrgID int64
|
|
User identity.Requester
|
|
CanSaveValue bool
|
|
CanEditValue bool
|
|
CanViewValue bool
|
|
CanAdminValue bool
|
|
CanViewUIDs []string
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanSave() (bool, error) {
|
|
return g.CanSaveValue, nil
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanEdit() (bool, error) {
|
|
return g.CanEditValue, nil
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanView() (bool, error) {
|
|
if g.CanViewUIDs != nil {
|
|
return slices.Contains(g.CanViewUIDs, g.DashUID), nil
|
|
}
|
|
return g.CanViewValue, nil
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanAdmin() (bool, error) {
|
|
return g.CanAdminValue, nil
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanDelete() (bool, error) {
|
|
return g.CanSaveValue, nil
|
|
}
|
|
|
|
func (g *FakeDashboardGuardian) CanCreate(_ int64, _ bool) (bool, error) {
|
|
return g.CanSaveValue, nil
|
|
}
|
|
|
|
// nolint:unused
|
|
func MockDashboardGuardian(mock *FakeDashboardGuardian) {
|
|
New = func(_ context.Context, dashID int64, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
mock.OrgID = orgId
|
|
mock.DashID = dashID
|
|
mock.User = user
|
|
return mock, nil
|
|
}
|
|
|
|
NewByUID = func(_ context.Context, dashUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
mock.OrgID = orgId
|
|
mock.DashUID = dashUID
|
|
mock.User = user
|
|
return mock, nil
|
|
}
|
|
|
|
NewByDashboard = func(_ context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
mock.OrgID = orgId
|
|
mock.DashUID = dash.UID
|
|
mock.DashID = dash.ID
|
|
mock.User = user
|
|
return mock, nil
|
|
}
|
|
|
|
NewByFolder = func(_ context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
mock.OrgID = orgId
|
|
mock.DashUID = f.UID
|
|
// nolint:staticcheck
|
|
mock.DashID = f.ID
|
|
mock.User = user
|
|
return mock, nil
|
|
}
|
|
}
|