mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Nested Folders: Support getting of nested folder in folder service wh… (#58597)
* Nested Folders: Support getting of nested folder in folder service when feature flag is set * Fix lint * Fix some tests * Fix ngalert test * ngalert fix * Fix API tests * Fix some tests and lint * Fix lint 2 * Fix library elements and panels * Add access control to get folder * Cleanup and minor test change
This commit is contained in:
parent
88a829e103
commit
080ea88af7
@ -24,6 +24,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"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/org"
|
||||
pref "github.com/grafana/grafana/pkg/services/preference"
|
||||
@ -394,14 +395,17 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
cmd.OrgId = c.OrgID
|
||||
cmd.UserId = c.UserID
|
||||
if cmd.FolderUid != "" {
|
||||
folder, err := hs.folderService.GetFolderByUID(ctx, c.SignedInUser, c.OrgID, cmd.FolderUid)
|
||||
folder, err := hs.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||
OrgID: c.OrgID,
|
||||
UID: &cmd.FolderUid,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, dashboards.ErrFolderNotFound) {
|
||||
return response.Error(400, "Folder not found", err)
|
||||
}
|
||||
return response.Error(500, "Error while checking folder ID", err)
|
||||
}
|
||||
cmd.FolderId = folder.Id
|
||||
cmd.FolderId = folder.ID
|
||||
}
|
||||
|
||||
dash := cmd.GetDashboardModel()
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboardversion/dashvertest"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/libraryelements"
|
||||
"github.com/grafana/grafana/pkg/services/live"
|
||||
@ -642,8 +643,8 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
dashboardService.On("SaveDashboard", mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"), mock.AnythingOfType("bool")).
|
||||
Return(&models.Dashboard{Id: dashID, Uid: "uid", Title: "Dash", Slug: "dash", Version: 2}, nil)
|
||||
|
||||
mockFolder := &fakeFolderService{
|
||||
GetFolderByUIDResult: &models.Folder{Id: 1, Uid: "folderUID", Title: "Folder"},
|
||||
mockFolder := &foldertest.FakeService{
|
||||
ExpectedFolder: &folder.Folder{ID: 1, UID: "folderUID", Title: "Folder"},
|
||||
}
|
||||
|
||||
postDashboardScenario(t, "When calling POST on", "/api/dashboards", "/api/dashboards", cmd, dashboardService, mockFolder, func(sc *scenarioContext) {
|
||||
@ -673,8 +674,8 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
|
||||
dashboardService := dashboards.NewFakeDashboardService(t)
|
||||
|
||||
mockFolder := &fakeFolderService{
|
||||
GetFolderByUIDError: errors.New("Error while searching Folder ID"),
|
||||
mockFolder := &foldertest.FakeService{
|
||||
ExpectedError: errors.New("Error while searching Folder ID"),
|
||||
}
|
||||
|
||||
postDashboardScenario(t, "When calling POST on", "/api/dashboards", "/api/dashboards", cmd, dashboardService, mockFolder, func(sc *scenarioContext) {
|
||||
|
@ -67,13 +67,14 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response {
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
folder, err := hs.folderService.GetFolderByUID(c.Req.Context(), c.SignedInUser, c.OrgID, 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})
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c, g, folder))
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, folder))
|
||||
}
|
||||
|
||||
// swagger:route GET /folders/id/{folder_id} folders getFolderByID
|
||||
@ -93,13 +94,13 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||
}
|
||||
folder, err := hs.folderService.GetFolderByID(c.Req.Context(), c.SignedInUser, id, c.OrgID)
|
||||
folder, err := hs.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{ID: &id, OrgID: c.OrgID})
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c, g, folder))
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, folder))
|
||||
}
|
||||
|
||||
// swagger:route POST /folders folders createFolder
|
||||
@ -182,8 +183,8 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext) response.Response {
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
g := guardian.New(c.Req.Context(), result.Id, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c, g, result))
|
||||
g := guardian.New(c.Req.Context(), result.ID, c.OrgID, c.SignedInUser)
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, result))
|
||||
}
|
||||
|
||||
// swagger:route DELETE /folders/{folder_uid} folders deleteFolder
|
||||
@ -218,40 +219,6 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { //
|
||||
return response.JSON(http.StatusOK, "")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) toFolderDto(c *models.ReqContext, g guardian.DashboardGuardian, folder *models.Folder) dtos.Folder {
|
||||
canEdit, _ := g.CanEdit()
|
||||
canSave, _ := g.CanSave()
|
||||
canAdmin, _ := g.CanAdmin()
|
||||
canDelete, _ := g.CanDelete()
|
||||
|
||||
// Finding creator and last updater of the folder
|
||||
updater, creator := anonString, anonString
|
||||
if folder.CreatedBy > 0 {
|
||||
creator = hs.getUserLogin(c.Req.Context(), folder.CreatedBy)
|
||||
}
|
||||
if folder.UpdatedBy > 0 {
|
||||
updater = hs.getUserLogin(c.Req.Context(), folder.UpdatedBy)
|
||||
}
|
||||
|
||||
return dtos.Folder{
|
||||
Id: folder.Id,
|
||||
Uid: folder.Uid,
|
||||
Title: folder.Title,
|
||||
Url: folder.Url,
|
||||
HasACL: folder.HasACL,
|
||||
CanSave: canSave,
|
||||
CanEdit: canEdit,
|
||||
CanAdmin: canAdmin,
|
||||
CanDelete: canDelete,
|
||||
CreatedBy: creator,
|
||||
Created: folder.Created,
|
||||
UpdatedBy: updater,
|
||||
Updated: folder.Updated,
|
||||
Version: folder.Version,
|
||||
AccessControl: hs.getAccessControlMetadata(c, c.OrgID, dashboards.ScopeFoldersPrefix, folder.Uid),
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) newToFolderDto(c *models.ReqContext, g guardian.DashboardGuardian, folder *folder.Folder) dtos.Folder {
|
||||
canEdit, _ := g.CanEdit()
|
||||
canSave, _ := g.CanSave()
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@ -26,13 +27,14 @@ import (
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response {
|
||||
folder, err := hs.folderService.GetFolderByUID(c.Req.Context(), c.SignedInUser, c.OrgID, 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})
|
||||
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgID, c.SignedInUser)
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return apierrors.ToFolderErrorResponse(dashboards.ErrFolderAccessDenied)
|
||||
@ -49,7 +51,7 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
continue
|
||||
}
|
||||
|
||||
perm.FolderId = folder.Id
|
||||
perm.FolderId = folder.ID
|
||||
perm.DashboardId = 0
|
||||
|
||||
perm.UserAvatarUrl = dtos.GetGravatarUrl(perm.UserEmail)
|
||||
@ -87,12 +89,13 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
folder, err := hs.folderService.GetFolderByUID(c.Req.Context(), c.SignedInUser, c.OrgID, 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})
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgID, c.SignedInUser)
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
canAdmin, err := g.CanAdmin()
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
@ -106,7 +109,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
for _, item := range apiCmd.Items {
|
||||
items = append(items, &models.DashboardACL{
|
||||
OrgID: c.OrgID,
|
||||
DashboardID: folder.Id,
|
||||
DashboardID: folder.ID,
|
||||
UserID: item.UserID,
|
||||
TeamID: item.TeamID,
|
||||
Role: item.Role,
|
||||
@ -140,13 +143,13 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
if err != nil {
|
||||
return response.Error(500, "Error while checking dashboard permissions", err)
|
||||
}
|
||||
if err := hs.updateDashboardAccessControl(c.Req.Context(), c.OrgID, folder.Uid, true, items, old); err != nil {
|
||||
if err := hs.updateDashboardAccessControl(c.Req.Context(), c.OrgID, folder.UID, true, items, old); err != nil {
|
||||
return response.Error(500, "Failed to create permission", err)
|
||||
}
|
||||
return response.Success("Dashboard permissions updated")
|
||||
}
|
||||
|
||||
if err := hs.DashboardService.UpdateDashboardACL(c.Req.Context(), folder.Id, items); err != nil {
|
||||
if err := hs.DashboardService.UpdateDashboardACL(c.Req.Context(), folder.ID, items); err != nil {
|
||||
if errors.Is(err, models.ErrDashboardACLInfoMissing) {
|
||||
err = models.ErrFolderACLInfoMissing
|
||||
}
|
||||
@ -163,7 +166,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Folder permissions updated",
|
||||
"id": folder.Id,
|
||||
"id": folder.ID,
|
||||
"title": folder.Title,
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -294,47 +293,3 @@ func updateFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
fn(sc)
|
||||
})
|
||||
}
|
||||
|
||||
type fakeFolderService struct {
|
||||
folder.Service
|
||||
|
||||
GetFoldersResult []*models.Folder
|
||||
GetFoldersError error
|
||||
GetFolderByUIDResult *models.Folder
|
||||
GetFolderByUIDError error
|
||||
GetFolderByIDResult *models.Folder
|
||||
GetFolderByIDError error
|
||||
CreateFolderResult *models.Folder
|
||||
CreateFolderError error
|
||||
UpdateFolderResult *models.Folder
|
||||
UpdateFolderError error
|
||||
DeleteFolderResult *folder.Folder
|
||||
DeleteFolderError error
|
||||
DeletedFolderUids []string
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) GetFolders(ctx context.Context, user *user.SignedInUser, orgID int64, limit int64, page int64) ([]*models.Folder, error) {
|
||||
return s.GetFoldersResult, s.GetFoldersError
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) GetFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*models.Folder, error) {
|
||||
return s.GetFolderByIDResult, s.GetFolderByIDError
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) GetFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*models.Folder, error) {
|
||||
return s.GetFolderByUIDResult, s.GetFolderByUIDError
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) CreateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, title, uid string) (*models.Folder, error) {
|
||||
return s.CreateFolderResult, s.CreateFolderError
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error {
|
||||
cmd.Result = s.UpdateFolderResult
|
||||
return s.UpdateFolderError
|
||||
}
|
||||
|
||||
func (s *fakeFolderService) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
s.DeletedFolderUids = append(s.DeletedFolderUids, cmd.UID)
|
||||
return s.DeleteFolderError
|
||||
}
|
||||
|
@ -85,17 +85,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
|
||||
if req.FolderUid != "" {
|
||||
folder, err := s.folderService.GetFolderByUID(ctx, req.User, req.User.OrgID, req.FolderUid)
|
||||
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{
|
||||
OrgID: req.User.OrgID,
|
||||
UID: &req.FolderUid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.FolderId = folder.Id
|
||||
req.FolderId = folder.ID
|
||||
} else {
|
||||
folder, err := s.folderService.GetFolderByID(ctx, req.User, req.FolderId, req.User.OrgID)
|
||||
folder, err := s.folderService.Get(ctx, &folder.GetFolderQuery{ID: &req.FolderId, OrgID: req.User.OrgID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.FolderUid = folder.Uid
|
||||
req.FolderUid = folder.UID
|
||||
}
|
||||
|
||||
saveCmd := models.SaveDashboardCommand{
|
||||
|
@ -53,7 +53,7 @@ func NewFolderNameScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []string{ScopeFoldersProvider.GetResourceScopeUID(folder.Uid)}, nil
|
||||
return []string{ScopeFoldersProvider.GetResourceScopeUID(folder.UID)}, nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ func NewFolderIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []string{ScopeFoldersProvider.GetResourceScopeUID(folder.Uid)}, nil
|
||||
return []string{ScopeFoldersProvider.GetResourceScopeUID(folder.UID)}, nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ func resolveDashboardScope(ctx context.Context, db Store, orgID int64, dashboard
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
folderUID = folder.Uid
|
||||
folderUID = folder.UID
|
||||
}
|
||||
|
||||
return []string{
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@ -29,9 +30,7 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
orgId := rand.Int63()
|
||||
title := "Very complex :title with: and /" + util.GenerateShortUID()
|
||||
|
||||
db := models.NewFolder(title)
|
||||
db.Id = rand.Int63()
|
||||
db.Uid = util.GenerateShortUID()
|
||||
db := &folder.Folder{Title: title, ID: rand.Int63(), UID: util.GenerateShortUID()}
|
||||
dashboardStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
|
||||
scope := "folders:name:" + title
|
||||
@ -40,7 +39,7 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 1)
|
||||
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.Uid), resolvedScopes[0])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.UID), resolvedScopes[0])
|
||||
|
||||
dashboardStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title)
|
||||
})
|
||||
@ -88,17 +87,17 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
orgId := rand.Int63()
|
||||
uid := util.GenerateShortUID()
|
||||
|
||||
db := &models.Folder{Id: rand.Int63(), Uid: uid}
|
||||
db := &folder.Folder{ID: rand.Int63(), UID: uid}
|
||||
dashboardStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
|
||||
scope := "folders:id:" + strconv.FormatInt(db.Id, 10)
|
||||
scope := "folders:id:" + strconv.FormatInt(db.ID, 10)
|
||||
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 1)
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.Uid), resolvedScopes[0])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.UID), resolvedScopes[0])
|
||||
|
||||
dashboardStore.AssertCalled(t, "GetFolderByID", mock.Anything, orgId, db.Id)
|
||||
dashboardStore.AssertCalled(t, "GetFolderByID", mock.Anything, orgId, db.ID)
|
||||
})
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
@ -157,18 +156,18 @@ func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
_, resolver := NewDashboardIDScopeResolver(store)
|
||||
|
||||
orgID := rand.Int63()
|
||||
folder := &models.Folder{Id: 2, Uid: "2"}
|
||||
dashboard := &models.Dashboard{Id: 1, FolderId: folder.Id, Uid: "1"}
|
||||
folder := &folder.Folder{ID: 2, UID: "2"}
|
||||
dashboard := &models.Dashboard{Id: 1, FolderId: folder.ID, Uid: "1"}
|
||||
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.Id).Return(folder, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
|
||||
scope := ac.Scope("dashboards", "id", strconv.FormatInt(dashboard.Id, 10))
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgID, scope)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 2)
|
||||
require.Equal(t, fmt.Sprintf("dashboards:uid:%s", dashboard.Uid), resolvedScopes[0])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%s", folder.Uid), resolvedScopes[1])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%s", folder.UID), resolvedScopes[1])
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
@ -203,18 +202,18 @@ func TestNewDashboardUIDScopeResolver(t *testing.T) {
|
||||
_, resolver := NewDashboardUIDScopeResolver(store)
|
||||
|
||||
orgID := rand.Int63()
|
||||
folder := &models.Folder{Id: 2, Uid: "2"}
|
||||
dashboard := &models.Dashboard{Id: 1, FolderId: folder.Id, Uid: "1"}
|
||||
folder := &folder.Folder{ID: 2, UID: "2"}
|
||||
dashboard := &models.Dashboard{Id: 1, FolderId: folder.ID, Uid: "1"}
|
||||
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.Id).Return(folder, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
|
||||
scope := ac.Scope("dashboards", "uid", dashboard.Uid)
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgID, scope)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 2)
|
||||
require.Equal(t, fmt.Sprintf("dashboards:uid:%s", dashboard.Uid), resolvedScopes[0])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%s", folder.Uid), resolvedScopes[1])
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%s", folder.UID), resolvedScopes[1])
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
)
|
||||
|
||||
// DashboardService is a service for operating on dashboards.
|
||||
@ -89,9 +90,9 @@ type Store interface {
|
||||
//go:generate mockery --name FolderStore --structname FakeFolderStore --inpackage --filename folder_store_mock.go
|
||||
type FolderStore interface {
|
||||
// GetFolderByTitle retrieves a folder by its title
|
||||
GetFolderByTitle(ctx context.Context, orgID int64, title string) (*models.Folder, error)
|
||||
GetFolderByTitle(ctx context.Context, orgID int64, title string) (*folder.Folder, error)
|
||||
// GetFolderByUID retrieves a folder by its UID
|
||||
GetFolderByUID(ctx context.Context, orgID int64, uid string) (*models.Folder, error)
|
||||
GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error)
|
||||
// GetFolderByID retrieves a folder by its ID
|
||||
GetFolderByID(ctx context.Context, orgID int64, id int64) (*models.Folder, error)
|
||||
GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||
@ -74,7 +75,7 @@ func (d *DashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashbo
|
||||
return isParentFolderChanged, nil
|
||||
}
|
||||
|
||||
func (d *DashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*models.Folder, error) {
|
||||
func (d *DashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*folder.Folder, error) {
|
||||
if title == "" {
|
||||
return nil, dashboards.ErrFolderTitleEmpty
|
||||
}
|
||||
@ -94,10 +95,10 @@ func (d *DashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, titl
|
||||
dashboard.SetUid(dashboard.Uid)
|
||||
return nil
|
||||
})
|
||||
return models.DashboardToFolder(&dashboard), err
|
||||
return folder.FromDashboard(&dashboard), err
|
||||
}
|
||||
|
||||
func (d *DashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*models.Folder, error) {
|
||||
func (d *DashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) {
|
||||
dashboard := models.Dashboard{OrgId: orgID, FolderId: 0, Id: id}
|
||||
err := d.store.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
||||
has, err := sess.Table(&models.Dashboard{}).Where("is_folder = " + d.store.GetDialect().BooleanStr(true)).Where("folder_id=0").Get(&dashboard)
|
||||
@ -114,10 +115,10 @@ func (d *DashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int6
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return models.DashboardToFolder(&dashboard), nil
|
||||
return folder.FromDashboard(&dashboard), nil
|
||||
}
|
||||
|
||||
func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*models.Folder, error) {
|
||||
func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) {
|
||||
if uid == "" {
|
||||
return nil, dashboards.ErrDashboardIdentifierNotSet
|
||||
}
|
||||
@ -138,7 +139,7 @@ func (d *DashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return models.DashboardToFolder(&dashboard), nil
|
||||
return folder.FromDashboard(&dashboard), nil
|
||||
}
|
||||
|
||||
func (d *DashboardStore) GetProvisionedDataByDashboardID(ctx context.Context, dashboardID int64) (*models.DashboardProvisioning, error) {
|
||||
|
@ -481,7 +481,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("GetFolderByTitle should find the folder", func(t *testing.T) {
|
||||
result, err := dashboardStore.GetFolderByTitle(context.Background(), orgId, title)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, folder1.Id, result.Id)
|
||||
require.Equal(t, folder1.Id, result.ID)
|
||||
})
|
||||
})
|
||||
|
||||
@ -494,7 +494,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
t.Run("should return folder by UID", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByUID(context.Background(), orgId, folder.Uid)
|
||||
require.Equal(t, folder.Id, d.Id)
|
||||
require.Equal(t, folder.Id, d.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("should not find dashboard", func(t *testing.T) {
|
||||
@ -518,7 +518,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
|
||||
t.Run("should return folder by ID", func(t *testing.T) {
|
||||
d, err := dashboardStore.GetFolderByID(context.Background(), orgId, folder.Id)
|
||||
require.Equal(t, folder.Id, d.Id)
|
||||
require.Equal(t, folder.Id, d.ID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("should not find dashboard", func(t *testing.T) {
|
||||
|
@ -600,5 +600,5 @@ func (dr DashboardServiceImpl) CountDashboardsInFolder(ctx context.Context, quer
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return dr.dashboardStore.CountDashboardsInFolder(ctx, &dashboards.CountDashboardsInFolderRequest{FolderID: folder.Id, OrgID: u.OrgID})
|
||||
return dr.dashboardStore.CountDashboardsInFolder(ctx, &dashboards.CountDashboardsInFolderRequest{FolderID: folder.ID, OrgID: u.OrgID})
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"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"
|
||||
@ -226,7 +227,7 @@ func TestDashboardService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Count dashboards in folder", func(t *testing.T) {
|
||||
fakeStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&models.Folder{}, nil)
|
||||
fakeStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
fakeStore.On("CountDashboardsInFolder", mock.Anything, mock.AnythingOfType("*dashboards.CountDashboardsInFolderRequest")).Return(int64(3), nil)
|
||||
|
||||
// set up a ctx with signed in user
|
||||
|
@ -5,6 +5,7 @@ package dashboards
|
||||
import (
|
||||
context "context"
|
||||
|
||||
folder "github.com/grafana/grafana/pkg/services/folder"
|
||||
models "github.com/grafana/grafana/pkg/models"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
@ -194,15 +195,15 @@ func (_m *FakeDashboardStore) GetDashboardsByPluginID(ctx context.Context, query
|
||||
}
|
||||
|
||||
// GetFolderByID provides a mock function with given fields: ctx, orgID, id
|
||||
func (_m *FakeDashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*models.Folder, error) {
|
||||
func (_m *FakeDashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, id)
|
||||
|
||||
var r0 *models.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *models.Folder); ok {
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Folder)
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,15 +218,15 @@ func (_m *FakeDashboardStore) GetFolderByID(ctx context.Context, orgID int64, id
|
||||
}
|
||||
|
||||
// GetFolderByTitle provides a mock function with given fields: ctx, orgID, title
|
||||
func (_m *FakeDashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*models.Folder, error) {
|
||||
func (_m *FakeDashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, title)
|
||||
|
||||
var r0 *models.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.Folder); ok {
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, title)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Folder)
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,15 +241,15 @@ func (_m *FakeDashboardStore) GetFolderByTitle(ctx context.Context, orgID int64,
|
||||
}
|
||||
|
||||
// GetFolderByUID provides a mock function with given fields: ctx, orgID, uid
|
||||
func (_m *FakeDashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*models.Folder, error) {
|
||||
func (_m *FakeDashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, uid)
|
||||
|
||||
var r0 *models.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *models.Folder); ok {
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, uid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*models.Folder)
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ type Service struct {
|
||||
searchService *search.SearchService
|
||||
features *featuremgmt.FeatureManager
|
||||
permissions accesscontrol.FolderPermissionsService
|
||||
accessControl accesscontrol.AccessControl
|
||||
|
||||
// bus is currently used to publish events that cause scheduler to update rules.
|
||||
bus bus.Bus
|
||||
@ -62,10 +63,41 @@ func ProvideService(
|
||||
searchService: searchService,
|
||||
features: features,
|
||||
permissions: folderPermissionsService,
|
||||
accessControl: ac,
|
||||
bus: bus,
|
||||
}
|
||||
}
|
||||
|
||||
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 s.cfg.IsFeatureToggleEnabled(featuremgmt.FlagNestedFolders) {
|
||||
if ok, err := s.accessControl.Evaluate(ctx, user, accesscontrol.EvalPermission(
|
||||
dashboards.ActionFoldersRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(*cmd.UID),
|
||||
)); !ok {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
return s.store.Get(ctx, *cmd)
|
||||
}
|
||||
|
||||
switch {
|
||||
case cmd.UID != nil:
|
||||
return s.getFolderByUID(ctx, user, cmd.OrgID, *cmd.UID)
|
||||
case cmd.ID != nil:
|
||||
return s.getFolderByID(ctx, user, *cmd.ID, cmd.OrgID)
|
||||
case cmd.Title != nil:
|
||||
return s.getFolderByTitle(ctx, user, cmd.OrgID, *cmd.Title)
|
||||
default:
|
||||
return nil, folder.ErrBadRequest.Errorf("either on of UID, ID, Title fields must be present")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) GetFolders(ctx context.Context, user *user.SignedInUser, orgID int64, limit int64, page int64) ([]*models.Folder, error) {
|
||||
searchQuery := search.Query{
|
||||
SignedInUser: user,
|
||||
@ -95,9 +127,9 @@ func (s *Service) GetFolders(ctx context.Context, user *user.SignedInUser, orgID
|
||||
return folders, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*models.Folder, error) {
|
||||
func (s *Service) getFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*folder.Folder, error) {
|
||||
if id == 0 {
|
||||
return &models.Folder{Id: id, Title: "General"}, nil
|
||||
return &folder.Folder{ID: id, Title: "General"}, nil
|
||||
}
|
||||
|
||||
dashFolder, err := s.dashboardStore.GetFolderByID(ctx, orgID, id)
|
||||
@ -105,7 +137,7 @@ func (s *Service) GetFolderByID(ctx context.Context, user *user.SignedInUser, id
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
g := guardian.New(ctx, dashFolder.ID, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
@ -116,13 +148,13 @@ func (s *Service) GetFolderByID(ctx context.Context, user *user.SignedInUser, id
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*models.Folder, error) {
|
||||
func (s *Service) getFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*folder.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, orgID, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
g := guardian.New(ctx, dashFolder.ID, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
@ -133,13 +165,13 @@ func (s *Service) GetFolderByUID(ctx context.Context, user *user.SignedInUser, o
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*models.Folder, error) {
|
||||
func (s *Service) getFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*folder.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByTitle(ctx, orgID, title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
g := guardian.New(ctx, dashFolder.ID, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
@ -189,7 +221,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
|
||||
var createdFolder *models.Folder
|
||||
var createdFolder *folder.Folder
|
||||
createdFolder, err = s.dashboardStore.GetFolderByID(ctx, cmd.OrgID, dash.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -209,9 +241,9 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: models.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
|
||||
_, permissionErr = s.permissions.SetPermissions(ctx, cmd.OrgID, createdFolder.Uid, permissions...)
|
||||
_, permissionErr = s.permissions.SetPermissions(ctx, cmd.OrgID, createdFolder.UID, permissions...)
|
||||
} else if s.cfg.EditorsCanAdmin && user.IsRealUser() && !user.IsAnonymous {
|
||||
permissionErr = s.MakeUserAdmin(ctx, cmd.OrgID, userID, createdFolder.Id, true)
|
||||
permissionErr = s.MakeUserAdmin(ctx, cmd.OrgID, userID, createdFolder.ID, true)
|
||||
}
|
||||
|
||||
if permissionErr != nil {
|
||||
@ -242,7 +274,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
// We'll log the error and also roll back the previously-created
|
||||
// (legacy) folder.
|
||||
s.log.Error("error saving folder to nested folder store", err)
|
||||
err = s.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: createdFolder.Uid, OrgID: cmd.OrgID, ForceDeleteRules: true})
|
||||
err = s.DeleteFolder(ctx, &folder.DeleteFolderCommand{UID: createdFolder.UID, OrgID: cmd.OrgID, ForceDeleteRules: true})
|
||||
if err != nil {
|
||||
s.log.Error("error deleting folder after failed save to nested folder store", err)
|
||||
}
|
||||
@ -254,7 +286,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
return folder.FromDashboard(dash), nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
|
||||
func (s *Service) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*folder.Folder, error) {
|
||||
foldr, err := s.legacyUpdate(ctx, user, orgID, existingUid, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -276,7 +308,7 @@ func (s *Service) Update(ctx context.Context, user *user.SignedInUser, orgID int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = s.store.Update(ctx, folder.UpdateFolderCommand{
|
||||
foldr, err := s.store.Update(ctx, folder.UpdateFolderCommand{
|
||||
Folder: getFolder,
|
||||
NewUID: &cmd.Uid,
|
||||
NewTitle: &cmd.Title,
|
||||
@ -285,11 +317,12 @@ func (s *Service) Update(ctx context.Context, user *user.SignedInUser, orgID int
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return foldr, nil
|
||||
}
|
||||
return foldr, nil
|
||||
}
|
||||
|
||||
func (s *Service) legacyUpdate(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
|
||||
func (s *Service) legacyUpdate(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*folder.Folder, error) {
|
||||
query := models.GetDashboardQuery{OrgId: orgID, Uid: existingUid}
|
||||
_, err := s.dashboardStore.GetDashboard(ctx, &query)
|
||||
if err != nil {
|
||||
@ -322,7 +355,7 @@ func (s *Service) legacyUpdate(ctx context.Context, user *user.SignedInUser, org
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
|
||||
var foldr *models.Folder
|
||||
var foldr *folder.Folder
|
||||
foldr, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -359,7 +392,7 @@ func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderComm
|
||||
return err
|
||||
}
|
||||
|
||||
guard := guardian.New(ctx, dashFolder.Id, cmd.OrgID, user)
|
||||
guard := guardian.New(ctx, dashFolder.ID, cmd.OrgID, user)
|
||||
if canSave, err := guard.CanDelete(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return toFolderError(err)
|
||||
@ -367,7 +400,7 @@ func (s *Service) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderComm
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
deleteCmd := models.DeleteDashboardCommand{OrgId: cmd.OrgID, Id: dashFolder.Id, ForceDeleteFolderRules: cmd.ForceDeleteRules}
|
||||
deleteCmd := models.DeleteDashboardCommand{OrgId: cmd.OrgID, Id: dashFolder.ID, ForceDeleteFolderRules: cmd.ForceDeleteRules}
|
||||
|
||||
if err := s.dashboardStore.DeleteDashboard(ctx, &deleteCmd); err != nil {
|
||||
return toFolderError(err)
|
||||
@ -416,12 +449,6 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
|
||||
return 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
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashboardsvc "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
@ -79,26 +80,26 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
folderId := rand.Int63()
|
||||
folderUID := util.GenerateShortUID()
|
||||
|
||||
f := models.NewFolder("Folder")
|
||||
f.Id = folderId
|
||||
f.Uid = folderUID
|
||||
f := folder.NewFolder("Folder", "")
|
||||
f.ID = folderId
|
||||
f.UID = folderUID
|
||||
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, folderId).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) {
|
||||
_, err := service.GetFolderByID(context.Background(), usr, folderId, orgID)
|
||||
_, err := service.getFolderByID(context.Background(), usr, folderId, orgID)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) {
|
||||
folder, err := service.GetFolderByID(context.Background(), usr, 0, orgID)
|
||||
foldr, err := service.getFolderByID(context.Background(), usr, 0, orgID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, folder, &models.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) {
|
||||
_, err := service.GetFolderByUID(context.Background(), usr, orgID, folderUID)
|
||||
_, err := service.getFolderByUID(context.Background(), usr, orgID, folderUID)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
@ -157,7 +158,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
t.Run("When creating folder should not return access denied error", func(t *testing.T) {
|
||||
dash := models.NewDashboardFolder("Test-Folder")
|
||||
dash.Id = rand.Int63()
|
||||
f := models.DashboardToFolder(dash)
|
||||
f := folder.FromDashboard(dash)
|
||||
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dash, nil).Once()
|
||||
@ -170,7 +171,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
UID: "someuid",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f, actualFolder.ToLegacyModel())
|
||||
require.Equal(t, f, actualFolder)
|
||||
})
|
||||
|
||||
t.Run("When creating folder should return error if uid is general", func(t *testing.T) {
|
||||
@ -190,7 +191,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashboardFolder := models.NewDashboardFolder("Folder")
|
||||
dashboardFolder.Id = rand.Int63()
|
||||
dashboardFolder.Uid = util.GenerateShortUID()
|
||||
f := models.DashboardToFolder(dashboardFolder)
|
||||
f := folder.FromDashboard(dashboardFolder)
|
||||
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dashboardFolder, nil)
|
||||
@ -207,10 +208,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When deleting folder by uid should not return access denied error", func(t *testing.T) {
|
||||
f := models.NewFolder(util.GenerateShortUID())
|
||||
f.Id = rand.Int63()
|
||||
f.Uid = util.GenerateShortUID()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, f.Uid).Return(f, nil)
|
||||
f := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
f.ID = rand.Int63()
|
||||
f.UID = util.GenerateShortUID()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, f.UID).Return(f, nil)
|
||||
|
||||
var actualCmd *models.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
@ -221,13 +222,13 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = appcontext.WithUser(ctx, usr)
|
||||
err := service.DeleteFolder(ctx, &folder.DeleteFolderCommand{
|
||||
UID: f.Uid,
|
||||
UID: f.UID,
|
||||
OrgID: orgID,
|
||||
ForceDeleteRules: expectedForceDeleteRules,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
require.Equal(t, f.Id, actualCmd.Id)
|
||||
require.Equal(t, f.ID, actualCmd.Id)
|
||||
require.Equal(t, orgID, actualCmd.OrgId)
|
||||
require.Equal(t, expectedForceDeleteRules, actualCmd.ForceDeleteFolderRules)
|
||||
})
|
||||
@ -242,33 +243,33 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true})
|
||||
|
||||
t.Run("When get folder by id should return folder", func(t *testing.T) {
|
||||
expected := models.NewFolder(util.GenerateShortUID())
|
||||
expected.Id = rand.Int63()
|
||||
expected := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
expected.ID = rand.Int63()
|
||||
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, expected.Id).Return(expected, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, expected.ID).Return(expected, nil)
|
||||
|
||||
actual, err := service.GetFolderByID(context.Background(), usr, expected.Id, orgID)
|
||||
actual, err := service.getFolderByID(context.Background(), usr, expected.ID, orgID)
|
||||
require.Equal(t, expected, actual)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("When get folder by uid should return folder", func(t *testing.T) {
|
||||
expected := models.NewFolder(util.GenerateShortUID())
|
||||
expected.Uid = util.GenerateShortUID()
|
||||
expected := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
expected.UID = util.GenerateShortUID()
|
||||
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, expected.Uid).Return(expected, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, expected.UID).Return(expected, nil)
|
||||
|
||||
actual, err := service.GetFolderByUID(context.Background(), usr, orgID, expected.Uid)
|
||||
actual, err := service.getFolderByUID(context.Background(), usr, orgID, expected.UID)
|
||||
require.Equal(t, expected, actual)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("When get folder by title should return folder", func(t *testing.T) {
|
||||
expected := models.NewFolder("TEST-" + util.GenerateShortUID())
|
||||
expected := folder.NewFolder("TEST-"+util.GenerateShortUID(), "")
|
||||
|
||||
dashStore.On("GetFolderByTitle", mock.Anything, orgID, expected.Title).Return(expected, nil)
|
||||
|
||||
actual, err := service.GetFolderByTitle(context.Background(), usr, orgID, expected.Title)
|
||||
actual, err := service.getFolderByTitle(context.Background(), usr, orgID, expected.Title)
|
||||
require.Equal(t, expected, actual)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
@ -311,7 +312,7 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil)
|
||||
dashStore := dashboards.FakeDashboardStore{}
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
cfg := setting.NewCfg()
|
||||
cfg.RBACEnabled = false
|
||||
nestedFoldersEnabled := true
|
||||
@ -338,18 +339,6 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
require.NotNil(t, res.UID)
|
||||
})
|
||||
|
||||
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{})
|
||||
@ -378,12 +367,6 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNestedFolderService(t *testing.T) {
|
||||
@ -412,7 +395,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil)
|
||||
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{
|
||||
@ -430,7 +413,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*models.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&models.Folder{}, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
@ -463,6 +446,9 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashboardStore: dashStore,
|
||||
store: store,
|
||||
features: features,
|
||||
accessControl: actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("create, no error", func(t *testing.T) {
|
||||
@ -471,7 +457,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil)
|
||||
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,
|
||||
@ -493,8 +479,8 @@ func TestNestedFolderService(t *testing.T) {
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&models.Folder{}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
// return an error from the folder store
|
||||
store.ExpectedError = errors.New("FAILED")
|
||||
|
@ -14,29 +14,25 @@ type FakeService struct {
|
||||
ExpectedError error
|
||||
}
|
||||
|
||||
func NewFakeService() *FakeService {
|
||||
return &FakeService{}
|
||||
}
|
||||
|
||||
var _ folder.Service = (*FakeService)(nil)
|
||||
|
||||
func (s *FakeService) GetFolders(ctx context.Context, user *user.SignedInUser, orgID int64, limit int64, page int64) ([]*models.Folder, error) {
|
||||
return s.ExpectedFolders, s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) GetFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*models.Folder, error) {
|
||||
return s.ExpectedFolder.ToLegacyModel(), s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) GetFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*models.Folder, error) {
|
||||
if s.ExpectedFolder == nil {
|
||||
return nil, s.ExpectedError
|
||||
}
|
||||
return s.ExpectedFolder.ToLegacyModel(), s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) GetFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*models.Folder, error) {
|
||||
return s.ExpectedFolder.ToLegacyModel(), s.ExpectedError
|
||||
}
|
||||
|
||||
func (s *FakeService) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
|
||||
return s.ExpectedFolder, s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error) {
|
||||
func (s *FakeService) Get(ctx context.Context, cmd *folder.GetFolderQuery) (*folder.Folder, error) {
|
||||
return s.ExpectedFolder, s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*folder.Folder, error) {
|
||||
cmd.Result = s.ExpectedFolder.ToLegacyModel()
|
||||
return s.ExpectedFolder.ToLegacyModel(), s.ExpectedError
|
||||
return s.ExpectedFolder, s.ExpectedError
|
||||
}
|
||||
func (s *FakeService) DeleteFolder(ctx context.Context, cmd *folder.DeleteFolderCommand) error {
|
||||
return s.ExpectedError
|
||||
|
@ -9,13 +9,18 @@ import (
|
||||
|
||||
type Service interface {
|
||||
GetFolders(ctx context.Context, user *user.SignedInUser, orgID int64, limit int64, page int64) ([]*models.Folder, error)
|
||||
GetFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*models.Folder, error)
|
||||
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)
|
||||
|
||||
// GetFolder takes a GetFolderCommand and returns a folder matching the
|
||||
// request. One of ID, UID, or Title must be included. If multiple values
|
||||
// are included in the request, Grafana will select one in order of
|
||||
// specificity (ID, UID, Title).
|
||||
Get(ctx context.Context, cmd *GetFolderQuery) (*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, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*models.Folder, error)
|
||||
Update(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) (*Folder, error)
|
||||
DeleteFolder(ctx context.Context, cmd *DeleteFolderCommand) error
|
||||
MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error
|
||||
// Move changes a folder's parent folder to the requested new parent.
|
||||
@ -35,12 +40,6 @@ type NestedFolderService interface {
|
||||
// dashboards in the folder.
|
||||
Delete(ctx context.Context, cmd *DeleteFolderCommand) (*Folder, error)
|
||||
|
||||
// GetFolder takes a GetFolderCommand and returns a folder matching the
|
||||
// request. One of ID, UID, or Title must be included. If multiple values
|
||||
// are included in the request, Grafana will select one in order of
|
||||
// specificity (ID, UID, Title).
|
||||
Get(ctx context.Context, cmd *GetFolderQuery) (*Folder, error)
|
||||
|
||||
// GetParents returns an ordered list of parent folders for the given
|
||||
// folder, starting with the root node and ending with the requested child
|
||||
// node.
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
@ -47,11 +48,11 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Res
|
||||
if *cmd.FolderUID == "" {
|
||||
cmd.FolderID = 0
|
||||
} else {
|
||||
folder, err := l.folderService.GetFolderByUID(c.Req.Context(), c.SignedInUser, c.OrgID, *cmd.FolderUID)
|
||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID})
|
||||
if err != nil || folder == nil {
|
||||
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
||||
}
|
||||
cmd.FolderID = folder.Id
|
||||
cmd.FolderID = folder.ID
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,12 +62,12 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Res
|
||||
}
|
||||
|
||||
if element.FolderID != 0 {
|
||||
folder, err := l.folderService.GetFolderByID(c.Req.Context(), c.SignedInUser, element.FolderID, c.OrgID)
|
||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID})
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
||||
}
|
||||
element.FolderUID = folder.Uid
|
||||
element.Meta.FolderUID = folder.Uid
|
||||
element.FolderUID = folder.UID
|
||||
element.Meta.FolderUID = folder.UID
|
||||
element.Meta.FolderName = folder.Title
|
||||
}
|
||||
|
||||
@ -175,11 +176,11 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Resp
|
||||
if *cmd.FolderUID == "" {
|
||||
cmd.FolderID = 0
|
||||
} else {
|
||||
folder, err := l.folderService.GetFolderByUID(c.Req.Context(), c.SignedInUser, c.OrgID, *cmd.FolderUID)
|
||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, UID: cmd.FolderUID})
|
||||
if err != nil || folder == nil {
|
||||
return response.Error(http.StatusBadRequest, "failed to get folder", err)
|
||||
}
|
||||
cmd.FolderID = folder.Id
|
||||
cmd.FolderID = folder.ID
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,12 +190,12 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Resp
|
||||
}
|
||||
|
||||
if element.FolderID != 0 {
|
||||
folder, err := l.folderService.GetFolderByID(c.Req.Context(), c.SignedInUser, element.FolderID, c.OrgID)
|
||||
folder, err := l.folderService.Get(c.Req.Context(), &folder.GetFolderQuery{OrgID: c.OrgID, ID: &element.FolderID})
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "failed to get folder", err)
|
||||
}
|
||||
element.FolderUID = folder.Uid
|
||||
element.Meta.FolderUID = folder.Uid
|
||||
element.FolderUID = folder.UID
|
||||
element.Meta.FolderUID = folder.UID
|
||||
element.Meta.FolderName = folder.Title
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -39,12 +40,12 @@ func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Conte
|
||||
if isGeneralFolder(folderID) && user.HasRole(org.RoleViewer) {
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
folder, err := l.folderService.GetFolderByID(ctx, user, folderID, user.OrgID)
|
||||
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, folder.Id, user.OrgID, user)
|
||||
g := guardian.New(ctx, folder.ID, user.OrgID, user)
|
||||
|
||||
canEdit, err := g.CanEdit()
|
||||
if err != nil {
|
||||
@ -62,12 +63,12 @@ func (l *LibraryElementService) requireViewPermissionsOnFolder(ctx context.Conte
|
||||
return nil
|
||||
}
|
||||
|
||||
folder, err := l.folderService.GetFolderByID(ctx, user, folderID, user.OrgID)
|
||||
folder, err := l.folderService.Get(ctx, &folder.GetFolderQuery{ID: &folderID, OrgID: user.OrgID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, folder.Id, user.OrgID, user)
|
||||
g := guardian.New(ctx, folder.ID, user.OrgID, user)
|
||||
|
||||
canView, err := g.CanView()
|
||||
if err != nil {
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
func TestCreateLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to create a library panel that already exists, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
@ -65,7 +65,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
|
||||
testScenario(t, "When an admin tries to create a library panel that does not exists using an nonexistent UID, it should succeed",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Nonexistent UID")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Nonexistent UID")
|
||||
command.UID = util.GenerateShortUID()
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
@ -114,7 +114,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to create a library panel that does not exists using an existent UID, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Existing UID")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Existing UID")
|
||||
command.UID = sc.initialResult.Result.UID
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
@ -123,7 +123,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to create a library panel that does not exists using an invalid UID, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Invalid UID")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Invalid UID")
|
||||
command.UID = "Testing an invalid UID"
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
@ -132,7 +132,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to create a library panel that does not exists using an UID that is too long, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Invalid UID")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Invalid UID")
|
||||
command.UID = "j6T00KRZzj6T00KRZzj6T00KRZzj6T00KRZzj6T00K"
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
|
@ -73,7 +73,7 @@ func TestDeleteLibraryElement(t *testing.T) {
|
||||
Title: "Testing deleteHandler ",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
|
||||
err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -37,7 +37,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all panel elements and both panels and variables exist, it should only return panels",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
command := getCreateVariableCommand(sc.folder.ID, "query0")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -77,7 +77,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -103,7 +103,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all variable elements and both panels and variables exist, it should only return panels",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
command := getCreateVariableCommand(sc.folder.ID, "query0")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -142,7 +142,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -168,7 +168,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist, it should succeed",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -204,7 +204,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -239,7 +239,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[1].Meta.Created,
|
||||
Updated: result.Result.Elements[1].Meta.Updated,
|
||||
@ -265,7 +265,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and sort desc is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -304,7 +304,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -339,7 +339,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[1].Meta.Created,
|
||||
Updated: result.Result.Elements[1].Meta.Updated,
|
||||
@ -365,7 +365,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and typeFilter is set to existing types, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.ID, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@ -378,7 +378,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
command = getCreateCommandWithModel(sc.folder.Id, "BarGauge - Library Panel", models.PanelElement, []byte(`
|
||||
command = getCreateCommandWithModel(sc.folder.ID, "BarGauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@ -425,7 +425,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -460,7 +460,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[1].Meta.Created,
|
||||
Updated: result.Result.Elements[1].Meta.Updated,
|
||||
@ -486,7 +486,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and typeFilter is set to a nonexistent type, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.ID, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@ -621,7 +621,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to General folder, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -661,7 +661,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -696,7 +696,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[1].Meta.Created,
|
||||
Updated: result.Result.Elements[1].Meta.Updated,
|
||||
@ -722,7 +722,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and excludeUID is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -761,7 +761,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -787,7 +787,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -826,7 +826,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -852,7 +852,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 2, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -892,7 +892,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -918,7 +918,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in the description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Text - Library Panel2", models.PanelElement, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.ID, "Text - Library Panel2", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@ -967,7 +967,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -993,7 +993,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in both name and description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Some Other", models.PanelElement, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.ID, "Some Other", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@ -1040,7 +1040,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -1075,7 +1075,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[1].Meta.Created,
|
||||
Updated: result.Result.Elements[1].Meta.Updated,
|
||||
@ -1101,7 +1101,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 1 and searchString is panel2, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -1142,7 +1142,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.Elements[0].Meta.Created,
|
||||
Updated: result.Result.Elements[0].Meta.Updated,
|
||||
@ -1168,7 +1168,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString is panel, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -1199,7 +1199,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString does not exist, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel2")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
@ -49,7 +49,7 @@ func TestGetLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 0,
|
||||
Created: res.Result.Meta.Created,
|
||||
Updated: res.Result.Meta.Updated,
|
||||
@ -119,7 +119,7 @@ func TestGetLibraryElement(t *testing.T) {
|
||||
Title: "Testing getHandler",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
|
||||
err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -144,7 +144,7 @@ func TestGetLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
Meta: LibraryElementDTOMeta{
|
||||
FolderName: "ScenarioFolder",
|
||||
FolderUID: sc.folder.Uid,
|
||||
FolderUID: sc.folder.UID,
|
||||
ConnectedDashboards: 1,
|
||||
Created: res.Result.Meta.Created,
|
||||
Updated: res.Result.Meta.Updated,
|
||||
|
@ -187,7 +187,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with an existing UID, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Existing UID")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Existing UID")
|
||||
command.UID = util.GenerateShortUID()
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
@ -307,7 +307,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with a name that already exists, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Another Panel")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Another Panel")
|
||||
sc.ctx.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
@ -343,7 +343,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel in another org, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := PatchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
FolderID: sc.folder.ID,
|
||||
Version: 1,
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
@ -357,7 +357,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with an old version number, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := PatchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
FolderID: sc.folder.ID,
|
||||
Version: 1,
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
@ -373,7 +373,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with an other kind, it should succeed but panel should not change",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := PatchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
FolderID: sc.folder.ID,
|
||||
Version: 1,
|
||||
Kind: int64(models.VariableElement),
|
||||
}
|
||||
|
@ -73,23 +73,23 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) {
|
||||
Title: "Testing DeleteLibraryElementsInFolder",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
|
||||
err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid)
|
||||
err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.UID)
|
||||
require.EqualError(t, err, ErrFolderHasConnectedLibraryElements.Error())
|
||||
})
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to delete a folder uid that doesn't exist, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
err := sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid+"xxxx")
|
||||
err := sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.UID+"xxxx")
|
||||
require.EqualError(t, err, dashboards.ErrFolderNotFound.Error())
|
||||
})
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to delete a folder that contains disconnected elements, it should delete all disconnected elements too",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
command := getCreateVariableCommand(sc.folder.ID, "query0")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -102,7 +102,7 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) {
|
||||
require.NotNil(t, result.Result)
|
||||
require.Equal(t, 2, len(result.Result.Elements))
|
||||
|
||||
err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid)
|
||||
err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.UID)
|
||||
require.NoError(t, err)
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@ -146,7 +146,7 @@ func TestGetLibraryPanelConnections(t *testing.T) {
|
||||
Title: "Testing GetLibraryPanelConnections",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id)
|
||||
dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.ID)
|
||||
err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -256,7 +256,7 @@ type scenarioContext struct {
|
||||
service *LibraryElementService
|
||||
reqContext *models.ReqContext
|
||||
user user.SignedInUser
|
||||
folder *models.Folder
|
||||
folder *folder.Folder
|
||||
initialResult libraryElementResult
|
||||
sqlStore db.DB
|
||||
}
|
||||
@ -387,7 +387,7 @@ func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scena
|
||||
guardian.InitLegacyGuardian(store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
|
||||
|
||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel")
|
||||
command := getCreatePanelCommand(sc.folder.ID, "Text - Library Panel")
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
sc.initialResult = validateAndUnMarshalResponse(t, resp)
|
||||
@ -402,13 +402,26 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
t.Helper()
|
||||
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
ctx := web.Context{Req: &http.Request{
|
||||
orgID := int64(1)
|
||||
role := org.RoleAdmin
|
||||
usr := user.SignedInUser{
|
||||
UserID: 1,
|
||||
Name: "Signed In User",
|
||||
Login: "signed_in_user",
|
||||
Email: "signed.in.user@test.com",
|
||||
OrgID: orgID,
|
||||
OrgRole: role,
|
||||
LastSeenAt: time.Now(),
|
||||
}
|
||||
req := &http.Request{
|
||||
Header: http.Header{
|
||||
"Content-Type": []string{"application/json"},
|
||||
},
|
||||
}}
|
||||
orgID := int64(1)
|
||||
role := org.RoleAdmin
|
||||
}
|
||||
ctx := appcontext.WithUser(context.Background(), &usr)
|
||||
req = req.WithContext(ctx)
|
||||
webCtx := web.Context{Req: req}
|
||||
|
||||
sqlStore := db.InitTestDB(t)
|
||||
dashboardStore := database.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg))
|
||||
features := featuremgmt.WithFeatures()
|
||||
@ -428,16 +441,6 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil),
|
||||
}
|
||||
|
||||
usr := user.SignedInUser{
|
||||
UserID: 1,
|
||||
Name: "Signed In User",
|
||||
Login: "signed_in_user",
|
||||
Email: "signed.in.user@test.com",
|
||||
OrgID: orgID,
|
||||
OrgRole: role,
|
||||
LastSeenAt: time.Now(),
|
||||
}
|
||||
|
||||
// deliberate difference between signed in user and user in db to make it crystal clear
|
||||
// what to expect in the tests
|
||||
// In the real world these are identical
|
||||
@ -452,16 +455,16 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
|
||||
sc := scenarioContext{
|
||||
user: usr,
|
||||
ctx: &ctx,
|
||||
ctx: &webCtx,
|
||||
service: &service,
|
||||
sqlStore: sqlStore,
|
||||
reqContext: &models.ReqContext{
|
||||
Context: &ctx,
|
||||
Context: &webCtx,
|
||||
SignedInUser: &usr,
|
||||
},
|
||||
}
|
||||
|
||||
sc.folder = createFolderWithACL(t, sc.sqlStore, "ScenarioFolder", sc.user, []folderACLItem{}).ToLegacyModel()
|
||||
sc.folder = createFolderWithACL(t, sc.sqlStore, "ScenarioFolder", sc.user, []folderACLItem{})
|
||||
|
||||
fn(t, sc)
|
||||
})
|
||||
|
@ -850,12 +850,14 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
Login: userInDbName,
|
||||
}
|
||||
|
||||
_, err := sqlStore.CreateUser(context.Background(), cmd)
|
||||
ctx := appcontext.WithUser(context.Background(), usr)
|
||||
|
||||
_, err := sqlStore.CreateUser(ctx, cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
sc := scenarioContext{
|
||||
user: usr,
|
||||
ctx: context.Background(),
|
||||
ctx: ctx,
|
||||
service: &service,
|
||||
elementService: elementService,
|
||||
sqlStore: sqlStore,
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
@ -181,7 +182,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
|
||||
return response.JSON(http.StatusOK, ruleResponse)
|
||||
}
|
||||
|
||||
func (srv PrometheusSrv) toRuleGroup(groupName string, folder *models.Folder, rules []*ngmodels.AlertRule, labelOptions []ngmodels.LabelOption) *apimodels.RuleGroup {
|
||||
func (srv PrometheusSrv) toRuleGroup(groupName string, folder *folder.Folder, rules []*ngmodels.AlertRule, labelOptions []ngmodels.LabelOption) *apimodels.RuleGroup {
|
||||
newGroup := &apimodels.RuleGroup{
|
||||
Name: groupName,
|
||||
File: folder.Title, // file is what Prometheus uses for provisioning, we replace it with namespace.
|
||||
|
@ -83,7 +83,7 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *models.ReqContext, namespaceTitle s
|
||||
unauthz, provisioned := false, false
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
RuleGroup: ruleGroup,
|
||||
}
|
||||
if err = srv.store.ListAlertRules(ctx, &q); err != nil {
|
||||
@ -163,7 +163,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext, namespace
|
||||
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
}
|
||||
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
|
||||
@ -189,7 +189,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext, namespace
|
||||
if !authorizeAccessToRuleGroup(rules, hasAccess) {
|
||||
continue
|
||||
}
|
||||
result[namespaceTitle] = append(result[namespaceTitle], toGettableRuleGroupConfig(groupName, rules, namespace.Id, provenanceRecords))
|
||||
result[namespaceTitle] = append(result[namespaceTitle], toGettableRuleGroupConfig(groupName, rules, namespace.ID, provenanceRecords))
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
@ -205,7 +205,7 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext, namespaceTitl
|
||||
|
||||
q := ngmodels.ListAlertRulesQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUIDs: []string{namespace.Uid},
|
||||
NamespaceUIDs: []string{namespace.UID},
|
||||
RuleGroup: ruleGroup,
|
||||
}
|
||||
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
|
||||
@ -226,7 +226,7 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *models.ReqContext, namespaceTitl
|
||||
}
|
||||
|
||||
result := apimodels.RuleGroupConfigResponse{
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, q.Result, namespace.Id, provenanceRecords),
|
||||
GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, q.Result, namespace.ID, provenanceRecords),
|
||||
}
|
||||
return response.JSON(http.StatusAccepted, result)
|
||||
}
|
||||
@ -296,7 +296,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
|
||||
continue
|
||||
}
|
||||
namespace := folder.Title
|
||||
result[namespace] = append(result[namespace], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, folder.Id, provenanceRecords))
|
||||
result[namespace] = append(result[namespace], toGettableRuleGroupConfig(groupKey.RuleGroup, rules, folder.ID, provenanceRecords))
|
||||
}
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
@ -316,7 +316,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConf
|
||||
|
||||
groupKey := ngmodels.AlertRuleGroupKey{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
NamespaceUID: namespace.Uid,
|
||||
NamespaceUID: namespace.UID,
|
||||
RuleGroup: ruleGroupConfig.Name,
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
acMock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
|
||||
@ -382,7 +383,7 @@ func TestRouteGetNamespaceRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@ -426,12 +427,12 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
folder1 := randFolder()
|
||||
folder2 := randFolder()
|
||||
ruleStore.Folders[orgID] = []*models2.Folder{folder1, folder2}
|
||||
ruleStore.Folders[orgID] = []*folder.Folder{folder1, folder2}
|
||||
|
||||
group1Key := models.GenerateGroupKey(orgID)
|
||||
group1Key.NamespaceUID = folder1.Uid
|
||||
group1Key.NamespaceUID = folder1.UID
|
||||
group2Key := models.GenerateGroupKey(orgID)
|
||||
group2Key.NamespaceUID = folder2.Uid
|
||||
group2Key.NamespaceUID = folder2.UID
|
||||
|
||||
group1 := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(group1Key)))
|
||||
group2 := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(group2Key)))
|
||||
@ -464,7 +465,7 @@ func TestRouteGetRulesConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@ -509,7 +510,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(4)+2, models.AlertRuleGen(withGroupKey(groupKey)))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@ -544,7 +545,7 @@ func TestRouteGetRulesGroupConfig(t *testing.T) {
|
||||
ruleStore := fakes.NewRuleStore(t)
|
||||
ruleStore.Folders[orgID] = append(ruleStore.Folders[orgID], folder)
|
||||
groupKey := models.GenerateGroupKey(orgID)
|
||||
groupKey.NamespaceUID = folder.Uid
|
||||
groupKey.NamespaceUID = folder.UID
|
||||
|
||||
expectedRules := models.GenerateAlertRules(rand.Intn(5)+5, models.AlertRuleGen(withGroupKey(groupKey), models.WithUniqueGroupIndex()))
|
||||
ruleStore.PutRule(context.Background(), expectedRules...)
|
||||
@ -699,9 +700,9 @@ func withGroup(groupName string) func(rule *models.AlertRule) {
|
||||
}
|
||||
}
|
||||
|
||||
func withNamespace(namespace *models2.Folder) func(rule *models.AlertRule) {
|
||||
func withNamespace(namespace *folder.Folder) func(rule *models.AlertRule) {
|
||||
return func(rule *models.AlertRule) {
|
||||
rule.NamespaceUID = namespace.Uid
|
||||
rule.NamespaceUID = namespace.UID
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@ -18,7 +18,7 @@ func validateRuleNode(
|
||||
groupName string,
|
||||
interval time.Duration,
|
||||
orgId int64,
|
||||
namespace *models.Folder,
|
||||
namespace *folder.Folder,
|
||||
conditionValidator func(ngmodels.Condition) error,
|
||||
cfg *setting.UnifiedAlertingSettings) (*ngmodels.AlertRule, error) {
|
||||
intervalSeconds, err := validateInterval(cfg, interval)
|
||||
@ -93,7 +93,7 @@ func validateRuleNode(
|
||||
Data: ruleNode.GrafanaManagedAlert.Data,
|
||||
UID: ruleNode.GrafanaManagedAlert.UID,
|
||||
IntervalSeconds: intervalSeconds,
|
||||
NamespaceUID: namespace.Uid,
|
||||
NamespaceUID: namespace.UID,
|
||||
RuleGroup: groupName,
|
||||
NoDataState: noDataState,
|
||||
ExecErrState: errorState,
|
||||
@ -152,7 +152,7 @@ func validateForInterval(ruleNode *apimodels.PostableExtendedRuleNode) (time.Dur
|
||||
func validateRuleGroup(
|
||||
ruleGroupConfig *apimodels.PostableRuleGroupConfig,
|
||||
orgId int64,
|
||||
namespace *models.Folder,
|
||||
namespace *folder.Folder,
|
||||
conditionValidator func(ngmodels.Condition) error,
|
||||
cfg *setting.UnifiedAlertingSettings) ([]*ngmodels.AlertRule, error) {
|
||||
if ruleGroupConfig.Name == "" {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/exp/rand"
|
||||
|
||||
models2 "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@ -83,18 +83,18 @@ func validGroup(cfg *setting.UnifiedAlertingSettings, rules ...apimodels.Postabl
|
||||
}
|
||||
}
|
||||
|
||||
func randFolder() *models2.Folder {
|
||||
return &models2.Folder{
|
||||
Id: rand.Int63(),
|
||||
Uid: util.GenerateShortUID(),
|
||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||
Url: "",
|
||||
Version: 0,
|
||||
Created: time.Time{},
|
||||
Updated: time.Time{},
|
||||
UpdatedBy: 0,
|
||||
CreatedBy: 0,
|
||||
HasACL: false,
|
||||
func randFolder() *folder.Folder {
|
||||
return &folder.Folder{
|
||||
ID: rand.Int63(),
|
||||
UID: util.GenerateShortUID(),
|
||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||
// URL: "",
|
||||
// Version: 0,
|
||||
Created: time.Time{},
|
||||
Updated: time.Time{},
|
||||
// UpdatedBy: 0,
|
||||
// CreatedBy: 0,
|
||||
// HasACL: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
||||
require.Equal(t, int64(interval.Seconds()), alert.IntervalSeconds)
|
||||
require.Equal(t, int64(0), alert.Version)
|
||||
require.Equal(t, api.GrafanaManagedAlert.UID, alert.UID)
|
||||
require.Equal(t, folder.Uid, alert.NamespaceUID)
|
||||
require.Equal(t, folder.UID, alert.NamespaceUID)
|
||||
require.Nil(t, alert.DashboardUID)
|
||||
require.Nil(t, alert.PanelID)
|
||||
require.Equal(t, name, alert.RuleGroup)
|
||||
|
@ -3,15 +3,15 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
// RuleStore is the interface for persisting alert rules and instances
|
||||
type RuleStore interface {
|
||||
GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*models.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*models.Folder, error)
|
||||
GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*folder.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*folder.Folder, error)
|
||||
GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) error
|
||||
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
models2 "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@ -140,9 +140,9 @@ func WithOrgID(orgId int64) AlertRuleMutator {
|
||||
}
|
||||
}
|
||||
|
||||
func WithNamespace(namespace *models2.Folder) AlertRuleMutator {
|
||||
func WithNamespace(namespace *folder.Folder) AlertRuleMutator {
|
||||
return func(rule *AlertRule) {
|
||||
rule.NamespaceUID = namespace.Uid
|
||||
rule.NamespaceUID = namespace.UID
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
models2 "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/schedule"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||
@ -22,9 +22,9 @@ import (
|
||||
|
||||
func Test_subscribeToFolderChanges(t *testing.T) {
|
||||
orgID := rand.Int63()
|
||||
folder := &models2.Folder{
|
||||
Id: 0,
|
||||
Uid: util.GenerateShortUID(),
|
||||
folder := &folder.Folder{
|
||||
ID: 0,
|
||||
UID: util.GenerateShortUID(),
|
||||
Title: "Folder" + util.GenerateShortUID(),
|
||||
}
|
||||
rules := models.GenerateAlertRules(5, models.AlertRuleGen(models.WithOrgID(orgID), models.WithNamespace(folder)))
|
||||
@ -42,8 +42,8 @@ func Test_subscribeToFolderChanges(t *testing.T) {
|
||||
err := bus.Publish(context.Background(), &events.FolderTitleUpdated{
|
||||
Timestamp: time.Now(),
|
||||
Title: "Folder" + util.GenerateShortUID(),
|
||||
ID: folder.Id,
|
||||
UID: folder.Uid,
|
||||
ID: folder.ID,
|
||||
UID: folder.UID,
|
||||
OrgID: orgID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||
@ -298,8 +299,8 @@ func (st DBstore) GetRuleGroupInterval(ctx context.Context, orgID int64, namespa
|
||||
}
|
||||
|
||||
// GetUserVisibleNamespaces returns the folders that are visible to the user and have at least one alert in it
|
||||
func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, user *user.SignedInUser) (map[string]*models.Folder, error) {
|
||||
namespaceMap := make(map[string]*models.Folder)
|
||||
func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, user *user.SignedInUser) (map[string]*folder.Folder, error) {
|
||||
namespaceMap := make(map[string]*folder.Folder)
|
||||
|
||||
searchQuery := models.FindPersistedDashboardsQuery{
|
||||
OrgId: orgID,
|
||||
@ -330,9 +331,9 @@ func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, use
|
||||
if !hit.IsFolder {
|
||||
continue
|
||||
}
|
||||
namespaceMap[hit.UID] = &models.Folder{
|
||||
Id: hit.ID,
|
||||
Uid: hit.UID,
|
||||
namespaceMap[hit.UID] = &folder.Folder{
|
||||
ID: hit.ID,
|
||||
UID: hit.UID,
|
||||
Title: hit.Title,
|
||||
}
|
||||
}
|
||||
@ -342,15 +343,15 @@ 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.
|
||||
func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, orgID int64, user *user.SignedInUser, withCanSave bool) (*models.Folder, error) {
|
||||
folder, err := st.FolderService.GetFolderByTitle(ctx, user, orgID, namespace)
|
||||
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})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if access control is disabled, check that the user is allowed to save in the folder.
|
||||
if withCanSave && st.AccessControl.IsDisabled() {
|
||||
g := guardian.New(ctx, folder.Id, orgID, user)
|
||||
g := guardian.New(ctx, folder.ID, orgID, user)
|
||||
if canSave, err := g.CanSave(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
st.Logger.Error("checking can save permission has failed", "userId", user.UserID, "username", user.Login, "namespace", namespace, "orgId", orgID, "error", err)
|
||||
@ -363,8 +364,8 @@ 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.
|
||||
func (st DBstore) GetNamespaceByUID(ctx context.Context, uid string, orgID int64, user *user.SignedInUser) (*models.Folder, error) {
|
||||
folder, err := st.FolderService.GetFolderByUID(ctx, user, orgID, uid)
|
||||
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})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func TestIntegrationUpdateAlertRules(t *testing.T) {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
sqlStore := db.InitTestDB(t)
|
||||
store := DBstore{
|
||||
store := &DBstore{
|
||||
SQLStore: sqlStore,
|
||||
Cfg: setting.UnifiedAlertingSettings{
|
||||
BaseInterval: time.Duration(rand.Int63n(100)) * time.Second,
|
||||
@ -136,7 +136,7 @@ func TestIntegration_CountAlertRules(t *testing.T) {
|
||||
}
|
||||
|
||||
sqlStore := db.InitTestDB(t)
|
||||
store := DBstore{SQLStore: sqlStore}
|
||||
store := &DBstore{SQLStore: sqlStore}
|
||||
rule := createRule(t, store)
|
||||
|
||||
tests := map[string]struct {
|
||||
@ -175,7 +175,7 @@ func TestIntegration_CountAlertRules(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func createRule(t *testing.T, store DBstore) *models.AlertRule {
|
||||
func createRule(t *testing.T, store *DBstore) *models.AlertRule {
|
||||
rule := models.AlertRuleGen(withIntervalMatching(store.Cfg.BaseInterval))()
|
||||
err := store.SQLStore.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
_, err := sess.Table(models.AlertRule{}).InsertOne(rule)
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
models2 "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -23,7 +23,7 @@ type RuleStore struct {
|
||||
Rules map[int64][]*models.AlertRule
|
||||
Hook func(cmd interface{}) error // use Hook if you need to intercept some query and return an error
|
||||
RecordedOps []interface{}
|
||||
Folders map[int64][]*models2.Folder
|
||||
Folders map[int64][]*folder.Folder
|
||||
}
|
||||
|
||||
type GenericRecordedQuery struct {
|
||||
@ -38,7 +38,7 @@ func NewRuleStore(t *testing.T) *RuleStore {
|
||||
Hook: func(interface{}) error {
|
||||
return nil
|
||||
},
|
||||
Folders: map[int64][]*models2.Folder{},
|
||||
Folders: map[int64][]*folder.Folder{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,18 +58,18 @@ mainloop:
|
||||
rgs = append(rgs, r)
|
||||
f.Rules[r.OrgID] = rgs
|
||||
|
||||
var existing *models2.Folder
|
||||
var existing *folder.Folder
|
||||
folders := f.Folders[r.OrgID]
|
||||
for _, folder := range folders {
|
||||
if folder.Uid == r.NamespaceUID {
|
||||
if folder.UID == r.NamespaceUID {
|
||||
existing = folder
|
||||
break
|
||||
}
|
||||
}
|
||||
if existing == nil {
|
||||
folders = append(folders, &models2.Folder{
|
||||
Id: rand.Int63(),
|
||||
Uid: r.NamespaceUID,
|
||||
folders = append(folders, &folder.Folder{
|
||||
ID: rand.Int63(),
|
||||
UID: r.NamespaceUID,
|
||||
Title: "TEST-FOLDER-" + util.GenerateShortUID(),
|
||||
})
|
||||
f.Folders[r.OrgID] = folders
|
||||
@ -227,11 +227,11 @@ func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQu
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*models2.Folder, error) {
|
||||
func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*folder.Folder, error) {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
|
||||
namespacesMap := map[string]*models2.Folder{}
|
||||
namespacesMap := map[string]*folder.Folder{}
|
||||
|
||||
_, ok := f.Rules[orgID]
|
||||
if !ok {
|
||||
@ -239,12 +239,12 @@ func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *
|
||||
}
|
||||
|
||||
for _, folder := range f.Folders[orgID] {
|
||||
namespacesMap[folder.Uid] = folder
|
||||
namespacesMap[folder.UID] = folder
|
||||
}
|
||||
return namespacesMap, nil
|
||||
}
|
||||
|
||||
func (f *RuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID int64, _ *user.SignedInUser, _ bool) (*models2.Folder, error) {
|
||||
func (f *RuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID int64, _ *user.SignedInUser, _ bool) (*folder.Folder, error) {
|
||||
folders := f.Folders[orgID]
|
||||
for _, folder := range folders {
|
||||
if folder.Title == title {
|
||||
@ -254,7 +254,7 @@ func (f *RuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID i
|
||||
return nil, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
func (f *RuleStore) GetNamespaceByUID(_ context.Context, uid string, orgID int64, _ *user.SignedInUser) (*models2.Folder, error) {
|
||||
func (f *RuleStore) GetNamespaceByUID(_ context.Context, uid string, orgID int64, _ *user.SignedInUser) (*folder.Folder, error) {
|
||||
f.RecordedOps = append(f.RecordedOps, GenericRecordedQuery{
|
||||
Name: "GetNamespaceByUID",
|
||||
Params: []interface{}{orgID, uid},
|
||||
@ -262,7 +262,7 @@ func (f *RuleStore) GetNamespaceByUID(_ context.Context, uid string, orgID int64
|
||||
|
||||
folders := f.Folders[orgID]
|
||||
for _, folder := range folders {
|
||||
if folder.Uid == uid {
|
||||
if folder.UID == uid {
|
||||
return folder, nil
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
gfmodels "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
|
||||
@ -68,6 +67,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
|
||||
})
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
||||
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{
|
||||
BaseInterval: setting.SchedulerBaseInterval,
|
||||
}
|
||||
@ -127,12 +127,10 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
|
||||
}
|
||||
|
||||
ctx = appcontext.WithUser(ctx, user)
|
||||
f, err := dbstore.FolderService.Create(ctx, &folder.CreateFolderCommand{OrgID: orgID, Title: "FOLDER-" + util.GenerateShortUID(), UID: folderUID})
|
||||
var folder *gfmodels.Folder
|
||||
if err == nil {
|
||||
folder = f.ToLegacyModel()
|
||||
} else if errors.Is(err, dashboards.ErrFolderWithSameUIDExists) || errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
||||
folder, err = dbstore.FolderService.GetFolderByUID(ctx, user, orgID, folderUID)
|
||||
_, err := dbstore.FolderService.Create(ctx, &folder.CreateFolderCommand{OrgID: orgID, Title: "FOLDER-" + util.GenerateShortUID(), UID: folderUID})
|
||||
// var foldr *folder.Folder
|
||||
if errors.Is(err, dashboards.ErrFolderWithSameUIDExists) || errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
||||
_, err = dbstore.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, UID: &folderUID})
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -160,7 +158,7 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
|
||||
Labels: labels,
|
||||
Annotations: map[string]string{"testAnnoKey": "testAnnoValue"},
|
||||
IntervalSeconds: intervalSeconds,
|
||||
NamespaceUID: folder.Uid,
|
||||
NamespaceUID: folderUID,
|
||||
RuleGroup: ruleGroup,
|
||||
NoDataState: models.NoData,
|
||||
ExecErrState: models.AlertingErrState,
|
||||
@ -170,7 +168,7 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
|
||||
|
||||
q := models.ListAlertRulesQuery{
|
||||
OrgID: orgID,
|
||||
NamespaceUIDs: []string{folder.Uid},
|
||||
NamespaceUIDs: []string{folderUID},
|
||||
RuleGroup: ruleGroup,
|
||||
}
|
||||
err = dbstore.ListAlertRules(ctx, &q)
|
||||
@ -178,6 +176,6 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
|
||||
require.NotEmpty(t, q.Result)
|
||||
|
||||
rule := q.Result[0]
|
||||
t.Logf("alert definition: %v with title: %q interval: %d folder: %s created", rule.GetKey(), rule.Title, rule.IntervalSeconds, folder.Uid)
|
||||
t.Logf("alert definition: %v with title: %q interval: %d folder: %s created", rule.GetKey(), rule.Title, rule.IntervalSeconds, folderUID)
|
||||
return rule
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user