From a5206a1cda5701fa42e1b025e456c6a369e7591b Mon Sep 17 00:00:00 2001 From: Arati R <33031346+suntala@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:00:09 +0200 Subject: [PATCH] Nested folders: Provide count of all descendant dashboards and folders (#67184) * Add a method for getting descendant folders * Include dashboard count for descendant folders * Return subfolder count * Replace references to children with descendants * Update openapi specs * Add test for descendant counts * Add logging to GetDescendantCounts --- pkg/api/api.go | 2 +- pkg/api/folder.go | 18 +- pkg/services/folder/folderimpl/folder.go | 44 ++- pkg/services/folder/folderimpl/folder_test.go | 276 ++++++++++-------- pkg/services/folder/foldertest/foldertest.go | 12 +- pkg/services/folder/model.go | 8 +- pkg/services/folder/service.go | 2 +- public/api-merged.json | 22 +- public/openapi3.json | 22 +- 9 files changed, 237 insertions(+), 169 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 72f86ea6a34..e72f7c8768a 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -462,7 +462,7 @@ func (hs *HTTPServer) registerRoutes() { folderUidRoute.Put("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.UpdateFolder)) folderUidRoute.Post("/move", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersWrite, uidScope)), routing.Wrap(hs.MoveFolder)) folderUidRoute.Delete("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersDelete, uidScope)), routing.Wrap(hs.DeleteFolder)) - folderUidRoute.Get("/counts", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderChildrenCounts)) + folderUidRoute.Get("/counts", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersRead, uidScope)), routing.Wrap(hs.GetFolderDescendantCounts)) folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) { folderPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionFoldersPermissionsRead, uidScope)), routing.Wrap(hs.GetFolderPermissionList)) diff --git a/pkg/api/folder.go b/pkg/api/folder.go index 1f510d4396b..34497df298b 100644 --- a/pkg/api/folder.go +++ b/pkg/api/folder.go @@ -299,19 +299,19 @@ func (hs *HTTPServer) DeleteFolder(c *contextmodel.ReqContext) response.Response return response.JSON(http.StatusOK, "") } -// swagger:route GET /folders/{folder_uid}/counts folders getFolderChildrenCounts +// swagger:route GET /folders/{folder_uid}/counts folders getFolderDescendantCounts // // Gets the count of each descendant of a folder by kind. The folder is identified by UID. // // Responses: -// 200: getFolderChildrenCountsResponse +// 200: getFolderDescendantCountsResponse // 401: unauthorisedError // 403: forbiddenError // 404: notFoundError // 500: internalServerError -func (hs *HTTPServer) GetFolderChildrenCounts(c *contextmodel.ReqContext) response.Response { +func (hs *HTTPServer) GetFolderDescendantCounts(c *contextmodel.ReqContext) response.Response { uid := web.Params(c.Req)[":uid"] - counts, err := hs.folderService.GetChildrenCounts(c.Req.Context(), &folder.GetChildrenCountsQuery{OrgID: c.OrgID, UID: &uid, SignedInUser: c.SignedInUser}) + counts, err := hs.folderService.GetDescendantCounts(c.Req.Context(), &folder.GetDescendantCountsQuery{OrgID: c.OrgID, UID: &uid, SignedInUser: c.SignedInUser}) if err != nil { return apierrors.ToFolderErrorResponse(err) } @@ -546,16 +546,16 @@ type DeleteFolderResponse struct { } `json:"body"` } -// swagger:parameters getFolderChildrenCounts -type GetFolderChildrenCountsParams struct { +// swagger:parameters getFolderDescendantCounts +type GetFolderDescendantCountsParams struct { // in:path // required:true FolderUID string `json:"folder_uid"` } -// swagger:response getFolderChildrenCountsResponse -type GetFolderChildrenCountsResponse struct { +// swagger:response getFolderDescendantCountsResponse +type GetFolderDescendantCountsResponse struct { // The response message // in: body - Body folder.ChildrenCounts `json:"body"` + Body folder.DescendantCounts `json:"body"` } diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index cde1174ce9c..83a84bc9ea9 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -20,6 +20,7 @@ import ( "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/user" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -623,7 +624,8 @@ func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFold return result, nil } -func (s *Service) GetChildrenCounts(ctx context.Context, cmd *folder.GetChildrenCountsQuery) (folder.ChildrenCounts, error) { +func (s *Service) GetDescendantCounts(ctx context.Context, cmd *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { + logger := s.log.FromContext(ctx) if cmd.SignedInUser == nil { return nil, folder.ErrBadRequest.Errorf("missing signed-in user") } @@ -634,15 +636,47 @@ func (s *Service) GetChildrenCounts(ctx context.Context, cmd *folder.GetChildren return nil, folder.ErrBadRequest.Errorf("invalid orgID") } - countsMap := make(folder.ChildrenCounts, len(s.registry)) + result := []string{*cmd.UID} + countsMap := make(folder.DescendantCounts, len(s.registry)+1) + if s.features.IsEnabled(featuremgmt.FlagNestedFolders) { + subfolders, err := s.getNestedFolders(ctx, cmd.OrgID, *cmd.UID) + if err != nil { + logger.Error("failed to get subfolders", "error", err) + return nil, err + } + result = append(result, subfolders...) + countsMap[entity.StandardKindFolder] = int64(len(subfolders)) + } + for _, v := range s.registry { - c, err := v.CountInFolder(ctx, cmd.OrgID, *cmd.UID, cmd.SignedInUser) + for _, folder := range result { + c, err := v.CountInFolder(ctx, cmd.OrgID, folder, cmd.SignedInUser) + if err != nil { + logger.Error("failed to count folder descendants", "error", err) + return nil, err + } + countsMap[v.Kind()] += c + } + } + return countsMap, nil +} + +func (s *Service) getNestedFolders(ctx context.Context, orgID int64, uid string) ([]string, error) { + result := []string{} + folders, err := s.store.GetChildren(ctx, folder.GetChildrenQuery{UID: uid, OrgID: orgID}) + if err != nil { + return nil, err + } + + for _, f := range folders { + result = append(result, f.UID) + subfolders, err := s.getNestedFolders(ctx, f.OrgID, f.UID) if err != nil { return nil, err } - countsMap[v.Kind()] += c + result = append(result, subfolders...) } - return countsMap, nil + return result, nil } // MakeUserAdmin is copy of DashboardServiceImpl.MakeUserAdmin diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index 80e29f72c4f..73818503c0e 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db/dbtest" "github.com/grafana/grafana/pkg/infra/log" @@ -322,7 +321,7 @@ func TestIntegrationFolderService(t *testing.T) { }) } -func TestIntegrationDeleteNestedFolders(t *testing.T) { +func TestIntegrationNestedFolderService(t *testing.T) { if testing.Short() { t.Skip("skipping integration test") } @@ -347,6 +346,7 @@ func TestIntegrationDeleteNestedFolders(t *testing.T) { bus: bus.ProvideBus(tracing.InitializeTracerForTest()), db: db, accessControl: acimpl.ProvideAccessControl(cfg), + registry: make(map[string]folder.RegistryService), } signedInUser := user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{ @@ -358,77 +358,170 @@ func TestIntegrationDeleteNestedFolders(t *testing.T) { SignedInUser: &signedInUser, } - t.Run("With nested folder feature flag on", func(t *testing.T) { - origNewGuardian := guardian.New - guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) + t.Run("Should get descendant counts", func(t *testing.T) { + ac := acmock.New() + folderPermissions := acmock.NewMockedPermissionsService() + dashboardPermissions := acmock.NewMockedPermissionsService() + depth := 5 + t.Run("With nested folder feature flag on", func(t *testing.T) { + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) - serviceWithFlagOn.store = nestedFolderStore - ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, 3, "", createCmd) + _, err := service.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, nil, featuresFlagOn, folderPermissions, dashboardPermissions, ac, serviceWithFlagOn) + require.NoError(t, err) - deleteCmd := folder.DeleteFolderCommand{ - UID: ancestorUIDs[0], - OrgID: orgID, - SignedInUser: &signedInUser, - } - err = serviceWithFlagOn.Delete(context.Background(), &deleteCmd) - require.NoError(t, err) + ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, depth, "getDescendantCountsOn", createCmd) - for i, uid := range ancestorUIDs { - // dashboard table - _, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, uid) - require.ErrorIs(t, err, dashboards.ErrFolderNotFound) - // folder table - _, err = serviceWithFlagOn.store.Get(context.Background(), folder.GetFolderQuery{UID: &ancestorUIDs[i], OrgID: orgID}) - require.ErrorIs(t, err, folder.ErrFolderNotFound) - } - t.Cleanup(func() { - guardian.New = origNewGuardian + parent, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, ancestorUIDs[0]) + require.NoError(t, err) + subfolder, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, ancestorUIDs[1]) + require.NoError(t, err) + _ = insertTestDashboard(t, serviceWithFlagOn.dashboardStore, "dashboard in parent", orgID, parent.ID, "prod") + _ = insertTestDashboard(t, serviceWithFlagOn.dashboardStore, "dashboard in subfolder", orgID, subfolder.ID, "prod") + + countCmd := folder.GetDescendantCountsQuery{ + UID: &ancestorUIDs[0], + OrgID: orgID, + SignedInUser: &signedInUser, + } + m, err := serviceWithFlagOn.GetDescendantCounts(context.Background(), &countCmd) + require.NoError(t, err) + require.Equal(t, m["folder"], int64(depth-1)) + require.Equal(t, m["dashboard"], int64(2)) + + t.Cleanup(func() { + guardian.New = origNewGuardian + for _, uid := range ancestorUIDs { + err := serviceWithFlagOn.store.Delete(context.Background(), uid, orgID) + assert.NoError(t, err) + } + }) + }) + t.Run("With nested folder feature flag off", func(t *testing.T) { + featuresFlagOff := featuremgmt.WithFeatures() + dashStore, err := database.ProvideDashboardStore(db, db.Cfg, featuresFlagOff, tagimpl.ProvideService(db, db.Cfg), quotaService) + require.NoError(t, err) + nestedFolderStore := ProvideStore(db, db.Cfg, featuresFlagOff) + + serviceWithFlagOff := &Service{ + cfg: cfg, + log: log.New("test-folder-service"), + dashboardStore: dashStore, + dashboardFolderStore: folderStore, + store: nestedFolderStore, + features: featuresFlagOff, + bus: bus.ProvideBus(tracing.InitializeTracerForTest()), + db: db, + registry: make(map[string]folder.RegistryService), + } + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) + + _, err = service.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, nil, featuresFlagOff, folderPermissions, dashboardPermissions, ac, serviceWithFlagOff) + require.NoError(t, err) + + ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, depth, "getDescendantCountsOff", createCmd) + + parent, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, ancestorUIDs[0]) + require.NoError(t, err) + subfolder, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, ancestorUIDs[1]) + require.NoError(t, err) + _ = insertTestDashboard(t, serviceWithFlagOn.dashboardStore, "dashboard in parent", orgID, parent.ID, "prod") + _ = insertTestDashboard(t, serviceWithFlagOn.dashboardStore, "dashboard in subfolder", orgID, subfolder.ID, "prod") + + countCmd := folder.GetDescendantCountsQuery{ + UID: &ancestorUIDs[0], + OrgID: orgID, + SignedInUser: &signedInUser, + } + m, err := serviceWithFlagOff.GetDescendantCounts(context.Background(), &countCmd) + require.NoError(t, err) + require.Equal(t, m["folder"], int64(0)) + require.Equal(t, m["dashboard"], int64(1)) + + t.Cleanup(func() { + guardian.New = origNewGuardian + for _, uid := range ancestorUIDs { + err := serviceWithFlagOn.store.Delete(context.Background(), uid, orgID) + assert.NoError(t, err) + } + }) }) }) - t.Run("With feature flag unset", func(t *testing.T) { - featuresFlagOff := featuremgmt.WithFeatures() - dashStore, err := database.ProvideDashboardStore(db, db.Cfg, featuresFlagOff, tagimpl.ProvideService(db, db.Cfg), quotaService) - require.NoError(t, err) - nestedFolderStore := ProvideStore(db, db.Cfg, featuresFlagOff) - serviceWithFlagOff := &Service{ - cfg: cfg, - log: log.New("test-folder-service"), - dashboardStore: dashStore, - dashboardFolderStore: folderStore, - store: nestedFolderStore, - features: featuresFlagOff, - bus: bus.ProvideBus(tracing.InitializeTracerForTest()), - db: db, - } + t.Run("Should delete folders", func(t *testing.T) { + t.Run("With nested folder feature flag on", func(t *testing.T) { + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) - origNewGuardian := guardian.New - guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) + ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, 3, "", createCmd) - ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, 1, "", createCmd) - - deleteCmd := folder.DeleteFolderCommand{ - UID: ancestorUIDs[0], - OrgID: orgID, - SignedInUser: &signedInUser, - } - err = serviceWithFlagOff.Delete(context.Background(), &deleteCmd) - require.NoError(t, err) - - for i, uid := range ancestorUIDs { - // dashboard table - _, err := serviceWithFlagOff.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, uid) - require.ErrorIs(t, err, dashboards.ErrFolderNotFound) - // folder table - _, err = serviceWithFlagOff.store.Get(context.Background(), folder.GetFolderQuery{UID: &ancestorUIDs[i], OrgID: orgID}) + deleteCmd := folder.DeleteFolderCommand{ + UID: ancestorUIDs[0], + OrgID: orgID, + SignedInUser: &signedInUser, + } + err = serviceWithFlagOn.Delete(context.Background(), &deleteCmd) require.NoError(t, err) - } - t.Cleanup(func() { - guardian.New = origNewGuardian - for _, uid := range ancestorUIDs { - err := serviceWithFlagOff.store.Delete(context.Background(), uid, orgID) + + for i, uid := range ancestorUIDs { + // dashboard table + _, err := serviceWithFlagOn.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, uid) + require.ErrorIs(t, err, dashboards.ErrFolderNotFound) + // folder table + _, err = serviceWithFlagOn.store.Get(context.Background(), folder.GetFolderQuery{UID: &ancestorUIDs[i], OrgID: orgID}) + require.ErrorIs(t, err, folder.ErrFolderNotFound) + } + t.Cleanup(func() { + guardian.New = origNewGuardian + }) + }) + t.Run("With nested folder feature flag off", func(t *testing.T) { + featuresFlagOff := featuremgmt.WithFeatures() + dashStore, err := database.ProvideDashboardStore(db, db.Cfg, featuresFlagOff, tagimpl.ProvideService(db, db.Cfg), quotaService) + require.NoError(t, err) + nestedFolderStore := ProvideStore(db, db.Cfg, featuresFlagOff) + + serviceWithFlagOff := &Service{ + cfg: cfg, + log: log.New("test-folder-service"), + dashboardStore: dashStore, + dashboardFolderStore: folderStore, + store: nestedFolderStore, + features: featuresFlagOff, + bus: bus.ProvideBus(tracing.InitializeTracerForTest()), + db: db, + } + + origNewGuardian := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true}) + + ancestorUIDs := CreateSubtreeInStore(t, nestedFolderStore, serviceWithFlagOn, 1, "", createCmd) + + deleteCmd := folder.DeleteFolderCommand{ + UID: ancestorUIDs[0], + OrgID: orgID, + SignedInUser: &signedInUser, + } + err = serviceWithFlagOff.Delete(context.Background(), &deleteCmd) + require.NoError(t, err) + + for i, uid := range ancestorUIDs { + // dashboard table + _, err := serviceWithFlagOff.dashboardFolderStore.GetFolderByUID(context.Background(), orgID, uid) + require.ErrorIs(t, err, dashboards.ErrFolderNotFound) + // folder table + _, err = serviceWithFlagOff.store.Get(context.Background(), folder.GetFolderQuery{UID: &ancestorUIDs[i], OrgID: orgID}) require.NoError(t, err) } + t.Cleanup(func() { + guardian.New = origNewGuardian + for _, uid := range ancestorUIDs { + err := serviceWithFlagOff.store.Delete(context.Background(), uid, orgID) + require.NoError(t, err) + } + }) }) }) } @@ -930,65 +1023,6 @@ func TestNestedFolderService(t *testing.T) { }) } -func TestGetChildrenCounts(t *testing.T) { - g := guardian.New - guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true}) - t.Cleanup(func() { - guardian.New = g - }) - - folderId := rand.Int63() - folderUID := util.GenerateShortUID() - f := folder.NewFolder("Folder", "") - f.ID = folderId - f.UID = folderUID - f.OrgID = orgID - - nestedFolderStore := NewFakeStore() - nestedFolderStore.ExpectedFolder = f - - dashStore := dashboards.FakeDashboardStore{} - dashboardCount := int64(2) - countCmd := dashboards.CountDashboardsInFolderRequest{ - FolderID: f.ID, - OrgID: f.OrgID, - } - dashStore.On("CountDashboardsInFolder", mock.Anything, &countCmd).Return(dashboardCount, nil) - - dashboardFolderStore := foldertest.NewFakeFolderStore(t) - dashboardFolderStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(f, nil) - - cfg := setting.NewCfg() - cfg.RBACEnabled = false - features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) - folderService := &Service{ - cfg: cfg, - store: nestedFolderStore, - dashboardStore: &dashStore, - dashboardFolderStore: dashboardFolderStore, - features: features, - log: log.New("test-folder-service"), - accessControl: acimpl.ProvideAccessControl(cfg), - registry: make(map[string]folder.RegistryService), - } - - ac := acmock.New() - folderPermissions := acmock.NewMockedPermissionsService() - dashboardPermissions := acmock.NewMockedPermissionsService() - _, err := service.ProvideDashboardServiceImpl(cfg, &dashStore, dashboardFolderStore, nil, features, folderPermissions, dashboardPermissions, ac, folderService) - require.NoError(t, err) - - signedInUser := user.SignedInUser{UserID: 1, OrgID: orgID} - ctx := appcontext.WithUser(context.Background(), &signedInUser) - res, err := folderService.GetChildrenCounts(ctx, &folder.GetChildrenCountsQuery{ - SignedInUser: usr, - UID: &folderUID, - OrgID: orgID, - }) - require.NoError(t, err) - require.Equal(t, res["dashboard"], dashboardCount) -} - func CreateSubtreeInStore(t *testing.T, store *sqlStore, service *Service, depth int, prefix string, cmd folder.CreateFolderCommand) []string { t.Helper() diff --git a/pkg/services/folder/foldertest/foldertest.go b/pkg/services/folder/foldertest/foldertest.go index 9468186147a..dd865b07b36 100644 --- a/pkg/services/folder/foldertest/foldertest.go +++ b/pkg/services/folder/foldertest/foldertest.go @@ -7,10 +7,10 @@ import ( ) type FakeService struct { - ExpectedFolders []*folder.Folder - ExpectedFolder *folder.Folder - ExpectedError error - ExpectedChildrenCounts map[string]int64 + ExpectedFolders []*folder.Folder + ExpectedFolder *folder.Folder + ExpectedError error + ExpectedDescendantCounts map[string]int64 } func NewFakeService() *FakeService { @@ -51,6 +51,6 @@ func (s *FakeService) RegisterService(service folder.RegistryService) error { return s.ExpectedError } -func (s *FakeService) GetChildrenCounts(ctx context.Context, cmd *folder.GetChildrenCountsQuery) (folder.ChildrenCounts, error) { - return s.ExpectedChildrenCounts, s.ExpectedError +func (s *FakeService) GetDescendantCounts(ctx context.Context, cmd *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { + return s.ExpectedDescendantCounts, s.ExpectedError } diff --git a/pkg/services/folder/model.go b/pkg/services/folder/model.go index 1040c7a8088..91cda1d5533 100644 --- a/pkg/services/folder/model.go +++ b/pkg/services/folder/model.go @@ -155,13 +155,13 @@ type HasAdminPermissionInDashboardsOrFoldersQuery struct { SignedInUser *user.SignedInUser } -// GetChildrenCountsQuery captures the information required by the folder service -// to return the count of children in a folder. -type GetChildrenCountsQuery struct { +// GetDescendantCountsQuery captures the information required by the folder service +// to return the count of descendants (direct and indirect) in a folder. +type GetDescendantCountsQuery struct { UID *string OrgID int64 SignedInUser *user.SignedInUser `json:"-"` } -type ChildrenCounts map[string]int64 +type DescendantCounts map[string]int64 diff --git a/pkg/services/folder/service.go b/pkg/services/folder/service.go index 720f9dd5eed..74b10c61fe8 100644 --- a/pkg/services/folder/service.go +++ b/pkg/services/folder/service.go @@ -26,7 +26,7 @@ type Service interface { // Move changes a folder's parent folder to the requested new parent. Move(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error) RegisterService(service RegistryService) error - GetChildrenCounts(ctx context.Context, cmd *GetChildrenCountsQuery) (ChildrenCounts, error) + GetDescendantCounts(ctx context.Context, cmd *GetDescendantCountsQuery) (DescendantCounts, error) } // FolderStore is a folder store. diff --git a/public/api-merged.json b/public/api-merged.json index 8dec040b7ee..64a7f7463c9 100644 --- a/public/api-merged.json +++ b/public/api-merged.json @@ -5655,7 +5655,7 @@ "folders" ], "summary": "Gets the count of each descendant of a folder by kind. The folder is identified by UID.", - "operationId": "getFolderChildrenCounts", + "operationId": "getFolderDescendantCounts", "parameters": [ { "type": "string", @@ -5666,7 +5666,7 @@ ], "responses": { "200": { - "$ref": "#/responses/getFolderChildrenCountsResponse" + "$ref": "#/responses/getFolderDescendantCountsResponse" }, "401": { "$ref": "#/responses/unauthorisedError" @@ -11885,13 +11885,6 @@ } } }, - "ChildrenCounts": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int64" - } - }, "ConfFloat64": { "description": "ConfFloat64 is a float64. It Marshals float64 values of NaN of Inf\nto null.", "type": "number", @@ -13098,6 +13091,13 @@ } } }, + "DescendantCounts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int64" + } + }, "DiscordConfig": { "type": "object", "title": "DiscordConfig configures notifications via Discord.", @@ -20341,10 +20341,10 @@ "$ref": "#/definitions/DataSourceList" } }, - "getFolderChildrenCountsResponse": { + "getFolderDescendantCountsResponse": { "description": "(empty)", "schema": { - "$ref": "#/definitions/ChildrenCounts" + "$ref": "#/definitions/DescendantCounts" } }, "getFolderPermissionListResponse": { diff --git a/public/openapi3.json b/public/openapi3.json index bbdca11f0f6..cd0bc5bf846 100644 --- a/public/openapi3.json +++ b/public/openapi3.json @@ -792,11 +792,11 @@ }, "description": "(empty)" }, - "getFolderChildrenCountsResponse": { + "getFolderDescendantCountsResponse": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChildrenCounts" + "$ref": "#/components/schemas/DescendantCounts" } } }, @@ -2952,13 +2952,6 @@ }, "type": "object" }, - "ChildrenCounts": { - "additionalProperties": { - "format": "int64", - "type": "integer" - }, - "type": "object" - }, "ConfFloat64": { "description": "ConfFloat64 is a float64. It Marshals float64 values of NaN of Inf\nto null.", "format": "double", @@ -4165,6 +4158,13 @@ }, "type": "object" }, + "DescendantCounts": { + "additionalProperties": { + "format": "int64", + "type": "integer" + }, + "type": "object" + }, "DiscordConfig": { "properties": { "http_config": { @@ -17026,7 +17026,7 @@ }, "/folders/{folder_uid}/counts": { "get": { - "operationId": "getFolderChildrenCounts", + "operationId": "getFolderDescendantCounts", "parameters": [ { "in": "path", @@ -17039,7 +17039,7 @@ ], "responses": { "200": { - "$ref": "#/components/responses/getFolderChildrenCountsResponse" + "$ref": "#/components/responses/getFolderDescendantCountsResponse" }, "401": { "$ref": "#/components/responses/unauthorisedError"