Nested Folders: Set user in the API level (#59148)
This commit is contained in:
@@ -93,13 +93,12 @@ func (s *Service) DBMigration(db db.DB) {
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
|
||||
user, err := appcontext.User(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if cmd.SignedInUser == nil {
|
||||
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
}
|
||||
|
||||
if s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagNestedFolders) {
|
||||
if ok, err := s.accessControl.Evaluate(ctx, user, accesscontrol.EvalPermission(
|
||||
if ok, err := s.accessControl.Evaluate(ctx, cmd.SignedInUser, accesscontrol.EvalPermission(
|
||||
dashboards.ActionFoldersRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(*cmd.UID),
|
||||
)); !ok {
|
||||
if err != nil {
|
||||
@@ -112,11 +111,11 @@ func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.
|
||||
|
||||
switch {
|
||||
case cmd.UID != nil:
|
||||
return s.getFolderByUID(ctx, user, cmd.OrgID, *cmd.UID)
|
||||
return s.getFolderByUID(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.UID)
|
||||
case cmd.ID != nil:
|
||||
return s.getFolderByID(ctx, user, *cmd.ID, cmd.OrgID)
|
||||
return s.getFolderByID(ctx, cmd.SignedInUser, *cmd.ID, cmd.OrgID)
|
||||
case cmd.Title != nil:
|
||||
return s.getFolderByTitle(ctx, user, cmd.OrgID, *cmd.Title)
|
||||
return s.getFolderByTitle(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.Title)
|
||||
default:
|
||||
return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present")
|
||||
}
|
||||
@@ -217,10 +216,10 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
|
||||
dashFolder.SetUid(trimmedUID)
|
||||
|
||||
user, err := appcontext.User(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if cmd.SignedInUser == nil {
|
||||
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
}
|
||||
user := cmd.SignedInUser
|
||||
userID := user.UserID
|
||||
if userID == 0 {
|
||||
userID = -1
|
||||
@@ -433,9 +432,14 @@ func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderComm
|
||||
}
|
||||
|
||||
func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*folder.Folder, error) {
|
||||
if cmd.SignedInUser == nil {
|
||||
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
}
|
||||
|
||||
foldr, err := s.Get(ctx, &folder.GetFolderQuery{
|
||||
UID: &cmd.UID,
|
||||
OrgID: cmd.OrgID,
|
||||
UID: &cmd.UID,
|
||||
OrgID: cmd.OrgID,
|
||||
SignedInUser: cmd.SignedInUser,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -448,9 +452,14 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
if cmd.SignedInUser == nil {
|
||||
return folder.ErrBadRequest.Errorf("missing signed in user")
|
||||
}
|
||||
|
||||
_, err := s.Get(ctx, &folder.GetFolderQuery{
|
||||
UID: &cmd.UID,
|
||||
OrgID: cmd.OrgID,
|
||||
UID: &cmd.UID,
|
||||
OrgID: cmd.OrgID,
|
||||
SignedInUser: cmd.SignedInUser,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/xorcare/pointer"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||
@@ -88,18 +89,30 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(f, nil)
|
||||
|
||||
t.Run("When get folder by id should return access denied error", func(t *testing.T) {
|
||||
_, err := service.getFolderByID(context.Background(), usr, folderId, orgID)
|
||||
_, err := service.Get(context.Background(), &folder.GetFolderQuery{
|
||||
ID: &folderId,
|
||||
OrgID: orgID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) {
|
||||
foldr, err := service.getFolderByID(context.Background(), usr, 0, orgID)
|
||||
foldr, err := service.Get(context.Background(), &folder.GetFolderQuery{
|
||||
ID: pointer.Int64(0),
|
||||
OrgID: orgID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, foldr, &folder.Folder{ID: 0, Title: "General"})
|
||||
})
|
||||
|
||||
t.Run("When get folder by uid should return access denied error", func(t *testing.T) {
|
||||
_, err := service.getFolderByUID(context.Background(), usr, orgID, folderUID)
|
||||
_, err := service.Get(context.Background(), &folder.GetFolderQuery{
|
||||
UID: &folderUID,
|
||||
OrgID: orgID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
@@ -107,9 +120,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2)
|
||||
ctx := appcontext.WithUser(context.Background(), usr)
|
||||
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: f.Title,
|
||||
UID: folderUID,
|
||||
OrgID: orgID,
|
||||
Title: f.Title,
|
||||
UID: folderUID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
@@ -141,6 +155,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
UID: folderUID,
|
||||
OrgID: orgID,
|
||||
ForceDeleteRules: false,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
@@ -166,9 +181,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
|
||||
ctx := appcontext.WithUser(context.Background(), usr)
|
||||
actualFolder, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: dash.Title,
|
||||
UID: "someuid",
|
||||
OrgID: orgID,
|
||||
Title: dash.Title,
|
||||
UID: "someuid",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f, actualFolder)
|
||||
@@ -180,9 +196,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
|
||||
ctx := appcontext.WithUser(context.Background(), usr)
|
||||
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: dash.Title,
|
||||
UID: "general",
|
||||
OrgID: orgID,
|
||||
Title: dash.Title,
|
||||
UID: "general",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
||||
})
|
||||
@@ -225,6 +242,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
UID: f.UID,
|
||||
OrgID: orgID,
|
||||
ForceDeleteRules: expectedForceDeleteRules,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
@@ -334,7 +352,7 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
t.Run("create folder", func(t *testing.T) {
|
||||
folderStore.ExpectedFolder = &folder.Folder{}
|
||||
ctx := appcontext.WithUser(context.Background(), usr)
|
||||
res, err := folderService.Create(ctx, &folder.CreateFolderCommand{})
|
||||
res, err := folderService.Create(ctx, &folder.CreateFolderCommand{SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res.UID)
|
||||
})
|
||||
@@ -399,9 +417,10 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
ctx = appcontext.WithUser(ctx, usr)
|
||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// CreateFolder should not call the folder store create if the feature toggle is not enabled.
|
||||
@@ -418,7 +437,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
err := foldersvc.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID})
|
||||
err := foldersvc.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
@@ -460,9 +479,10 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
ctx = appcontext.WithUser(ctx, usr)
|
||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
@@ -488,9 +508,10 @@ func TestNestedFolderService(t *testing.T) {
|
||||
// the service return success as long as the legacy create succeeds
|
||||
ctx = appcontext.WithUser(ctx, usr)
|
||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.Error(t, err, "FAILED")
|
||||
|
||||
@@ -505,7 +526,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
t.Run("move, no error", func(t *testing.T) {
|
||||
store.ExpectedError = nil
|
||||
store.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
f, err := foldersvc.Move(ctx, &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID})
|
||||
f, err := foldersvc.Move(ctx, &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, f)
|
||||
})
|
||||
@@ -520,7 +541,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
err := foldersvc.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID})
|
||||
err := foldersvc.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user