Folder: Add folder service implementation (#58182)

* Folder: Add folder service implementation

* Add Move

* Add tests

* Add new servie method and adjust Update, Delete and Move

* Remove contains

* GetTree return children of depth one
This commit is contained in:
idafurjes 2022-11-08 11:33:13 +01:00 committed by GitHub
parent 5cfd983cc2
commit af2f51f196
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 157 additions and 4 deletions

View File

@ -18,9 +18,12 @@ import (
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
type Service struct {
store store
log log.Logger
cfg *setting.Cfg
dashboardService dashboards.DashboardService
@ -284,6 +287,76 @@ func (s *Service) DeleteFolder(ctx context.Context, user *user.SignedInUser, org
return dashFolder, nil
}
func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
if cmd.UID == "" {
cmd.UID = util.GenerateShortUID()
}
return s.store.Create(ctx, *cmd)
}
func (s *Service) Update(ctx context.Context, cmd *folder.UpdateFolderCommand) (*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
return s.store.Update(ctx, *cmd)
}
func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
foldr, err := s.Get(ctx, &folder.GetFolderQuery{
UID: &cmd.UID,
OrgID: cmd.OrgID,
})
if err != nil {
return nil, err
}
return s.store.Update(ctx, folder.UpdateFolderCommand{
Folder: foldr,
NewParentUID: &cmd.NewParentUID,
})
}
func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) (*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
// check if dashboard exists
foldr, err := s.Get(ctx, &folder.GetFolderQuery{
UID: &cmd.UID,
OrgID: cmd.OrgID,
})
if err != nil {
return nil, err
}
err = s.store.Delete(ctx, cmd.UID, cmd.OrgID)
if err != nil {
return nil, err
}
return foldr, nil
}
func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
return s.store.Get(ctx, *cmd)
}
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) GetTree(ctx context.Context, cmd *folder.GetTreeQuery) ([]*folder.Folder, error) {
// check the flag, if old - do whatever did before
// for new only the store
return s.store.GetChildren(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

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards"
dashboardsvc "github.com/grafana/grafana/pkg/services/dashboards/service"
"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/user"
"github.com/grafana/grafana/pkg/setting"
@ -259,3 +260,69 @@ func TestIntegrationFolderService(t *testing.T) {
})
})
}
func TestFolderService(t *testing.T) {
folderStore := NewFakeStore()
folderService := &Service{
store: folderStore,
}
t.Run("create folder", func(t *testing.T) {
folderStore.ExpectedFolder = &folder.Folder{}
res, err := folderService.Create(context.Background(), &folder.CreateFolderCommand{})
require.NoError(t, err)
require.NotNil(t, res.UID)
})
t.Run("update folder", func(t *testing.T) {
folderStore.ExpectedFolder = &folder.Folder{}
_, err := folderService.Update(context.Background(), &folder.UpdateFolderCommand{})
require.NoError(t, err)
})
t.Run("delete folder", func(t *testing.T) {
folderStore.ExpectedFolder = &folder.Folder{}
_, err := folderService.Delete(context.Background(), &folder.DeleteFolderCommand{})
require.NoError(t, err)
})
t.Run("get folder", func(t *testing.T) {
folderStore.ExpectedFolder = &folder.Folder{}
_, err := folderService.Get(context.Background(), &folder.GetFolderQuery{})
require.NoError(t, err)
})
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.ExpectedFolders = []*folder.Folder{
{
UID: "test",
},
{
UID: "test2",
},
{
UID: "test3",
},
{
UID: "test4",
},
}
res, err := folderService.GetTree(context.Background(),
&folder.GetTreeQuery{
UID: "test",
})
require.NoError(t, err)
require.Equal(t, 4, len(res))
})
t.Run("move folder", func(t *testing.T) {
folderStore.ExpectedFolder = &folder.Folder{}
_, err := folderService.Move(context.Background(), &folder.MoveFolderCommand{})
require.NoError(t, err)
})
}

View File

@ -120,6 +120,12 @@ func (ss *sqlStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand)
args = append(args, cmd.Folder.UID)
}
if cmd.NewParentUID != nil {
columnsToUpdate = append(columnsToUpdate, "parent_uid = ?")
cmd.Folder.ParentUID = *cmd.NewParentUID
args = append(args, cmd.Folder.UID)
}
if len(columnsToUpdate) == 0 {
return folder.ErrBadRequest.Errorf("no columns to update")
}

View File

@ -12,6 +12,10 @@ type FakeStore struct {
ExpectedError error
}
func NewFakeStore() *FakeStore {
return &FakeStore{}
}
var _ store = (*FakeStore)(nil)
func (f *FakeStore) Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) {
@ -26,8 +30,8 @@ func (f *FakeStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand)
return f.ExpectedFolder, f.ExpectedError
}
func (f *FakeStore) Move(ctx context.Context, cmd folder.MoveFolderCommand) (*folder.Folder, error) {
return f.ExpectedFolder, f.ExpectedError
func (f *FakeStore) Move(ctx context.Context, cmd folder.MoveFolderCommand) error {
return f.ExpectedError
}
func (f *FakeStore) Get(ctx context.Context, cmd folder.GetFolderQuery) (*folder.Folder, error) {

View File

@ -60,6 +60,7 @@ type CreateFolderCommand struct {
type UpdateFolderCommand struct {
Folder *Folder `json:"folder"` // The extant folder
NewUID *string `json:"uid" xorm:"uid"`
NewParentUID *string `json:"parent_uid" xorm:"parent_uid"`
NewTitle *string `json:"title"`
NewDescription *string `json:"description"`
}
@ -69,12 +70,14 @@ type UpdateFolderCommand struct {
type MoveFolderCommand struct {
UID string `json:"uid"`
NewParentUID string `json:"new_parent_uid"`
OrgID int64 `json:"orgId"`
}
// DeleteFolderCommand captures the information required by the folder service
// to delete a folder.
type DeleteFolderCommand struct {
UID string `json:"uid" xorm:"uid"`
UID string `json:"uid" xorm:"uid"`
OrgID int64 `json:"orgId" xorm:"org_id"`
}
// GetFolderQuery is used for all folder Get requests. Only one of UID, ID, or

View File

@ -55,5 +55,5 @@ type NestedFolderService interface {
//
// The map keys are folder uids and the values are the list of child folders
// for that parent.
GetTree(ctx context.Context, cmd *GetTreeQuery) (map[string][]*Folder, error)
GetTree(ctx context.Context, cmd *GetTreeQuery) ([]*Folder, error)
}