mirror of
https://github.com/grafana/grafana.git
synced 2024-11-28 03:34:15 -06:00
Nested Folders: Set user in the API level (#59148)
This commit is contained in:
parent
4a628f18b0
commit
02b6b09121
@ -396,8 +396,9 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
|||||||
cmd.UserId = c.UserID
|
cmd.UserId = c.UserID
|
||||||
if cmd.FolderUid != "" {
|
if cmd.FolderUid != "" {
|
||||||
folder, err := hs.folderService.Get(ctx, &folder.GetFolderQuery{
|
folder, err := hs.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||||
OrgID: c.OrgID,
|
OrgID: c.OrgID,
|
||||||
UID: &cmd.FolderUid,
|
UID: &cmd.FolderUid,
|
||||||
|
SignedInUser: c.SignedInUser,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||||
|
@ -68,7 +68,7 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response {
|
|||||||
// 500: internalServerError
|
// 500: internalServerError
|
||||||
func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||||
uid := web.Params(c.Req)[":uid"]
|
uid := web.Params(c.Req)[":uid"]
|
||||||
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid})
|
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid, SignedInUser: c.SignedInUser})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.ToFolderErrorResponse(err)
|
return apierrors.ToFolderErrorResponse(err)
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||||
}
|
}
|
||||||
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{ID: &id, OrgID: c.OrgID})
|
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{ID: &id, OrgID: c.OrgID, SignedInUser: c.SignedInUser})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.ToFolderErrorResponse(err)
|
return apierrors.ToFolderErrorResponse(err)
|
||||||
}
|
}
|
||||||
@ -122,6 +122,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext) response.Response {
|
|||||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||||
}
|
}
|
||||||
cmd.OrgID = c.OrgID
|
cmd.OrgID = c.OrgID
|
||||||
|
cmd.SignedInUser = c.SignedInUser
|
||||||
|
|
||||||
folder, err := hs.folderService.Create(c.Req.Context(), &cmd)
|
folder, err := hs.folderService.Create(c.Req.Context(), &cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
// 500: internalServerError
|
// 500: internalServerError
|
||||||
func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response {
|
func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response {
|
||||||
uid := web.Params(c.Req)[":uid"]
|
uid := web.Params(c.Req)[":uid"]
|
||||||
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid})
|
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid, SignedInUser: c.SignedInUser})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.ToFolderErrorResponse(err)
|
return apierrors.ToFolderErrorResponse(err)
|
||||||
@ -90,7 +90,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
uid := web.Params(c.Req)[":uid"]
|
uid := web.Params(c.Req)[":uid"]
|
||||||
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid})
|
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: &uid, SignedInUser: c.SignedInUser})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apierrors.ToFolderErrorResponse(err)
|
return apierrors.ToFolderErrorResponse(err)
|
||||||
}
|
}
|
||||||
|
@ -86,15 +86,20 @@ func (s *ImportDashboardService) ImportDashboard(ctx context.Context, req *dashb
|
|||||||
// here we need to get FolderId from FolderUID if it present in the request, if both exist, FolderUID would overwrite FolderID
|
// here we need to get FolderId from FolderUID if it present in the request, if both exist, FolderUID would overwrite FolderID
|
||||||
if req.FolderUid != "" {
|
if req.FolderUid != "" {
|
||||||
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
|
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||||
OrgID: req.User.OrgID,
|
OrgID: req.User.OrgID,
|
||||||
UID: &req.FolderUid,
|
UID: &req.FolderUid,
|
||||||
|
SignedInUser: req.User,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.FolderId = folder.ID
|
req.FolderId = folder.ID
|
||||||
} else {
|
} else {
|
||||||
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{ID: &req.FolderId, OrgID: req.User.OrgID})
|
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||||
|
ID: &req.FolderId,
|
||||||
|
OrgID: req.User.OrgID,
|
||||||
|
SignedInUser: req.User,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -93,13 +93,12 @@ func (s *Service) DBMigration(db db.DB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
|
func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
|
||||||
user, err := appcontext.User(ctx)
|
if cmd.SignedInUser == nil {
|
||||||
if err != nil {
|
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagNestedFolders) {
|
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),
|
dashboards.ActionFoldersRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(*cmd.UID),
|
||||||
)); !ok {
|
)); !ok {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -112,11 +111,11 @@ func (s *Service) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cmd.UID != nil:
|
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:
|
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:
|
case cmd.Title != nil:
|
||||||
return s.getFolderByTitle(ctx, user, cmd.OrgID, *cmd.Title)
|
return s.getFolderByTitle(ctx, cmd.SignedInUser, cmd.OrgID, *cmd.Title)
|
||||||
default:
|
default:
|
||||||
return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present")
|
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)
|
dashFolder.SetUid(trimmedUID)
|
||||||
|
|
||||||
user, err := appcontext.User(ctx)
|
if cmd.SignedInUser == nil {
|
||||||
if err != nil {
|
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
user := cmd.SignedInUser
|
||||||
userID := user.UserID
|
userID := user.UserID
|
||||||
if userID == 0 {
|
if userID == 0 {
|
||||||
userID = -1
|
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) {
|
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{
|
foldr, err := s.Get(ctx, &folder.GetFolderQuery{
|
||||||
UID: &cmd.UID,
|
UID: &cmd.UID,
|
||||||
OrgID: cmd.OrgID,
|
OrgID: cmd.OrgID,
|
||||||
|
SignedInUser: cmd.SignedInUser,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
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{
|
_, err := s.Get(ctx, &folder.GetFolderQuery{
|
||||||
UID: &cmd.UID,
|
UID: &cmd.UID,
|
||||||
OrgID: cmd.OrgID,
|
OrgID: cmd.OrgID,
|
||||||
|
SignedInUser: cmd.SignedInUser,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/xorcare/pointer"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
"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)
|
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) {
|
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)
|
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) {
|
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.NoError(t, err)
|
||||||
require.Equal(t, foldr, &folder.Folder{ID: 0, Title: "General"})
|
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) {
|
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)
|
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)
|
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2)
|
||||||
ctx := appcontext.WithUser(context.Background(), usr)
|
ctx := appcontext.WithUser(context.Background(), usr)
|
||||||
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: f.Title,
|
Title: f.Title,
|
||||||
UID: folderUID,
|
UID: folderUID,
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||||
})
|
})
|
||||||
@ -141,6 +155,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
|||||||
UID: folderUID,
|
UID: folderUID,
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
ForceDeleteRules: false,
|
ForceDeleteRules: false,
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||||
@ -166,9 +181,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
|||||||
|
|
||||||
ctx := appcontext.WithUser(context.Background(), usr)
|
ctx := appcontext.WithUser(context.Background(), usr)
|
||||||
actualFolder, err := service.Create(ctx, &folder.CreateFolderCommand{
|
actualFolder, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: dash.Title,
|
Title: dash.Title,
|
||||||
UID: "someuid",
|
UID: "someuid",
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, f, actualFolder)
|
require.Equal(t, f, actualFolder)
|
||||||
@ -180,9 +196,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
|||||||
|
|
||||||
ctx := appcontext.WithUser(context.Background(), usr)
|
ctx := appcontext.WithUser(context.Background(), usr)
|
||||||
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
_, err := service.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: dash.Title,
|
Title: dash.Title,
|
||||||
UID: "general",
|
UID: "general",
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
||||||
})
|
})
|
||||||
@ -225,6 +242,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
|||||||
UID: f.UID,
|
UID: f.UID,
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
ForceDeleteRules: expectedForceDeleteRules,
|
ForceDeleteRules: expectedForceDeleteRules,
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, actualCmd)
|
require.NotNil(t, actualCmd)
|
||||||
@ -334,7 +352,7 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
|||||||
t.Run("create folder", func(t *testing.T) {
|
t.Run("create folder", func(t *testing.T) {
|
||||||
folderStore.ExpectedFolder = &folder.Folder{}
|
folderStore.ExpectedFolder = &folder.Folder{}
|
||||||
ctx := appcontext.WithUser(context.Background(), usr)
|
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.NoError(t, err)
|
||||||
require.NotNil(t, res.UID)
|
require.NotNil(t, res.UID)
|
||||||
})
|
})
|
||||||
@ -399,9 +417,10 @@ func TestNestedFolderService(t *testing.T) {
|
|||||||
|
|
||||||
ctx = appcontext.WithUser(ctx, usr)
|
ctx = appcontext.WithUser(ctx, usr)
|
||||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: "myFolder",
|
Title: "myFolder",
|
||||||
UID: "myFolder",
|
UID: "myFolder",
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// CreateFolder should not call the folder store create if the feature toggle is not enabled.
|
// 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
|
g := guardian.New
|
||||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
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.NoError(t, err)
|
||||||
require.NotNil(t, actualCmd)
|
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)
|
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||||
ctx = appcontext.WithUser(ctx, usr)
|
ctx = appcontext.WithUser(ctx, usr)
|
||||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: "myFolder",
|
Title: "myFolder",
|
||||||
UID: "myFolder",
|
UID: "myFolder",
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// CreateFolder should also call the folder store's create method.
|
// 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
|
// the service return success as long as the legacy create succeeds
|
||||||
ctx = appcontext.WithUser(ctx, usr)
|
ctx = appcontext.WithUser(ctx, usr)
|
||||||
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
_, err := foldersvc.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
Title: "myFolder",
|
Title: "myFolder",
|
||||||
UID: "myFolder",
|
UID: "myFolder",
|
||||||
|
SignedInUser: usr,
|
||||||
})
|
})
|
||||||
require.Error(t, err, "FAILED")
|
require.Error(t, err, "FAILED")
|
||||||
|
|
||||||
@ -505,7 +526,7 @@ func TestNestedFolderService(t *testing.T) {
|
|||||||
t.Run("move, no error", func(t *testing.T) {
|
t.Run("move, no error", func(t *testing.T) {
|
||||||
store.ExpectedError = nil
|
store.ExpectedError = nil
|
||||||
store.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
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.NoError(t, err)
|
||||||
require.NotNil(t, f)
|
require.NotNil(t, f)
|
||||||
})
|
})
|
||||||
@ -520,7 +541,7 @@ func TestNestedFolderService(t *testing.T) {
|
|||||||
g := guardian.New
|
g := guardian.New
|
||||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
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.NoError(t, err)
|
||||||
require.NotNil(t, actualCmd)
|
require.NotNil(t, actualCmd)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util/errutil"
|
"github.com/grafana/grafana/pkg/util/errutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,6 +67,8 @@ type CreateFolderCommand struct {
|
|||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
ParentUID string `json:"parent_uid"`
|
ParentUID string `json:"parent_uid"`
|
||||||
|
|
||||||
|
SignedInUser *user.SignedInUser `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFolderCommand captures the information required by the folder service
|
// UpdateFolderCommand captures the information required by the folder service
|
||||||
@ -75,6 +78,8 @@ type UpdateFolderCommand struct {
|
|||||||
NewUID *string `json:"uid" xorm:"uid"`
|
NewUID *string `json:"uid" xorm:"uid"`
|
||||||
NewTitle *string `json:"title"`
|
NewTitle *string `json:"title"`
|
||||||
NewDescription *string `json:"description"`
|
NewDescription *string `json:"description"`
|
||||||
|
|
||||||
|
SignedInUser *user.SignedInUser `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveFolderCommand captures the information required by the folder service
|
// MoveFolderCommand captures the information required by the folder service
|
||||||
@ -83,6 +88,8 @@ type MoveFolderCommand struct {
|
|||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
NewParentUID string `json:"new_parent_uid"`
|
NewParentUID string `json:"new_parent_uid"`
|
||||||
OrgID int64 `json:"-"`
|
OrgID int64 `json:"-"`
|
||||||
|
|
||||||
|
SignedInUser *user.SignedInUser `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteFolderCommand captures the information required by the folder service
|
// DeleteFolderCommand captures the information required by the folder service
|
||||||
@ -91,6 +98,8 @@ type DeleteFolderCommand struct {
|
|||||||
UID string `json:"uid" xorm:"uid"`
|
UID string `json:"uid" xorm:"uid"`
|
||||||
OrgID int64 `json:"orgId" xorm:"org_id"`
|
OrgID int64 `json:"orgId" xorm:"org_id"`
|
||||||
ForceDeleteRules bool `json:"forceDeleteRules"`
|
ForceDeleteRules bool `json:"forceDeleteRules"`
|
||||||
|
|
||||||
|
SignedInUser *user.SignedInUser `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFolderQuery is used for all folder Get requests. Only one of UID, ID, or
|
// GetFolderQuery is used for all folder Get requests. Only one of UID, ID, or
|
||||||
@ -102,6 +111,8 @@ type GetFolderQuery struct {
|
|||||||
ID *int64
|
ID *int64
|
||||||
Title *string
|
Title *string
|
||||||
OrgID int64
|
OrgID int64
|
||||||
|
|
||||||
|
SignedInUser *user.SignedInUser `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParentsQuery captures the information required by the folder service to
|
// GetParentsQuery captures the information required by the folder service to
|
||||||
|
@ -48,7 +48,7 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Res
|
|||||||
if *cmd.FolderUID == "" {
|
if *cmd.FolderUID == "" {
|
||||||
cmd.FolderID = 0
|
cmd.FolderID = 0
|
||||||
} else {
|
} else {
|
||||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID})
|
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID, SignedInUser: c.SignedInUser})
|
||||||
if err != nil || folder == nil {
|
if err != nil || folder == nil {
|
||||||
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
if element.FolderID != 0 {
|
if element.FolderID != 0 {
|
||||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID})
|
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID, SignedInUser: c.SignedInUser})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Resp
|
|||||||
if *cmd.FolderUID == "" {
|
if *cmd.FolderUID == "" {
|
||||||
cmd.FolderID = 0
|
cmd.FolderID = 0
|
||||||
} else {
|
} else {
|
||||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID})
|
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID, SignedInUser: c.SignedInUser})
|
||||||
if err != nil || folder == nil {
|
if err != nil || folder == nil {
|
||||||
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Resp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if element.FolderID != 0 {
|
if element.FolderID != 0 {
|
||||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID})
|
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID, SignedInUser: c.SignedInUser})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Conte
|
|||||||
if isGeneralFolder(folderID) && user.HasRole(org.RoleViewer) {
|
if isGeneralFolder(folderID) && user.HasRole(org.RoleViewer) {
|
||||||
return dashboards.ErrFolderAccessDenied
|
return dashboards.ErrFolderAccessDenied
|
||||||
}
|
}
|
||||||
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID})
|
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID, SignedInUser: user})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ func (l *LibraryElementService) requireViewPermissionsOnFolder(ctx context.Conte
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID})
|
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID, SignedInUser: user})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user user.S
|
|||||||
t.Logf("Creating folder with title and UID %q", title)
|
t.Logf("Creating folder with title and UID %q", title)
|
||||||
ctx := appcontext.WithUser(context.Background(), &user)
|
ctx := appcontext.WithUser(context.Background(), &user)
|
||||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: user.OrgID, Title: title, UID: title,
|
OrgID: user.OrgID, Title: title, UID: title, SignedInUser: &user,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -728,7 +728,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user *user.
|
|||||||
|
|
||||||
t.Logf("Creating folder with title and UID %q", title)
|
t.Logf("Creating folder with title and UID %q", title)
|
||||||
ctx := appcontext.WithUser(context.Background(), user)
|
ctx := appcontext.WithUser(context.Background(), user)
|
||||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{OrgID: user.OrgID, Title: title, UID: title})
|
folder, err := s.Create(ctx, &folder.CreateFolderCommand{OrgID: user.OrgID, Title: title, UID: title, SignedInUser: user})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
updateFolderACL(t, dashboardStore, folder.ID, items)
|
updateFolderACL(t, dashboardStore, folder.ID, items)
|
||||||
|
@ -368,7 +368,7 @@ func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, use
|
|||||||
|
|
||||||
// GetNamespaceByTitle is a handler for retrieving a namespace by its title. Alerting rules follow a Grafana folder-like structure which we call namespaces.
|
// GetNamespaceByTitle is a handler for retrieving a namespace by its title. Alerting rules follow a Grafana folder-like structure which we call namespaces.
|
||||||
func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, orgID int64, user *user.SignedInUser, withCanSave bool) (*folder.Folder, error) {
|
func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, orgID int64, user *user.SignedInUser, withCanSave bool) (*folder.Folder, error) {
|
||||||
folder, err := st.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, Title: &namespace})
|
folder, err := st.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, Title: &namespace, SignedInUser: user})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -389,7 +389,7 @@ func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, org
|
|||||||
|
|
||||||
// GetNamespaceByUID is a handler for retrieving a namespace by its UID. Alerting rules follow a Grafana folder-like structure which we call namespaces.
|
// GetNamespaceByUID is a handler for retrieving a namespace by its UID. Alerting rules follow a Grafana folder-like structure which we call namespaces.
|
||||||
func (st DBstore) GetNamespaceByUID(ctx context.Context, uid string, orgID int64, user *user.SignedInUser) (*folder.Folder, error) {
|
func (st DBstore) GetNamespaceByUID(ctx context.Context, uid string, orgID int64, user *user.SignedInUser) (*folder.Folder, error) {
|
||||||
folder, err := st.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, Title: &uid})
|
folder, err := st.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, Title: &uid, SignedInUser: user})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -130,10 +130,10 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx = appcontext.WithUser(ctx, user)
|
ctx = appcontext.WithUser(ctx, user)
|
||||||
_, err := dbstore.FolderService.Create(ctx, &folder.CreateFolderCommand{OrgID: orgID, Title: "FOLDER-" + util.GenerateShortUID(), UID: folderUID})
|
_, err := dbstore.FolderService.Create(ctx, &folder.CreateFolderCommand{OrgID: orgID, Title: "FOLDER-" + util.GenerateShortUID(), UID: folderUID, SignedInUser: user})
|
||||||
// var foldr *folder.Folder
|
// var foldr *folder.Folder
|
||||||
if errors.Is(err, dashboards.ErrFolderWithSameUIDExists) || errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
if errors.Is(err, dashboards.ErrFolderWithSameUIDExists) || errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
||||||
_, err = dbstore.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, UID: &folderUID})
|
_, err = dbstore.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, UID: &folderUID, SignedInUser: user})
|
||||||
}
|
}
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user