mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 18:12:26 +08:00
Folders: Set folder creation permission as part of legacy create (#94040)
* Add folder store to dashboard permissions * Include folder store in annotation scope resolver * Add folder store when initialising library elements * Include folder store in search v2 service initialisation * Include folder store in GetInheritedScopes * Add folder store to folder permissions provider * Include cfg, folder permissions in folder service * Move setting of folder permissions for folder service create method
This commit is contained in:
@ -587,7 +587,7 @@ func (hs *HTTPServer) GetAnnotationTags(c *contextmodel.ReqContext) response.Res
|
||||
// where <type> is the type of annotation with id <id>.
|
||||
// If annotationPermissionUpdate feature toggle is enabled, dashboard annotation scope will be resolved to the corresponding
|
||||
// dashboard and folder scopes (eg, "dashboards:uid:<annotation_dashboard_uid>", "folders:uid:<parent_folder_uid>" etc).
|
||||
func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features featuremgmt.FeatureToggles, dashSvc dashboards.DashboardService, folderSvc folder.Service) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features featuremgmt.FeatureToggles, dashSvc dashboards.DashboardService, folderStore folder.Store) (string, accesscontrol.ScopeAttributeResolver) {
|
||||
prefix := accesscontrol.ScopeAnnotationsProvider.GetResourceScope("")
|
||||
return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
scopeParts := strings.Split(initialScope, ":")
|
||||
@ -649,7 +649,7 @@ func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, feature
|
||||
// Append dashboard parent scopes if dashboard is in a folder or the general scope if dashboard is not in a folder
|
||||
if dashboard.FolderUID != "" {
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(dashboard.FolderUID))
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, dashboard.FolderUID, folderSvc)
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, dashboard.FolderUID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -397,14 +397,15 @@ func TestAPI_Annotations(t *testing.T) {
|
||||
dashService := &dashboards.FakeDashboardService{}
|
||||
dashService.On("GetDashboard", mock.Anything, mock.Anything).Return(&dashboards.Dashboard{UID: dashUID, FolderUID: folderUID, FolderID: 1}, nil)
|
||||
folderService := &foldertest.FakeService{}
|
||||
fStore := folder.NewFakeStore()
|
||||
folderService.ExpectedFolder = &folder.Folder{UID: folderUID, ID: 1}
|
||||
folderDB := &foldertest.FakeFolderStore{}
|
||||
folderDB.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(&folder.Folder{UID: folderUID, ID: 1}, nil)
|
||||
hs.DashboardService = dashService
|
||||
hs.folderService = folderService
|
||||
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, hs.Features, dashService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderDB, dashService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, hs.Features, dashService, fStore))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderDB, dashService, fStore))
|
||||
})
|
||||
var body io.Reader
|
||||
if tt.body != "" {
|
||||
@ -504,7 +505,7 @@ func TestService_AnnotationTypeScopeResolver(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
features := featuremgmt.WithFeatures(tc.featureToggles...)
|
||||
prefix, resolver := AnnotationTypeScopeResolver(fakeAnnoRepo, features, dashSvc, &foldertest.FakeService{})
|
||||
prefix, resolver := AnnotationTypeScopeResolver(fakeAnnoRepo, features, dashSvc, folder.NewFakeStore())
|
||||
require.Equal(t, "annotations:id:", prefix)
|
||||
|
||||
resolved, err := resolver.Resolve(context.Background(), 1, tc.given)
|
||||
|
@ -836,7 +836,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
|
||||
db := db.InitTestDB(t)
|
||||
fStore := folderimpl.ProvideStore(db)
|
||||
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()),
|
||||
dashboardStore, folderStore, db, features,
|
||||
dashboardStore, folderStore, db, features, cfg, folderPermissions,
|
||||
supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
if dashboardService == nil {
|
||||
dashboardService, err = service.ProvideDashboardServiceImpl(
|
||||
|
@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -12,12 +11,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
folderalpha1 "github.com/grafana/grafana/pkg/apis/folder/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders"
|
||||
@ -31,7 +28,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements/model"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/util/errhttp"
|
||||
@ -219,10 +215,6 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
if err := hs.setDefaultFolderPermissions(c.Req.Context(), cmd.OrgID, cmd.SignedInUser, folder); err != nil {
|
||||
hs.log.Error("Could not set the default folder permissions", "folder", folder.Title, "user", cmd.SignedInUser, "error", err)
|
||||
}
|
||||
|
||||
// Clear permission cache for the user who's created the folder, so that new permissions are fetched for their next call
|
||||
// Required for cases when caller wants to immediately interact with the newly created object
|
||||
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
|
||||
@ -236,36 +228,6 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
|
||||
return response.JSON(http.StatusOK, folderDTO)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int64, user identity.Requester, folder *folder.Folder) error {
|
||||
if !hs.Cfg.RBAC.PermissionsOnCreation("folder") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var permissions []accesscontrol.SetResourcePermissionCommand
|
||||
|
||||
if user.IsIdentityType(claims.TypeUser) {
|
||||
userID, err := user.GetInternalID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
|
||||
isNested := folder.ParentUID != ""
|
||||
if !isNested || !hs.Features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) {
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
}
|
||||
|
||||
_, err := hs.folderPermissionsService.SetPermissions(ctx, orgID, folder.UID, permissions...)
|
||||
return err
|
||||
}
|
||||
|
||||
// swagger:route POST /folders/{folder_uid}/move folders moveFolder
|
||||
//
|
||||
// Move folder.
|
||||
|
@ -464,14 +464,15 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog
|
||||
features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(),
|
||||
)
|
||||
fStore := folderimpl.ProvideStore(sc.db)
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions(
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, fStore, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
require.NoError(b, err)
|
||||
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderStore, sc.db, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions(
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, fStore, acSvc, sc.teamSvc, sc.userSvc, actionSets)
|
||||
require.NoError(b, err)
|
||||
|
||||
dashboardSvc, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||
|
@ -253,6 +253,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
authInfoService login.AuthInfoService, storageService store.StorageService,
|
||||
notificationService notifications.Service, dashboardService dashboards.DashboardService,
|
||||
dashboardProvisioningService dashboards.DashboardProvisioningService, folderService folder.Service,
|
||||
folderStore folder.Store,
|
||||
dsGuardian guardian.DatasourceGuardianProvider,
|
||||
dashboardsnapshotsService dashboardsnapshots.Service, pluginSettings pluginSettings.Service,
|
||||
avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service,
|
||||
@ -379,7 +380,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
||||
hs.registerRoutes()
|
||||
|
||||
// Register access control scope resolver for annotations
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, features, dashboardService, folderService))
|
||||
hs.AccessControl.RegisterScopeAttributeResolver(AnnotationTypeScopeResolver(hs.annotationsRepo, features, dashboardService, folderStore))
|
||||
|
||||
if err := hs.declareFixedRoles(); err != nil {
|
||||
return nil, err
|
||||
|
@ -93,7 +93,7 @@ func registerDashboardRoles(cfg *setting.Cfg, features featuremgmt.FeatureToggle
|
||||
|
||||
func ProvideDashboardPermissions(
|
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, ac accesscontrol.AccessControl,
|
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service,
|
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderStore folder.Store, service accesscontrol.Service,
|
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService,
|
||||
) (*DashboardPermissionsService, error) {
|
||||
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*dashboards.Dashboard, error) {
|
||||
@ -145,7 +145,7 @@ func ProvideDashboardPermissions(
|
||||
}
|
||||
parentScope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(queryResult.UID)
|
||||
|
||||
nestedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, queryResult.UID, folderService)
|
||||
nestedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, queryResult.UID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ func registerFolderRoles(cfg *setting.Cfg, features featuremgmt.FeatureToggles,
|
||||
|
||||
func ProvideFolderPermissions(
|
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, router routing.RouteRegister, sql db.DB, accesscontrol accesscontrol.AccessControl,
|
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderService folder.Service, service accesscontrol.Service,
|
||||
license licensing.Licensing, dashboardStore dashboards.Store, folderStore folder.Store, service accesscontrol.Service,
|
||||
teamService team.Service, userService user.Service, actionSetService resourcepermissions.ActionSetService,
|
||||
) (*FolderPermissionsService, error) {
|
||||
if err := registerFolderRoles(cfg, features, service); err != nil {
|
||||
@ -111,7 +111,7 @@ func ProvideFolderPermissions(
|
||||
return nil
|
||||
},
|
||||
InheritedScopesSolver: func(ctx context.Context, orgID int64, resourceID string) ([]string, error) {
|
||||
return dashboards.GetInheritedScopes(ctx, orgID, resourceID, folderService)
|
||||
return dashboards.GetInheritedScopes(ctx, orgID, resourceID, folderStore)
|
||||
},
|
||||
Assignments: resourcepermissions.Assignments{
|
||||
Users: true,
|
||||
|
@ -0,0 +1,83 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/permreg"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/bundleregistry"
|
||||
"github.com/grafana/grafana/pkg/services/team/teamimpl"
|
||||
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func ProvideFolderPermissions(
|
||||
features featuremgmt.FeatureToggles,
|
||||
cfg *setting.Cfg,
|
||||
sqlStore *sqlstore.SQLStore,
|
||||
) (*ossaccesscontrol.FolderPermissionsService, error) {
|
||||
actionSets := resourcepermissions.NewActionSetService(features)
|
||||
acSvc := acimpl.ProvideOSSService(
|
||||
cfg, acdb.ProvideService(sqlStore), actionSets, localcache.ProvideService(),
|
||||
features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sqlStore, permreg.ProvidePermissionRegistry(),
|
||||
)
|
||||
|
||||
license := licensingtest.NewFakeLicensing()
|
||||
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
|
||||
|
||||
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
||||
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
|
||||
quotaService := quotatest.New(false, nil)
|
||||
orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
teamSvc, err := teamimpl.ProvideService(sqlStore, cfg, tracing.InitializeTracerForTest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cache := localcache.ProvideService()
|
||||
|
||||
userSvc, err := userimpl.ProvideService(
|
||||
sqlStore,
|
||||
orgService,
|
||||
cfg,
|
||||
teamSvc,
|
||||
cache,
|
||||
tracing.InitializeTracerForTest(),
|
||||
quotaService,
|
||||
bundleregistry.ProvideService(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ossaccesscontrol.ProvideFolderPermissions(
|
||||
cfg,
|
||||
features,
|
||||
routing.NewRouteRegister(),
|
||||
sqlStore,
|
||||
ac,
|
||||
license,
|
||||
&dashboards.FakeDashboardStore{},
|
||||
fStore,
|
||||
acSvc,
|
||||
teamSvc,
|
||||
userSvc,
|
||||
actionSets,
|
||||
)
|
||||
}
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
ftestutil "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana"
|
||||
@ -227,10 +228,11 @@ func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) {
|
||||
})
|
||||
|
||||
ac := acimpl.ProvideAccessControl(features, zanzana.NewNoopClient())
|
||||
folderPermissions, err := ftestutil.ProvideFolderPermissions(features, cfg, sql)
|
||||
require.NoError(t, err)
|
||||
fStore := folderimpl.ProvideStore(sql)
|
||||
folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderimpl.ProvideDashboardFolderStore(sql), sql, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
folderimpl.ProvideDashboardFolderStore(sql), sql, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
cfg.AnnotationMaximumTagsLength = 60
|
||||
|
||||
store := NewXormStore(cfg, log.New("annotation.test"), sql, tagService)
|
||||
|
@ -43,7 +43,7 @@ var (
|
||||
)
|
||||
|
||||
// NewFolderNameScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:name:" into an uid based scope.
|
||||
func NewFolderNameScopeResolver(folderDB folder.FolderStore, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func NewFolderNameScopeResolver(folderDB folder.FolderStore, folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeFoldersProvider.GetResourceScopeName("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.NewFolderNameScopeResolver")
|
||||
@ -63,7 +63,7 @@ func NewFolderNameScopeResolver(folderDB folder.FolderStore, folderSvc folder.Se
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := GetInheritedScopes(ctx, folder.OrgID, folder.UID, folderSvc)
|
||||
result, err := GetInheritedScopes(ctx, folder.OrgID, folder.UID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -74,7 +74,7 @@ func NewFolderNameScopeResolver(folderDB folder.FolderStore, folderSvc folder.Se
|
||||
}
|
||||
|
||||
// NewFolderIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:id:" into an uid based scope.
|
||||
func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeFoldersProvider.GetResourceScope("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.NewFolderIDScopeResolver")
|
||||
@ -98,7 +98,7 @@ func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderSvc folder.Serv
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := GetInheritedScopes(ctx, folder.OrgID, folder.UID, folderSvc)
|
||||
result, err := GetInheritedScopes(ctx, folder.OrgID, folder.UID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -110,7 +110,7 @@ func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderSvc folder.Serv
|
||||
|
||||
// NewFolderUIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:uid:"
|
||||
// into uid based scopes for folder and its parents
|
||||
func NewFolderUIDScopeResolver(folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func NewFolderUIDScopeResolver(folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeFoldersProvider.GetResourceScopeUID("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.NewFolderUIDScopeResolver")
|
||||
@ -125,7 +125,7 @@ func NewFolderUIDScopeResolver(folderSvc folder.Service) (string, ac.ScopeAttrib
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inheritedScopes, err := GetInheritedScopes(ctx, orgID, uid, folderSvc)
|
||||
inheritedScopes, err := GetInheritedScopes(ctx, orgID, uid, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -135,7 +135,7 @@ func NewFolderUIDScopeResolver(folderSvc folder.Service) (string, ac.ScopeAttrib
|
||||
|
||||
// NewDashboardIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:id:"
|
||||
// into uid based scopes for both dashboard and folder
|
||||
func NewDashboardIDScopeResolver(folderDB folder.FolderStore, ds DashboardService, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func NewDashboardIDScopeResolver(folderDB folder.FolderStore, ds DashboardService, folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeDashboardsProvider.GetResourceScope("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.NewDashboardIDScopeResolver")
|
||||
@ -155,13 +155,13 @@ func NewDashboardIDScopeResolver(folderDB folder.FolderStore, ds DashboardServic
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resolveDashboardScope(ctx, folderDB, orgID, dashboard, folderSvc)
|
||||
return resolveDashboardScope(ctx, folderDB, orgID, dashboard, folderStore)
|
||||
})
|
||||
}
|
||||
|
||||
// NewDashboardUIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:uid:"
|
||||
// into uid based scopes for both dashboard and folder
|
||||
func NewDashboardUIDScopeResolver(folderDB folder.FolderStore, ds DashboardService, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func NewDashboardUIDScopeResolver(folderDB folder.FolderStore, ds DashboardService, folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeDashboardsProvider.GetResourceScopeUID("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.NewDashboardUIDScopeResolver")
|
||||
@ -181,11 +181,11 @@ func NewDashboardUIDScopeResolver(folderDB folder.FolderStore, ds DashboardServi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resolveDashboardScope(ctx, folderDB, orgID, dashboard, folderSvc)
|
||||
return resolveDashboardScope(ctx, folderDB, orgID, dashboard, folderStore)
|
||||
})
|
||||
}
|
||||
|
||||
func resolveDashboardScope(ctx context.Context, folderDB folder.FolderStore, orgID int64, dashboard *Dashboard, folderSvc folder.Service) ([]string, error) {
|
||||
func resolveDashboardScope(ctx context.Context, folderDB folder.FolderStore, orgID int64, dashboard *Dashboard, folderStore folder.Store) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.resolveDashboardScope")
|
||||
span.End()
|
||||
|
||||
@ -208,7 +208,7 @@ func resolveDashboardScope(ctx context.Context, folderDB folder.FolderStore, org
|
||||
folderUID = folder.UID
|
||||
}
|
||||
|
||||
result, err := GetInheritedScopes(ctx, orgID, folderUID, folderSvc)
|
||||
result, err := GetInheritedScopes(ctx, orgID, folderUID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -223,17 +223,24 @@ func resolveDashboardScope(ctx context.Context, folderDB folder.FolderStore, org
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetInheritedScopes(ctx context.Context, orgID int64, folderUID string, folderSvc folder.Service) ([]string, error) {
|
||||
func GetInheritedScopes(ctx context.Context, orgID int64, folderUID string, folderStore folder.Store) ([]string, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.GetInheritedScopes")
|
||||
span.End()
|
||||
|
||||
if folderUID == ac.GeneralFolderUID {
|
||||
return nil, nil
|
||||
}
|
||||
ancestors, err := folderSvc.GetParents(ctx, folder.GetParentsQuery{
|
||||
|
||||
var ancestors []*folder.Folder
|
||||
var err error
|
||||
if folderUID == folder.SharedWithMeFolderUID {
|
||||
ancestors = []*folder.Folder{&folder.SharedWithMeFolder}
|
||||
} else {
|
||||
ancestors, err = folderStore.GetParents(ctx, folder.GetParentsQuery{
|
||||
UID: folderUID,
|
||||
OrgID: orgID,
|
||||
})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, folder.ErrFolderNotFound) {
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
|
||||
func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
prefix, _ := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
require.Equal(t, "folders:name:", prefix)
|
||||
})
|
||||
|
||||
@ -31,7 +31,7 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
|
||||
scope := "folders:name:" + title
|
||||
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, foldertest.NewFakeService())
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, folder.NewFakeStore())
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 1)
|
||||
@ -49,8 +49,8 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
|
||||
scope := "folders:name:" + title
|
||||
|
||||
folderSvc := foldertest.NewFakeService()
|
||||
folderSvc.ExpectedFolders = []*folder.Folder{
|
||||
fStore := folder.NewFakeStore()
|
||||
fStore.ExpectedParentFolders = []*folder.Folder{
|
||||
{
|
||||
UID: "parent",
|
||||
},
|
||||
@ -58,7 +58,7 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
UID: "grandparent",
|
||||
},
|
||||
}
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, folderSvc)
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, fStore)
|
||||
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.NoError(t, err)
|
||||
@ -75,20 +75,20 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
folderStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title, mock.Anything)
|
||||
})
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
||||
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
_, resolver := NewFolderNameScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:name:")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
||||
folderStore := foldertest.NewFakeFolderStore(t)
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, foldertest.NewFakeService())
|
||||
_, resolver := NewFolderNameScopeResolver(folderStore, folder.NewFakeStore())
|
||||
|
||||
orgId := rand.Int63()
|
||||
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
@ -103,12 +103,12 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
prefix, _ := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
require.Equal(t, "folders:id:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:uid:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
@ -118,7 +118,7 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
var (
|
||||
orgId = rand.Int63()
|
||||
scope = "folders:id:0"
|
||||
_, resolver = NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
_, resolver = NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
)
|
||||
|
||||
resolved, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
@ -129,7 +129,7 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
||||
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService())
|
||||
_, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), folder.NewFakeStore())
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
@ -137,7 +137,7 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
||||
folderStore := foldertest.NewFakeFolderStore(t)
|
||||
folderStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
_, resolver := NewFolderIDScopeResolver(folderStore, foldertest.NewFakeService())
|
||||
_, resolver := NewFolderIDScopeResolver(folderStore, folder.NewFakeStore())
|
||||
|
||||
orgId := rand.Int63()
|
||||
scope := "folders:id:10"
|
||||
@ -149,12 +149,12 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
||||
prefix, _ := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, folder.NewFakeStore())
|
||||
require.Equal(t, "dashboards:id:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
||||
_, resolver := NewDashboardIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, folder.NewFakeStore())
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:uid:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
@ -162,12 +162,12 @@ func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewDashboardUIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
||||
prefix, _ := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, folder.NewFakeStore())
|
||||
require.Equal(t, "dashboards:uid:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, foldertest.NewFakeService())
|
||||
_, resolver := NewDashboardUIDScopeResolver(foldertest.NewFakeFolderStore(t), &FakeDashboardService{}, folder.NewFakeStore())
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:id:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
|
@ -303,8 +303,10 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
|
||||
folderPermissions := mock.NewMockedPermissionsService()
|
||||
folderStore := folderimpl.ProvideStore(sqlStore)
|
||||
folderSvc := folderimpl.ProvideService(folderStore, mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore), sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
folderSvc := folderimpl.ProvideService(folderStore, mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore),
|
||||
sqlStore, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
parentUID := ""
|
||||
for i := 0; ; i++ {
|
||||
|
@ -16,6 +16,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@ -829,10 +831,11 @@ func TestIntegrationFindDashboardsByTitle(t *testing.T) {
|
||||
insertTestDashboard(t, dashboardStore, "dashboard under general", orgID, 0, "", false)
|
||||
|
||||
ac := acimpl.ProvideAccessControl(features, zanzana.NewNoopClient())
|
||||
folderPermissions := mock.NewMockedPermissionsService()
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore,
|
||||
folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
folderStore, sqlStore, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
user := &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
@ -951,8 +954,11 @@ func TestIntegrationFindDashboardsByFolder(t *testing.T) {
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
|
||||
folderPermissions, err := testutil.ProvideFolderPermissions(features, cfg, sqlStore)
|
||||
require.NoError(t, err)
|
||||
|
||||
folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore,
|
||||
folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
folderStore, sqlStore, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
user := &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
|
@ -81,8 +81,8 @@ func ProvideDashboardServiceImpl(
|
||||
metrics: newDashboardsMetrics(r),
|
||||
}
|
||||
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderStore, dashSvc, folderSvc))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(folderStore, dashSvc, folderSvc))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(folderStore, dashSvc, fStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(folderStore, dashSvc, fStore))
|
||||
|
||||
if err := folderSvc.RegisterService(dashSvc); err != nil {
|
||||
return nil, err
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/grafana/dskit/concurrency"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@ -29,11 +30,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/store/entity"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@ -46,6 +49,8 @@ type Service struct {
|
||||
dashboardStore dashboards.Store
|
||||
dashboardFolderStore folder.FolderStore
|
||||
features featuremgmt.FeatureToggles
|
||||
cfg *setting.Cfg
|
||||
folderPermissions accesscontrol.FolderPermissionsService
|
||||
accessControl accesscontrol.AccessControl
|
||||
// bus is currently used to publish event in case of folder full path change.
|
||||
// For example when a folder is moved to another folder or when a folder is renamed.
|
||||
@ -65,6 +70,8 @@ func ProvideService(
|
||||
folderStore folder.FolderStore,
|
||||
db db.DB, // DB for the (new) nested folder store
|
||||
features featuremgmt.FeatureToggles,
|
||||
cfg *setting.Cfg,
|
||||
folderPermissions accesscontrol.FolderPermissionsService,
|
||||
supportBundles supportbundles.Service,
|
||||
r prometheus.Registerer,
|
||||
tracer tracing.Tracer,
|
||||
@ -75,6 +82,8 @@ func ProvideService(
|
||||
dashboardFolderStore: folderStore,
|
||||
store: store,
|
||||
features: features,
|
||||
cfg: cfg,
|
||||
folderPermissions: folderPermissions,
|
||||
accessControl: ac,
|
||||
bus: bus,
|
||||
db: db,
|
||||
@ -86,9 +95,9 @@ func ProvideService(
|
||||
|
||||
supportBundles.RegisterSupportItemCollector(srv.supportBundleCollector())
|
||||
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(folderStore, srv))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(folderStore, srv))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(srv))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(folderStore, store))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(folderStore, store))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(store))
|
||||
return srv
|
||||
}
|
||||
|
||||
@ -658,9 +667,43 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
if nestedFolder != nil && nestedFolder.ParentUID != "" {
|
||||
f.ParentUID = nestedFolder.ParentUID
|
||||
}
|
||||
if err = s.setDefaultFolderPermissions(ctx, cmd.OrgID, user, f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (s *Service) setDefaultFolderPermissions(ctx context.Context, orgID int64, user identity.Requester, folder *folder.Folder) error {
|
||||
if !s.cfg.RBAC.PermissionsOnCreation("folder") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var permissions []accesscontrol.SetResourcePermissionCommand
|
||||
|
||||
if user.IsIdentityType(claims.TypeUser) {
|
||||
userID, err := user.GetInternalID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
|
||||
isNested := folder.ParentUID != ""
|
||||
if !isNested || !s.features.IsEnabled(ctx, featuremgmt.FlagNestedFolders) {
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
}
|
||||
|
||||
_, err := s.folderPermissions.SetPermissions(ctx, orgID, folder.UID, permissions...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
|
||||
ctx, span := s.tracer.Start(ctx, "folder.Update")
|
||||
defer span.End()
|
||||
|
@ -62,10 +62,11 @@ func TestIntegrationProvideFolderService(t *testing.T) {
|
||||
}
|
||||
t.Run("should register scope resolvers", func(t *testing.T) {
|
||||
ac := acmock.New()
|
||||
db, _ := db.InitTestDBWithCfg(t)
|
||||
db, cfg := db.InitTestDBWithCfg(t)
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
store := ProvideStore(db)
|
||||
ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), nil, nil, db,
|
||||
featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
featuremgmt.WithFeatures(), cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 3)
|
||||
})
|
||||
@ -97,6 +98,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: features,
|
||||
cfg: cfg,
|
||||
bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
|
||||
db: db,
|
||||
accessControl: acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()),
|
||||
@ -439,6 +441,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: featuresFlagOn,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
accessControl: ac,
|
||||
@ -494,7 +497,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac)
|
||||
require.NoError(t, err)
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOn, featuresFlagOn, ac)
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOn, serviceWithFlagOn.store, featuresFlagOn, ac)
|
||||
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOn)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -554,6 +557,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: featuresFlagOff,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
registry: make(map[string]folder.RegistryService),
|
||||
@ -576,7 +580,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac)
|
||||
require.NoError(t, err)
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOff, featuresFlagOff, ac)
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOff, serviceWithFlagOff.store, featuresFlagOff, ac)
|
||||
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOff)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -632,6 +636,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
log: slog.New(logtest.NewTestHandler(t)).With("logger", "test-folder-service"),
|
||||
dashboardFolderStore: folderStore,
|
||||
features: featuresFlagOff,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
registry: make(map[string]folder.RegistryService),
|
||||
@ -705,7 +710,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
|
||||
CanEditValue: true,
|
||||
})
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, tc.service, tc.featuresFlag, ac)
|
||||
elementService := libraryelements.ProvideService(cfg, db, routeRegister, tc.service, tc.service.store, tc.featuresFlag, ac)
|
||||
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, tc.service)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -810,6 +815,7 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
dashboardStore: &dashStore,
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
cfg: setting.NewCfg(),
|
||||
accessControl: acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient()),
|
||||
metrics: newFoldersMetrics(nil),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
@ -847,6 +853,7 @@ func TestFolderServiceDualWrite(t *testing.T) {
|
||||
dashboardStore: dashStore,
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
cfg: cfg,
|
||||
accessControl: acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient()),
|
||||
metrics: newFoldersMetrics(nil),
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
@ -1479,6 +1486,7 @@ func TestIntegrationNestedFolderSharedWithMe(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: featuresFlagOn,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
accessControl: ac,
|
||||
@ -1901,6 +1909,7 @@ func TestFolderServiceGetFolder(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: features,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
accessControl: ac,
|
||||
@ -1983,6 +1992,7 @@ func TestFolderServiceGetFolders(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: featuresFlagOff,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
accessControl: ac,
|
||||
@ -2070,6 +2080,7 @@ func TestGetChildrenFilterByPermission(t *testing.T) {
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
features: features,
|
||||
cfg: cfg,
|
||||
bus: b,
|
||||
db: db,
|
||||
accessControl: ac,
|
||||
@ -2533,6 +2544,7 @@ func setup(t *testing.T, dashStore dashboards.Store, dashboardFolderStore folder
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
store: nestedFolderStore,
|
||||
features: features,
|
||||
cfg: setting.NewCfg(),
|
||||
accessControl: ac,
|
||||
db: db,
|
||||
metrics: newFoldersMetrics(nil),
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/authz/zanzana"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
"github.com/grafana/grafana/pkg/services/licensing/licensingtest"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -958,13 +959,13 @@ func setupAccessControlGuardianTest(
|
||||
fakeDashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Maybe().Return(d, nil)
|
||||
|
||||
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())
|
||||
folderSvc := foldertest.NewFakeService()
|
||||
|
||||
fStore := folder.NewFakeStore()
|
||||
folderStore := foldertest.NewFakeFolderStore(t)
|
||||
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(folderStore, fakeDashboardService, folderSvc))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(folderSvc))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(folderStore, folderSvc))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(folderStore, fakeDashboardService, fStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(fStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(folderStore, fStore))
|
||||
|
||||
license := licensingtest.NewFakeLicensing()
|
||||
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
|
||||
|
@ -35,7 +35,7 @@ var (
|
||||
|
||||
// LibraryPanelUIDScopeResolver provides a ScopeAttributeResolver that is able to convert a scope prefixed with "library.panels:uid:"
|
||||
// into uid based scopes for a library panel and its associated folder hierarchy
|
||||
func LibraryPanelUIDScopeResolver(l *LibraryElementService, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) {
|
||||
func LibraryPanelUIDScopeResolver(l *LibraryElementService, folderStore folder.Store) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeLibraryPanelsProvider.GetResourceScopeUID("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
if !strings.HasPrefix(scope, prefix) {
|
||||
@ -60,7 +60,7 @@ func LibraryPanelUIDScopeResolver(l *LibraryElementService, folderSvc folder.Ser
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, libElDTO.FolderUID, folderSvc)
|
||||
inheritedScopes, err := dashboards.GetInheritedScopes(ctx, orgID, libElDTO.FolderUID, folderStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) *LibraryElementService {
|
||||
func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service, folderStore folder.Store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) *LibraryElementService {
|
||||
l := &LibraryElementService{
|
||||
Cfg: cfg,
|
||||
SQLStore: sqlStore,
|
||||
@ -27,7 +27,7 @@ func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.Rout
|
||||
}
|
||||
|
||||
l.registerAPIEndpoints()
|
||||
ac.RegisterScopeAttributeResolver(LibraryPanelUIDScopeResolver(l, l.folderService))
|
||||
ac.RegisterScopeAttributeResolver(LibraryPanelUIDScopeResolver(l, folderStore))
|
||||
|
||||
return l
|
||||
}
|
||||
|
@ -324,6 +324,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder
|
||||
features := featuremgmt.WithFeatures()
|
||||
cfg := setting.NewCfg()
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService)
|
||||
require.NoError(t, err)
|
||||
@ -331,7 +332,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
||||
store := folderimpl.ProvideStore(sc.sqlStore)
|
||||
s := folderimpl.ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
t.Logf("Creating folder with title and UID %q", title)
|
||||
ctx := identity.WithRequester(context.Background(), &sc.user)
|
||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
||||
@ -463,7 +464,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
guardian.InitAccessControlGuardian(cfg, ac, dashService)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
folderSrv := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracer), dashboardStore, folderStore, sqlStore,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
service := LibraryElementService{
|
||||
Cfg: cfg,
|
||||
features: featuremgmt.WithFeatures(),
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
dashboardservice "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
@ -747,6 +748,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder
|
||||
|
||||
features := featuremgmt.WithFeatures()
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
cfg := setting.NewCfg()
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService)
|
||||
@ -754,7 +756,7 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
||||
fStore := folderimpl.ProvideStore(sc.sqlStore)
|
||||
s := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
t.Logf("Creating folder with title and UID %q", title)
|
||||
ctx := identity.WithRequester(context.Background(), sc.user)
|
||||
@ -838,10 +840,12 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
require.NoError(t, err)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
|
||||
folderPermissions, err := testutil.ProvideFolderPermissions(features, cfg, sqlStore)
|
||||
require.NoError(t, err)
|
||||
folderService := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, features, ac)
|
||||
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, fStore, features, ac)
|
||||
service := LibraryPanelService{
|
||||
Cfg: cfg,
|
||||
SQLStore: sqlStore,
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
@ -1817,13 +1818,14 @@ func createTestEnv(t *testing.T, testConfig string) testEnvironment {
|
||||
}}, nil).Maybe()
|
||||
|
||||
ac := &recordingAccessControlFake{}
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil))
|
||||
require.NoError(t, err)
|
||||
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
folderService := folderimpl.ProvideService(fStore, actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore,
|
||||
featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
featuremgmt.WithFeatures(), cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
store := store.DBstore{
|
||||
Logger: log,
|
||||
SQLStore: sqlStore,
|
||||
|
@ -1546,11 +1546,11 @@ func TestProvisiongWithFullpath(t *testing.T) {
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||
_, dashboardStore := testutil.SetupDashboardService(t, sqlStore, folderStore, cfg)
|
||||
ac := acmock.New()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)
|
||||
fStore := folderimpl.ProvideStore(sqlStore)
|
||||
folderService := folderimpl.ProvideService(fStore, ac, inProcBus, dashboardStore, folderStore, sqlStore,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
ruleService := createAlertRuleService(t, folderService)
|
||||
var orgID int64 = 1
|
||||
|
||||
|
@ -27,9 +27,10 @@ import (
|
||||
|
||||
func SetupFolderService(tb testing.TB, cfg *setting.Cfg, db db.DB, dashboardStore dashboards.Store, folderStore *folderimpl.DashboardFolderStoreImpl, bus *bus.InProcBus, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service {
|
||||
tb.Helper()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
fStore := folderimpl.ProvideStore(db)
|
||||
return folderimpl.ProvideService(fStore, ac, bus, dashboardStore, folderStore, db,
|
||||
features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
}
|
||||
|
||||
func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.DashboardFolderStoreImpl, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) {
|
||||
|
@ -24,7 +24,7 @@ var _ FutureAuthService = (*simpleAuthService)(nil)
|
||||
type simpleAuthService struct {
|
||||
sql db.DB
|
||||
ac accesscontrol.Service
|
||||
folderService folder.Service
|
||||
folderStore folder.Store
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
@ -32,14 +32,14 @@ func (a *simpleAuthService) GetDashboardReadFilter(ctx context.Context, orgID in
|
||||
canReadDashboard, canReadFolder := accesscontrol.Checker(user, dashboards.ActionDashboardsRead), accesscontrol.Checker(user, dashboards.ActionFoldersRead)
|
||||
return func(kind entityKind, uid, parent string) bool {
|
||||
if kind == entityKindFolder {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderService)
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderStore)
|
||||
if err != nil {
|
||||
a.logger.Debug("Could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid))
|
||||
return canReadFolder(scopes...)
|
||||
} else if kind == entityKindDashboard {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderService)
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderStore)
|
||||
if err != nil {
|
||||
a.logger.Debug("Could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
@ -754,7 +754,7 @@ func setupIntegrationEnv(t *testing.T, folderCount, dashboardsPerFolder int, sql
|
||||
ExpectedOrgs: []*org.OrgDTO{{ID: 1}},
|
||||
}
|
||||
searchService, ok := ProvideService(cfg, sqlStore, store.NewDummyEntityEventsService(), actest.FakeService{},
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, foldertest.NewFakeService()).(*StandardSearchService)
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, folder.NewFakeStore()).(*StandardSearchService)
|
||||
require.True(t, ok)
|
||||
|
||||
err = runSearchService(searchService)
|
||||
|
@ -85,7 +85,7 @@ func (s *StandardSearchService) IsReady(ctx context.Context, orgId int64) IsSear
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, sql db.DB, entityEventStore store.EntityEventsService,
|
||||
ac accesscontrol.Service, tracer tracing.Tracer, features featuremgmt.FeatureToggles, orgService org.Service,
|
||||
userService user.Service, folderService folder.Service) SearchService {
|
||||
userService user.Service, folderStore folder.Store) SearchService {
|
||||
extender := &NoopExtender{}
|
||||
logger := log.New("searchV2")
|
||||
s := &StandardSearchService{
|
||||
@ -95,7 +95,7 @@ func ProvideService(cfg *setting.Cfg, sql db.DB, entityEventStore store.EntityEv
|
||||
auth: &simpleAuthService{
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
folderService: folderService,
|
||||
folderStore: folderStore,
|
||||
logger: logger,
|
||||
},
|
||||
dashboardIndex: newSearchIndex(
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
@ -42,7 +42,7 @@ func setupBenchEnv(b *testing.B, folderCount, dashboardsPerFolder int) (*Standar
|
||||
ExpectedOrgs: []*org.OrgDTO{{ID: 1}},
|
||||
}
|
||||
searchService, ok := ProvideService(cfg, sqlStore, store.NewDummyEntityEventsService(), actest.FakeService{},
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, foldertest.NewFakeService()).(*StandardSearchService)
|
||||
tracing.InitializeTracerForTest(), features, orgSvc, nil, folder.NewFakeStore()).(*StandardSearchService)
|
||||
require.True(b, ok)
|
||||
|
||||
err = runSearchService(searchService)
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol/testutil"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
@ -822,10 +823,11 @@ func setupNestedTest(t *testing.T, usr *user.SignedInUser, perms []accesscontrol
|
||||
dashStore, err := database.ProvideDashboardStore(db, cfg, features, tagimpl.ProvideService(db), quotatest.New(false, nil))
|
||||
require.NoError(t, err)
|
||||
|
||||
folderPermissions, err := testutil.ProvideFolderPermissions(features, cfg, db)
|
||||
require.NoError(t, err)
|
||||
fStore := folderimpl.ProvideStore(db)
|
||||
folderSvc := folderimpl.ProvideService(fStore, actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore,
|
||||
folderimpl.ProvideDashboardFolderStore(db), db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
folderimpl.ProvideDashboardFolderStore(db), db, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
// create parent folder
|
||||
parent, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
UID: "parent",
|
||||
|
@ -78,12 +78,13 @@ func setupBenchMark(b *testing.B, usr user.SignedInUser, features featuremgmt.Fe
|
||||
|
||||
quotaService := quotatest.New(false, nil)
|
||||
|
||||
folderPermissions := mock.NewMockedPermissionsService()
|
||||
dashboardWriteStore, err := database.ProvideDashboardStore(store, cfg, features, tagimpl.ProvideService(store), quotaService)
|
||||
require.NoError(b, err)
|
||||
|
||||
fStore := folderimpl.ProvideStore(store)
|
||||
folderSvc := folderimpl.ProvideService(fStore, mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(store),
|
||||
store, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
store, features, cfg, folderPermissions, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest())
|
||||
|
||||
origNewGuardian := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true})
|
||||
|
Reference in New Issue
Block a user