Library panels: Move to integration tests (#108737)
This commit is contained in:
@@ -216,80 +216,6 @@ func TestIntegration_GetLibraryPanelConnections(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithPanel(t, "When a user tries to get connections of library panel, dashboards in inaccessible folders should not be returned",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
accessibleFolder := createFolder(t, sc, "AccessibleFolder", sc.service.folderService)
|
||||
inaccessibleFolder := createFolder(t, sc, "InAccessibleFolder", sc.service.folderService)
|
||||
restrictedUser := user.SignedInUser{
|
||||
UserID: 2,
|
||||
Name: "Non-Admin User",
|
||||
Login: "non-admin-user",
|
||||
OrgID: sc.user.OrgID,
|
||||
OrgRole: org.RoleViewer,
|
||||
LastSeenAt: time.Now(),
|
||||
Permissions: map[int64]map[string][]string{
|
||||
sc.user.OrgID: {
|
||||
dashboards.ActionFoldersRead: {
|
||||
dashboards.ScopeFoldersProvider.GetResourceScopeUID(accessibleFolder.UID),
|
||||
},
|
||||
dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsProvider.GetResourceScopeUID("*")},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
command := getCreatePanelCommand(accessibleFolder.ID, accessibleFolder.UID, "Accessible Library Panel") // nolint:staticcheck
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
libraryElement := validateAndUnMarshalResponse(t, resp)
|
||||
|
||||
dashJSON := map[string]any{
|
||||
"panels": []any{
|
||||
map[string]any{
|
||||
"id": int64(1),
|
||||
"gridPos": map[string]any{
|
||||
"h": 6,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
},
|
||||
"libraryPanel": map[string]any{
|
||||
"uid": libraryElement.Result.UID,
|
||||
"name": libraryElement.Result.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
accessibleDash := dashboards.Dashboard{
|
||||
Title: "Accessible Dashboard",
|
||||
Data: simplejson.NewFromAny(dashJSON),
|
||||
}
|
||||
|
||||
// create the dashboard in the general folder, an accessible folder, and an inaccessible folder
|
||||
dashInGeneral := createDashboard(t, sc.sqlStore, restrictedUser, &accessibleDash, 0, "")
|
||||
err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{libraryElement.Result.UID}, dashInGeneral.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
dashInAccessibleFolder := createDashboard(t, sc.sqlStore, restrictedUser, &accessibleDash, 0, accessibleFolder.UID)
|
||||
err = sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{libraryElement.Result.UID}, dashInAccessibleFolder.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
dashInInaccessibleFolder := createDashboard(t, sc.sqlStore, restrictedUser, &accessibleDash, 0, inaccessibleFolder.UID)
|
||||
err = sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{libraryElement.Result.UID}, dashInInaccessibleFolder.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
sc.reqContext.SignedInUser = &restrictedUser
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": libraryElement.Result.UID})
|
||||
|
||||
// connections should return the general folder one and the accessible folder one
|
||||
connectionsResp := sc.service.getConnectionsHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalConnectionResponse(t, connectionsResp)
|
||||
require.Len(t, result.Result, 2)
|
||||
uids := []string{result.Result[0].ConnectionUID, result.Result[1].ConnectionUID}
|
||||
require.Contains(t, uids, dashInGeneral.UID)
|
||||
require.Contains(t, uids, dashInAccessibleFolder.UID)
|
||||
require.NotContains(t, uids, dashInInaccessibleFolder.UID)
|
||||
})
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to create a connection with an element that exists, but the original folder does not, it should still succeed",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
b, err := json.Marshal(map[string]string{"test": "test"})
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apiserver/rest"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/tests/apis"
|
||||
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||
)
|
||||
@@ -292,3 +293,145 @@ func deleteLibraryElement(t *testing.T, ctx TestContext, user apis.User, uid str
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestIntegrationLibraryPanelConnectionsWithFolderAccess(t *testing.T) {
|
||||
dualWriterModes := []rest.DualWriterMode{rest.Mode0, rest.Mode1, rest.Mode2, rest.Mode3, rest.Mode4, rest.Mode5}
|
||||
for _, dualWriterMode := range dualWriterModes {
|
||||
t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) {
|
||||
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
||||
DisableAnonymous: true,
|
||||
EnableFeatureToggles: []string{
|
||||
"unifiedStorageSearch",
|
||||
"kubernetesLibraryPanels",
|
||||
"kubernetesClientDashboardsFolders",
|
||||
},
|
||||
})
|
||||
ctx := createTestContext(t, helper, helper.Org1, dualWriterMode)
|
||||
|
||||
accessibleFolder, err := createFolder(t, ctx.Helper, ctx.AdminUser, "AccessibleFolder")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, accessibleFolder)
|
||||
|
||||
inaccessibleFolder, err := createFolder(t, ctx.Helper, ctx.AdminUser, "InAccessibleFolder")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, inaccessibleFolder)
|
||||
|
||||
setResourceUserPermission(t, ctx, ctx.AdminUser, false, accessibleFolder.UID, addUserPermission(t, nil, ctx.ViewerUser, ResourcePermissionLevelView))
|
||||
setResourceUserPermission(t, ctx, ctx.AdminUser, false, inaccessibleFolder.UID, []ResourcePermissionSetting{})
|
||||
|
||||
libraryElement := map[string]interface{}{
|
||||
"kind": 1,
|
||||
"name": "Accessible Library Panel",
|
||||
"folderUid": accessibleFolder.UID,
|
||||
"model": map[string]interface{}{
|
||||
"type": "text",
|
||||
"title": "Accessible Library Panel",
|
||||
},
|
||||
}
|
||||
libraryElementURL := "/api/library-elements"
|
||||
libraryElementData, err := postHelper(t, &ctx, libraryElementURL, libraryElement, ctx.AdminUser)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, libraryElementData)
|
||||
data := libraryElementData["result"].(map[string]interface{})
|
||||
uid := data["uid"].(string)
|
||||
require.NotEmpty(t, uid)
|
||||
|
||||
dashInGeneral := createDashboardObject(t, "Dashboard in General", "", 1)
|
||||
dashInGeneral.Object["spec"].(map[string]interface{})["panels"] = []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Library Panel",
|
||||
"type": "library-panel-ref",
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": uid,
|
||||
"name": "Accessible Library Panel",
|
||||
},
|
||||
},
|
||||
}
|
||||
adminClient := getResourceClient(t, ctx.Helper, ctx.AdminUser, getDashboardGVR())
|
||||
createdDashInGeneral, err := adminClient.Resource.Create(context.Background(), dashInGeneral, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, createdDashInGeneral)
|
||||
|
||||
dashInAccessibleFolder := createDashboardObject(t, "Dashboard in Accessible Folder", accessibleFolder.UID, 1)
|
||||
dashInAccessibleFolder.Object["spec"].(map[string]interface{})["panels"] = []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Library Panel",
|
||||
"type": "library-panel-ref",
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": uid,
|
||||
"name": "Accessible Library Panel",
|
||||
},
|
||||
},
|
||||
}
|
||||
createdDashInAccessible, err := adminClient.Resource.Create(context.Background(), dashInAccessibleFolder, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, createdDashInAccessible)
|
||||
|
||||
dashInInaccessibleFolder := createDashboardObject(t, "Dashboard in Inaccessible Folder", inaccessibleFolder.UID, 1)
|
||||
dashInInaccessibleFolder.Object["spec"].(map[string]interface{})["panels"] = []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Library Panel",
|
||||
"type": "library-panel-ref",
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": uid,
|
||||
"name": "Accessible Library Panel",
|
||||
},
|
||||
},
|
||||
}
|
||||
createdDashInInaccessible, err := adminClient.Resource.Create(context.Background(), dashInInaccessibleFolder, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, createdDashInInaccessible)
|
||||
|
||||
connectionsURL := fmt.Sprintf("/api/library-elements/%s/connections", uid)
|
||||
connectionsData, err := getDashboardViaHTTP(t, &ctx, connectionsURL, ctx.AdminUser)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, connectionsData)
|
||||
connections := connectionsData["result"].([]interface{})
|
||||
require.Len(t, connections, 3, "Admin should see all connections")
|
||||
connectionUIDs := make([]string, 0, len(connections))
|
||||
for _, conn := range connections {
|
||||
connMap := conn.(map[string]interface{})
|
||||
if connectionUID, ok := connMap["connectionUid"].(string); ok {
|
||||
connectionUIDs = append(connectionUIDs, connectionUID)
|
||||
}
|
||||
}
|
||||
generalDashUID := createdDashInGeneral.GetName()
|
||||
accessibleDashUID := createdDashInAccessible.GetName()
|
||||
inaccessibleDashUID := createdDashInInaccessible.GetName()
|
||||
require.Contains(t, connectionUIDs, generalDashUID, "Admin should see dashboard in general folder")
|
||||
require.Contains(t, connectionUIDs, accessibleDashUID, "Admin should see dashboard in accessible folder")
|
||||
require.Contains(t, connectionUIDs, inaccessibleDashUID, "Admin should see dashboard in inaccessible folder")
|
||||
|
||||
limitedUser := ctx.Helper.CreateUser("limited-user", "Org1", org.RoleViewer, nil)
|
||||
// can access accessibleFolder but not inaccessibleFolder
|
||||
setResourceUserPermission(t, ctx, ctx.AdminUser, false, accessibleFolder.UID, addUserPermission(t, nil, limitedUser, ResourcePermissionLevelView))
|
||||
setResourceUserPermission(t, ctx, ctx.AdminUser, false, inaccessibleFolder.UID, []ResourcePermissionSetting{})
|
||||
connectionsDataLimited, err := getDashboardViaHTTP(t, &ctx, connectionsURL, limitedUser)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, connectionsDataLimited)
|
||||
connectionsLimited := connectionsDataLimited["result"].([]interface{})
|
||||
require.Len(t, connectionsLimited, 2, "Limited user should only see connections to accessible dashboards")
|
||||
|
||||
connectionUIDsLimited := make([]string, 0, len(connectionsLimited))
|
||||
for _, conn := range connectionsLimited {
|
||||
connMap := conn.(map[string]interface{})
|
||||
if connectionUID, ok := connMap["connectionUid"].(string); ok {
|
||||
connectionUIDsLimited = append(connectionUIDsLimited, connectionUID)
|
||||
}
|
||||
}
|
||||
require.Contains(t, connectionUIDsLimited, generalDashUID, "Limited user should see dashboard in general folder")
|
||||
require.Contains(t, connectionUIDsLimited, accessibleDashUID, "Limited user should see dashboard in accessible folder")
|
||||
require.NotContains(t, connectionUIDsLimited, inaccessibleDashUID, "Limited user should NOT see dashboard in inaccessible folder")
|
||||
|
||||
err = adminClient.Resource.Delete(context.Background(), createdDashInGeneral.GetName(), v1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
err = adminClient.Resource.Delete(context.Background(), createdDashInAccessible.GetName(), v1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
err = adminClient.Resource.Delete(context.Background(), createdDashInInaccessible.GetName(), v1.DeleteOptions{})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user