Nested Folders: Unify folder services (#60390)

* Nested Folders: Unify folder services
This commit is contained in:
Sofia Papagiannaki 2022-12-20 17:38:09 +02:00 committed by GitHub
parent 53d1f4e50b
commit 4df78cebc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 16 additions and 100 deletions

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}