grafana/pkg/tests/api/annotations/annotations_test.go
Jo 31f062cb49
Some checks failed
Actionlint / Lint GitHub Actions files (push) Has been cancelled
Backend Code Checks / Detect whether code changed (push) Has been cancelled
Backend Unit Tests / Detect whether code changed (push) Has been cancelled
CodeQL checks / Detect whether code changed (push) Has been cancelled
Deploy Storybook / Detect whether code changed (push) Has been cancelled
Lint Frontend / Detect whether code changed (push) Has been cancelled
Lint Frontend / Verify API clients (push) Has been cancelled
Lint Frontend / Verify API clients (enterprise) (push) Has been cancelled
golangci-lint / Detect whether code changed (push) Has been cancelled
Verify i18n / verify-i18n (push) Has been cancelled
Documentation / Build & Verify Docs (push) Has been cancelled
End-to-end tests / Detect whether code changed (push) Has been cancelled
Frontend tests / Detect whether code changed (push) Has been cancelled
Integration Tests / Detect whether code changed (push) Has been cancelled
publish-technical-documentation-next / sync (push) Has been cancelled
Reject GitHub secrets / reject-gh-secrets (push) Has been cancelled
Build Release Packages / setup (push) Has been cancelled
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Has been cancelled
Shellcheck / Shellcheck scripts (push) Has been cancelled
Run Storybook a11y tests / Detect whether code changed (push) Has been cancelled
Swagger generated code / Detect whether code changed (push) Has been cancelled
Dispatch sync to mirror / dispatch-job (push) Has been cancelled
Backend Code Checks / Validate Backend Configs (push) Has been cancelled
Backend Unit Tests / Grafana (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana (8/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (1/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (2/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (3/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (4/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (5/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (6/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (7/8) (push) Has been cancelled
Backend Unit Tests / Grafana Enterprise (8/8) (push) Has been cancelled
Backend Unit Tests / All backend unit tests complete (push) Has been cancelled
CodeQL checks / Analyze (push) Has been cancelled
Deploy Storybook / Deploy Storybook (push) Has been cancelled
Lint Frontend / Lint (push) Has been cancelled
Lint Frontend / Typecheck (push) Has been cancelled
Lint Frontend / Verify packed frontend packages (push) Has been cancelled
golangci-lint / go-fmt (push) Has been cancelled
golangci-lint / lint-go (push) Has been cancelled
End-to-end tests / Build & Package Grafana (push) Has been cancelled
End-to-end tests / Build E2E test runner (push) Has been cancelled
End-to-end tests / push-docker-image (push) Has been cancelled
End-to-end tests / dashboards-suite (old arch) (push) Has been cancelled
End-to-end tests / panels-suite (old arch) (push) Has been cancelled
End-to-end tests / smoke-tests-suite (old arch) (push) Has been cancelled
End-to-end tests / various-suite (old arch) (push) Has been cancelled
End-to-end tests / Verify Storybook (Playwright) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (1/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (2/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (3/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (4/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (5/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (6/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (7/8) (push) Has been cancelled
End-to-end tests / Playwright E2E tests (8/8) (push) Has been cancelled
End-to-end tests / run-azure-monitor-e2e (push) Has been cancelled
End-to-end tests / All Playwright tests complete (push) Has been cancelled
End-to-end tests / A11y test (push) Has been cancelled
End-to-end tests / Publish metrics (push) Has been cancelled
End-to-end tests / All E2E tests complete (push) Has been cancelled
Frontend tests / Unit tests (1 / 16) (push) Has been cancelled
Frontend tests / Unit tests (10 / 16) (push) Has been cancelled
Frontend tests / Unit tests (11 / 16) (push) Has been cancelled
Frontend tests / Unit tests (12 / 16) (push) Has been cancelled
Frontend tests / Unit tests (13 / 16) (push) Has been cancelled
Frontend tests / Unit tests (14 / 16) (push) Has been cancelled
Frontend tests / Unit tests (15 / 16) (push) Has been cancelled
Frontend tests / Unit tests (16 / 16) (push) Has been cancelled
Frontend tests / Unit tests (2 / 16) (push) Has been cancelled
Frontend tests / Unit tests (3 / 16) (push) Has been cancelled
Frontend tests / Unit tests (4 / 16) (push) Has been cancelled
Frontend tests / Unit tests (5 / 16) (push) Has been cancelled
Frontend tests / Unit tests (6 / 16) (push) Has been cancelled
Frontend tests / Unit tests (7 / 16) (push) Has been cancelled
Frontend tests / Unit tests (8 / 16) (push) Has been cancelled
Frontend tests / Unit tests (9 / 16) (push) Has been cancelled
Frontend tests / Decoupled plugin tests (push) Has been cancelled
Frontend tests / Packages unit tests (push) Has been cancelled
Frontend tests / All frontend unit tests complete (push) Has been cancelled
Frontend tests / Devenv frontend-service build (push) Has been cancelled
Integration Tests / Sqlite (1/4) (push) Has been cancelled
Integration Tests / Sqlite (2/4) (push) Has been cancelled
Integration Tests / Sqlite (3/4) (push) Has been cancelled
Integration Tests / Sqlite (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo (profiled) (push) Has been cancelled
Integration Tests / MySQL (1/16) (push) Has been cancelled
Integration Tests / MySQL (10/16) (push) Has been cancelled
Integration Tests / MySQL (11/16) (push) Has been cancelled
Integration Tests / MySQL (12/16) (push) Has been cancelled
Integration Tests / MySQL (13/16) (push) Has been cancelled
Integration Tests / MySQL (14/16) (push) Has been cancelled
Integration Tests / MySQL (15/16) (push) Has been cancelled
Integration Tests / MySQL (16/16) (push) Has been cancelled
Integration Tests / MySQL (2/16) (push) Has been cancelled
Integration Tests / MySQL (3/16) (push) Has been cancelled
Integration Tests / MySQL (4/16) (push) Has been cancelled
Integration Tests / MySQL (5/16) (push) Has been cancelled
Integration Tests / MySQL (6/16) (push) Has been cancelled
Integration Tests / MySQL (7/16) (push) Has been cancelled
Integration Tests / MySQL (8/16) (push) Has been cancelled
Integration Tests / MySQL (9/16) (push) Has been cancelled
Integration Tests / Postgres (1/16) (push) Has been cancelled
Integration Tests / Postgres (10/16) (push) Has been cancelled
Integration Tests / Postgres (11/16) (push) Has been cancelled
Integration Tests / Postgres (12/16) (push) Has been cancelled
Integration Tests / Postgres (13/16) (push) Has been cancelled
Integration Tests / Postgres (14/16) (push) Has been cancelled
Integration Tests / Postgres (15/16) (push) Has been cancelled
Integration Tests / Postgres (16/16) (push) Has been cancelled
Integration Tests / Postgres (2/16) (push) Has been cancelled
Integration Tests / Postgres (3/16) (push) Has been cancelled
Integration Tests / Postgres (4/16) (push) Has been cancelled
Integration Tests / Postgres (5/16) (push) Has been cancelled
Integration Tests / Postgres (6/16) (push) Has been cancelled
Integration Tests / Postgres (7/16) (push) Has been cancelled
Integration Tests / Postgres (8/16) (push) Has been cancelled
Integration Tests / Postgres (9/16) (push) Has been cancelled
Integration Tests / Sqlite Enterprise (1/4) (push) Has been cancelled
Integration Tests / Sqlite Enterprise (2/4) (push) Has been cancelled
Integration Tests / Sqlite Enterprise (3/4) (push) Has been cancelled
Integration Tests / Sqlite Enterprise (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo Enterprise (1/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo Enterprise (2/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo Enterprise (3/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo Enterprise (4/4) (push) Has been cancelled
Integration Tests / Sqlite Without CGo Enterprise (profiled) (push) Has been cancelled
Integration Tests / MySQL Enterprise (1/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (10/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (11/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (12/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (13/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (14/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (15/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (16/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (2/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (3/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (4/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (5/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (6/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (7/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (8/16) (push) Has been cancelled
Integration Tests / MySQL Enterprise (9/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (1/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (10/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (11/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (12/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (13/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (14/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (15/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (16/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (2/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (3/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (4/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (5/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (6/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (7/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (8/16) (push) Has been cancelled
Integration Tests / Postgres Enterprise (9/16) (push) Has been cancelled
Integration Tests / All backend integration tests complete (push) Has been cancelled
Build Release Packages / Dispatch grafana-enterprise build (push) Has been cancelled
Build Release Packages / / darwin-amd64 (push) Has been cancelled
Build Release Packages / / darwin-arm64 (push) Has been cancelled
Build Release Packages / / linux-amd64 (push) Has been cancelled
Build Release Packages / / linux-armv6 (push) Has been cancelled
Build Release Packages / / linux-armv7 (push) Has been cancelled
Build Release Packages / / linux-arm64 (push) Has been cancelled
Build Release Packages / / linux-s390x (push) Has been cancelled
Build Release Packages / / windows-amd64 (push) Has been cancelled
Build Release Packages / / windows-arm64 (push) Has been cancelled
Build Release Packages / Upload artifacts (push) Has been cancelled
Build Release Packages / publish-dockerhub (push) Has been cancelled
Build Release Packages / Dispatch publish NPM canaries (push) Has been cancelled
Build Release Packages / notify-pr (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (light theme) (push) Has been cancelled
Run Storybook a11y tests / Run Storybook a11y tests (dark theme) (push) Has been cancelled
Swagger generated code / Verify committed API specs match (push) Has been cancelled
RBAC: Remove annotationPermissionUpdate feature toggle (#117213)
* Remove fully rolled out ft annotationPermissionUpdate

* fix annot test and lint

* fix frontend tests

* fix integration test

* fix flaky test
2026-01-31 02:23:48 +00:00

437 lines
14 KiB
Go

package annotations
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/tests"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/grafana/grafana/pkg/tests/testsuite"
"github.com/grafana/grafana/pkg/util/testutil"
)
func TestMain(m *testing.M) {
testsuite.Run(m)
}
func TestIntegrationAnnotations(t *testing.T) {
testutil.SkipIntegrationTestInShortMode(t)
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
DisableAuthZClientCache: true,
DisableAnonymous: true,
})
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
noneUserID := tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
DefaultOrgRole: string(org.RoleNone),
Login: "noneuser",
Password: "noneuser",
IsAdmin: false,
OrgID: 1,
})
tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
DefaultOrgRole: string(org.RoleEditor),
Login: "editor",
Password: "editor",
IsAdmin: false,
OrgID: 1,
})
tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
DefaultOrgRole: string(org.RoleViewer),
Login: "viewer",
Password: "viewer",
IsAdmin: false,
OrgID: 1,
})
savedFolder := createFolder(t, grafanaListedAddr, "Test Folder")
dash1 := createDashboard(t, grafanaListedAddr, "Dashboard 1", savedFolder.ID, savedFolder.UID) // nolint:staticcheck
dash2 := createDashboard(t, grafanaListedAddr, "Dashboard 2", savedFolder.ID, savedFolder.UID) // nolint:staticcheck
createAnnotation(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
"dashboardId": dash1.ID,
"panelId": 1,
"text": "Dashboard 1 annotation",
"time": 1234567890000,
})
createAnnotation(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
"dashboardId": dash2.ID,
"panelId": 1,
"text": "Dashboard 2 annotation",
"time": 1234567890000,
})
createAnnotation(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
"text": "Organization annotation",
"time": 1234567890000,
})
t.Run("basic tests", func(t *testing.T) {
t.Run("should allow accessing annotations for specific dashboard", func(t *testing.T) {
url := fmt.Sprintf("http://admin:admin@%s/api/annotations?dashboardId=%d", grafanaListedAddr, dash1.ID)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 1)
})
t.Run("should allow accessing annotations for specific dashboard by UID", func(t *testing.T) {
url := fmt.Sprintf("http://admin:admin@%s/api/annotations?dashboardUID=%s", grafanaListedAddr, dash1.UID)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 1)
})
})
t.Run("access control tests", func(t *testing.T) {
viewPermissions := []map[string]interface{}{
{
"permission": 1,
"userId": noneUserID,
},
}
t.Run("should have no dashboards if missing annotation read permission on dashboards", func(t *testing.T) {
url := fmt.Sprintf("http://noneuser:noneuser@%s/api/annotations", grafanaListedAddr)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, resp.StatusCode, http.StatusForbidden)
err = resp.Body.Close()
require.NoError(t, err)
})
t.Run("should be able to see annotations for dashboards that user has access to", func(t *testing.T) {
setDashboardPermissions(t, grafanaListedAddr, dash1.UID, viewPermissions)
// should be able to get first one
url := fmt.Sprintf("http://noneuser:noneuser@%s/api/annotations?dashboardId=%d", grafanaListedAddr, dash1.ID)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
// cannot get the second one
url = fmt.Sprintf("http://noneuser:noneuser@%s/api/annotations?dashboardId=%d", grafanaListedAddr, dash2.ID)
resp, err = http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
})
t.Run("should inherit folder permissions", func(t *testing.T) {
setFolderPermissions(t, grafanaListedAddr, savedFolder.UID, viewPermissions)
url := fmt.Sprintf("http://noneuser:noneuser@%s/api/annotations", grafanaListedAddr)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 2)
})
t.Run("should allow admin to access all annotations", func(t *testing.T) {
url := fmt.Sprintf("http://admin:admin@%s/api/annotations", grafanaListedAddr)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 3)
})
dash3 := createDashboard(t, grafanaListedAddr, "Dashboard 3", 0, "")
createAnnotation(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{
"dashboardId": dash3.ID,
"panelId": 1,
"text": "Dashboard 3 annotation",
"time": 1234567890000,
})
t.Run("should allow editor to access org annotations and annotations for dashboards they have access to (dash3)", func(t *testing.T) {
url := fmt.Sprintf("http://editor:editor@%s/api/annotations", grafanaListedAddr)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 2)
})
t.Run("should allow viewer to access org annotations and annotations for dashboards they have access to (dash3)", func(t *testing.T) {
url := fmt.Sprintf("http://viewer:viewer@%s/api/annotations", grafanaListedAddr)
resp, err := http.Get(url) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
err = resp.Body.Close()
require.NoError(t, err)
var annotations []interface{}
err = json.Unmarshal(body, &annotations)
require.NoError(t, err)
assert.Len(t, annotations, 2)
})
t.Run("should allow editor to create org annotations", func(t *testing.T) {
annotationPayload := map[string]interface{}{
"text": "Test annotations",
"time": 1234567890000,
}
payloadBytes, err := json.Marshal(annotationPayload)
require.NoError(t, err)
url := fmt.Sprintf("http://editor:editor@%s/api/annotations", grafanaListedAddr)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
})
t.Run("should deny viewer from creating org annotations", func(t *testing.T) {
annotationPayload := map[string]interface{}{
"text": "Test annotation",
"time": 1234567890000,
}
payloadBytes, err := json.Marshal(annotationPayload)
require.NoError(t, err)
url := fmt.Sprintf("http://viewer:viewer@%s/api/annotations", grafanaListedAddr)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
})
t.Run("should allow editor to create dashboard annotations", func(t *testing.T) {
annotationPayload := map[string]interface{}{
"dashboardId": dash3.ID,
"panelId": 1,
"text": "Test annotations",
"time": 1234567890000,
}
payloadBytes, err := json.Marshal(annotationPayload)
require.NoError(t, err)
url := fmt.Sprintf("http://editor:editor@%s/api/annotations", grafanaListedAddr)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
})
t.Run("should deny viewer from creating dashboard annotations", func(t *testing.T) {
annotationPayload := map[string]interface{}{
"dashboardId": dash3.ID,
"panelId": 1,
"text": "Test annotation",
"time": 1234567890000,
}
payloadBytes, err := json.Marshal(annotationPayload)
require.NoError(t, err)
url := fmt.Sprintf("http://viewer:viewer@%s/api/annotations", grafanaListedAddr)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
})
})
}
func createAnnotation(t *testing.T, grafanaListedAddr string, username, password string, payload map[string]interface{}) {
t.Helper()
payloadBytes, err := json.Marshal(payload)
require.NoError(t, err)
url := fmt.Sprintf("http://%s:%s@%s/api/annotations", username, password, grafanaListedAddr)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
}
func setDashboardPermissions(t *testing.T, grafanaListedAddr string, dashboardUID string, permissions []map[string]interface{}) {
t.Helper()
payload := map[string]interface{}{
"items": permissions,
}
payloadBytes, err := json.Marshal(payload)
require.NoError(t, err)
url := fmt.Sprintf("http://admin:admin@%s/api/dashboards/uid/%s/permissions", grafanaListedAddr, dashboardUID)
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
}
func setFolderPermissions(t *testing.T, grafanaListedAddr string, folderUID string, permissions []map[string]interface{}) {
t.Helper()
payload := map[string]interface{}{
"items": permissions,
}
payloadBytes, err := json.Marshal(payload)
require.NoError(t, err)
url := fmt.Sprintf("http://admin:admin@%s/api/folders/%s/permissions", grafanaListedAddr, folderUID)
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
err = resp.Body.Close()
require.NoError(t, err)
}
func createFolder(t *testing.T, grafanaListedAddr string, title string) *dtos.Folder {
t.Helper()
buf1 := &bytes.Buffer{}
err := json.NewEncoder(buf1).Encode(folder.CreateFolderCommand{
Title: title,
})
require.NoError(t, err)
u := fmt.Sprintf("http://admin:admin@%s/api/folders", grafanaListedAddr)
// nolint:gosec
resp, err := http.Post(u, "application/json", buf1)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
var f *dtos.Folder
err = json.Unmarshal(b, &f)
require.NoError(t, err)
return f
}
func createDashboard(t *testing.T, grafanaListedAddr string, title string, folderID int64, folderUID string) *dashboards.Dashboard {
t.Helper()
buf := &bytes.Buffer{}
err := json.NewEncoder(buf).Encode(map[string]interface{}{
"dashboard": map[string]interface{}{
"title": title,
},
"folderId": folderID,
"folderUid": folderUID,
"overwrite": true,
})
require.NoError(t, err)
u := fmt.Sprintf("http://admin:admin@%s/api/dashboards/db", grafanaListedAddr)
// nolint:gosec
resp, err := http.Post(u, "application/json", buf)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
var saveResp struct {
Status string `json:"status"`
Slug string `json:"slug"`
Version int64 `json:"version"`
ID int64 `json:"id"`
UID string `json:"uid"`
URL string `json:"url"`
FolderUID string `json:"folderUid"`
}
err = json.Unmarshal(b, &saveResp)
require.NoError(t, err)
require.NotEmpty(t, saveResp.UID)
return &dashboards.Dashboard{
ID: saveResp.ID, // nolint:staticcheck
UID: saveResp.UID,
Slug: saveResp.Slug,
Version: int(saveResp.Version),
FolderUID: saveResp.FolderUID,
}
}