mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Folders: Fix guardian to use folder service (#99339)
This commit is contained in:
parent
59b246dbea
commit
192a81d07f
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
@ -40,7 +41,7 @@ func TestHTTPServer_DeleteDashboardSnapshot(t *testing.T) {
|
|||||||
hs.DashboardService = svc
|
hs.DashboardService = svc
|
||||||
|
|
||||||
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
||||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService)
|
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ func TestHTTPServer_GetDashboard_AccessControl(t *testing.T) {
|
|||||||
hs.starService = startest.NewStarServiceFake()
|
hs.starService = startest.NewStarServiceFake()
|
||||||
hs.dashboardProvisioningService = mockDashboardProvisioningService{}
|
hs.dashboardProvisioningService = mockDashboardProvisioningService{}
|
||||||
|
|
||||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService)
|
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ func TestHTTPServer_DeleteDashboardByUID_AccessControl(t *testing.T) {
|
|||||||
license.On("FeatureEnabled", publicdashboardModels.FeaturePublicDashboardsEmailSharing).Return(false)
|
license.On("FeatureEnabled", publicdashboardModels.FeaturePublicDashboardsEmailSharing).Return(false)
|
||||||
hs.PublicDashboardsApi = api.ProvideApi(pubDashService, nil, hs.AccessControl, featuremgmt.WithFeatures(), middleware, hs.Cfg, license)
|
hs.PublicDashboardsApi = api.ProvideApi(pubDashService, nil, hs.AccessControl, featuremgmt.WithFeatures(), middleware, hs.Cfg, license)
|
||||||
|
|
||||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService)
|
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
deleteDashboard := func(server *webtest.Server, permissions []accesscontrol.Permission) (*http.Response, error) {
|
deleteDashboard := func(server *webtest.Server, permissions []accesscontrol.Permission) (*http.Response, error) {
|
||||||
@ -330,7 +330,7 @@ func TestHTTPServer_GetDashboardVersions_AccessControl(t *testing.T) {
|
|||||||
ExpectedDashboardVersion: &dashver.DashboardVersionDTO{},
|
ExpectedDashboardVersion: &dashver.DashboardVersionDTO{},
|
||||||
}
|
}
|
||||||
|
|
||||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService)
|
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +495,7 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog
|
|||||||
}
|
}
|
||||||
|
|
||||||
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
||||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService)
|
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||||
|
|
||||||
m.Get("/api/folders", hs.GetFolders)
|
m.Get("/api/folders", hs.GetFolders)
|
||||||
m.Get("/api/search", hs.Search)
|
m.Get("/api/search", hs.Search)
|
||||||
|
@ -56,6 +56,7 @@ var (
|
|||||||
provisionerPermissions = []accesscontrol.Permission{
|
provisionerPermissions = []accesscontrol.Permission{
|
||||||
{Action: dashboards.ActionFoldersCreate, Scope: dashboards.ScopeFoldersAll},
|
{Action: dashboards.ActionFoldersCreate, Scope: dashboards.ScopeFoldersAll},
|
||||||
{Action: dashboards.ActionFoldersWrite, Scope: dashboards.ScopeFoldersAll},
|
{Action: dashboards.ActionFoldersWrite, Scope: dashboards.ScopeFoldersAll},
|
||||||
|
{Action: dashboards.ActionFoldersRead, Scope: dashboards.ScopeFoldersAll},
|
||||||
{Action: dashboards.ActionDashboardsCreate, Scope: dashboards.ScopeFoldersAll},
|
{Action: dashboards.ActionDashboardsCreate, Scope: dashboards.ScopeFoldersAll},
|
||||||
{Action: dashboards.ActionDashboardsWrite, Scope: dashboards.ScopeFoldersAll},
|
{Action: dashboards.ActionDashboardsWrite, Scope: dashboards.ScopeFoldersAll},
|
||||||
{Action: datasources.ActionRead, Scope: datasources.ScopeAll},
|
{Action: datasources.ActionRead, Scope: datasources.ScopeAll},
|
||||||
@ -611,13 +612,28 @@ func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashbo
|
|||||||
if newDashboard {
|
if newDashboard {
|
||||||
// if it's a new dashboard/folder check the parent folder permissions
|
// if it's a new dashboard/folder check the parent folder permissions
|
||||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
||||||
// nolint:staticcheck
|
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
guard, err := guardian.New(ctx, d.FolderID, d.OrgID, user)
|
ID: d.FolderID, // nolint:staticcheck
|
||||||
|
OrgID: d.OrgID,
|
||||||
|
}, d.OrgID, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return guard, nil
|
return guard, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.IsFolder {
|
||||||
|
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
|
ID: d.ID, // nolint:staticcheck
|
||||||
|
UID: d.UID,
|
||||||
|
OrgID: d.OrgID,
|
||||||
|
}, d.OrgID, user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return guard, nil
|
||||||
|
}
|
||||||
|
|
||||||
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
|
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||||
@ -896,7 +897,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc
|
|||||||
)
|
)
|
||||||
dashboardService.RegisterDashboardPermissions(dashboardPermissions)
|
dashboardService.RegisterDashboardPermissions(dashboardPermissions)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
guardian.InitAccessControlGuardian(cfg, ac, dashboardService)
|
guardian.InitAccessControlGuardian(cfg, ac, dashboardService, folderService, log.NewNopLogger())
|
||||||
|
|
||||||
savedFolder := saveTestFolder(t, "Saved folder", testOrgID, sqlStore)
|
savedFolder := saveTestFolder(t, "Saved folder", testOrgID, sqlStore)
|
||||||
savedDashInFolder := saveTestDashboard(t, "Saved dash in folder", testOrgID, savedFolder.UID, sqlStore)
|
savedDashInFolder := saveTestDashboard(t, "Saved dash in folder", testOrgID, savedFolder.UID, sqlStore)
|
||||||
|
@ -392,7 +392,7 @@ func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQu
|
|||||||
|
|
||||||
// we only need to check access to the folder
|
// we only need to check access to the folder
|
||||||
// if the parent is accessible then the subfolders are accessible as well (due to inheritance)
|
// if the parent is accessible then the subfolders are accessible as well (due to inheritance)
|
||||||
g, err := guardian.NewByUID(ctx, q.UID, q.OrgID, q.SignedInUser)
|
g, err := guardian.NewByFolderUID(ctx, q.UID, q.OrgID, q.SignedInUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -941,7 +941,7 @@ func (s *Service) DeleteLegacy(ctx context.Context, cmd *folder.DeleteFolderComm
|
|||||||
return folder.ErrBadRequest.Errorf("invalid orgID")
|
return folder.ErrBadRequest.Errorf("invalid orgID")
|
||||||
}
|
}
|
||||||
|
|
||||||
guard, err := guardian.NewByUID(ctx, cmd.UID, cmd.OrgID, cmd.SignedInUser)
|
guard, err := guardian.NewByFolderUID(ctx, cmd.UID, cmd.OrgID, cmd.SignedInUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1414,13 +1414,19 @@ func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashbo
|
|||||||
// if it's a new dashboard/folder check the parent folder permissions
|
// if it's a new dashboard/folder check the parent folder permissions
|
||||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
|
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Folder).Inc()
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
guard, err := guardian.New(ctx, d.FolderID, d.OrgID, user)
|
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
|
ID: d.FolderID, // nolint:staticcheck
|
||||||
|
OrgID: d.OrgID,
|
||||||
|
}, d.OrgID, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return guard, nil
|
return guard, nil
|
||||||
}
|
}
|
||||||
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
|
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
|
UID: d.UID,
|
||||||
|
OrgID: d.OrgID,
|
||||||
|
}, d.OrgID, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ var _ DashboardGuardian = new(accessControlDashboardGuardian)
|
|||||||
func NewAccessControlDashboardGuardian(
|
func NewAccessControlDashboardGuardian(
|
||||||
ctx context.Context, cfg *setting.Cfg, dashboardId int64, user identity.Requester,
|
ctx context.Context, cfg *setting.Cfg, dashboardId int64, user identity.Requester,
|
||||||
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
||||||
|
foldersService folder.Service, logger log.Logger,
|
||||||
) (DashboardGuardian, error) {
|
) (DashboardGuardian, error) {
|
||||||
var dashboard *dashboards.Dashboard
|
var dashboard *dashboards.Dashboard
|
||||||
if dashboardId != 0 {
|
if dashboardId != 0 {
|
||||||
@ -37,6 +38,7 @@ func NewAccessControlDashboardGuardian(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dashboard != nil && dashboard.IsFolder {
|
if dashboard != nil && dashboard.IsFolder {
|
||||||
|
logger.Info("using dashboard guardian for folder", "folder", dashboard.UID)
|
||||||
return &accessControlFolderGuardian{
|
return &accessControlFolderGuardian{
|
||||||
accessControlBaseGuardian: accessControlBaseGuardian{
|
accessControlBaseGuardian: accessControlBaseGuardian{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@ -58,68 +60,22 @@ func NewAccessControlDashboardGuardian(
|
|||||||
user: user,
|
user: user,
|
||||||
ac: ac,
|
ac: ac,
|
||||||
dashboardService: dashboardService,
|
dashboardService: dashboardService,
|
||||||
},
|
folderService: foldersService,
|
||||||
dashboard: dashboard,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboardUID.
|
|
||||||
func NewAccessControlDashboardGuardianByUID(
|
|
||||||
ctx context.Context, cfg *setting.Cfg, dashboardUID string, user identity.Requester,
|
|
||||||
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
|
||||||
) (DashboardGuardian, error) {
|
|
||||||
var dashboard *dashboards.Dashboard
|
|
||||||
if dashboardUID != "" {
|
|
||||||
q := &dashboards.GetDashboardQuery{
|
|
||||||
UID: dashboardUID,
|
|
||||||
OrgID: user.GetOrgID(),
|
|
||||||
}
|
|
||||||
|
|
||||||
qResult, err := dashboardService.GetDashboard(ctx, q)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
|
||||||
return nil, ErrGuardianDashboardNotFound.Errorf("failed to get dashboard by UID: %w", err)
|
|
||||||
}
|
|
||||||
return nil, ErrGuardianGetDashboardFailure.Errorf("failed to get dashboard by UID: %w", err)
|
|
||||||
}
|
|
||||||
dashboard = qResult
|
|
||||||
}
|
|
||||||
|
|
||||||
if dashboard != nil && dashboard.IsFolder {
|
|
||||||
return &accessControlFolderGuardian{
|
|
||||||
accessControlBaseGuardian: accessControlBaseGuardian{
|
|
||||||
ctx: ctx,
|
|
||||||
cfg: cfg,
|
|
||||||
log: log.New("folder.permissions"),
|
|
||||||
user: user,
|
|
||||||
ac: ac,
|
|
||||||
dashboardService: dashboardService,
|
|
||||||
},
|
|
||||||
folder: dashboards.FromDashboard(dashboard),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &accessControlDashboardGuardian{
|
|
||||||
accessControlBaseGuardian: accessControlBaseGuardian{
|
|
||||||
cfg: cfg,
|
|
||||||
ctx: ctx,
|
|
||||||
log: log.New("dashboard.permissions"),
|
|
||||||
user: user,
|
|
||||||
ac: ac,
|
|
||||||
dashboardService: dashboardService,
|
|
||||||
},
|
},
|
||||||
dashboard: dashboard,
|
dashboard: dashboard,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboard.
|
// NewAccessControlDashboardGuardianByDashboard creates a dashboard guardian by the provided dashboard.
|
||||||
// This constructor should be preferred over the other two if the dashboard in available
|
// This constructor should be preferred over the other two if the dashboard is available
|
||||||
// since it avoids querying the database for fetching the dashboard.
|
// since it avoids querying the database for fetching the dashboard.
|
||||||
func NewAccessControlDashboardGuardianByDashboard(
|
func NewAccessControlDashboardGuardianByDashboard(
|
||||||
ctx context.Context, cfg *setting.Cfg, dashboard *dashboards.Dashboard, user identity.Requester,
|
ctx context.Context, cfg *setting.Cfg, dashboard *dashboards.Dashboard, user identity.Requester,
|
||||||
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService, folderService folder.Service,
|
||||||
|
logger log.Logger,
|
||||||
) (DashboardGuardian, error) {
|
) (DashboardGuardian, error) {
|
||||||
if dashboard != nil && dashboard.IsFolder {
|
if dashboard != nil && dashboard.IsFolder {
|
||||||
|
logger.Info("using by dashboard guardian for folder", "folder", dashboard.UID)
|
||||||
return &accessControlFolderGuardian{
|
return &accessControlFolderGuardian{
|
||||||
accessControlBaseGuardian: accessControlBaseGuardian{
|
accessControlBaseGuardian: accessControlBaseGuardian{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@ -128,6 +84,7 @@ func NewAccessControlDashboardGuardianByDashboard(
|
|||||||
user: user,
|
user: user,
|
||||||
ac: ac,
|
ac: ac,
|
||||||
dashboardService: dashboardService,
|
dashboardService: dashboardService,
|
||||||
|
folderService: folderService,
|
||||||
},
|
},
|
||||||
folder: dashboards.FromDashboard(dashboard),
|
folder: dashboards.FromDashboard(dashboard),
|
||||||
}, nil
|
}, nil
|
||||||
@ -141,16 +98,35 @@ func NewAccessControlDashboardGuardianByDashboard(
|
|||||||
user: user,
|
user: user,
|
||||||
ac: ac,
|
ac: ac,
|
||||||
dashboardService: dashboardService,
|
dashboardService: dashboardService,
|
||||||
|
folderService: folderService,
|
||||||
},
|
},
|
||||||
dashboard: dashboard,
|
dashboard: dashboard,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccessControlFolderGuardian creates a folder guardian by the provided folder.
|
// NewAccessControlFolderGuardianByUID creates a folder guardian by the provided folderUID.
|
||||||
func NewAccessControlFolderGuardian(
|
func NewAccessControlFolderGuardianByUID(
|
||||||
ctx context.Context, cfg *setting.Cfg, f *folder.Folder, user identity.Requester,
|
ctx context.Context, cfg *setting.Cfg, folderUID string, user identity.Requester,
|
||||||
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService, foldersService folder.Service,
|
||||||
) (DashboardGuardian, error) {
|
) (DashboardGuardian, error) {
|
||||||
|
var f *folder.Folder
|
||||||
|
if folderUID != "" {
|
||||||
|
q := &folder.GetFolderQuery{
|
||||||
|
UID: &folderUID,
|
||||||
|
OrgID: user.GetOrgID(),
|
||||||
|
SignedInUser: user,
|
||||||
|
}
|
||||||
|
|
||||||
|
qResult, err := foldersService.Get(ctx, q)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||||
|
return nil, ErrGuardianFolderNotFound.Errorf("failed to get folder by UID: %w", err)
|
||||||
|
}
|
||||||
|
return nil, ErrGuardianGetFolderFailure.Errorf("failed to get folder by UID: %w", err)
|
||||||
|
}
|
||||||
|
f = qResult
|
||||||
|
}
|
||||||
|
|
||||||
return &accessControlFolderGuardian{
|
return &accessControlFolderGuardian{
|
||||||
accessControlBaseGuardian: accessControlBaseGuardian{
|
accessControlBaseGuardian: accessControlBaseGuardian{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@ -159,6 +135,44 @@ func NewAccessControlFolderGuardian(
|
|||||||
user: user,
|
user: user,
|
||||||
ac: ac,
|
ac: ac,
|
||||||
dashboardService: dashboardService,
|
dashboardService: dashboardService,
|
||||||
|
folderService: foldersService,
|
||||||
|
},
|
||||||
|
folder: f,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAccessControlFolderGuardian creates a folder guardian by the provided folder.
|
||||||
|
func NewAccessControlFolderGuardian(
|
||||||
|
ctx context.Context, cfg *setting.Cfg, f *folder.Folder, user identity.Requester,
|
||||||
|
ac accesscontrol.AccessControl, orgID int64, dashboardService dashboards.DashboardService,
|
||||||
|
folderService folder.Service,
|
||||||
|
) (DashboardGuardian, error) {
|
||||||
|
if f.UID == "" { // nolint:staticcheck
|
||||||
|
query := &folder.GetFolderQuery{
|
||||||
|
ID: &f.ID, // nolint:staticcheck
|
||||||
|
OrgID: orgID,
|
||||||
|
SignedInUser: user,
|
||||||
|
}
|
||||||
|
|
||||||
|
folder, err := folderService.Get(ctx, query)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||||
|
return nil, ErrGuardianFolderNotFound.Errorf("failed to get folder: %w", err)
|
||||||
|
}
|
||||||
|
return nil, ErrGuardianGetFolderFailure.Errorf("failed to get folder: %w", err)
|
||||||
|
}
|
||||||
|
f = folder
|
||||||
|
}
|
||||||
|
|
||||||
|
return &accessControlFolderGuardian{
|
||||||
|
accessControlBaseGuardian: accessControlBaseGuardian{
|
||||||
|
ctx: ctx,
|
||||||
|
cfg: cfg,
|
||||||
|
log: log.New("folder.permissions"),
|
||||||
|
user: user,
|
||||||
|
ac: ac,
|
||||||
|
dashboardService: dashboardService,
|
||||||
|
folderService: folderService,
|
||||||
},
|
},
|
||||||
folder: f,
|
folder: f,
|
||||||
}, nil
|
}, nil
|
||||||
@ -171,6 +185,7 @@ type accessControlBaseGuardian struct {
|
|||||||
user identity.Requester
|
user identity.Requester
|
||||||
ac accesscontrol.AccessControl
|
ac accesscontrol.AccessControl
|
||||||
dashboardService dashboards.DashboardService
|
dashboardService dashboards.DashboardService
|
||||||
|
folderService folder.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
type accessControlDashboardGuardian struct {
|
type accessControlDashboardGuardian struct {
|
||||||
@ -353,24 +368,24 @@ func (a *accessControlFolderGuardian) evaluate(evaluator accesscontrol.Evaluator
|
|||||||
return ok, err
|
return ok, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *accessControlDashboardGuardian) loadParentFolder(folderID int64) (*dashboards.Dashboard, error) {
|
func (a *accessControlDashboardGuardian) loadParentFolder(folderID int64) (*folder.Folder, error) {
|
||||||
if folderID == 0 {
|
if folderID == 0 {
|
||||||
return &dashboards.Dashboard{UID: accesscontrol.GeneralFolderUID}, nil
|
return &folder.Folder{UID: accesscontrol.GeneralFolderUID, OrgID: a.user.GetOrgID()}, nil
|
||||||
}
|
}
|
||||||
folderQuery := &dashboards.GetDashboardQuery{ID: folderID, OrgID: a.user.GetOrgID()}
|
folderQuery := &folder.GetFolderQuery{ID: &folderID, OrgID: a.user.GetOrgID(), SignedInUser: a.user}
|
||||||
folderQueryResult, err := a.dashboardService.GetDashboard(a.ctx, folderQuery)
|
folderQueryResult, err := a.folderService.Get(a.ctx, folderQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return folderQueryResult, nil
|
return folderQueryResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *accessControlFolderGuardian) loadParentFolder(folderID int64) (*dashboards.Dashboard, error) {
|
func (a *accessControlFolderGuardian) loadParentFolder(folderID int64) (*folder.Folder, error) {
|
||||||
if folderID == 0 {
|
if folderID == 0 {
|
||||||
return &dashboards.Dashboard{UID: accesscontrol.GeneralFolderUID}, nil
|
return &folder.Folder{UID: accesscontrol.GeneralFolderUID, OrgID: a.user.GetOrgID()}, nil
|
||||||
}
|
}
|
||||||
folderQuery := &dashboards.GetDashboardQuery{ID: folderID, OrgID: a.user.GetOrgID()}
|
folderQuery := &folder.GetFolderQuery{ID: &folderID, OrgID: a.user.GetOrgID(), SignedInUser: a.user}
|
||||||
folderQueryResult, err := a.dashboardService.GetDashboard(a.ctx, folderQuery)
|
folderQueryResult, err := a.folderService.Get(a.ctx, folderQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
@ -976,7 +977,7 @@ func setupAccessControlGuardianTest(
|
|||||||
userPermissions[orgID][p.Action] = append(userPermissions[orgID][p.Action], p.Scope)
|
userPermissions[orgID][p.Action] = append(userPermissions[orgID][p.Action], p.Scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := NewAccessControlDashboardGuardianByDashboard(context.Background(), cfg, d, &user.SignedInUser{OrgID: orgID, Permissions: userPermissions}, ac, fakeDashboardService)
|
g, err := NewAccessControlDashboardGuardianByDashboard(context.Background(), cfg, d, &user.SignedInUser{OrgID: orgID, Permissions: userPermissions}, ac, fakeDashboardService, folderSvc, log.NewNopLogger())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ var (
|
|||||||
ErrGuardianGetDashboardFailure = errutil.Internal("guardian.getDashboardFailure", errutil.WithPublicMessage("Failed to get dashboard"))
|
ErrGuardianGetDashboardFailure = errutil.Internal("guardian.getDashboardFailure", errutil.WithPublicMessage("Failed to get dashboard"))
|
||||||
ErrGuardianDashboardNotFound = errutil.NotFound("guardian.dashboardNotFound")
|
ErrGuardianDashboardNotFound = errutil.NotFound("guardian.dashboardNotFound")
|
||||||
ErrGuardianFolderNotFound = errutil.NotFound("guardian.folderNotFound")
|
ErrGuardianFolderNotFound = errutil.NotFound("guardian.folderNotFound")
|
||||||
|
ErrGuardianGetFolderFailure = errutil.Internal("guardian.getFolderFailure", errutil.WithPublicMessage("Failed to get folder"))
|
||||||
)
|
)
|
||||||
|
|
||||||
// DashboardGuardian to be used for guard against operations without access on dashboard and acl
|
// DashboardGuardian to be used for guard against operations without access on dashboard and acl
|
||||||
@ -33,18 +34,18 @@ var New = func(ctx context.Context, dashId int64, orgId int64, user identity.Req
|
|||||||
panic("no guardian factory implementation provided")
|
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
|
// NewByDashboard factory for creating a new dashboard guardian instance
|
||||||
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
// 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) {
|
var NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
panic("no guardian factory implementation provided")
|
panic("no guardian factory implementation provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewByFolderUID factory for creating a new folder guardian instance
|
||||||
|
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
||||||
|
var NewByFolderUID = func(ctx context.Context, folderUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
|
panic("no guardian factory implementation provided")
|
||||||
|
}
|
||||||
|
|
||||||
// NewByFolder factory for creating a new folder guardian instance
|
// NewByFolder factory for creating a new folder guardian instance
|
||||||
// When using access control this function is replaced on startup and the AccessControlDashboardGuardian is returned
|
// 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) {
|
var NewByFolder = func(ctx context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
@ -107,14 +108,6 @@ func MockDashboardGuardian(mock *FakeDashboardGuardian) {
|
|||||||
mock.User = user
|
mock.User = user
|
||||||
return mock, nil
|
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) {
|
NewByDashboard = func(_ context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
mock.OrgID = orgId
|
mock.OrgID = orgId
|
||||||
mock.DashUID = dash.UID
|
mock.DashUID = dash.UID
|
||||||
@ -123,6 +116,13 @@ func MockDashboardGuardian(mock *FakeDashboardGuardian) {
|
|||||||
return mock, nil
|
return mock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewByFolderUID = func(_ context.Context, folderUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
|
mock.OrgID = orgId
|
||||||
|
mock.DashUID = folderUID
|
||||||
|
mock.User = user
|
||||||
|
return mock, nil
|
||||||
|
}
|
||||||
|
|
||||||
NewByFolder = func(_ context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
NewByFolder = func(_ context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
mock.OrgID = orgId
|
mock.OrgID = orgId
|
||||||
mock.DashUID = f.UID
|
mock.DashUID = f.UID
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/folder"
|
"github.com/grafana/grafana/pkg/services/folder"
|
||||||
@ -16,28 +17,29 @@ type Provider struct{}
|
|||||||
func ProvideService(
|
func ProvideService(
|
||||||
cfg *setting.Cfg, ac accesscontrol.AccessControl,
|
cfg *setting.Cfg, ac accesscontrol.AccessControl,
|
||||||
dashboardService dashboards.DashboardService, teamService team.Service,
|
dashboardService dashboards.DashboardService, teamService team.Service,
|
||||||
|
folderService folder.Service,
|
||||||
) *Provider {
|
) *Provider {
|
||||||
// TODO: Fix this hack, see https://github.com/grafana/grafana-enterprise/issues/2935
|
// TODO: Fix this hack, see https://github.com/grafana/grafana-enterprise/issues/2935
|
||||||
InitAccessControlGuardian(cfg, ac, dashboardService)
|
InitAccessControlGuardian(cfg, ac, dashboardService, folderService, log.New("guardian"))
|
||||||
return &Provider{}
|
return &Provider{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitAccessControlGuardian(
|
func InitAccessControlGuardian(
|
||||||
cfg *setting.Cfg, ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
cfg *setting.Cfg, ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService, folderService folder.Service, logger log.Logger,
|
||||||
) {
|
) {
|
||||||
New = func(ctx context.Context, dashId int64, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
New = func(ctx context.Context, dashId int64, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
return NewAccessControlDashboardGuardian(ctx, cfg, dashId, user, ac, dashboardService)
|
return NewAccessControlDashboardGuardian(ctx, cfg, dashId, user, ac, dashboardService, folderService, logger)
|
||||||
}
|
|
||||||
|
|
||||||
NewByUID = func(ctx context.Context, dashUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
|
||||||
return NewAccessControlDashboardGuardianByUID(ctx, cfg, dashUID, user, ac, dashboardService)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
NewByDashboard = func(ctx context.Context, dash *dashboards.Dashboard, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
return NewAccessControlDashboardGuardianByDashboard(ctx, cfg, dash, user, ac, dashboardService)
|
return NewAccessControlDashboardGuardianByDashboard(ctx, cfg, dash, user, ac, dashboardService, folderService, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
NewByFolderUID = func(ctx context.Context, folderUID string, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
|
return NewAccessControlFolderGuardianByUID(ctx, cfg, folderUID, user, ac, dashboardService, folderService)
|
||||||
}
|
}
|
||||||
|
|
||||||
NewByFolder = func(ctx context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
NewByFolder = func(ctx context.Context, f *folder.Folder, orgId int64, user identity.Requester) (DashboardGuardian, error) {
|
||||||
return NewAccessControlFolderGuardian(ctx, cfg, f, user, ac, dashboardService)
|
return NewAccessControlFolderGuardian(ctx, cfg, f, user, ac, orgId, dashboardService, folderService)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/services/folder"
|
||||||
"github.com/grafana/grafana/pkg/services/guardian"
|
"github.com/grafana/grafana/pkg/services/guardian"
|
||||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
@ -41,7 +42,7 @@ func (l *LibraryElementService) requireEditPermissionsOnFolderUID(ctx context.Co
|
|||||||
return dashboards.ErrFolderAccessDenied
|
return dashboards.ErrFolderAccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := guardian.NewByUID(ctx, folderUID, user.GetOrgID(), user)
|
g, err := guardian.NewByFolderUID(ctx, folderUID, user.GetOrgID(), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -67,7 +68,10 @@ func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Conte
|
|||||||
return dashboards.ErrFolderAccessDenied
|
return dashboards.ErrFolderAccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := guardian.New(ctx, folderID, user.GetOrgID(), user)
|
g, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
|
ID: folderID,
|
||||||
|
OrgID: user.GetOrgID(),
|
||||||
|
}, user.GetOrgID(), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -88,7 +92,10 @@ func (l *LibraryElementService) requireViewPermissionsOnFolder(ctx context.Conte
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
g, err := guardian.New(ctx, folderID, user.GetOrgID(), user)
|
g, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||||
|
ID: folderID,
|
||||||
|
OrgID: user.GetOrgID(),
|
||||||
|
}, user.GetOrgID(), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -539,7 +539,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilterUIDs is set to existing folders, it should succeed and the result should be correct",
|
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilterUIDs is set to existing folders, it should succeed and the result should be correct",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolder(t, sc, "NewFolder")
|
newFolder := createFolder(t, sc, "NewFolder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(newFolder.ID, newFolder.UID, "Text - Library Panel2")
|
command := getCreatePanelCommand(newFolder.ID, newFolder.UID, "Text - Library Panel2")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
@ -608,7 +608,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to a nonexistent folders, it should succeed and the result should be correct",
|
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to a nonexistent folders, it should succeed and the result should be correct",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolder(t, sc, "NewFolder")
|
newFolder := createFolder(t, sc, "NewFolder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(newFolder.ID, sc.folder.UID, "Text - Library Panel2")
|
command := getCreatePanelCommand(newFolder.ID, sc.folder.UID, "Text - Library Panel2")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
@ -24,7 +24,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel that exists, it should succeed",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel that exists, it should succeed",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolder(t, sc, "NewFolder")
|
newFolder := createFolder(t, sc, "NewFolder", nil)
|
||||||
cmd := model.PatchLibraryElementCommand{
|
cmd := model.PatchLibraryElementCommand{
|
||||||
FolderID: newFolder.ID, // nolint:staticcheck
|
FolderID: newFolder.ID, // nolint:staticcheck
|
||||||
FolderUID: &newFolder.UID,
|
FolderUID: &newFolder.UID,
|
||||||
@ -91,7 +91,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with folder only, it should change folder successfully and return correct result",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel with folder only, it should change folder successfully and return correct result",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolder(t, sc, "NewFolder")
|
newFolder := createFolder(t, sc, "NewFolder", nil)
|
||||||
cmd := model.PatchLibraryElementCommand{
|
cmd := model.PatchLibraryElementCommand{
|
||||||
FolderID: newFolder.ID, // nolint:staticcheck
|
FolderID: newFolder.ID, // nolint:staticcheck
|
||||||
FolderUID: &newFolder.UID,
|
FolderUID: &newFolder.UID,
|
||||||
@ -335,7 +335,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with a folder where a library panel with the same name already exists, it should fail",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel with a folder where a library panel with the same name already exists, it should fail",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolder(t, sc, "NewFolder")
|
newFolder := createFolder(t, sc, "NewFolder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(newFolder.ID, newFolder.UID, "Text - Library Panel")
|
command := getCreatePanelCommand(newFolder.ID, newFolder.UID, "Text - Library Panel")
|
||||||
sc.ctx.Req.Body = mockRequestBody(command)
|
sc.ctx.Req.Body = mockRequestBody(command)
|
||||||
|
@ -38,7 +38,7 @@ func TestLibraryElementPermissionsGeneralFolder(t *testing.T) {
|
|||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to the General folder, it should return correct status", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to the General folder, it should return correct status", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
@ -56,7 +56,7 @@ func TestLibraryElementPermissionsGeneralFolder(t *testing.T) {
|
|||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it from the General folder, it should return correct status", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it from the General folder, it should return correct status", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", nil)
|
||||||
command := getCreatePanelCommand(0, "", "Library Panel Name")
|
command := getCreatePanelCommand(0, "", "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
@ -178,7 +178,7 @@ func TestLibraryElementCreatePermissions(t *testing.T) {
|
|||||||
for _, testCase := range accessCases {
|
for _, testCase := range accessCases {
|
||||||
testScenario(t, testCase.desc,
|
testScenario(t, testCase.desc,
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", nil)
|
||||||
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
1: testCase.permissions,
|
1: testCase.permissions,
|
||||||
}
|
}
|
||||||
@ -235,14 +235,14 @@ func TestLibraryElementPatchPermissions(t *testing.T) {
|
|||||||
for _, testCase := range accessCases {
|
for _, testCase := range accessCases {
|
||||||
testScenario(t, testCase.desc,
|
testScenario(t, testCase.desc,
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
fromFolder := createFolder(t, sc, "FromFolder")
|
fromFolder := createFolder(t, sc, "FromFolder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(fromFolder.ID, fromFolder.UID, "Library Panel Name")
|
command := getCreatePanelCommand(fromFolder.ID, fromFolder.UID, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
|
||||||
toFolder := createFolder(t, sc, "ToFolder")
|
toFolder := createFolder(t, sc, "ToFolder", nil)
|
||||||
|
|
||||||
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
1: testCase.permissions,
|
1: testCase.permissions,
|
||||||
@ -268,6 +268,7 @@ func TestLibraryElementDeletePermissions(t *testing.T) {
|
|||||||
desc: "can delete library elements when granted write access to the correct folder",
|
desc: "can delete library elements when granted write access to the correct folder",
|
||||||
permissions: map[string][]string{
|
permissions: map[string][]string{
|
||||||
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
},
|
},
|
||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
},
|
},
|
||||||
@ -275,6 +276,7 @@ func TestLibraryElementDeletePermissions(t *testing.T) {
|
|||||||
desc: "can delete library elements when granted write access to all folders",
|
desc: "can delete library elements when granted write access to all folders",
|
||||||
permissions: map[string][]string{
|
permissions: map[string][]string{
|
||||||
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
},
|
},
|
||||||
status: http.StatusOK,
|
status: http.StatusOK,
|
||||||
},
|
},
|
||||||
@ -282,6 +284,7 @@ func TestLibraryElementDeletePermissions(t *testing.T) {
|
|||||||
desc: "can't delete library elements when granted write access to the wrong folder",
|
desc: "can't delete library elements when granted write access to the wrong folder",
|
||||||
permissions: map[string][]string{
|
permissions: map[string][]string{
|
||||||
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
||||||
},
|
},
|
||||||
status: http.StatusForbidden,
|
status: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
@ -297,7 +300,7 @@ func TestLibraryElementDeletePermissions(t *testing.T) {
|
|||||||
for _, testCase := range accessCases {
|
for _, testCase := range accessCases {
|
||||||
testScenario(t, testCase.desc,
|
testScenario(t, testCase.desc,
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", sc.service.folderService)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
@ -327,7 +330,7 @@ func TestLibraryElementsWithMissingFolders(t *testing.T) {
|
|||||||
|
|
||||||
testScenario(t, "When a user tries to patch a library panel by moving it to a folder that doesn't exist, it should fail",
|
testScenario(t, "When a user tries to patch a library panel by moving it to a folder that doesn't exist, it should fail",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
command := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
@ -368,7 +371,7 @@ func TestLibraryElementsGetPermissions(t *testing.T) {
|
|||||||
for _, testCase := range getCases {
|
for _, testCase := range getCases {
|
||||||
testScenario(t, testCase.desc,
|
testScenario(t, testCase.desc,
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolder(t, sc, "Folder")
|
folder := createFolder(t, sc, "Folder", nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
cmd := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel")
|
cmd := getCreatePanelCommand(folder.ID, folder.UID, "Library Panel")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
@ -419,7 +422,7 @@ func TestLibraryElementsGetAllPermissions(t *testing.T) {
|
|||||||
testScenario(t, testCase.desc,
|
testScenario(t, testCase.desc,
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
for i := 1; i <= 2; i++ {
|
for i := 1; i <= 2; i++ {
|
||||||
folder := createFolder(t, sc, fmt.Sprintf("Folder%d", i))
|
folder := createFolder(t, sc, fmt.Sprintf("Folder%d", i), nil)
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
cmd := getCreatePanelCommand(folder.ID, folder.UID, fmt.Sprintf("Library Panel %d", i))
|
cmd := getCreatePanelCommand(folder.ID, folder.UID, fmt.Sprintf("Library Panel %d", i))
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
|
@ -32,7 +32,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/folder"
|
"github.com/grafana/grafana/pkg/services/folder"
|
||||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/guardian"
|
"github.com/grafana/grafana/pkg/services/guardian"
|
||||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
@ -99,7 +98,7 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) {
|
|||||||
scenarioWithPanel(t, "When an admin tries to delete a folder uid that doesn't exist, it should fail",
|
scenarioWithPanel(t, "When an admin tries to delete a folder uid that doesn't exist, it should fail",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
err := sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.UID+"xxxx")
|
err := sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.UID+"xxxx")
|
||||||
require.EqualError(t, err, dashboards.ErrFolderNotFound.Error())
|
require.EqualError(t, err, guardian.ErrGuardianFolderNotFound.Errorf("failed to get folder by UID: %w", dashboards.ErrFolderNotFound).Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to delete a folder that contains disconnected elements, it should delete all disconnected elements too",
|
scenarioWithPanel(t, "When an admin tries to delete a folder that contains disconnected elements, it should delete all disconnected elements too",
|
||||||
@ -300,17 +299,19 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
folderPermissions := acmock.NewMockedPermissionsService()
|
folderPermissions := acmock.NewMockedPermissionsService()
|
||||||
|
folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
dashboardPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
dashboardPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
var expectedFolder *folder.Folder
|
fStore := folderimpl.ProvideStore(sqlStore)
|
||||||
if dash.FolderUID != "" || dash.FolderID != 0 { // nolint:staticcheck
|
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore,
|
||||||
expectedFolder = &folder.Folder{ID: folderID, UID: folderUID}
|
folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
||||||
}
|
_, err = folderSvc.Create(context.Background(), &folder.CreateFolderCommand{UID: folderUID, SignedInUser: &user, Title: folderUID + "-title"})
|
||||||
|
require.NoError(t, err)
|
||||||
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashboardStore, folderStore,
|
cfg, dashboardStore, folderStore,
|
||||||
features, folderPermissions, ac,
|
features, folderPermissions, ac,
|
||||||
&foldertest.FakeService{ExpectedFolder: expectedFolder},
|
folderSvc,
|
||||||
folder.NewFakeStore(),
|
folder.NewFakeStore(),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -327,22 +328,24 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash
|
|||||||
return dashboard
|
return dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder {
|
func createFolder(t *testing.T, sc scenarioContext, title string, folderSvc folder.Service) *folder.Folder {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
features := featuremgmt.WithFeatures()
|
if folderSvc == nil {
|
||||||
cfg := setting.NewCfg()
|
features := featuremgmt.WithFeatures()
|
||||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
cfg := setting.NewCfg()
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore))
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
require.NoError(t, err)
|
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
||||||
store := folderimpl.ProvideStore(sc.sqlStore)
|
store := folderimpl.ProvideStore(sc.sqlStore)
|
||||||
s := folderimpl.ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore,
|
folderSvc = folderimpl.ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore,
|
||||||
features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
||||||
t.Logf("Creating folder with title and UID %q", title)
|
t.Logf("Creating folder with title and UID %q", title)
|
||||||
|
}
|
||||||
ctx := identity.WithRequester(context.Background(), &sc.user)
|
ctx := identity.WithRequester(context.Background(), &sc.user)
|
||||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
folder, err := folderSvc.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: sc.user.OrgID, Title: title, UID: title, SignedInUser: &sc.user,
|
OrgID: sc.user.OrgID, Title: title, UID: title, SignedInUser: &sc.user,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -399,15 +402,18 @@ func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scena
|
|||||||
folderPermissions := acmock.NewMockedPermissionsService()
|
folderPermissions := acmock.NewMockedPermissionsService()
|
||||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
|
fStore := folderimpl.ProvideStore(sqlStore)
|
||||||
|
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore,
|
||||||
|
folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
||||||
dashboardService, svcErr := dashboardservice.ProvideDashboardServiceImpl(
|
dashboardService, svcErr := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashboardStore, folderStore,
|
cfg, dashboardStore, folderStore,
|
||||||
features, folderPermissions, ac,
|
features, folderPermissions, ac,
|
||||||
foldertest.NewFakeService(), folder.NewFakeStore(),
|
folderSvc, fStore,
|
||||||
nil, nil, nil, nil, quotaService, nil,
|
nil, nil, nil, nil, quotaService, nil,
|
||||||
)
|
)
|
||||||
require.NoError(t, svcErr)
|
require.NoError(t, svcErr)
|
||||||
dashboardService.RegisterDashboardPermissions(dashboardPermissions)
|
dashboardService.RegisterDashboardPermissions(dashboardPermissions)
|
||||||
guardian.InitAccessControlGuardian(cfg, ac, dashboardService)
|
guardian.InitAccessControlGuardian(cfg, ac, dashboardService, folderSvc, log.NewNopLogger())
|
||||||
|
|
||||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||||
// nolint:staticcheck
|
// nolint:staticcheck
|
||||||
@ -462,23 +468,23 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
|
fStore := folderimpl.ProvideStore(sqlStore)
|
||||||
|
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore,
|
||||||
|
folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
||||||
dashService, dashSvcErr := dashboardservice.ProvideDashboardServiceImpl(
|
dashService, dashSvcErr := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashboardStore, folderStore,
|
cfg, dashboardStore, folderStore,
|
||||||
features, folderPermissions, ac,
|
features, folderPermissions, ac,
|
||||||
foldertest.NewFakeService(), folder.NewFakeStore(),
|
folderSvc, fStore,
|
||||||
nil, nil, nil, nil, quotaService, nil,
|
nil, nil, nil, nil, quotaService, nil,
|
||||||
)
|
)
|
||||||
require.NoError(t, dashSvcErr)
|
require.NoError(t, dashSvcErr)
|
||||||
dashService.RegisterDashboardPermissions(dashboardPermissions)
|
dashService.RegisterDashboardPermissions(dashboardPermissions)
|
||||||
guardian.InitAccessControlGuardian(cfg, ac, dashService)
|
guardian.InitAccessControlGuardian(cfg, ac, dashService, folderSvc, log.NewNopLogger())
|
||||||
fStore := folderimpl.ProvideStore(sqlStore)
|
|
||||||
folderSrv := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracer), dashboardStore, folderStore, sqlStore,
|
|
||||||
features, supportbundlestest.NewFakeBundleService(), cfg, nil, tracing.InitializeTracerForTest())
|
|
||||||
service := LibraryElementService{
|
service := LibraryElementService{
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
features: featuremgmt.WithFeatures(),
|
features: featuremgmt.WithFeatures(),
|
||||||
SQLStore: sqlStore,
|
SQLStore: sqlStore,
|
||||||
folderService: folderSrv,
|
folderService: folderSvc,
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliberate difference between signed in user and user in db to make it crystal clear
|
// deliberate difference between signed in user and user in db to make it crystal clear
|
||||||
@ -510,7 +516,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.folder = createFolder(t, sc, "ScenarioFolder")
|
sc.folder = createFolder(t, sc, "ScenarioFolder", folderSvc)
|
||||||
|
|
||||||
fn(t, sc)
|
fn(t, sc)
|
||||||
})
|
})
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/slugify"
|
"github.com/grafana/grafana/pkg/infra/slugify"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
||||||
@ -823,18 +824,19 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
|
|
||||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
dashStore := &dashboards.FakeDashboardStore{}
|
dashStore := &dashboards.FakeDashboardStore{}
|
||||||
dashStore.On("GetDashboard", mock.Anything, mock.Anything).Return(&dashboards.Dashboard{ID: 1}, nil)
|
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
dashPermissionService := acmock.NewMockedPermissionsService()
|
dashPermissionService := acmock.NewMockedPermissionsService()
|
||||||
|
folderSvc := foldertest.NewFakeService()
|
||||||
|
folderSvc.ExpectedFolder = &folder.Folder{ID: 1}
|
||||||
dashService, err := dashboardservice.ProvideDashboardServiceImpl(
|
dashService, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashStore, folderStore,
|
cfg, dashStore, folderStore,
|
||||||
features, acmock.NewMockedPermissionsService(), ac,
|
features, acmock.NewMockedPermissionsService(), ac,
|
||||||
foldertest.NewFakeService(), folder.NewFakeStore(),
|
folderSvc, folder.NewFakeStore(),
|
||||||
nil, nil, nil, nil, quotaService, nil,
|
nil, nil, nil, nil, quotaService, nil,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dashService.RegisterDashboardPermissions(dashPermissionService)
|
dashService.RegisterDashboardPermissions(dashPermissionService)
|
||||||
guardian.InitAccessControlGuardian(cfg, ac, dashService)
|
guardian.InitAccessControlGuardian(cfg, ac, dashService, folderSvc, log.NewNopLogger())
|
||||||
|
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore))
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user