mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
Nested Folders: Unify folder services (#60390)
* Nested Folders: Unify folder services
This commit is contained in:
parent
53d1f4e50b
commit
4df78cebc2
@ -245,7 +245,7 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { //
|
||||
}
|
||||
|
||||
uid := web.Params(c.Req)[":uid"]
|
||||
err = hs.folderService.DeleteFolder(c.Req.Context(), &folder.DeleteFolderCommand{UID: uid, OrgID: c.OrgID, ForceDeleteRules: c.QueryBool("forceDeleteRules"), SignedInUser: c.SignedInUser})
|
||||
err = hs.folderService.Delete(c.Req.Context(), &folder.DeleteFolderCommand{UID: uid, OrgID: c.OrgID, ForceDeleteRules: c.QueryBool("forceDeleteRules"), SignedInUser: c.SignedInUser})
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
@ -488,14 +488,14 @@ func prepareForUpdate(dashFolder *models.Dashboard, orgId int64, userId int64, c
|
||||
dashFolder.UpdateSlug()
|
||||
}
|
||||
|
||||
func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
logger := s.log.FromContext(ctx)
|
||||
if cmd.SignedInUser == nil {
|
||||
return folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
}
|
||||
|
||||
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
||||
err := s.Delete(ctx, cmd)
|
||||
err := s.nestedFolderDelete(ctx, cmd)
|
||||
if err != nil {
|
||||
logger.Error("the delete folder on folder table failed with err: ", "error", err)
|
||||
return err
|
||||
@ -519,6 +519,10 @@ func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderComm
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return s.legacyDelete(ctx, cmd, dashFolder)
|
||||
}
|
||||
|
||||
func (s *Service) legacyDelete(ctx context.Context, cmd *folder.DeleteFolderCommand, dashFolder *folder.Folder) error {
|
||||
deleteCmd := models.DeleteDashboardCommand{OrgId: cmd.OrgID, Id: dashFolder.ID, ForceDeleteFolderRules: cmd.ForceDeleteRules}
|
||||
|
||||
if err := s.dashboardStore.DeleteDashboard(ctx, &deleteCmd); err != nil {
|
||||
@ -549,7 +553,7 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parents, err := s.GetParents(ctx, &folder.GetParentsQuery{UID: cmd.NewParentUID, OrgID: cmd.OrgID})
|
||||
parents, err := s.store.GetParents(ctx, folder.GetParentsQuery{UID: cmd.NewParentUID, OrgID: cmd.OrgID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -574,7 +578,7 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
logger := s.log.FromContext(ctx)
|
||||
if cmd.SignedInUser == nil {
|
||||
return folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
@ -595,7 +599,7 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
|
||||
}
|
||||
for _, f := range folders {
|
||||
logger.Info("deleting subfolder", "org_id", f.OrgID, "uid", f.UID)
|
||||
err := s.Delete(ctx, &folder.DeleteFolderCommand{UID: f.UID, OrgID: f.OrgID, ForceDeleteRules: cmd.ForceDeleteRules, SignedInUser: cmd.SignedInUser})
|
||||
err := s.nestedFolderDelete(ctx, &folder.DeleteFolderCommand{UID: f.UID, OrgID: f.OrgID, ForceDeleteRules: cmd.ForceDeleteRules, SignedInUser: cmd.SignedInUser})
|
||||
if err != nil {
|
||||
logger.Error("failed deleting subfolder", "org_id", f.OrgID, "uid", f.UID, "error", err)
|
||||
return err
|
||||
@ -610,12 +614,6 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetParents(ctx context.Context, cmd *folder.GetParentsQuery) ([]*folder.Folder, error) {
|
||||
// check the flag, if old - do whatever did before
|
||||
// for new only the store
|
||||
return s.store.GetParents(ctx, *cmd)
|
||||
}
|
||||
|
||||
func (s *Service) MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error {
|
||||
return s.dashboardService.MakeUserAdmin(ctx, orgID, userID, folderID, setViewAndEditPermissions)
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(newFolder, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(newFolder, nil)
|
||||
|
||||
err := service.DeleteFolder(context.Background(), &folder.DeleteFolderCommand{
|
||||
err := service.Delete(context.Background(), &folder.DeleteFolderCommand{
|
||||
UID: folderUID,
|
||||
OrgID: orgID,
|
||||
ForceDeleteRules: false,
|
||||
@ -235,7 +235,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
}).Return(nil).Once()
|
||||
|
||||
expectedForceDeleteRules := rand.Int63()%2 == 0
|
||||
err := service.DeleteFolder(context.Background(), &folder.DeleteFolderCommand{
|
||||
err := service.Delete(context.Background(), &folder.DeleteFolderCommand{
|
||||
UID: f.UID,
|
||||
OrgID: orgID,
|
||||
ForceDeleteRules: expectedForceDeleteRules,
|
||||
@ -345,56 +345,6 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
require.NotNil(t, res.UID)
|
||||
require.NotEmpty(t, res.ParentUID)
|
||||
})
|
||||
|
||||
t.Run("get parents folder", func(t *testing.T) {
|
||||
folderStore.ExpectedFolder = &folder.Folder{}
|
||||
_, err := folderService.GetParents(context.Background(), &folder.GetParentsQuery{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("get children folder", func(t *testing.T) {
|
||||
folderStore.ExpectedChildFolders = []*folder.Folder{
|
||||
{
|
||||
UID: "test",
|
||||
},
|
||||
{
|
||||
UID: "test2",
|
||||
},
|
||||
{
|
||||
UID: "test3",
|
||||
},
|
||||
{
|
||||
UID: "test4",
|
||||
},
|
||||
}
|
||||
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
res, err := folderService.GetChildren(context.Background(),
|
||||
&folder.GetChildrenQuery{
|
||||
UID: "test",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(res))
|
||||
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
res, err = folderService.GetChildren(context.Background(),
|
||||
&folder.GetChildrenQuery{
|
||||
UID: "test",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 4, len(res))
|
||||
})
|
||||
}
|
||||
|
||||
func TestNestedFolderService(t *testing.T) {
|
||||
@ -443,7 +393,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
err := foldersvc.DeleteFolder(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
err := foldersvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
@ -697,7 +647,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true, CanViewValue: true})
|
||||
|
||||
err := foldersvc.DeleteFolder(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
err := foldersvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
|
@ -30,7 +30,7 @@ func (s *FakeService) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*fol
|
||||
func (s *FakeService) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
|
||||
return s.ExpectedFolder, s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
func (s *FakeService) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
return s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error {
|
||||
@ -40,13 +40,3 @@ func (s *FakeService) MakeUserAdmin(ctx context.Context, orgID int64, userID, fo
|
||||
func (s *FakeService) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
|
||||
return s.ExpectedFolder, s.ExpectedError
|
||||
}
|
||||
|
||||
func (s *FakeService) GetParents(ctx context.Context, orgID int64, folderUID string) ([]*folder.Folder, error) {
|
||||
return s.ExpectedFolders, s.ExpectedError
|
||||
}
|
||||
|
||||
func (s *FakeService) GetTree(ctx context.Context, orgID int64, folderUID string, depth int64) (map[string][]*folder.Folder, error) {
|
||||
ret := make(map[string][]*folder.Folder)
|
||||
ret[folderUID] = s.ExpectedFolders
|
||||
return ret, s.ExpectedError
|
||||
}
|
||||
|
@ -18,30 +18,8 @@ type Service interface {
|
||||
// Update is used to update a folder's UID, Title and Description. To change
|
||||
// a folder's parent folder, use Move.
|
||||
Update(ctx context.Context, cmd *UpdateFolderCommand) (*Folder, error)
|
||||
DeleteFolder(ctx context.Context, cmd *DeleteFolderCommand) error
|
||||
Delete(ctx context.Context, cmd *DeleteFolderCommand) error
|
||||
MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error
|
||||
// Move changes a folder's parent folder to the requested new parent.
|
||||
Move(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error)
|
||||
}
|
||||
|
||||
// NestedFolderService is the temporary interface definition for the folder
|
||||
// Service which includes any new or alternate methods. These will be collapsed
|
||||
// into a single service when the nested folder implementation is rolled out.
|
||||
// Note that the commands in this service use models from this package, while
|
||||
// the legacy FolderService uses models from the models package.
|
||||
type NestedFolderService interface {
|
||||
// Create creates a new folder.
|
||||
Create(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error)
|
||||
|
||||
// Delete deletes a folder. This will return an error if there are any
|
||||
// dashboards in the folder.
|
||||
Delete(ctx context.Context, cmd *DeleteFolderCommand) (*Folder, error)
|
||||
|
||||
// GetParents returns an ordered list of parent folders for the given
|
||||
// folder, starting with the root node and ending with the requested child
|
||||
// node.
|
||||
GetParents(ctx context.Context, cmd *GetParentsQuery) ([]*Folder, error)
|
||||
|
||||
// GetChildren returns an array containing all child folders.
|
||||
GetChildren(ctx context.Context, cmd *GetChildrenQuery) ([]*Folder, error)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user