mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
RBAC: Update library element tests to use RBAC (#66782)
* update library element tests to use RBAC * update bits of code to use RBAC * update library panel tests * linting * more linting * and more linting * PR feedback
This commit is contained in:
parent
4e10118c3a
commit
a37bf1ac2a
@ -250,9 +250,7 @@ func getLibraryElements(c context.Context, store db.DB, cfg *setting.Cfg, signed
|
|||||||
builder.Write(getFromLibraryElementDTOWithMeta(store.GetDialect()))
|
builder.Write(getFromLibraryElementDTOWithMeta(store.GetDialect()))
|
||||||
builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id <> 0")
|
builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id <> 0")
|
||||||
writeParamSelectorSQL(&builder, params...)
|
writeParamSelectorSQL(&builder, params...)
|
||||||
if signedInUser.OrgRole != org.RoleAdmin {
|
|
||||||
builder.WriteDashboardPermissionFilter(signedInUser, dashboards.PERMISSION_VIEW)
|
builder.WriteDashboardPermissionFilter(signedInUser, dashboards.PERMISSION_VIEW)
|
||||||
}
|
|
||||||
builder.Write(` OR dashboard.id=0`)
|
builder.Write(` OR dashboard.id=0`)
|
||||||
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElements); err != nil {
|
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElements); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -32,6 +32,7 @@ func (l *LibraryElementService) requireSupportedElementKind(kindAsInt int64) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Context, user *user.SignedInUser, folderID int64) error {
|
func (l *LibraryElementService) requireEditPermissionsOnFolder(ctx context.Context, user *user.SignedInUser, folderID int64) error {
|
||||||
|
// TODO remove these special cases and handle General folder case in access control guardian
|
||||||
if isGeneralFolder(folderID) && user.HasRole(org.RoleEditor) {
|
if isGeneralFolder(folderID) && user.HasRole(org.RoleEditor) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,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 existing folders, it should succeed and the result should be correct",
|
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to existing folders, it should succeed and the result should be correct",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
newFolder := createFolder(t, sc, "NewFolder")
|
||||||
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel2")
|
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel2")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
@ -591,7 +591,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 a nonexistent folders, it should succeed and the result should be correct",
|
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to a nonexistent folders, it should succeed and the result should be correct",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
newFolder := createFolder(t, sc, "NewFolder")
|
||||||
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel2")
|
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel2")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
@ -69,6 +69,8 @@ func TestGetLibraryElement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.Permissions[sc.reqContext.OrgID][dashboards.ActionFoldersRead] = []string{dashboards.ScopeFoldersAll}
|
||||||
|
|
||||||
// by uid
|
// by uid
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||||
resp := sc.service.getHandler(sc.reqContext)
|
resp := sc.service.getHandler(sc.reqContext)
|
||||||
@ -164,6 +166,8 @@ func TestGetLibraryElement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.Permissions[sc.reqContext.OrgID][dashboards.ActionFoldersRead] = []string{dashboards.ScopeFoldersAll}
|
||||||
|
|
||||||
// by uid
|
// by uid
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||||
resp := sc.service.getHandler(sc.reqContext)
|
resp := sc.service.getHandler(sc.reqContext)
|
||||||
|
@ -24,7 +24,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel that exists, it should succeed",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel that exists, it should succeed",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
newFolder := createFolder(t, sc, "NewFolder")
|
||||||
cmd := model.PatchLibraryElementCommand{
|
cmd := model.PatchLibraryElementCommand{
|
||||||
FolderID: newFolder.ID,
|
FolderID: newFolder.ID,
|
||||||
Name: "Panel - New name",
|
Name: "Panel - New name",
|
||||||
@ -89,7 +89,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with folder only, it should change folder successfully and return correct result",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel with folder only, it should change folder successfully and return correct result",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
newFolder := createFolder(t, sc, "NewFolder")
|
||||||
cmd := model.PatchLibraryElementCommand{
|
cmd := model.PatchLibraryElementCommand{
|
||||||
FolderID: newFolder.ID,
|
FolderID: newFolder.ID,
|
||||||
Kind: int64(model.PanelElement),
|
Kind: int64(model.PanelElement),
|
||||||
@ -325,7 +325,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
|||||||
|
|
||||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with a folder where a library panel with the same name already exists, it should fail",
|
scenarioWithPanel(t, "When an admin tries to patch a library panel with a folder where a library panel with the same name already exists, it should fail",
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
newFolder := createFolder(t, sc, "NewFolder")
|
||||||
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel")
|
command := getCreatePanelCommand(newFolder.ID, "Text - Library Panel")
|
||||||
sc.ctx.Req.Body = mockRequestBody(command)
|
sc.ctx.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
@ -3,6 +3,7 @@ package libraryelements
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
@ -14,122 +15,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/web"
|
"github.com/grafana/grafana/pkg/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLibraryElementPermissions(t *testing.T) {
|
func TestLibraryElementPermissionsGeneralFolder(t *testing.T) {
|
||||||
var defaultPermissions = []folderACLItem{}
|
|
||||||
var adminOnlyPermissions = []folderACLItem{{org.RoleAdmin, dashboards.PERMISSION_EDIT}}
|
|
||||||
var editorOnlyPermissions = []folderACLItem{{org.RoleEditor, dashboards.PERMISSION_EDIT}}
|
|
||||||
var editorAndViewerPermissions = []folderACLItem{{org.RoleEditor, dashboards.PERMISSION_EDIT}, {org.RoleViewer, dashboards.PERMISSION_EDIT}}
|
|
||||||
var viewerOnlyPermissions = []folderACLItem{{org.RoleViewer, dashboards.PERMISSION_EDIT}}
|
|
||||||
var everyonePermissions = []folderACLItem{{org.RoleAdmin, dashboards.PERMISSION_EDIT}, {org.RoleEditor, dashboards.PERMISSION_EDIT}, {org.RoleViewer, dashboards.PERMISSION_EDIT}}
|
|
||||||
var noPermissions = []folderACLItem{{org.RoleViewer, dashboards.PERMISSION_VIEW}}
|
|
||||||
var folderCases = [][]folderACLItem{
|
|
||||||
defaultPermissions,
|
|
||||||
adminOnlyPermissions,
|
|
||||||
editorOnlyPermissions,
|
|
||||||
editorAndViewerPermissions,
|
|
||||||
viewerOnlyPermissions,
|
|
||||||
everyonePermissions,
|
|
||||||
noPermissions,
|
|
||||||
}
|
|
||||||
var defaultDesc = "default permissions"
|
|
||||||
var adminOnlyDesc = "admin only permissions"
|
|
||||||
var editorOnlyDesc = "editor only permissions"
|
|
||||||
var editorAndViewerDesc = "editor and viewer permissions"
|
|
||||||
var viewerOnlyDesc = "viewer only permissions"
|
|
||||||
var everyoneDesc = "everyone has editor permissions"
|
|
||||||
var noDesc = "everyone has view permissions"
|
|
||||||
var accessCases = []struct {
|
|
||||||
role org.RoleType
|
|
||||||
items []folderACLItem
|
|
||||||
desc string
|
|
||||||
status int
|
|
||||||
}{
|
|
||||||
{org.RoleAdmin, defaultPermissions, defaultDesc, 200},
|
|
||||||
{org.RoleAdmin, adminOnlyPermissions, adminOnlyDesc, 200},
|
|
||||||
{org.RoleAdmin, editorOnlyPermissions, editorOnlyDesc, 200},
|
|
||||||
{org.RoleAdmin, editorAndViewerPermissions, editorAndViewerDesc, 200},
|
|
||||||
{org.RoleAdmin, viewerOnlyPermissions, viewerOnlyDesc, 200},
|
|
||||||
{org.RoleAdmin, everyonePermissions, everyoneDesc, 200},
|
|
||||||
{org.RoleAdmin, noPermissions, noDesc, 200},
|
|
||||||
|
|
||||||
{org.RoleEditor, defaultPermissions, defaultDesc, 200},
|
|
||||||
{org.RoleEditor, adminOnlyPermissions, adminOnlyDesc, 403},
|
|
||||||
{org.RoleEditor, editorOnlyPermissions, editorOnlyDesc, 200},
|
|
||||||
{org.RoleEditor, editorAndViewerPermissions, editorAndViewerDesc, 200},
|
|
||||||
{org.RoleEditor, viewerOnlyPermissions, viewerOnlyDesc, 403},
|
|
||||||
{org.RoleEditor, everyonePermissions, everyoneDesc, 200},
|
|
||||||
{org.RoleEditor, noPermissions, noDesc, 403},
|
|
||||||
|
|
||||||
{org.RoleViewer, defaultPermissions, defaultDesc, 403},
|
|
||||||
{org.RoleViewer, adminOnlyPermissions, adminOnlyDesc, 403},
|
|
||||||
{org.RoleViewer, editorOnlyPermissions, editorOnlyDesc, 403},
|
|
||||||
{org.RoleViewer, editorAndViewerPermissions, editorAndViewerDesc, 200},
|
|
||||||
{org.RoleViewer, viewerOnlyPermissions, viewerOnlyDesc, 200},
|
|
||||||
{org.RoleViewer, everyonePermissions, everyoneDesc, 200},
|
|
||||||
{org.RoleViewer, noPermissions, noDesc, 403},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range accessCases {
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to create a library panel in a folder with %s, it should return correct status", testCase.role, testCase.desc),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
require.Equal(t, testCase.status, resp.Status())
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to a folder with %s, it should return correct status", testCase.role, testCase.desc),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
fromFolder := createFolderWithACL(t, sc.sqlStore, "Everyone", sc.user, everyonePermissions)
|
|
||||||
command := getCreatePanelCommand(fromFolder.ID, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
cmd := model.PatchLibraryElementCommand{FolderID: toFolder.ID, Version: 1, Kind: int64(model.PanelElement)}
|
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp = sc.service.patchHandler(sc.reqContext)
|
|
||||||
require.Equal(t, testCase.status, resp.Status())
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it from a folder with %s, it should return correct status", testCase.role, testCase.desc),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
fromFolder := createFolderWithACL(t, sc.sqlStore, "Everyone", sc.user, testCase.items)
|
|
||||||
command := getCreatePanelCommand(fromFolder.ID, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
cmd := model.PatchLibraryElementCommand{FolderID: toFolder.ID, Version: 1, Kind: int64(model.PanelElement)}
|
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp = sc.service.patchHandler(sc.reqContext)
|
|
||||||
require.Equal(t, testCase.status, resp.Status())
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to delete a library panel in a folder with %s, it should return correct status", testCase.role, testCase.desc),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
|
||||||
cmd := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
|
||||||
resp = sc.service.deleteHandler(sc.reqContext)
|
|
||||||
require.Equal(t, testCase.status, resp.Status())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var generalFolderCases = []struct {
|
var generalFolderCases = []struct {
|
||||||
role org.RoleType
|
role org.RoleType
|
||||||
status int
|
status int
|
||||||
@ -152,7 +38,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
|||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to the General folder, it should return correct status", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to the General folder, it should return correct status", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
folder := createFolder(t, sc, "Folder")
|
||||||
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
@ -168,7 +54,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
|||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it from the General folder, it should return correct status", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it from the General folder, it should return correct status", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
folder := createFolder(t, sc, "Folder")
|
||||||
command := getCreatePanelCommand(0, "Library Panel Name")
|
command := getCreatePanelCommand(0, "Library Panel Name")
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
@ -194,79 +80,6 @@ func TestLibraryElementPermissions(t *testing.T) {
|
|||||||
resp = sc.service.deleteHandler(sc.reqContext)
|
resp = sc.service.deleteHandler(sc.reqContext)
|
||||||
require.Equal(t, testCase.status, resp.Status())
|
require.Equal(t, testCase.status, resp.Status())
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
var missingFolderCases = []struct {
|
|
||||||
role org.RoleType
|
|
||||||
}{
|
|
||||||
{org.RoleAdmin},
|
|
||||||
{org.RoleEditor},
|
|
||||||
{org.RoleViewer},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range missingFolderCases {
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to create a library panel in a folder that doesn't exist, it should fail", testCase.role),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
command := getCreatePanelCommand(-100, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
require.Equal(t, 404, resp.Status())
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to patch a library panel by moving it to a folder that doesn't exist, it should fail", testCase.role),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
|
||||||
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
cmd := model.PatchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(model.PanelElement)}
|
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp = sc.service.patchHandler(sc.reqContext)
|
|
||||||
require.Equal(t, 404, resp.Status())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var getCases = []struct {
|
|
||||||
role org.RoleType
|
|
||||||
statuses []int
|
|
||||||
}{
|
|
||||||
{org.RoleAdmin, []int{200, 200, 200, 200, 200, 200, 200}},
|
|
||||||
{org.RoleEditor, []int{200, 404, 200, 200, 200, 200, 200}},
|
|
||||||
{org.RoleViewer, []int{200, 404, 404, 200, 200, 200, 200}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range getCases {
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to get a library panel, it should return correct response", testCase.role),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
var results []libraryElement
|
|
||||||
for i, folderCase := range folderCases {
|
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, fmt.Sprintf("Folder%v", i), sc.user, folderCase)
|
|
||||||
cmd := getCreatePanelCommand(folder.ID, fmt.Sprintf("Library Panel in Folder%v", i))
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
|
||||||
result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar
|
|
||||||
result.Result.Meta.UpdatedBy.Name = userInDbName
|
|
||||||
result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar
|
|
||||||
result.Result.Meta.FolderName = folder.Title
|
|
||||||
result.Result.Meta.FolderUID = folder.UID
|
|
||||||
results = append(results, result.Result)
|
|
||||||
}
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
for i, result := range results {
|
|
||||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.UID})
|
|
||||||
resp := sc.service.getHandler(sc.reqContext)
|
|
||||||
require.Equal(t, testCase.statuses[i], resp.Status())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to get a library panel from General folder, it should return correct response", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to get a library panel from General folder, it should return correct response", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
@ -292,73 +105,6 @@ func TestLibraryElementPermissions(t *testing.T) {
|
|||||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
var getAllCases = []struct {
|
|
||||||
role org.RoleType
|
|
||||||
panels int
|
|
||||||
folderIndexes []int
|
|
||||||
}{
|
|
||||||
{org.RoleAdmin, 7, []int{0, 1, 2, 3, 4, 5, 6}},
|
|
||||||
{org.RoleEditor, 6, []int{0, 2, 3, 4, 5, 6}},
|
|
||||||
{org.RoleViewer, 5, []int{0, 3, 4, 5, 6}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range getAllCases {
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to get all library panels, it should return correct response", testCase.role),
|
|
||||||
func(t *testing.T, sc scenarioContext) {
|
|
||||||
var results []libraryElement
|
|
||||||
for i, folderCase := range folderCases {
|
|
||||||
folder := createFolderWithACL(t, sc.sqlStore, fmt.Sprintf("Folder%v", i), sc.user, folderCase)
|
|
||||||
cmd := getCreatePanelCommand(folder.ID, fmt.Sprintf("Library Panel in Folder%v", i))
|
|
||||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
|
||||||
resp := sc.service.createHandler(sc.reqContext)
|
|
||||||
result := validateAndUnMarshalResponse(t, resp)
|
|
||||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
|
||||||
result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar
|
|
||||||
result.Result.Meta.UpdatedBy.Name = userInDbName
|
|
||||||
result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar
|
|
||||||
result.Result.Meta.FolderName = folder.Title
|
|
||||||
result.Result.Meta.FolderUID = folder.UID
|
|
||||||
results = append(results, result.Result)
|
|
||||||
}
|
|
||||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
|
||||||
|
|
||||||
resp := sc.service.getAllHandler(sc.reqContext)
|
|
||||||
require.Equal(t, 200, resp.Status())
|
|
||||||
var actual libraryElementsSearch
|
|
||||||
err := json.Unmarshal(resp.Body(), &actual)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, testCase.panels, len(actual.Result.Elements))
|
|
||||||
for _, folderIndex := range testCase.folderIndexes {
|
|
||||||
var folderID = int64(folderIndex + 2) // testScenario creates one folder and general folder doesn't count
|
|
||||||
var foundExists = false
|
|
||||||
var foundResult libraryElement
|
|
||||||
var actualExists = false
|
|
||||||
var actualResult libraryElement
|
|
||||||
for _, result := range results {
|
|
||||||
if result.FolderID == folderID {
|
|
||||||
foundExists = true
|
|
||||||
foundResult = result
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require.Equal(t, foundExists, true)
|
|
||||||
|
|
||||||
for _, result := range actual.Result.Elements {
|
|
||||||
if result.FolderID == folderID {
|
|
||||||
actualExists = true
|
|
||||||
actualResult = result
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require.Equal(t, actualExists, true)
|
|
||||||
|
|
||||||
if diff := cmp.Diff(foundResult, actualResult, getCompareOptions()...); diff != "" {
|
|
||||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
testScenario(t, fmt.Sprintf("When %s tries to get all library panels from General folder, it should return correct response", testCase.role),
|
testScenario(t, fmt.Sprintf("When %s tries to get all library panels from General folder, it should return correct response", testCase.role),
|
||||||
func(t *testing.T, sc scenarioContext) {
|
func(t *testing.T, sc scenarioContext) {
|
||||||
@ -385,3 +131,300 @@ func TestLibraryElementPermissions(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementCreatePermissions(t *testing.T) {
|
||||||
|
var accessCases = []struct {
|
||||||
|
permissions map[string][]string
|
||||||
|
desc string
|
||||||
|
status int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "can create library elements when granted write access to the correct folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can create library elements when granted write access to all folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't create library elements when granted write access to the wrong folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't create library elements when granted read access to the right folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range accessCases {
|
||||||
|
testScenario(t, testCase.desc,
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
folder := createFolder(t, sc, "Folder")
|
||||||
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
|
1: testCase.permissions,
|
||||||
|
}
|
||||||
|
|
||||||
|
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
require.Equal(t, testCase.status, resp.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementPatchPermissions(t *testing.T) {
|
||||||
|
var accessCases = []struct {
|
||||||
|
permissions map[string][]string
|
||||||
|
desc string
|
||||||
|
status int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "can move library elements when granted write access to the source and destination folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("FromFolder"), dashboards.ScopeFoldersProvider.GetResourceScopeUID("ToFolder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can move library elements when granted write access to all folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't move library elements when granted write access only to the source folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("FromFolder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't move library elements when granted write access to the destination folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("ToFolder")},
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range accessCases {
|
||||||
|
testScenario(t, testCase.desc,
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
fromFolder := createFolder(t, sc, "FromFolder")
|
||||||
|
command := getCreatePanelCommand(fromFolder.ID, "Library Panel Name")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
|
||||||
|
toFolder := createFolder(t, sc, "ToFolder")
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
|
1: testCase.permissions,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := model.PatchLibraryElementCommand{FolderID: toFolder.ID, Version: 1, Kind: int64(model.PanelElement)}
|
||||||
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
|
resp = sc.service.patchHandler(sc.reqContext)
|
||||||
|
require.Equal(t, testCase.status, resp.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementDeletePermissions(t *testing.T) {
|
||||||
|
var accessCases = []struct {
|
||||||
|
permissions map[string][]string
|
||||||
|
desc string
|
||||||
|
status int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "can delete library elements when granted write access to the correct folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can delete library elements when granted write access to all folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't delete library elements when granted write access to the wrong folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't delete library elements when granted read access to the right folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Folder")},
|
||||||
|
},
|
||||||
|
status: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range accessCases {
|
||||||
|
testScenario(t, testCase.desc,
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
folder := createFolder(t, sc, "Folder")
|
||||||
|
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
|
1: testCase.permissions,
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||||
|
resp = sc.service.deleteHandler(sc.reqContext)
|
||||||
|
require.Equal(t, testCase.status, resp.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementsWithMissingFolders(t *testing.T) {
|
||||||
|
testScenario(t, "When a user tries to create a library panel in a folder that doesn't exist, it should fail",
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
command := getCreatePanelCommand(-100, "Library Panel Name")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
require.Equal(t, 404, resp.Status())
|
||||||
|
})
|
||||||
|
|
||||||
|
testScenario(t, "When a user tries to patch a library panel by moving it to a folder that doesn't exist, it should fail",
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
folder := createFolder(t, sc, "Folder")
|
||||||
|
command := getCreatePanelCommand(folder.ID, "Library Panel Name")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
|
||||||
|
cmd := model.PatchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(model.PanelElement)}
|
||||||
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
|
resp = sc.service.patchHandler(sc.reqContext)
|
||||||
|
require.Equal(t, 404, resp.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementsGetPermissions(t *testing.T) {
|
||||||
|
var getCases = []struct {
|
||||||
|
permissions map[string][]string
|
||||||
|
desc string
|
||||||
|
status int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "can get a library element when granted read access to all folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't list library element when granted read access to the wrong folder",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("Other_folder")},
|
||||||
|
},
|
||||||
|
status: http.StatusNotFound,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, testCase := range getCases {
|
||||||
|
testScenario(t, testCase.desc,
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
folder := createFolder(t, sc, "Folder")
|
||||||
|
cmd := getCreatePanelCommand(folder.ID, "Library Panel")
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
result.Result.Meta.CreatedBy.Name = userInDbName
|
||||||
|
result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar
|
||||||
|
result.Result.Meta.UpdatedBy.Name = userInDbName
|
||||||
|
result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar
|
||||||
|
result.Result.Meta.FolderName = folder.Title
|
||||||
|
result.Result.Meta.FolderUID = folder.UID
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.OrgRole = org.RoleViewer
|
||||||
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
|
1: testCase.permissions,
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||||
|
resp = sc.service.getHandler(sc.reqContext)
|
||||||
|
require.Equal(t, testCase.status, resp.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLibraryElementsGetAllPermissions(t *testing.T) {
|
||||||
|
var getCases = []struct {
|
||||||
|
permissions map[string][]string
|
||||||
|
desc string
|
||||||
|
status int
|
||||||
|
expectedResultCount int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "can get all library elements when granted read access to all folders",
|
||||||
|
permissions: map[string][]string{
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceAllScope()},
|
||||||
|
},
|
||||||
|
expectedResultCount: 2,
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "can't get any library element when doesn't have access to any folders",
|
||||||
|
permissions: map[string][]string{},
|
||||||
|
expectedResultCount: 0,
|
||||||
|
status: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, testCase := range getCases {
|
||||||
|
testScenario(t, testCase.desc,
|
||||||
|
func(t *testing.T, sc scenarioContext) {
|
||||||
|
for i := 1; i <= 2; i++ {
|
||||||
|
folder := createFolder(t, sc, fmt.Sprintf("Folder%d", i))
|
||||||
|
cmd := getCreatePanelCommand(folder.ID, fmt.Sprintf("Library Panel %d", i))
|
||||||
|
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||||
|
resp := sc.service.createHandler(sc.reqContext)
|
||||||
|
result := validateAndUnMarshalResponse(t, resp)
|
||||||
|
result.Result.Meta.FolderUID = folder.UID
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.reqContext.SignedInUser.OrgRole = org.RoleViewer
|
||||||
|
sc.reqContext.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||||
|
1: testCase.permissions,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := sc.service.getAllHandler(sc.reqContext)
|
||||||
|
require.Equal(t, 200, resp.Status())
|
||||||
|
var actual libraryElementsSearch
|
||||||
|
err := json.Unmarshal(resp.Body(), &actual)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, testCase.expectedResultCount, len(actual.Result.Elements))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/api/response"
|
"github.com/grafana/grafana/pkg/api/response"
|
||||||
@ -17,9 +18,11 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||||
"github.com/grafana/grafana/pkg/services/alerting"
|
"github.com/grafana/grafana/pkg/services/alerting"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
@ -37,7 +40,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||||
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/team/teamtest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
@ -268,11 +270,6 @@ type scenarioContext struct {
|
|||||||
sqlStore db.DB
|
sqlStore db.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type folderACLItem struct {
|
|
||||||
roleType org.RoleType
|
|
||||||
permission dashboards.PermissionType
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash *dashboards.Dashboard, folderID int64) *dashboards.Dashboard {
|
func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash *dashboards.Dashboard, folderID int64) *dashboards.Dashboard {
|
||||||
dash.FolderID = folderID
|
dash.FolderID = folderID
|
||||||
dashItem := &dashboards.SaveDashboardDTO{
|
dashItem := &dashboards.SaveDashboardDTO{
|
||||||
@ -284,16 +281,16 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
|
||||||
features := featuremgmt.WithFeatures()
|
features := featuremgmt.WithFeatures()
|
||||||
cfg.IsFeatureToggleEnabled = features.IsEnabled
|
cfg.IsFeatureToggleEnabled = features.IsEnabled
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dashAlertExtractor := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
dashAlertExtractor := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
||||||
ac := acmock.New()
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
folderPermissions := acmock.NewMockedPermissionsService()
|
folderPermissions := acmock.NewMockedPermissionsService()
|
||||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
|
dashboardPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashboardStore, folderStore, dashAlertExtractor,
|
cfg, dashboardStore, folderStore, dashAlertExtractor,
|
||||||
@ -307,57 +304,34 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash
|
|||||||
return dashboard
|
return dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user user.SignedInUser,
|
func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder {
|
||||||
items []folderACLItem) *folder.Folder {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
|
||||||
features := featuremgmt.WithFeatures()
|
features := featuremgmt.WithFeatures()
|
||||||
cfg.IsFeatureToggleEnabled = features.IsEnabled
|
cfg.IsFeatureToggleEnabled = features.IsEnabled
|
||||||
ac := acmock.New()
|
ac := actest.FakeAccessControl{}
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sc.sqlStore, cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
||||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
||||||
t.Logf("Creating folder with title and UID %q", title)
|
t.Logf("Creating folder with title and UID %q", title)
|
||||||
ctx := appcontext.WithUser(context.Background(), &user)
|
ctx := appcontext.WithUser(context.Background(), &sc.user)
|
||||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
||||||
OrgID: user.OrgID, Title: title, UID: title, SignedInUser: &user,
|
OrgID: sc.user.OrgID, Title: title, UID: title, SignedInUser: &sc.user,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
updateFolderACL(t, dashboardStore, folder.ID, items)
|
// Set user permissions on the newly created folder so that they can interact with library elements stored in it
|
||||||
|
sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionFoldersWrite] = append(sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionFoldersWrite], dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.UID))
|
||||||
|
sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionFoldersRead] = append(sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionFoldersRead], dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.UID))
|
||||||
|
sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionDashboardsCreate] = append(sc.reqContext.SignedInUser.Permissions[sc.user.OrgID][dashboards.ActionDashboardsCreate], dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder.UID))
|
||||||
|
|
||||||
return folder
|
return folder
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFolderACL(t *testing.T, dashboardStore dashboards.Store, folderID int64, items []folderACLItem) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var aclItems []*dashboards.DashboardACL
|
|
||||||
for _, item := range items {
|
|
||||||
role := item.roleType
|
|
||||||
permission := item.permission
|
|
||||||
aclItems = append(aclItems, &dashboards.DashboardACL{
|
|
||||||
DashboardID: folderID,
|
|
||||||
Role: &role,
|
|
||||||
Permission: permission,
|
|
||||||
Created: time.Now(),
|
|
||||||
Updated: time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
err := dashboardStore.UpdateDashboardACL(context.Background(), folderID, aclItems)
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateAndUnMarshalResponse(t *testing.T, resp response.Response) libraryElementResult {
|
func validateAndUnMarshalResponse(t *testing.T, resp response.Response) libraryElementResult {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
@ -392,8 +366,23 @@ func validateAndUnMarshalArrayResponse(t *testing.T, resp response.Response) lib
|
|||||||
|
|
||||||
func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
|
func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
store := dbtest.NewFakeDB()
|
|
||||||
guardian.InitLegacyGuardian(setting.NewCfg(), store, &dashboards.FakeDashboardService{}, &teamtest.FakeService{})
|
sqlStore := db.InitTestDB(t)
|
||||||
|
ac := actest.FakeAccessControl{}
|
||||||
|
quotaService := quotatest.New(false, nil)
|
||||||
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||||
|
require.NoError(t, err)
|
||||||
|
features := featuremgmt.WithFeatures()
|
||||||
|
folderPermissions := acmock.NewMockedPermissionsService()
|
||||||
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
|
dashboardService, svcErr := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
|
sqlStore.Cfg, dashboardStore, folderStore, nil,
|
||||||
|
features, folderPermissions, dashboardPermissions, ac,
|
||||||
|
foldertest.NewFakeService(),
|
||||||
|
)
|
||||||
|
require.NoError(t, svcErr)
|
||||||
|
guardian.InitAccessControlGuardian(sqlStore.Cfg, sqlStore, ac, folderPermissions, dashboardPermissions, dashboardService)
|
||||||
|
|
||||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
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")
|
||||||
@ -421,6 +410,10 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
OrgRole: role,
|
OrgRole: role,
|
||||||
LastSeenAt: time.Now(),
|
LastSeenAt: time.Now(),
|
||||||
|
// Allow user to create folders
|
||||||
|
Permissions: map[int64]map[string][]string{
|
||||||
|
1: {dashboards.ActionFoldersCreate: {}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
req := &http.Request{
|
req := &http.Request{
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
@ -436,21 +429,21 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
features := featuremgmt.WithFeatures()
|
features := featuremgmt.WithFeatures()
|
||||||
ac := acmock.New().WithDisabled()
|
ac := acimpl.ProvideAccessControl(sqlStore.Cfg)
|
||||||
// TODO: Update tests to work with rbac
|
|
||||||
sqlStore.Cfg.RBACEnabled = false
|
|
||||||
folderPermissions := acmock.NewMockedPermissionsService()
|
folderPermissions := acmock.NewMockedPermissionsService()
|
||||||
|
folderPermissions.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
dashboardService, err := dashboardservice.ProvideDashboardServiceImpl(
|
dashService, dashSvcErr := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
sqlStore.Cfg, dashboardStore, folderStore, nil,
|
sqlStore.Cfg, dashboardStore, folderStore, nil,
|
||||||
features, folderPermissions, dashboardPermissions, ac,
|
features, folderPermissions, dashboardPermissions, ac,
|
||||||
foldertest.NewFakeService(),
|
foldertest.NewFakeService(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, dashSvcErr)
|
||||||
guardian.InitLegacyGuardian(sqlStore.Cfg, sqlStore, dashboardService, &teamtest.FakeService{})
|
guardian.InitAccessControlGuardian(sqlStore.Cfg, sqlStore, ac, folderPermissions, dashboardPermissions, dashService)
|
||||||
service := LibraryElementService{
|
service := LibraryElementService{
|
||||||
Cfg: sqlStore.Cfg,
|
Cfg: sqlStore.Cfg,
|
||||||
|
features: featuremgmt.WithFeatures(),
|
||||||
SQLStore: sqlStore,
|
SQLStore: sqlStore,
|
||||||
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardStore, folderStore, nil, features),
|
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardStore, folderStore, nil, features),
|
||||||
}
|
}
|
||||||
@ -481,7 +474,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.folder = createFolderWithACL(t, sc.sqlStore, "ScenarioFolder", sc.user, []folderACLItem{})
|
sc.folder = createFolder(t, sc, "ScenarioFolder")
|
||||||
|
|
||||||
fn(t, sc)
|
fn(t, sc)
|
||||||
})
|
})
|
||||||
|
@ -15,10 +15,11 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/appcontext"
|
"github.com/grafana/grafana/pkg/infra/appcontext"
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/db/dbtest"
|
|
||||||
"github.com/grafana/grafana/pkg/infra/slugify"
|
"github.com/grafana/grafana/pkg/infra/slugify"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
"github.com/grafana/grafana/pkg/kinds/librarypanel"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
|
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||||
"github.com/grafana/grafana/pkg/services/alerting"
|
"github.com/grafana/grafana/pkg/services/alerting"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
@ -36,7 +37,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||||
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
|
||||||
"github.com/grafana/grafana/pkg/services/team/teamtest"
|
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
@ -609,11 +609,6 @@ type scenarioContext struct {
|
|||||||
sqlStore db.DB
|
sqlStore db.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type folderACLItem struct {
|
|
||||||
roleType org.RoleType
|
|
||||||
permission dashboards.PermissionType
|
|
||||||
}
|
|
||||||
|
|
||||||
func toLibraryElement(t *testing.T, res model.LibraryElementDTO) libraryElement {
|
func toLibraryElement(t *testing.T, res model.LibraryElementDTO) libraryElement {
|
||||||
var libraryElementModel = libraryElementModel{}
|
var libraryElementModel = libraryElementModel{}
|
||||||
err := json.Unmarshal(res.Model, &libraryElementModel)
|
err := json.Unmarshal(res.Model, &libraryElementModel)
|
||||||
@ -699,17 +694,18 @@ func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
|
||||||
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
||||||
ac := acmock.New()
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
|
dashPermissionService := acmock.NewMockedPermissionsService()
|
||||||
|
dashPermissionService.On("SetPermissions", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]accesscontrol.ResourcePermission{}, nil)
|
||||||
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
service, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
cfg, dashboardStore, folderStore, dashAlertService,
|
cfg, dashboardStore, folderStore, dashAlertService,
|
||||||
featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), acmock.NewMockedPermissionsService(), ac,
|
featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), dashPermissionService, ac,
|
||||||
foldertest.NewFakeService(),
|
foldertest.NewFakeService(),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -719,68 +715,28 @@ func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash
|
|||||||
return dashboard
|
return dashboard
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user *user.SignedInUser,
|
func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder {
|
||||||
items []folderACLItem) *folder.Folder {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
ac := acmock.New()
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
cfg := setting.NewCfg()
|
cfg := setting.NewCfg()
|
||||||
cfg.RBACEnabled = false
|
|
||||||
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
||||||
features := featuremgmt.WithFeatures()
|
features := featuremgmt.WithFeatures()
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sc.sqlStore, cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore)
|
||||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
||||||
|
|
||||||
t.Logf("Creating folder with title and UID %q", title)
|
t.Logf("Creating folder with title and UID %q", title)
|
||||||
ctx := appcontext.WithUser(context.Background(), user)
|
ctx := appcontext.WithUser(context.Background(), sc.user)
|
||||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{OrgID: user.OrgID, Title: title, UID: title, SignedInUser: user})
|
folder, err := s.Create(ctx, &folder.CreateFolderCommand{OrgID: sc.user.OrgID, Title: title, UID: title, SignedInUser: sc.user})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
updateFolderACL(t, dashboardStore, folder.ID, items)
|
|
||||||
|
|
||||||
return folder
|
return folder
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFolderACL(t *testing.T, dashboardStore dashboards.Store, folderID int64, items []folderACLItem) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if len(items) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var aclItems []*dashboards.DashboardACL
|
|
||||||
for _, item := range items {
|
|
||||||
role := item.roleType
|
|
||||||
permission := item.permission
|
|
||||||
aclItems = append(aclItems, &dashboards.DashboardACL{
|
|
||||||
DashboardID: folderID,
|
|
||||||
Role: &role,
|
|
||||||
Permission: permission,
|
|
||||||
Created: time.Now(),
|
|
||||||
Updated: time.Now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
err := dashboardStore.UpdateDashboardACL(context.Background(), folderID, aclItems)
|
|
||||||
require.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
|
func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, sc scenarioContext)) {
|
||||||
store := dbtest.NewFakeDB()
|
|
||||||
|
|
||||||
dashSvc := dashboards.NewFakeDashboardService(t)
|
|
||||||
var result *dashboards.Dashboard
|
|
||||||
dashSvc.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Run(func(args mock.Arguments) {
|
|
||||||
q := args.Get(1).(*dashboards.GetDashboardQuery)
|
|
||||||
result = &dashboards.Dashboard{
|
|
||||||
ID: q.ID,
|
|
||||||
UID: q.UID,
|
|
||||||
}
|
|
||||||
}).Return(result, nil)
|
|
||||||
guardian.InitLegacyGuardian(setting.NewCfg(), store, dashSvc, &teamtest.FakeService{})
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||||
@ -829,19 +785,28 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
t.Run(desc, func(t *testing.T) {
|
t.Run(desc, func(t *testing.T) {
|
||||||
cfg := setting.NewCfg()
|
|
||||||
cfg.RBACEnabled = false
|
|
||||||
orgID := int64(1)
|
orgID := int64(1)
|
||||||
role := org.RoleAdmin
|
role := org.RoleAdmin
|
||||||
sqlStore, cfg := db.InitTestDBwithCfg(t)
|
sqlStore, cfg := db.InitTestDBwithCfg(t)
|
||||||
quotaService := quotatest.New(false, nil)
|
quotaService := quotatest.New(false, nil)
|
||||||
|
|
||||||
|
ac := actest.FakeAccessControl{ExpectedEvaluate: true}
|
||||||
|
dashStore := &dashboards.FakeDashboardStore{}
|
||||||
|
dashStore.On("GetDashboard", mock.Anything, mock.Anything).Return(&dashboards.Dashboard{ID: 1}, nil)
|
||||||
|
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
||||||
|
dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
||||||
|
dashPermissionService := acmock.NewMockedPermissionsService()
|
||||||
|
dashService, err := dashboardservice.ProvideDashboardServiceImpl(
|
||||||
|
setting.NewCfg(), dashStore, folderStore, dashAlertService,
|
||||||
|
featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), dashPermissionService, ac,
|
||||||
|
foldertest.NewFakeService(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
guardian.InitAccessControlGuardian(setting.NewCfg(), sqlStore, ac, acmock.NewMockedPermissionsService(), acmock.NewMockedPermissionsService(), dashService)
|
||||||
|
|
||||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
features := featuremgmt.WithFeatures()
|
features := featuremgmt.WithFeatures()
|
||||||
ac := acmock.New()
|
|
||||||
|
|
||||||
folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore)
|
|
||||||
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, folderStore, nil, features)
|
||||||
|
|
||||||
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, featuremgmt.WithFeatures())
|
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, featuremgmt.WithFeatures())
|
||||||
@ -859,6 +824,12 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
OrgID: orgID,
|
OrgID: orgID,
|
||||||
OrgRole: role,
|
OrgRole: role,
|
||||||
LastSeenAt: time.Now(),
|
LastSeenAt: time.Now(),
|
||||||
|
// Allow the user to create folders
|
||||||
|
Permissions: map[int64]map[string][]string{
|
||||||
|
orgID: {
|
||||||
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersAll},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliberate difference between signed in user and user in db to make it crystal clear
|
// deliberate difference between signed in user and user in db to make it crystal clear
|
||||||
@ -884,7 +855,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
|||||||
sqlStore: sqlStore,
|
sqlStore: sqlStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
foldr := createFolderWithACL(t, sc.sqlStore, "ScenarioFolder", sc.user, []folderACLItem{})
|
foldr := createFolder(t, sc, "ScenarioFolder")
|
||||||
sc.folder = &folder.Folder{
|
sc.folder = &folder.Folder{
|
||||||
ID: foldr.ID,
|
ID: foldr.ID,
|
||||||
UID: foldr.UID,
|
UID: foldr.UID,
|
||||||
|
Loading…
Reference in New Issue
Block a user