From bb7efb655a026029f7a34cc0416c1951d9ebe12d Mon Sep 17 00:00:00 2001 From: Dominik Broj Date: Mon, 26 Aug 2024 07:39:07 +0200 Subject: [PATCH] chore: more adjustments to irm monorepo (#4915) # What this PR does - remove hardcoded plugin id so it can run from IRM monorepo context - minor e2e tests tweaks ## Which issue(s) this PR closes Related to https://github.com/grafana/irm/issues/41 ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --- grafana-plugin/.gitignore | 5 +++- .../e2e-tests/users/usersActions.test.ts | 24 +++++++++---------- .../e2e-tests/utils/integrations.ts | 1 + grafana-plugin/pkg/plugin/permissions.go | 4 ++-- grafana-plugin/pkg/plugin/settings.go | 11 ++++++++- .../src/network/grafana-api/http-client.ts | 4 +++- grafana-plugin/src/utils/consts.ts | 3 +-- grafana-plugin/src/utils/utils.ts | 4 ++-- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/grafana-plugin/.gitignore b/grafana-plugin/.gitignore index a833c0d1b7..e6fd455302 100644 --- a/grafana-plugin/.gitignore +++ b/grafana-plugin/.gitignore @@ -21,4 +21,7 @@ grafana-plugin.yml # Jest test report jest_html_reporters.html -jest-html-reporters* \ No newline at end of file +jest-html-reporters* + +.turbo +tsconfig.tsbuildinfo \ No newline at end of file diff --git a/grafana-plugin/e2e-tests/users/usersActions.test.ts b/grafana-plugin/e2e-tests/users/usersActions.test.ts index d72fd70f92..13e46fd08e 100644 --- a/grafana-plugin/e2e-tests/users/usersActions.test.ts +++ b/grafana-plugin/e2e-tests/users/usersActions.test.ts @@ -4,18 +4,6 @@ import { goToOnCallPage } from '../utils/navigation'; import { verifyThatUserCanViewOtherUsers, accessProfileTabs } from '../utils/users'; test.describe('Users screen actions', () => { - test("Admin is allowed to edit other users' profile", async ({ adminRolePage: { page } }) => { - await goToOnCallPage(page, 'users'); - const editableUsers = page.getByTestId('users-table').getByRole('button', { name: 'Edit', disabled: false }); - await editableUsers.first().waitFor(); - const editableUsersCount = await editableUsers.count(); - expect(editableUsersCount).toBeGreaterThan(1); - }); - - test('Admin is allowed to view the list of users', async ({ adminRolePage: { page } }) => { - await verifyThatUserCanViewOtherUsers(page); - }); - test('Viewer is not allowed to view the list of users', async ({ viewerRolePage: { page } }) => { await verifyThatUserCanViewOtherUsers(page, false); }); @@ -66,6 +54,18 @@ test.describe('Users screen actions', () => { expect(usersCountWithDisabledEdit).toBeGreaterThan(1); }); + test("Admin is allowed to edit other users' profile", async ({ adminRolePage: { page } }) => { + await goToOnCallPage(page, 'users'); + const editableUsers = page.getByTestId('users-table').getByRole('button', { name: 'Edit', disabled: false }); + await editableUsers.first().waitFor(); + const editableUsersCount = await editableUsers.count(); + expect(editableUsersCount).toBeGreaterThan(1); + }); + + test('Admin is allowed to view the list of users', async ({ adminRolePage: { page } }) => { + await verifyThatUserCanViewOtherUsers(page); + }); + test('Search updates the table view', async ({ adminRolePage }) => { const { page, userName } = adminRolePage; await goToOnCallPage(page, 'users'); diff --git a/grafana-plugin/e2e-tests/utils/integrations.ts b/grafana-plugin/e2e-tests/utils/integrations.ts index 68884d449a..1a3e7a203c 100644 --- a/grafana-plugin/e2e-tests/utils/integrations.ts +++ b/grafana-plugin/e2e-tests/utils/integrations.ts @@ -47,6 +47,7 @@ export const createIntegration = async ({ await searchIntegrationAndAssertItsPresence({ page, integrationName }); await page.getByRole('link', { name: integrationName }).click(); + await page.waitForLoadState('networkidle'); }; export const assignEscalationChainToIntegration = async (page: Page, escalationChainName: string): Promise => { diff --git a/grafana-plugin/pkg/plugin/permissions.go b/grafana-plugin/pkg/plugin/permissions.go index 2b5813af2e..88515672bd 100644 --- a/grafana-plugin/pkg/plugin/permissions.go +++ b/grafana-plugin/pkg/plugin/permissions.go @@ -47,7 +47,7 @@ func (a *App) GetPermissions(settings *OnCallPluginSettings, onCallUser *OnCallU if res.StatusCode == 200 { var filtered []OnCallPermission for _, permission := range permissions { - if strings.HasPrefix(permission.Action, "grafana-oncall-app") { + if strings.HasPrefix(permission.Action, settings.PluginID) { filtered = append(filtered, permission) } } @@ -65,7 +65,7 @@ func (a *App) GetAllPermissions(settings *OnCallPluginSettings) (map[string]map[ reqURL.Path += "api/access-control/users/permissions/search" q := reqURL.Query() - q.Set("actionPrefix", "grafana-oncall-app") + q.Set("actionPrefix", settings.PluginID) reqURL.RawQuery = q.Encode() req, err := http.NewRequest("GET", reqURL.String(), nil) diff --git a/grafana-plugin/pkg/plugin/settings.go b/grafana-plugin/pkg/plugin/settings.go index 54af3b12f6..d896b3fd7f 100644 --- a/grafana-plugin/pkg/plugin/settings.go +++ b/grafana-plugin/pkg/plugin/settings.go @@ -46,6 +46,7 @@ type OnCallPluginSettings struct { StackID int `json:"stack_id"` OrgID int `json:"org_id"` License string `json:"license"` + PluginID string `json:"plugin_id"` GrafanaURL string `json:"grafana_url"` GrafanaToken string `json:"grafana_token"` RBACEnabled bool `json:"rbac_enabled"` @@ -71,6 +72,9 @@ func (a *OnCallPluginSettings) Equal(b *OnCallPluginSettings) bool { if a.License != b.License { return false } + if a.PluginID != b.PluginID { + return false + } if a.GrafanaURL != b.GrafanaURL { return false } @@ -127,6 +131,11 @@ func (a *App) OnCallSettingsFromContext(ctx context.Context) (*OnCallPluginSetti GrafanaURL: pluginSettingsJson.GrafanaURL, } + settings.PluginID = pluginContext.PluginID + if settings.PluginID == "" { + return nil, fmt.Errorf("OnCallSettingsFromContext: couldn't get plugin ID from plugin context") + } + version := pluginContext.PluginVersion if version == "" { // older Grafana versions do not have the plugin version in the context @@ -286,7 +295,7 @@ func (a *App) SaveOnCallSettings(settings *OnCallPluginSettings) error { return fmt.Errorf("Marshal OnCall settings JSON: %w", err) } - settingsUrl, err := url.JoinPath(settings.GrafanaURL, fmt.Sprintf("api/plugins/grafana-oncall-app/settings")) + settingsUrl, err := url.JoinPath(settings.GrafanaURL, fmt.Sprintf("api/plugins/%s/settings", settings.PluginID)) if err != nil { return err } diff --git a/grafana-plugin/src/network/grafana-api/http-client.ts b/grafana-plugin/src/network/grafana-api/http-client.ts index 05fc0ff58b..e4173c3303 100644 --- a/grafana-plugin/src/network/grafana-api/http-client.ts +++ b/grafana-plugin/src/network/grafana-api/http-client.ts @@ -1,6 +1,8 @@ import { getBackendSrv } from '@grafana/runtime'; import { OnCallPluginMetaJSONData } from 'types'; +import { getPluginId } from 'utils/consts'; + import { ApiAuthKeyDTO, NewApiKeyResult, @@ -14,7 +16,7 @@ const KEYS_BASE_URL = '/api/auth/keys'; const SERVICE_ACCOUNTS_BASE_URL = '/api/serviceaccounts'; const ONCALL_KEY_NAME = 'OnCall'; const ONCALL_SERVICE_ACCOUNT_NAME = 'sa-autogen-OnCall'; -const GRAFANA_PLUGIN_SETTINGS_URL = '/api/plugins/grafana-oncall-app/settings'; +const GRAFANA_PLUGIN_SETTINGS_URL = `/api/plugins/${getPluginId()}/settings`; export class GrafanaApiClient { static grafanaBackend = getBackendSrv(); diff --git a/grafana-plugin/src/utils/consts.ts b/grafana-plugin/src/utils/consts.ts index 98d72dd657..18463ce393 100644 --- a/grafana-plugin/src/utils/consts.ts +++ b/grafana-plugin/src/utils/consts.ts @@ -50,7 +50,6 @@ export const BREAKPOINT_TABS = 1024; // Default redirect page export const DEFAULT_PAGE = 'alert-groups'; -export const PLUGIN_ID = 'grafana-oncall-app'; export const PLUGIN_ROOT = `/a/${getPluginId()}`; export const PLUGIN_CONFIG = `/plugins/${getPluginId()}`; @@ -82,7 +81,7 @@ const getGrafanaSubUrl = () => { export const getOnCallApiPath = (subpath = '') => { // We need to consider the grafanaSubUrl in case Grafana is served from subpath, e.g. http://localhost:3000/grafana - return `${getGrafanaSubUrl()}/api/plugins/${PLUGIN_ID}/resources${subpath}`; + return `${getGrafanaSubUrl()}/api/plugins/${getPluginId()}/resources${subpath}`; }; // Faro diff --git a/grafana-plugin/src/utils/utils.ts b/grafana-plugin/src/utils/utils.ts index 9574cf4e85..30b0a6047f 100644 --- a/grafana-plugin/src/utils/utils.ts +++ b/grafana-plugin/src/utils/utils.ts @@ -8,7 +8,7 @@ import { isArray, concat, every, isEmpty, isObject, isPlainObject, flatMap, map, import { isNetworkError } from 'network/network'; -import { CLOUD_VERSION_REGEX, PLUGIN_ID } from './consts'; +import { CLOUD_VERSION_REGEX, getPluginId } from './consts'; export class KeyValuePair { key: T; @@ -153,7 +153,7 @@ export const isCurrentGrafanaVersionEqualOrGreaterThan = ({ ); }; -export const getIsRunningOpenSourceVersion = () => !CLOUD_VERSION_REGEX.test(config.apps[PLUGIN_ID]?.version); +export const getIsRunningOpenSourceVersion = () => !CLOUD_VERSION_REGEX.test(config.apps[getPluginId()]?.version); export const getIsExternalServiceAccountFeatureAvailable = () => isCurrentGrafanaVersionEqualOrGreaterThan({ minMajor: 10, minMinor: 3 }) &&