mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
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:
parent
5cfd983cc2
commit
af2f51f196
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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"`
|
||||
OrgID int64 `json:"orgId" xorm:"org_id"`
|
||||
}
|
||||
|
||||
// GetFolderQuery is used for all folder Get requests. Only one of UID, ID, or
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user