Folder: Add implementation for Update for nested folder (#58479)

* Add implementation for Update nested folder

* Remove parent uid from Update

* Fix update
This commit is contained in:
idafurjes 2022-11-10 14:28:55 +01:00 committed by GitHub
parent bd6ac793a0
commit 30f0d66983
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 69 additions and 54 deletions

View File

@ -151,12 +151,12 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext) response.Response {
if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}
err := hs.folderService.UpdateFolder(c.Req.Context(), c.SignedInUser, c.OrgID, web.Params(c.Req)[":uid"], &cmd)
result, err := hs.folderService.Update(c.Req.Context(), c.SignedInUser, c.OrgID, web.Params(c.Req)[":uid"], &cmd)
if err != nil {
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(c.Req.Context(), cmd.Result.Id, c.OrgID, c.SignedInUser)
return response.JSON(http.StatusOK, hs.toFolderDto(c, g, cmd.Result))
g := guardian.New(c.Req.Context(), result.Id, c.OrgID, c.SignedInUser)
return response.JSON(http.StatusOK, hs.toFolderDto(c, g, result))
}
// swagger:route DELETE /folders/{folder_uid} folders deleteFolder

View File

@ -80,10 +80,11 @@ type CreateFolderCommand struct {
}
type UpdateFolderCommand struct {
Uid string `json:"uid"`
Title string `json:"title"`
Version int `json:"version"`
Overwrite bool `json:"overwrite"`
Uid string `json:"uid"`
Title string `json:"title"`
Version int `json:"version"`
Description string `json:"description"`
Overwrite bool `json:"overwrite"`
Result *Folder `json:"-"`
}

View File

@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/org"
@ -253,17 +254,53 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
return folder.FromDashboard(dash), nil
}
func (s *Service) UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error {
func (s *Service) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
foldr, err := s.legacyUpdate(ctx, user, orgID, existingUid, cmd)
if err != nil {
return nil, err
}
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) {
if cmd.Uid != "" {
if !util.IsValidShortUID(cmd.Uid) {
return nil, dashboards.ErrDashboardInvalidUid
} else if util.IsShortUIDTooLong(cmd.Uid) {
return nil, dashboards.ErrDashboardUidTooLong
}
}
getFolder, err := s.store.Get(ctx, folder.GetFolderQuery{
UID: &existingUid,
OrgID: orgID,
})
if err != nil {
return nil, err
}
_, err = s.store.Update(ctx, folder.UpdateFolderCommand{
Folder: getFolder,
NewUID: &cmd.Uid,
NewTitle: &cmd.Title,
NewDescription: &cmd.Description,
})
if err != nil {
return nil, err
}
}
return foldr, nil
}
func (s *Service) legacyUpdate(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
query := models.GetDashboardQuery{OrgId: orgID, Uid: existingUid}
if _, err := s.dashboardStore.GetDashboard(ctx, &query); err != nil {
return toFolderError(err)
_, err := s.dashboardStore.GetDashboard(ctx, &query)
if err != nil {
return nil, toFolderError(err)
}
dashFolder := query.Result
currentTitle := dashFolder.Title
if !dashFolder.IsFolder {
return dashboards.ErrFolderNotFound
return nil, dashboards.ErrFolderNotFound
}
cmd.UpdateDashboardModel(dashFolder, orgID, user.UserID)
@ -277,34 +314,32 @@ func (s *Service) UpdateFolder(ctx context.Context, user *user.SignedInUser, org
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
if err != nil {
return toFolderError(err)
return nil, toFolderError(err)
}
dash, err := s.dashboardStore.SaveDashboard(ctx, *saveDashboardCmd)
if err != nil {
return toFolderError(err)
return nil, toFolderError(err)
}
var folder *models.Folder
folder, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id)
var foldr *models.Folder
foldr, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id)
if err != nil {
return err
return nil, err
}
cmd.Result = folder
if currentTitle != folder.Title {
if currentTitle != foldr.Title {
if err := s.bus.Publish(ctx, &events.FolderTitleUpdated{
Timestamp: folder.Updated,
Title: folder.Title,
Timestamp: foldr.Updated,
Title: foldr.Title,
ID: dash.Id,
UID: dash.Uid,
OrgID: orgID,
}); err != nil {
s.log.Error("failed to publish FolderTitleUpdated event", "folder", folder.Title, "user", user.UserID, "error", err)
s.log.Error("failed to publish FolderTitleUpdated event", "folder", foldr.Title, "user", user.UserID, "error", err)
}
}
return nil
return foldr, nil
}
func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
@ -340,12 +375,6 @@ func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderComm
return nil
}
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
@ -359,8 +388,8 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
}
return s.store.Update(ctx, folder.UpdateFolderCommand{
Folder: foldr,
NewParentUID: &cmd.NewParentUID,
Folder: foldr,
// NewParentUID: &cmd.NewParentUID,
})
}

View File

@ -119,7 +119,7 @@ func TestIntegrationFolderService(t *testing.T) {
folder.Result = models.NewDashboard("dashboard-test")
folder.Result.IsFolder = true
}).Return(&models.Dashboard{}, nil)
err := service.UpdateFolder(context.Background(), usr, orgID, folderUID, &models.UpdateFolderCommand{
_, err := service.Update(context.Background(), usr, orgID, folderUID, &models.UpdateFolderCommand{
Uid: folderUID,
Title: "Folder-TEST",
})
@ -201,9 +201,9 @@ func TestIntegrationFolderService(t *testing.T) {
Title: "TEST-Folder",
}
err := service.UpdateFolder(context.Background(), usr, orgID, dashboardFolder.Uid, req)
reqResult, err := service.Update(context.Background(), usr, orgID, dashboardFolder.Uid, req)
require.NoError(t, err)
require.Equal(t, f, req.Result)
require.Equal(t, f, reqResult)
})
t.Run("When deleting folder by uid should not return access denied error", func(t *testing.T) {
@ -338,12 +338,6 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
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{})

View File

@ -122,12 +122,6 @@ 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

@ -34,9 +34,9 @@ func (s *FakeService) GetFolderByTitle(ctx context.Context, user *user.SignedInU
func (s *FakeService) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
return s.ExpectedFolder, s.ExpectedError
}
func (s *FakeService) UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error {
func (s *FakeService) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
cmd.Result = s.ExpectedFolder.ToLegacyModel()
return s.ExpectedError
return s.ExpectedFolder.ToLegacyModel(), s.ExpectedError
}
func (s *FakeService) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
return s.ExpectedError

View File

@ -73,7 +73,6 @@ 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"`
}

View File

@ -13,7 +13,9 @@ type Service interface {
GetFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*models.Folder, error)
GetFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*models.Folder, error)
Create(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error)
UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error
// 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, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error)
DeleteFolder(ctx context.Context, cmd *DeleteFolderCommand) error
MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error
}
@ -27,10 +29,6 @@ type NestedFolderService interface {
// Create creates a new folder.
Create(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error)
// 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)
// Move changes a folder's parent folder to the requested new parent.
Move(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error)