RBAC: Remove dashboard guardians pt 1 (#102314)
* replace the usage of dashboard guardians with calling AC evaluators or checking access in middleware * linting fixes * fix test * more test fixes * remove a todo comment
This commit is contained in:
+14
-11
@@ -462,22 +462,24 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// Dashboard
|
||||
apiRoute.Group("/dashboards", func(dashboardRoute routing.RouteRegister) {
|
||||
dashboardRoute.Get("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsRead)), routing.Wrap(hs.GetDashboard))
|
||||
dashUIDScope := dashboards.ScopeDashboardsProvider.GetResourceScopeUID(ac.Parameter(":uid"))
|
||||
|
||||
dashboardRoute.Get("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsRead, dashUIDScope)), routing.Wrap(hs.GetDashboard))
|
||||
|
||||
if hs.Features.IsEnabledGlobally(featuremgmt.FlagDashboardRestore) {
|
||||
dashboardRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.SoftDeleteDashboard))
|
||||
dashboardRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete, dashUIDScope)), routing.Wrap(hs.SoftDeleteDashboard))
|
||||
} else {
|
||||
dashboardRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.DeleteDashboardByUID))
|
||||
dashboardRoute.Delete("/uid/:uid", authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete, dashUIDScope)), routing.Wrap(hs.DeleteDashboardByUID))
|
||||
}
|
||||
|
||||
dashboardRoute.Group("/uid/:uid", func(dashUidRoute routing.RouteRegister) {
|
||||
dashUidRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions))
|
||||
dashUidRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
dashUidRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion))
|
||||
dashUidRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashUIDScope)), routing.Wrap(hs.GetDashboardVersions))
|
||||
dashUidRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashUIDScope)), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
dashUidRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashUIDScope)), routing.Wrap(hs.GetDashboardVersion))
|
||||
|
||||
if hs.Features.IsEnabledGlobally(featuremgmt.FlagDashboardRestore) {
|
||||
dashUidRoute.Patch("/trash", reqOrgAdmin, routing.Wrap(hs.RestoreDeletedDashboard))
|
||||
dashUidRoute.Delete("/trash", reqOrgAdmin, routing.Wrap(hs.HardDeleteDashboardByUID))
|
||||
dashUidRoute.Patch("/trash", reqOrgAdmin, authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashUIDScope)), routing.Wrap(hs.RestoreDeletedDashboard))
|
||||
dashUidRoute.Delete("/trash", reqOrgAdmin, authorize(ac.EvalPermission(dashboards.ActionDashboardsDelete, dashUIDScope)), routing.Wrap(hs.HardDeleteDashboardByUID))
|
||||
}
|
||||
|
||||
dashUidRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
||||
@@ -497,9 +499,10 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// Deprecated: use /uid/:uid API instead.
|
||||
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) {
|
||||
dashIdRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
dashIDScope := dashboards.ScopeDashboardsProvider.GetResourceScope(ac.Parameter(":dashboardId"))
|
||||
dashIdRoute.Get("/versions", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashIDScope)), routing.Wrap(hs.GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashIDScope)), routing.Wrap(hs.GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", authorize(ac.EvalPermission(dashboards.ActionDashboardsWrite, dashIDScope)), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
|
||||
dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
||||
dashboardPermissionRoute.Get("/", authorize(ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList))
|
||||
|
||||
+19
-77
@@ -27,7 +27,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboardversion/dashverimpl"
|
||||
"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"
|
||||
publicdashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
@@ -141,18 +140,21 @@ func (hs *HTTPServer) GetDashboard(c *contextmodel.ReqContext) response.Response
|
||||
dash.Data.Set("id", dash.ID)
|
||||
}
|
||||
}
|
||||
guardian, err := guardian.NewByDashboard(ctx, dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canView, err := guardian.CanView(); err != nil || !canView {
|
||||
return dashboardGuardianResponse(err)
|
||||
dashScope := dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dash.UID)
|
||||
writeEvaluator := accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite, dashScope)
|
||||
canSave, _ := hs.AccessControl.Evaluate(ctx, c.SignedInUser, writeEvaluator)
|
||||
canEdit := canSave
|
||||
//nolint:staticcheck // ViewersCanEdit is deprecated but still used for backward compatibility
|
||||
if hs.Cfg.ViewersCanEdit {
|
||||
canEdit = true
|
||||
}
|
||||
canEdit, _ := guardian.CanEdit()
|
||||
canSave, _ := guardian.CanSave()
|
||||
canAdmin, _ := guardian.CanAdmin()
|
||||
canDelete, _ := guardian.CanDelete()
|
||||
deleteEvaluator := accesscontrol.EvalPermission(dashboards.ActionDashboardsDelete, dashScope)
|
||||
canDelete, _ := hs.AccessControl.Evaluate(ctx, c.SignedInUser, deleteEvaluator)
|
||||
adminEvaluator := accesscontrol.EvalAll(
|
||||
accesscontrol.EvalPermission(dashboards.ActionDashboardsPermissionsRead, dashScope),
|
||||
accesscontrol.EvalPermission(dashboards.ActionDashboardsPermissionsWrite, dashScope))
|
||||
canAdmin, _ := hs.AccessControl.Evaluate(ctx, c.SignedInUser, adminEvaluator)
|
||||
|
||||
isStarred, err := hs.isDashboardStarredByUser(c, dash.ID)
|
||||
if err != nil {
|
||||
@@ -369,15 +371,6 @@ func (hs *HTTPServer) RestoreDeletedDashboard(c *contextmodel.ReqContext) respon
|
||||
return response.Error(http.StatusNotFound, "Dashboard not found", err)
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canRestore, err := guardian.CanSave(); err != nil || !canRestore {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
err = hs.DashboardService.RestoreDashboard(c.Req.Context(), dash, c.SignedInUser, cmd.FolderUID)
|
||||
if err != nil {
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
@@ -417,16 +410,7 @@ func (hs *HTTPServer) SoftDeleteDashboard(c *contextmodel.ReqContext) response.R
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canDelete, err := guardian.CanDelete(); err != nil || !canDelete {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
err = hs.DashboardService.SoftDeleteDashboard(c.Req.Context(), c.SignedInUser.GetOrgID(), uid)
|
||||
err := hs.DashboardService.SoftDeleteDashboard(c.Req.Context(), c.SignedInUser.GetOrgID(), uid)
|
||||
if err != nil {
|
||||
var dashboardErr dashboards.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
@@ -498,21 +482,12 @@ func (hs *HTTPServer) deleteDashboard(c *contextmodel.ReqContext) response.Respo
|
||||
}
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canDelete, err := guardian.CanDelete(); err != nil || !canDelete {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
if dash.IsFolder {
|
||||
return response.Error(http.StatusBadRequest, "Use folders endpoint for deleting folders.", nil)
|
||||
}
|
||||
|
||||
// disconnect all library elements for this dashboard
|
||||
err = hs.LibraryElementService.DisconnectElementsFromDashboard(c.Req.Context(), dash.ID)
|
||||
err := hs.LibraryElementService.DisconnectElementsFromDashboard(c.Req.Context(), dash.ID)
|
||||
if err != nil {
|
||||
hs.log.Error(
|
||||
"Failed to disconnect library elements",
|
||||
@@ -840,14 +815,6 @@ func (hs *HTTPServer) GetDashboardVersions(c *contextmodel.ReqContext) response.
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
query := dashver.ListDashboardVersionsQuery{
|
||||
OrgID: c.SignedInUser.GetOrgID(),
|
||||
DashboardID: dash.ID,
|
||||
@@ -959,15 +926,6 @@ func (hs *HTTPServer) GetDashboardVersion(c *contextmodel.ReqContext) response.R
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
version, err := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 64)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
@@ -1027,22 +985,15 @@ func (hs *HTTPServer) CalculateDashboardDiff(c *contextmodel.ReqContext) respons
|
||||
if err := web.Bind(c.Req, &apiOptions); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
guardianBase, err := guardian.New(c.Req.Context(), apiOptions.Base.DashboardId, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardianBase.CanSave(); err != nil || !canSave {
|
||||
evaluator := accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite, dashboards.ScopeDashboardsProvider.GetResourceScope(strconv.FormatInt(apiOptions.Base.DashboardId, 10)))
|
||||
if canWrite, err := hs.AccessControl.Evaluate(c.Req.Context(), c.SignedInUser, evaluator); err != nil || !canWrite {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
if apiOptions.Base.DashboardId != apiOptions.New.DashboardId {
|
||||
guardianNew, err := guardian.New(c.Req.Context(), apiOptions.New.DashboardId, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardianNew.CanSave(); err != nil || !canSave {
|
||||
evaluator = accesscontrol.EvalPermission(dashboards.ActionDashboardsWrite, dashboards.ScopeDashboardsProvider.GetResourceScope(strconv.FormatInt(apiOptions.New.DashboardId, 10)))
|
||||
if canWrite, err := hs.AccessControl.Evaluate(c.Req.Context(), c.SignedInUser, evaluator); err != nil || !canWrite {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
}
|
||||
@@ -1159,15 +1110,6 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *contextmodel.ReqContext) respon
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
versionQuery := dashver.GetDashboardVersionQuery{DashboardID: dashID, DashboardUID: dash.UID, Version: apiCmd.Version, OrgID: c.SignedInUser.GetOrgID()}
|
||||
version, err := hs.dashboardVersionService.Get(c.Req.Context(), &versionQuery)
|
||||
if err != nil {
|
||||
|
||||
+45
-96
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -327,12 +328,16 @@ func TestHTTPServer_GetDashboardVersions_AccessControl(t *testing.T) {
|
||||
hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
||||
hs.starService = startest.NewStarServiceFake()
|
||||
|
||||
hs.dashboardVersionService = &dashvertest.FakeDashboardVersionService{
|
||||
ExpectedListDashboarVersions: []*dashver.DashboardVersionDTO{},
|
||||
ExpectedDashboardVersion: &dashver.DashboardVersionDTO{},
|
||||
expectedDashVersions := []*dashver.DashboardVersionDTO{
|
||||
{Data: simplejson.NewFromAny(map[string]any{"title": "Dash"})},
|
||||
{Data: simplejson.NewFromAny(map[string]any{"title": "Dash updated"})},
|
||||
}
|
||||
|
||||
guardian.InitAccessControlGuardian(hs.Cfg, hs.AccessControl, hs.DashboardService, hs.folderService, log.NewNopLogger())
|
||||
hs.dashboardVersionService = &dashvertest.FakeDashboardVersionService{
|
||||
ExpectedListDashboarVersions: []*dashver.DashboardVersionDTO{},
|
||||
ExpectedDashboardVersions: expectedDashVersions,
|
||||
ExpectedDashboardVersion: &dashver.DashboardVersionDTO{},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -344,6 +349,17 @@ func TestHTTPServer_GetDashboardVersions_AccessControl(t *testing.T) {
|
||||
return server.Send(webtest.RequestWithSignedInUser(server.NewGetRequest("/api/dashboards/uid/1/versions"), userWithPermissions(1, permissions)))
|
||||
}
|
||||
|
||||
calculateDiff := func(server *webtest.Server, permissions []accesscontrol.Permission) (*http.Response, error) {
|
||||
cmd := &dtos.CalculateDiffOptions{
|
||||
Base: dtos.CalculateDiffTarget{DashboardId: 1, Version: 1},
|
||||
New: dtos.CalculateDiffTarget{DashboardId: 1, Version: 2},
|
||||
DiffType: "json",
|
||||
}
|
||||
jsonBytes, err := json.Marshal(cmd)
|
||||
require.NoError(t, err)
|
||||
return server.SendJSON(webtest.RequestWithSignedInUser(server.NewPostRequest("/api/dashboards/calculate-diff", bytes.NewReader(jsonBytes)), userWithPermissions(1, permissions)))
|
||||
}
|
||||
|
||||
t.Run("Should not be able to list dashboard versions without correct permission", func(t *testing.T) {
|
||||
server := setup()
|
||||
|
||||
@@ -363,7 +379,6 @@ func TestHTTPServer_GetDashboardVersions_AccessControl(t *testing.T) {
|
||||
server := setup()
|
||||
|
||||
permissions := []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||
{Action: dashboards.ActionDashboardsWrite, Scope: "dashboards:uid:1"},
|
||||
}
|
||||
|
||||
@@ -378,6 +393,28 @@ func TestHTTPServer_GetDashboardVersions_AccessControl(t *testing.T) {
|
||||
|
||||
require.NoError(t, res.Body.Close())
|
||||
})
|
||||
|
||||
t.Run("Should be able to diff dashboards with correct permissions", func(t *testing.T) {
|
||||
server := setup()
|
||||
|
||||
permissions := []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsWrite, Scope: dashboards.ScopeDashboardsAll},
|
||||
}
|
||||
|
||||
res, err := calculateDiff(server, permissions)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
require.NoError(t, res.Body.Close())
|
||||
})
|
||||
|
||||
t.Run("Should not be able to diff dashboards without permissions", func(t *testing.T) {
|
||||
server := setup()
|
||||
|
||||
res, err := calculateDiff(server, []accesscontrol.Permission{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusForbidden, res.StatusCode)
|
||||
require.NoError(t, res.Body.Close())
|
||||
})
|
||||
}
|
||||
|
||||
func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
@@ -527,39 +564,6 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
}),
|
||||
},
|
||||
}
|
||||
sqlmock := dbtest.NewFakeDB()
|
||||
cmd := dtos.CalculateDiffOptions{
|
||||
Base: dtos.CalculateDiffTarget{
|
||||
DashboardId: 1,
|
||||
Version: 1,
|
||||
},
|
||||
New: dtos.CalculateDiffTarget{
|
||||
DashboardId: 2,
|
||||
Version: 2,
|
||||
},
|
||||
DiffType: "basic",
|
||||
}
|
||||
|
||||
t.Run("when user does not have permission", func(t *testing.T) {
|
||||
role := org.RoleViewer
|
||||
postDiffScenario(t, "When calling POST on", "/api/dashboards/calculate-diff", "/api/dashboards/calculate-diff", cmd, role, func(sc *scenarioContext) {
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: false})
|
||||
|
||||
callPostDashboard(sc)
|
||||
assert.Equal(t, http.StatusForbidden, sc.resp.Code)
|
||||
}, sqlmock, fakeDashboardVersionService)
|
||||
})
|
||||
|
||||
t.Run("when user does have permission", func(t *testing.T) {
|
||||
role := org.RoleAdmin
|
||||
postDiffScenario(t, "When calling POST on", "/api/dashboards/calculate-diff", "/api/dashboards/calculate-diff", cmd, role, func(sc *scenarioContext) {
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
// This test shouldn't hit GetDashboardACLInfoList, so no setup needed
|
||||
sc.dashboardVersionService = fakeDashboardVersionService
|
||||
callPostDashboard(sc)
|
||||
assert.Equal(t, http.StatusOK, sc.resp.Code)
|
||||
}, sqlmock, fakeDashboardVersionService)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given dashboard in folder being restored should restore to folder", func(t *testing.T) {
|
||||
@@ -588,11 +592,6 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
},
|
||||
}
|
||||
mockSQLStore := dbtest.NewFakeDB()
|
||||
origNewGuardian := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
|
||||
restoreDashboardVersionScenario(t, "When calling POST on", "/api/dashboards/id/1/restore",
|
||||
"/api/dashboards/id/:dashboardId/restore", dashboardService, fakeDashboardVersionService, cmd, func(sc *scenarioContext) {
|
||||
@@ -648,7 +647,6 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
qResult := &dashboards.Dashboard{ID: 1, Data: dataValue}
|
||||
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true})
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
|
||||
fakeProvisioningService := provisioning.NewProvisioningServiceMock(context.Background())
|
||||
@@ -678,7 +676,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
LibraryElementService: &libraryelementsfake.LibraryElementService{},
|
||||
dashboardProvisioningService: mockDashboardProvisioningService{},
|
||||
SQLStore: mockSQLStore,
|
||||
AccessControl: accesscontrolmock.New(),
|
||||
AccessControl: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
DashboardService: dashboardService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
starService: startest.NewStarServiceFake(),
|
||||
@@ -710,7 +708,6 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
Data: dataValue,
|
||||
}
|
||||
dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(qResult, nil)
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true})
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/dash", "/api/dashboards/uid/:uid", org.RoleEditor, func(sc *scenarioContext) {
|
||||
hs := &HTTPServer{
|
||||
@@ -718,7 +715,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
LibraryPanelService: &mockLibraryPanelService{},
|
||||
LibraryElementService: &libraryelementsfake.LibraryElementService{},
|
||||
SQLStore: mockSQLStore,
|
||||
AccessControl: accesscontrolmock.New(),
|
||||
AccessControl: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
DashboardService: dashboardService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
starService: startest.NewStarServiceFake(),
|
||||
@@ -753,7 +750,7 @@ func TestDashboardVersionsAPIEndpoint(t *testing.T) {
|
||||
Cfg: cfg,
|
||||
pluginStore: &pluginstore.FakePluginStore{},
|
||||
SQLStore: mockSQLStore,
|
||||
AccessControl: accesscontrolmock.New(),
|
||||
AccessControl: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
DashboardService: dashboardService,
|
||||
dashboardVersionService: fakeDashboardVersionService,
|
||||
@@ -765,13 +762,8 @@ func TestDashboardVersionsAPIEndpoint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
setUp := func() {
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
}
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When user exists and calling GET on", "GET", "/api/dashboards/id/2/versions",
|
||||
"/api/dashboards/id/:dashboardId/versions", org.RoleEditor, func(sc *scenarioContext) {
|
||||
setUp()
|
||||
fakeDashboardVersionService.ExpectedListDashboarVersions = []*dashver.DashboardVersionDTO{
|
||||
{
|
||||
Version: 1,
|
||||
@@ -797,7 +789,6 @@ func TestDashboardVersionsAPIEndpoint(t *testing.T) {
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When user does not exist and calling GET on", "GET", "/api/dashboards/id/2/versions",
|
||||
"/api/dashboards/id/:dashboardId/versions", org.RoleEditor, func(sc *scenarioContext) {
|
||||
setUp()
|
||||
fakeDashboardVersionService.ExpectedListDashboarVersions = []*dashver.DashboardVersionDTO{
|
||||
{
|
||||
Version: 1,
|
||||
@@ -823,7 +814,6 @@ func TestDashboardVersionsAPIEndpoint(t *testing.T) {
|
||||
|
||||
loggedInUserScenarioWithRole(t, "When failing to get user and calling GET on", "GET", "/api/dashboards/id/2/versions",
|
||||
"/api/dashboards/id/:dashboardId/versions", org.RoleEditor, func(sc *scenarioContext) {
|
||||
setUp()
|
||||
fakeDashboardVersionService.ExpectedListDashboarVersions = []*dashver.DashboardVersionDTO{
|
||||
{
|
||||
Version: 1,
|
||||
@@ -978,47 +968,6 @@ func postDashboardScenario(t *testing.T, desc string, url string, routePattern s
|
||||
})
|
||||
}
|
||||
|
||||
func postDiffScenario(t *testing.T, desc string, url string, routePattern string, cmd dtos.CalculateDiffOptions,
|
||||
role org.RoleType, fn scenarioFunc, sqlmock db.DB, fakeDashboardVersionService *dashvertest.FakeDashboardVersionService,
|
||||
) {
|
||||
t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
hs := HTTPServer{
|
||||
Cfg: cfg,
|
||||
ProvisioningService: provisioning.NewProvisioningServiceMock(context.Background()),
|
||||
Live: newTestLive(t, db.InitTestDB(t)),
|
||||
QuotaService: quotatest.New(false, nil),
|
||||
LibraryPanelService: &mockLibraryPanelService{},
|
||||
LibraryElementService: &libraryelementsfake.LibraryElementService{},
|
||||
SQLStore: sqlmock,
|
||||
dashboardVersionService: fakeDashboardVersionService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
DashboardService: dashSvc,
|
||||
tracer: tracing.InitializeTracerForTest(),
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *contextmodel.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
c.Req.Header.Add("Content-Type", "application/json")
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &user.SignedInUser{
|
||||
OrgID: testOrgID,
|
||||
UserID: testUserID,
|
||||
}
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return hs.CalculateDashboardDiff(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
fn(sc)
|
||||
})
|
||||
}
|
||||
|
||||
func restoreDashboardVersionScenario(t *testing.T, desc string, url string, routePattern string,
|
||||
mock *dashboards.FakeDashboardService, fakeDashboardVersionService *dashvertest.FakeDashboardVersionService,
|
||||
cmd dtos.RestoreDashboardVersionCommand, fn scenarioFunc, sqlStore db.DB,
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/testutil"
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
dashboardsservice "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/search/sort"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||
@@ -42,16 +41,13 @@ func TestIntegrationAuthorize(t *testing.T) {
|
||||
}
|
||||
|
||||
sql, cfg := db.InitTestDBWithCfg(t)
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sql)
|
||||
fStore := folderimpl.ProvideStore(sql)
|
||||
dashStore, err := database.ProvideDashboardStore(sql, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql))
|
||||
require.NoError(t, err)
|
||||
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
folderSvc := folderimpl.ProvideService(
|
||||
fStore, accesscontrolmock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore,
|
||||
fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore,
|
||||
nil, sql, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService())
|
||||
dashSvc, err := dashboardsservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuremgmt.WithFeatures(), accesscontrolmock.NewMockedPermissionsService(),
|
||||
ac, folderSvc, fStore, nil, client.MockTestRestConfig{}, nil, quotatest.New(false, nil), nil, nil, nil, dualwrite.ProvideTestService(), sort.ProvideService())
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/annotations/testutil"
|
||||
@@ -54,16 +54,13 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) {
|
||||
features := featuremgmt.WithFeatures()
|
||||
tagService := tagimpl.ProvideService(sql)
|
||||
ruleStore := alertingStore.SetupStoreForTesting(t, sql)
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{})
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sql)
|
||||
fStore := folderimpl.ProvideStore(sql)
|
||||
dashStore, err := database.ProvideDashboardStore(sql, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sql))
|
||||
require.NoError(t, err)
|
||||
ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures())
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
folderSvc := folderimpl.ProvideService(
|
||||
fStore, accesscontrolmock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore,
|
||||
fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore,
|
||||
nil, sql, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService())
|
||||
dashSvc, err := dashboardsservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuremgmt.WithFeatures(), accesscontrolmock.NewMockedPermissionsService(),
|
||||
ac, folderSvc, fStore, nil, client.MockTestRestConfig{}, nil, quotatest.New(false, nil), nil, nil, nil, dualwrite.ProvideTestService(), sort.ProvideService())
|
||||
@@ -242,7 +239,7 @@ func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
|
||||
ac := acimpl.ProvideAccessControl(features)
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
fStore := folderimpl.ProvideStore(sql)
|
||||
folderStore := folderimpl.ProvideDashboardFolderStore(sql)
|
||||
folderSvc := folderimpl.ProvideService(
|
||||
|
||||
@@ -43,7 +43,6 @@ import (
|
||||
dashboardsearch "github.com/grafana/grafana/pkg/services/dashboards/service/search"
|
||||
"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"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
@@ -413,14 +412,24 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
}
|
||||
|
||||
if isParentFolderChanged {
|
||||
// Check that the user is allowed to add a dashboard to the folder
|
||||
guardian, err := guardian.NewByDashboard(ctx, dash, dto.OrgID, dto.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if canCreate, err := dr.canCreateDashboard(ctx, dto.User, dash); err != nil || !canCreate {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
if dash.ID == 0 {
|
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
||||
// nolint:staticcheck
|
||||
if canSave, err := guardian.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canSave {
|
||||
if canCreate, err := dr.canCreateDashboard(ctx, dto.User, dash); err != nil || !canCreate {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
} else {
|
||||
if canSave, err := dr.canSaveDashboard(ctx, dto.User, dash); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -439,29 +448,6 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
|
||||
}
|
||||
}
|
||||
|
||||
guard, err := getGuardianForSavePermissionCheck(ctx, dash, dto.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dash.ID == 0 {
|
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
||||
// nolint:staticcheck
|
||||
if canCreate, err := guard.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canCreate {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
} else {
|
||||
if canSave, err := guard.CanSave(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
var userID int64
|
||||
if id, err := identity.UserIdentifier(dto.User.GetID()); err == nil {
|
||||
userID = id
|
||||
@@ -561,6 +547,30 @@ func (dr *DashboardServiceImpl) ValidateDashboardBeforeSave(ctx context.Context,
|
||||
return isParentFolderChanged, nil
|
||||
}
|
||||
|
||||
func (dr *DashboardServiceImpl) canSaveDashboard(ctx context.Context, user identity.Requester, dash *dashboards.Dashboard) (bool, error) {
|
||||
action := dashboards.ActionDashboardsWrite
|
||||
if dash.IsFolder {
|
||||
action = dashboards.ActionFoldersWrite
|
||||
}
|
||||
scope := dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dash.UID)
|
||||
if dash.IsFolder {
|
||||
scope = dashboards.ScopeFoldersProvider.GetResourceScopeUID(dash.UID)
|
||||
}
|
||||
return dr.ac.Evaluate(ctx, user, accesscontrol.EvalPermission(action, scope))
|
||||
}
|
||||
|
||||
func (dr *DashboardServiceImpl) canCreateDashboard(ctx context.Context, user identity.Requester, dash *dashboards.Dashboard) (bool, error) {
|
||||
action := dashboards.ActionDashboardsCreate
|
||||
if dash.IsFolder {
|
||||
action = dashboards.ActionFoldersCreate
|
||||
}
|
||||
scope := dashboards.ScopeFoldersProvider.GetResourceScopeUID(dash.FolderUID)
|
||||
if dash.FolderUID == "" {
|
||||
scope = dashboards.ScopeFoldersProvider.GetResourceScopeUID(accesscontrol.GeneralFolderUID)
|
||||
}
|
||||
return dr.ac.Evaluate(ctx, user, accesscontrol.EvalPermission(action, scope))
|
||||
}
|
||||
|
||||
// waitForSearchQuery waits for the search query to return the expected number of hits.
|
||||
// Since US doesn't offer search-after-write guarantees, we can use this to wait after writes until the indexer is up to date.
|
||||
func (dr *DashboardServiceImpl) waitForSearchQuery(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery, maxRetries int, expectedHits int64) error {
|
||||
@@ -620,46 +630,6 @@ func (dr *DashboardServiceImpl) DeleteOrphanedProvisionedDashboards(ctx context.
|
||||
return dr.dashboardStore.DeleteOrphanedProvisionedDashboards(ctx, cmd)
|
||||
}
|
||||
|
||||
// getGuardianForSavePermissionCheck returns the guardian to be used for checking permission of dashboard
|
||||
// It replaces deleted Dashboard.GetDashboardIdForSavePermissionCheck()
|
||||
func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashboard, user identity.Requester) (guardian.DashboardGuardian, error) {
|
||||
ctx, span := tracer.Start(ctx, "dashboards.service.getGuardianForSavePermissionCheck")
|
||||
defer span.End()
|
||||
|
||||
newDashboard := d.ID == 0
|
||||
|
||||
if newDashboard {
|
||||
// if it's a new dashboard/folder check the parent folder permissions
|
||||
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
|
||||
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||
ID: d.FolderID, // nolint:staticcheck
|
||||
OrgID: d.OrgID,
|
||||
}, d.OrgID, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guard, nil
|
||||
}
|
||||
|
||||
if d.IsFolder {
|
||||
guard, err := guardian.NewByFolder(ctx, &folder.Folder{
|
||||
ID: d.ID, // nolint:staticcheck
|
||||
UID: d.UID,
|
||||
OrgID: d.OrgID,
|
||||
}, d.OrgID, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guard, nil
|
||||
}
|
||||
|
||||
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guard, nil
|
||||
}
|
||||
|
||||
func validateDashboardRefreshInterval(minRefreshInterval string, dash *dashboards.Dashboard) error {
|
||||
if minRefreshInterval == "" {
|
||||
return nil
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,13 +20,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/client"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
@@ -50,6 +50,7 @@ func TestDashboardService(t *testing.T) {
|
||||
log: log.New("test.logger"),
|
||||
dashboardStore: &fakeStore,
|
||||
folderService: folderSvc,
|
||||
ac: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
features: featuremgmt.WithFeatures(),
|
||||
publicDashboardService: fakePublicDashboardService,
|
||||
}
|
||||
@@ -57,10 +58,6 @@ func TestDashboardService(t *testing.T) {
|
||||
folderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(nil, dashboards.ErrFolderNotFound).Once()
|
||||
service.folderStore = &folderStore
|
||||
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
t.Run("Save dashboard validation", func(t *testing.T) {
|
||||
dto := &dashboards.SaveDashboardDTO{}
|
||||
|
||||
@@ -1292,13 +1289,10 @@ func TestSetDefaultPermissionsWhenSavingFolderForProvisionedDashboards(t *testin
|
||||
UID: "general",
|
||||
},
|
||||
},
|
||||
ac: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
log: log.NewNopLogger(),
|
||||
}
|
||||
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
cmd := &folder.CreateFolderCommand{
|
||||
Title: "foo",
|
||||
OrgID: 1,
|
||||
@@ -1326,13 +1320,10 @@ func TestSaveProvisionedDashboard(t *testing.T) {
|
||||
UID: "general",
|
||||
},
|
||||
},
|
||||
ac: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
log: log.NewNopLogger(),
|
||||
}
|
||||
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
query := &dashboards.SaveDashboardDTO{
|
||||
OrgID: 1,
|
||||
User: &user.SignedInUser{UserID: 1},
|
||||
@@ -1392,12 +1383,9 @@ func TestSaveDashboard(t *testing.T) {
|
||||
folderService: &foldertest.FakeService{
|
||||
ExpectedFolder: &folder.Folder{},
|
||||
},
|
||||
ac: actest.FakeAccessControl{ExpectedEvaluate: true},
|
||||
}
|
||||
|
||||
origNewDashboardGuardian := guardian.New
|
||||
defer func() { guardian.New = origNewDashboardGuardian }()
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
query := &dashboards.SaveDashboardDTO{
|
||||
OrgID: 1,
|
||||
User: &user.SignedInUser{UserID: 1},
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
dashsvc "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
@@ -1392,7 +1391,7 @@ func TestPublicDashboardServiceImpl_ListPublicDashboards(t *testing.T) {
|
||||
testDB, cfg := db.InitTestDBWithCfg(t)
|
||||
dashStore, err := dashboardsDB.ProvideDashboardStore(testDB, cfg, features, tagimpl.ProvideService(testDB))
|
||||
require.NoError(t, err)
|
||||
ac := acmock.New()
|
||||
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||
|
||||
fStore := folderimpl.ProvideStore(testDB)
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
@@ -1404,12 +1403,6 @@ func TestPublicDashboardServiceImpl_ListPublicDashboards(t *testing.T) {
|
||||
dashboardService, err := dashsvc.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuremgmt.WithFeatures(), folderPermissions, ac, folderSvc, fStore, nil, client.MockTestRestConfig{}, nil, quotatest.New(false, nil), nil, nil, nil, dualwrite.ProvideTestService(), sort.ProvideService())
|
||||
require.NoError(t, err)
|
||||
dashboardService.RegisterDashboardPermissions(&actest.FakePermissionsService{})
|
||||
fakeGuardian := &guardian.FakeDashboardGuardian{
|
||||
CanSaveValue: true,
|
||||
CanEditUIDs: []string{},
|
||||
CanViewUIDs: []string{},
|
||||
}
|
||||
guardian.MockDashboardGuardian(fakeGuardian)
|
||||
|
||||
// insert in test data so we can check that permissions are working properly through the dashboard service
|
||||
// this will create 4 dashboards and 3 users
|
||||
|
||||
Reference in New Issue
Block a user