diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index 7901d005151..db2067c7202 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -459,13 +459,13 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient()) cfg := setting.NewCfg() actionSets := resourcepermissions.NewActionSetService(features) - acSvc := acimpl.ProvideOSSService( - sc.cfg, acdb.ProvideService(sc.db), actionSets, localcache.ProvideService(), - features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(), nil, - ) fStore := folderimpl.ProvideStore(sc.db) folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + acSvc := acimpl.ProvideOSSService( + sc.cfg, acdb.ProvideService(sc.db), actionSets, localcache.ProvideService(), + features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(), nil, folderServiceWithFlagOn, + ) folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions( cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) require.NoError(b, err) diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 7a749adf4ae..95bd6b81415 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -300,6 +300,7 @@ var wireBasicSet = wire.NewSet( dashboardservice.ProvideDashboardPluginService, dashboardstore.ProvideDashboardStore, folderimpl.ProvideService, + wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index d4fe1735f05..3a13f94af69 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -55,7 +55,7 @@ func ProvideService( cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegister, cache *localcache.CacheService, accessControl accesscontrol.AccessControl, userService user.Service, actionResolver accesscontrol.ActionResolver, features featuremgmt.FeatureToggles, tracer tracing.Tracer, zclient zanzana.Client, permRegistry permreg.PermissionRegistry, - lock *serverlock.ServerLockService, + lock *serverlock.ServerLockService, folderService folder.Service, ) (*Service, error) { service := ProvideOSSService( cfg, @@ -68,6 +68,7 @@ func ProvideService( db, permRegistry, lock, + folderService, ) api.NewAccessControlAPI(routeRegister, accessControl, service, userService, features).RegisterAPIEndpoints() @@ -89,7 +90,8 @@ func ProvideService( func ProvideOSSService( cfg *setting.Cfg, store accesscontrol.Store, actionResolver accesscontrol.ActionResolver, cache *localcache.CacheService, features featuremgmt.FeatureToggles, tracer tracing.Tracer, - zclient zanzana.Client, db db.DB, permRegistry permreg.PermissionRegistry, lock *serverlock.ServerLockService, + zclient zanzana.Client, db db.DB, permRegistry permreg.PermissionRegistry, + lock *serverlock.ServerLockService, folderService folder.Service, ) *Service { s := &Service{ actionResolver: actionResolver, @@ -99,7 +101,7 @@ func ProvideOSSService( log: log.New("accesscontrol.service"), roles: accesscontrol.BuildBasicRoleDefinitions(), store: store, - reconciler: dualwrite.NewZanzanaReconciler(cfg, zclient, db, lock), + reconciler: dualwrite.NewZanzanaReconciler(cfg, zclient, db, lock, folderService), permRegistry: permRegistry, } diff --git a/pkg/services/accesscontrol/acimpl/service_test.go b/pkg/services/accesscontrol/acimpl/service_test.go index 2dc2303443c..674fb544775 100644 --- a/pkg/services/accesscontrol/acimpl/service_test.go +++ b/pkg/services/accesscontrol/acimpl/service_test.go @@ -74,6 +74,7 @@ func TestUsageMetrics(t *testing.T) { nil, permreg.ProvidePermissionRegistry(), nil, + nil, ) assert.Equal(t, tt.expectedValue, s.GetUsageStats(context.Background())["stats.oss.accesscontrol.enabled.count"]) }) diff --git a/pkg/services/accesscontrol/dualwrite/collectors.go b/pkg/services/accesscontrol/dualwrite/collectors.go index c38803eebfd..d7ea5a1343c 100644 --- a/pkg/services/accesscontrol/dualwrite/collectors.go +++ b/pkg/services/accesscontrol/dualwrite/collectors.go @@ -8,6 +8,9 @@ import ( "github.com/grafana/grafana/pkg/infra/db" authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1" "github.com/grafana/grafana/pkg/services/authz/zanzana" + "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/folder" + "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" ) @@ -63,24 +66,26 @@ func teamMembershipCollector(store db.DB) legacyTupleCollector { } // folderTreeCollector collects folder tree structure and writes it as relation tuples -func folderTreeCollector(store db.DB) legacyTupleCollector { +func folderTreeCollector(folderService folder.Service) legacyTupleCollector { return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) { ctx, span := tracer.Start(ctx, "accesscontrol.migrator.folderTreeCollector") defer span.End() - const query = ` - SELECT uid, parent_uid, org_id FROM folder WHERE org_id = ? - ` - type folder struct { - FolderUID string `xorm:"uid"` - ParentUID string `xorm:"parent_uid"` + user := &user.SignedInUser{ + Login: "folder-tree-collector", + OrgRole: "Admin", + IsGrafanaAdmin: true, + IsServiceAccount: true, + Permissions: map[int64]map[string][]string{orgID: {dashboards.ActionFoldersRead: {dashboards.ScopeFoldersAll}}}, + OrgID: orgID, } - var folders []folder - err := store.WithDbSession(ctx, func(sess *db.Session) error { - return sess.SQL(query, orgID).Find(&folders) - }) + q := folder.GetFoldersQuery{ + OrgID: orgID, + SignedInUser: user, + } + folders, err := folderService.GetFolders(ctx, q) if err != nil { return nil, err } @@ -94,7 +99,7 @@ func folderTreeCollector(store db.DB) legacyTupleCollector { } tuple = &openfgav1.TupleKey{ - Object: zanzana.NewTupleEntry(zanzana.TypeFolder, f.FolderUID, ""), + Object: zanzana.NewTupleEntry(zanzana.TypeFolder, f.UID, ""), Relation: zanzana.RelationParent, User: zanzana.NewTupleEntry(zanzana.TypeFolder, f.ParentUID, ""), } diff --git a/pkg/services/accesscontrol/dualwrite/reconciler.go b/pkg/services/accesscontrol/dualwrite/reconciler.go index e5cbecfa1fc..0aa51d95592 100644 --- a/pkg/services/accesscontrol/dualwrite/reconciler.go +++ b/pkg/services/accesscontrol/dualwrite/reconciler.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/serverlock" "github.com/grafana/grafana/pkg/services/authz/zanzana" + "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/setting" ) @@ -34,7 +35,7 @@ type ZanzanaReconciler struct { reconcilers []resourceReconciler } -func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, lock *serverlock.ServerLockService) *ZanzanaReconciler { +func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, lock *serverlock.ServerLockService, folderService folder.Service) *ZanzanaReconciler { zanzanaReconciler := &ZanzanaReconciler{ cfg: cfg, log: log.New("zanzana.reconciler"), @@ -50,7 +51,7 @@ func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, ), newResourceReconciler( "folder tree", - folderTreeCollector(store), + folderTreeCollector(folderService), zanzanaCollector([]string{zanzana.RelationParent}), client, ), diff --git a/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go b/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go index 3af775f8600..01b6aaa1db9 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go @@ -33,10 +33,6 @@ func ProvideFolderPermissions( 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(), nil, - ) license := licensingtest.NewFakeLicensing() license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe() @@ -55,6 +51,12 @@ func ProvideFolderPermissions( dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + acSvc := acimpl.ProvideOSSService( + cfg, acdb.ProvideService(sqlStore), actionSets, localcache.ProvideService(), + features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sqlStore, permreg.ProvidePermissionRegistry(), + nil, fService, + ) + orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) if err != nil { return nil, err diff --git a/pkg/services/dashboards/service/zanzana_integration_test.go b/pkg/services/dashboards/service/zanzana_integration_test.go index fe7d9971bca..178979c2aca 100644 --- a/pkg/services/dashboards/service/zanzana_integration_test.go +++ b/pkg/services/dashboards/service/zanzana_integration_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/serverlock" "github.com/grafana/grafana/pkg/infra/tracing" @@ -23,6 +24,7 @@ import ( "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/quota/quotatest" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" + "github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest" "github.com/grafana/grafana/pkg/services/tag/tagimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" @@ -87,10 +89,24 @@ func TestIntegrationDashboardServiceZanzana(t *testing.T) { createDashboards(t, service, 100, "test-a") createDashboards(t, service, 100, "test-b") + folderImplStore := folderimpl.ProvideStore(db) + folderService := folderimpl.ProvideService( + folderImplStore, + ac, + bus.ProvideBus(tracing.InitializeTracerForTest()), + dashboardStore, + folderStore, + db, + featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders), + supportbundlestest.NewFakeBundleService(), + nil, + tracing.InitializeTracerForTest(), + ) + // Sync Grafana DB with zanzana (migrate data) tracer := tracing.InitializeTracerForTest() lock := serverlock.ProvideService(db, tracer) - zanzanaSyncronizer := dualwrite.NewZanzanaReconciler(cfg, zclient, db, lock) + zanzanaSyncronizer := dualwrite.NewZanzanaReconciler(cfg, zclient, db, lock, folderService) err = zanzanaSyncronizer.ReconcileSync(context.Background()) require.NoError(t, err) diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index 880d964b0b2..4e7037a8074 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -68,7 +68,7 @@ func ProvideService( supportBundles supportbundles.Service, r prometheus.Registerer, tracer tracing.Tracer, -) folder.Service { +) *Service { srv := &Service{ log: slog.Default().With("logger", "folder-service"), dashboardStore: dashboardStore, diff --git a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go index 55ed6867c2d..71e45e37376 100644 --- a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go +++ b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go @@ -55,7 +55,7 @@ func setupTestEnv(t *testing.T) *TestEnv { acSvc: acimpl.ProvideOSSService( cfg, env.AcStore, &resourcepermissions.FakeActionSetSvc{}, localcache.New(0, 0), fmgt, tracing.InitializeTracerForTest(), nil, nil, - permreg.ProvidePermissionRegistry(), nil, + permreg.ProvidePermissionRegistry(), nil, nil, ), defaultOrgID: autoAssignOrgID, logger: logger,