mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Guardian: Introduce additional constructors (#59577)
* Guardian: Use dashboard UID instead of ID * Apply suggestions from code review Introduce several guardian constructors and each time use the most appropriate one.
This commit is contained in:
committed by
GitHub
parent
6478d0a5ef
commit
11d8bcbea9
@@ -693,7 +693,10 @@ func (hs *HTTPServer) PauseAlert(legacyAlertingEnabled *bool) func(c *models.Req
|
||||
return response.Error(500, "Get Alert failed", err)
|
||||
}
|
||||
|
||||
guardian := guardian.New(c.Req.Context(), query.Result.DashboardId, c.OrgID, c.SignedInUser)
|
||||
guardian, err := guardian.New(c.Req.Context(), query.Result.DashboardId, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Error while creating permission guardian", err)
|
||||
}
|
||||
if canEdit, err := guardian.CanEdit(); err != nil || !canEdit {
|
||||
if err != nil {
|
||||
return response.Error(500, "Error while checking permissions for Alert", err)
|
||||
|
||||
@@ -504,7 +504,11 @@ func (hs *HTTPServer) canSaveAnnotation(c *models.ReqContext, annotation *annota
|
||||
}
|
||||
|
||||
func canEditDashboard(c *models.ReqContext, dashboardID int64) (bool, error) {
|
||||
guard := guardian.New(c.Req.Context(), dashboardID, c.OrgID, c.SignedInUser)
|
||||
guard, err := guardian.New(c.Req.Context(), dashboardID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if canEdit, err := guard.CanEdit(); err != nil || !canEdit {
|
||||
return false, err
|
||||
}
|
||||
@@ -606,6 +610,7 @@ func (hs *HTTPServer) canCreateAnnotation(c *models.ReqContext, dashboardId int6
|
||||
return canSave, err
|
||||
}
|
||||
}
|
||||
|
||||
return canEditDashboard(c, dashboardId)
|
||||
} else { // organization annotations
|
||||
if !hs.AccessControl.IsDisabled() {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
@@ -24,6 +25,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/team/teamtest"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
func TestAnnotationsAPIEndpoint(t *testing.T) {
|
||||
@@ -154,8 +156,9 @@ func TestAnnotationsAPIEndpoint(t *testing.T) {
|
||||
|
||||
t.Run("When user is an Org Viewer", func(t *testing.T) {
|
||||
role := org.RoleViewer
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
t.Run("Should not be allowed to save an annotation", func(t *testing.T) {
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, nil, func(sc *scenarioContext) {
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, dashSvc, func(sc *scenarioContext) {
|
||||
setUpACL()
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
assert.Equal(t, 403, sc.resp.Code)
|
||||
@@ -186,7 +189,8 @@ func TestAnnotationsAPIEndpoint(t *testing.T) {
|
||||
t.Run("When user is an Org Editor", func(t *testing.T) {
|
||||
role := org.RoleEditor
|
||||
t.Run("Should be able to save an annotation", func(t *testing.T) {
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, nil, func(sc *scenarioContext) {
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, dashSvc, func(sc *scenarioContext) {
|
||||
setUpACL()
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
@@ -220,12 +224,6 @@ func TestAnnotationsAPIEndpoint(t *testing.T) {
|
||||
mockStore := mockstore.NewSQLStoreMock()
|
||||
|
||||
t.Run("Should be able to do anything", func(t *testing.T) {
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, nil, func(sc *scenarioContext) {
|
||||
setUpACL()
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
})
|
||||
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
@@ -234,6 +232,12 @@ func TestAnnotationsAPIEndpoint(t *testing.T) {
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, cmd, store, dashSvc, func(sc *scenarioContext) {
|
||||
setUpACL()
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
assert.Equal(t, 200, sc.resp.Code)
|
||||
})
|
||||
|
||||
postAnnotationScenario(t, "When calling POST on", "/api/annotations", "/api/annotations", role, dashboardUIDCmd, mockStore, dashSvc, func(sc *scenarioContext) {
|
||||
setUpACL()
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
@@ -387,7 +391,31 @@ func TestAPI_Annotations_AccessControl(t *testing.T) {
|
||||
_, err := sc.hs.orgService.CreateWithMember(context.Background(), &org.CreateOrgCommand{Name: "TestOrg", UserID: testUserID})
|
||||
require.NoError(t, err)
|
||||
|
||||
dashboardAnnotation := &annotations.Item{Id: 1, DashboardId: 1}
|
||||
origNewGuardian := guardian.New
|
||||
t.Cleanup(func() {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
|
||||
// Create a dashboard
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
sc.dashboardPermissionsService.On("SetPermissions", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string"), mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||
cmd := &dashboards.SaveDashboardDTO{
|
||||
OrgId: testOrgID,
|
||||
User: &user.SignedInUser{UserID: testUserID, OrgID: testOrgID},
|
||||
Dashboard: &models.Dashboard{
|
||||
OrgId: testOrgID,
|
||||
Title: "1 test dash",
|
||||
Data: simplejson.NewFromAny(map[string]interface{}{}),
|
||||
}}
|
||||
dashboard, err := sc.hs.DashboardService.SaveDashboard(context.Background(), cmd, false)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dashboard)
|
||||
t.Cleanup(func() {
|
||||
err := sc.hs.DashboardService.DeleteDashboard(context.Background(), dashboard.Id, dashboard.OrgId)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
dashboardAnnotation := &annotations.Item{Id: 1, DashboardId: dashboard.Id}
|
||||
organizationAnnotation := &annotations.Item{Id: 2, DashboardId: 0}
|
||||
|
||||
_ = sc.hs.annotationsRepo.Save(context.Background(), dashboardAnnotation)
|
||||
@@ -796,6 +824,30 @@ func TestAPI_MassDeleteAnnotations_AccessControl(t *testing.T) {
|
||||
method string
|
||||
}
|
||||
|
||||
origNewGuardian := guardian.New
|
||||
t.Cleanup(func() {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
|
||||
// Create a dashboard
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
sc.dashboardPermissionsService.On("SetPermissions", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string"), mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||
cmd := &dashboards.SaveDashboardDTO{
|
||||
OrgId: testOrgID,
|
||||
User: &user.SignedInUser{UserID: testUserID, OrgID: testOrgID},
|
||||
Dashboard: &models.Dashboard{
|
||||
OrgId: testOrgID,
|
||||
Title: "1 test dash",
|
||||
Data: simplejson.NewFromAny(map[string]interface{}{}),
|
||||
}}
|
||||
dashboard, err := sc.hs.DashboardService.SaveDashboard(context.Background(), cmd, false)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dashboard)
|
||||
t.Cleanup(func() {
|
||||
err := sc.hs.DashboardService.DeleteDashboard(context.Background(), dashboard.Id, dashboard.OrgId)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
@@ -834,7 +886,7 @@ func TestAPI_MassDeleteAnnotations_AccessControl(t *testing.T) {
|
||||
url: "/api/annotations/mass-delete",
|
||||
method: http.MethodPost,
|
||||
body: mockRequestBody(dtos.MassDeleteAnnotationsCmd{
|
||||
DashboardId: 1,
|
||||
DashboardId: dashboard.Id,
|
||||
PanelId: 1,
|
||||
}),
|
||||
},
|
||||
@@ -932,6 +984,13 @@ func setUpACL() {
|
||||
{Role: &editorRole, Permission: models.PERMISSION_EDIT},
|
||||
}
|
||||
}).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
|
||||
guardian.InitLegacyGuardian(store, dashSvc, teamSvc)
|
||||
}
|
||||
|
||||
@@ -305,9 +305,11 @@ type accessControlScenarioContext struct {
|
||||
// cfg is the setting provider
|
||||
cfg *setting.Cfg
|
||||
|
||||
dashboardsStore dashboards.Store
|
||||
teamService team.Service
|
||||
userService user.Service
|
||||
dashboardsStore dashboards.Store
|
||||
teamService team.Service
|
||||
userService user.Service
|
||||
folderPermissionsService *accesscontrolmock.MockPermissionsService
|
||||
dashboardPermissionsService *accesscontrolmock.MockPermissionsService
|
||||
}
|
||||
|
||||
func setAccessControlPermissions(acmock *accesscontrolmock.Mock, perms []accesscontrol.Permission, org int64) {
|
||||
@@ -417,6 +419,9 @@ func setupHTTPServerWithCfgDb(
|
||||
teamPermissionService, err := ossaccesscontrol.ProvideTeamPermissions(cfg, routeRegister, db, ac, license, acService, teamService, userSvc)
|
||||
require.NoError(t, err)
|
||||
|
||||
folderPermissionsService := accesscontrolmock.NewMockedPermissionsService()
|
||||
dashboardPermissionsService := accesscontrolmock.NewMockedPermissionsService()
|
||||
|
||||
// Create minimal HTTP Server
|
||||
hs := &HTTPServer{
|
||||
Cfg: cfg,
|
||||
@@ -432,7 +437,7 @@ func setupHTTPServerWithCfgDb(
|
||||
searchUsersService: searchusers.ProvideUsersService(filters.ProvideOSSSearchUserFilter(), usertest.NewUserServiceFake()),
|
||||
DashboardService: dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardsStore, nil, features,
|
||||
accesscontrolmock.NewMockedPermissionsService(), accesscontrolmock.NewMockedPermissionsService(), ac,
|
||||
folderPermissionsService, dashboardPermissionsService, ac,
|
||||
),
|
||||
preferenceService: preftest.NewPreferenceServiceFake(),
|
||||
userService: userSvc,
|
||||
@@ -469,15 +474,17 @@ func setupHTTPServerWithCfgDb(
|
||||
hs.RouteRegister.Register(m.Router)
|
||||
|
||||
return accessControlScenarioContext{
|
||||
server: m,
|
||||
initCtx: initCtx,
|
||||
hs: hs,
|
||||
acmock: acmock,
|
||||
db: db,
|
||||
cfg: cfg,
|
||||
dashboardsStore: dashboardsStore,
|
||||
teamService: teamService,
|
||||
userService: userSvc,
|
||||
server: m,
|
||||
initCtx: initCtx,
|
||||
hs: hs,
|
||||
acmock: acmock,
|
||||
db: db,
|
||||
cfg: cfg,
|
||||
dashboardsStore: dashboardsStore,
|
||||
teamService: teamService,
|
||||
userService: userSvc,
|
||||
dashboardPermissionsService: dashboardPermissionsService,
|
||||
folderPermissionsService: folderPermissionsService,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,11 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Error while loading dashboard, dashboard data is invalid", nil)
|
||||
}
|
||||
}
|
||||
guardian := guardian.New(c.Req.Context(), dash.Id, c.OrgID, c.SignedInUser)
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canView, err := guardian.CanView(); err != nil || !canView {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -308,13 +312,17 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response {
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
}
|
||||
guardian := guardian.New(c.Req.Context(), dash.Id, c.OrgID, c.SignedInUser)
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canDelete, err := guardian.CanDelete(); err != nil || !canDelete {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
// 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", "dashboard", dash.Id, "user", c.SignedInUser.UserID, "error", err)
|
||||
}
|
||||
@@ -630,32 +638,32 @@ func (hs *HTTPServer) GetDashboardVersions(c *models.ReqContext) response.Respon
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "dashboardId is invalid", err)
|
||||
}
|
||||
} else {
|
||||
q := models.GetDashboardQuery{
|
||||
OrgId: c.SignedInUser.OrgID,
|
||||
Uid: dashUID,
|
||||
}
|
||||
if err := hs.DashboardService.GetDashboard(c.Req.Context(), &q); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "failed to get dashboard by UID", err)
|
||||
}
|
||||
dashID = q.Result.Id
|
||||
}
|
||||
guardian := guardian.New(c.Req.Context(), dashID, c.OrgID, c.SignedInUser)
|
||||
|
||||
dash, rsp := hs.getDashboardHelper(c.Req.Context(), c.OrgID, dashID, dashUID)
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, 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.OrgID,
|
||||
DashboardID: dashID,
|
||||
DashboardUID: dashUID,
|
||||
DashboardID: dash.Id,
|
||||
DashboardUID: dash.Uid,
|
||||
Limit: c.QueryInt("limit"),
|
||||
Start: c.QueryInt("start"),
|
||||
}
|
||||
|
||||
res, err := hs.dashboardVersionService.List(c.Req.Context(), &query)
|
||||
if err != nil {
|
||||
return response.Error(404, fmt.Sprintf("No versions found for dashboardId %d", dashID), err)
|
||||
return response.Error(404, fmt.Sprintf("No versions found for dashboardId %d", dash.Id), err)
|
||||
}
|
||||
|
||||
for _, version := range res {
|
||||
@@ -708,23 +716,24 @@ func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Respons
|
||||
var err error
|
||||
dashUID := web.Params(c.Req)[":uid"]
|
||||
|
||||
var dash *models.Dashboard
|
||||
if dashUID == "" {
|
||||
dashID, err = strconv.ParseInt(web.Params(c.Req)[":dashboardId"], 10, 64)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "dashboardId is invalid", err)
|
||||
}
|
||||
} else {
|
||||
q := models.GetDashboardQuery{
|
||||
OrgId: c.SignedInUser.OrgID,
|
||||
Uid: dashUID,
|
||||
}
|
||||
if err := hs.DashboardService.GetDashboard(c.Req.Context(), &q); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "failed to get dashboard by UID", err)
|
||||
}
|
||||
dashID = q.Result.Id
|
||||
}
|
||||
|
||||
guardian := guardian.New(c.Req.Context(), dashID, c.OrgID, c.SignedInUser)
|
||||
dash, rsp := hs.getDashboardHelper(c.Req.Context(), c.OrgID, dashID, dashUID)
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
}
|
||||
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -732,13 +741,13 @@ func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Respons
|
||||
version, _ := strconv.ParseInt(web.Params(c.Req)[":id"], 10, 32)
|
||||
query := dashver.GetDashboardVersionQuery{
|
||||
OrgID: c.OrgID,
|
||||
DashboardID: dashID,
|
||||
DashboardID: dash.Id,
|
||||
Version: int(version),
|
||||
}
|
||||
|
||||
res, err := hs.dashboardVersionService.Get(c.Req.Context(), &query)
|
||||
if err != nil {
|
||||
return response.Error(500, fmt.Sprintf("Dashboard version %d not found for dashboardId %d", query.Version, dashID), err)
|
||||
return response.Error(500, fmt.Sprintf("Dashboard version %d not found for dashboardId %d", query.Version, dash.Id), err)
|
||||
}
|
||||
|
||||
creator := anonString
|
||||
@@ -843,13 +852,21 @@ func (hs *HTTPServer) CalculateDashboardDiff(c *models.ReqContext) response.Resp
|
||||
if err := web.Bind(c.Req, &apiOptions); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
guardianBase := guardian.New(c.Req.Context(), apiOptions.Base.DashboardId, c.OrgID, c.SignedInUser)
|
||||
guardianBase, err := guardian.New(c.Req.Context(), apiOptions.Base.DashboardId, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardianBase.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
if apiOptions.Base.DashboardId != apiOptions.New.DashboardId {
|
||||
guardianNew := guardian.New(c.Req.Context(), apiOptions.New.DashboardId, c.OrgID, c.SignedInUser)
|
||||
guardianNew, err := guardian.New(c.Req.Context(), apiOptions.New.DashboardId, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canSave, err := guardianNew.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -964,11 +981,11 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext) response.Res
|
||||
return rsp
|
||||
}
|
||||
|
||||
if dash != nil && dash.Id != 0 {
|
||||
dashID = dash.Id
|
||||
guardian, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
guardian := guardian.New(c.Req.Context(), dashID, c.OrgID, c.SignedInUser)
|
||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
@@ -56,12 +56,11 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.
|
||||
return rsp
|
||||
}
|
||||
|
||||
if dashID == 0 {
|
||||
dashID = dash.Id
|
||||
g, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), dashID, c.OrgID, c.SignedInUser)
|
||||
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -147,11 +146,11 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext) response.
|
||||
return rsp
|
||||
}
|
||||
|
||||
if dashUID != "" {
|
||||
dashID = dash.Id
|
||||
g, err := guardian.NewByDashboard(c.Req.Context(), dash, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), dashID, c.OrgID, c.SignedInUser)
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,13 @@ func TestDashboardPermissionAPIEndpoint(t *testing.T) {
|
||||
t.Run("Dashboard permissions test", func(t *testing.T) {
|
||||
settings := setting.NewCfg()
|
||||
dashboardStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardStore.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Return(nil, nil)
|
||||
dashboardStore.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil, nil)
|
||||
defer dashboardStore.AssertExpectations(t)
|
||||
|
||||
features := featuremgmt.WithFeatures()
|
||||
|
||||
@@ -342,7 +342,11 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res
|
||||
dashboardID := query.Result.Dashboard.Get("id").MustInt64()
|
||||
|
||||
if dashboardID != 0 {
|
||||
guardian := guardian.New(c.Req.Context(), dashboardID, c.OrgID, c.SignedInUser)
|
||||
guardian, err := guardian.New(c.Req.Context(), dashboardID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
canEdit, err := guardian.CanEdit()
|
||||
// check for permissions only if the dashboard is found
|
||||
if err != nil && !errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
|
||||
@@ -73,7 +73,15 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
|
||||
|
||||
teamSvc := &teamtest.FakeService{}
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil).Maybe()
|
||||
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*models.GetDashboardACLInfoListQuery")).Return(nil).Maybe()
|
||||
hs.DashboardService = dashSvc
|
||||
|
||||
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec()
|
||||
@@ -121,13 +129,28 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
|
||||
|
||||
loggedInUserScenarioWithRole(t, "Should be able to delete a snapshot when calling DELETE on", "DELETE",
|
||||
"/api/snapshots/12345", "/api/snapshots/:key", org.RoleEditor, func(sc *scenarioContext) {
|
||||
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
|
||||
var externalRequest *http.Request
|
||||
ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.WriteHeader(200)
|
||||
externalRequest = req
|
||||
})
|
||||
hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, ts.URL)}
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
OrgId: q.OrgId,
|
||||
}
|
||||
}).Return(nil).Maybe()
|
||||
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*models.GetDashboardACLInfoListQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardACLInfoListQuery)
|
||||
q.Result = []*models.DashboardACLInfoDTO{
|
||||
{Role: &viewerRole, Permission: models.PERMISSION_VIEW},
|
||||
{Role: &editorRole, Permission: models.PERMISSION_EDIT},
|
||||
}
|
||||
}).Return(nil)
|
||||
guardian.InitLegacyGuardian(sc.sqlStore, dashSvc, teamSvc)
|
||||
hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, ts.URL), DashboardService: dashSvc}
|
||||
sc.handlerFunc = hs.DeleteDashboardSnapshot
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec()
|
||||
|
||||
@@ -146,8 +169,9 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
|
||||
loggedInUserScenarioWithRole(t, "Should be able to delete a snapshot when calling DELETE on",
|
||||
"DELETE", "/api/snapshots/12345", "/api/snapshots/:key", org.RoleEditor, func(sc *scenarioContext) {
|
||||
d := setUpSnapshotTest(t, testUserID, "")
|
||||
hs := &HTTPServer{dashboardsnapshotsService: d}
|
||||
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
hs := &HTTPServer{dashboardsnapshotsService: d, DashboardService: dashSvc}
|
||||
sc.handlerFunc = hs.DeleteDashboardSnapshot
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec()
|
||||
|
||||
@@ -169,7 +193,9 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) {
|
||||
rw.WriteHeader(500)
|
||||
_, writeErr = rw.Write([]byte(`{"message":"Failed to get dashboard snapshot"}`))
|
||||
})
|
||||
hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, testUserID, ts.URL)}
|
||||
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, testUserID, ts.URL), DashboardService: dashSvc}
|
||||
sc.handlerFunc = hs.DeleteDashboardSnapshot
|
||||
sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec()
|
||||
|
||||
|
||||
@@ -808,6 +808,13 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
teamSvc := &teamtest.FakeService{}
|
||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
||||
dashSvc.On("GetDashboardACLInfoList", mock.Anything, mock.AnythingOfType("*models.GetDashboardACLInfoListQuery")).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
OrgId: q.OrgId,
|
||||
Id: q.Id,
|
||||
}
|
||||
}).Return(nil)
|
||||
guardian.InitLegacyGuardian(&sqlmock, dashSvc, teamSvc)
|
||||
}
|
||||
|
||||
@@ -1152,6 +1159,8 @@ func postDiffScenario(t *testing.T, desc string, url string, routePattern string
|
||||
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()),
|
||||
@@ -1163,6 +1172,7 @@ func postDiffScenario(t *testing.T, desc string, url string, routePattern string
|
||||
dashboardVersionService: fakeDashboardVersionService,
|
||||
Features: featuremgmt.WithFeatures(),
|
||||
Kinds: corekind.NewBase(nil),
|
||||
DashboardService: dashSvc,
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
|
||||
@@ -73,7 +73,11 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
g, err := guardian.NewByUID(c.Req.Context(), folder.UID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, folder))
|
||||
}
|
||||
|
||||
@@ -99,7 +103,10 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
g, err := guardian.NewByUID(c.Req.Context(), folder.UID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, folder))
|
||||
}
|
||||
|
||||
@@ -135,7 +142,11 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext) response.Response {
|
||||
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
g, err := guardian.NewByUID(c.Req.Context(), folder.UID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
// TODO set ParentUID if nested folders are enabled
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, folder))
|
||||
}
|
||||
@@ -190,7 +201,11 @@ 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)
|
||||
g, err := guardian.NewByUID(c.Req.Context(), result.UID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, hs.newToFolderDto(c, g, result))
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,10 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
g, err := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
|
||||
return apierrors.ToFolderErrorResponse(dashboards.ErrFolderAccessDenied)
|
||||
@@ -95,7 +98,11 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
g, err := guardian.New(c.Req.Context(), folder.ID, c.OrgID, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.Err(err)
|
||||
}
|
||||
|
||||
canAdmin, err := g.CanAdmin()
|
||||
if err != nil {
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
|
||||
@@ -240,6 +240,13 @@ func createFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
q := args.Get(1).(*models.GetDashboardACLInfoListQuery)
|
||||
q.Result = aclMockResp
|
||||
}).Return(nil)
|
||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
||||
q := args.Get(1).(*models.GetDashboardQuery)
|
||||
q.Result = &models.Dashboard{
|
||||
Id: q.Id,
|
||||
Uid: q.Uid,
|
||||
}
|
||||
}).Return(nil)
|
||||
store := mockstore.NewSQLStoreMock()
|
||||
guardian.InitLegacyGuardian(store, dashSvc, teamSvc)
|
||||
hs := HTTPServer{
|
||||
|
||||
Reference in New Issue
Block a user