Compare commits

...

3 Commits

Author SHA1 Message Date
Ezequiel Victorero
7e966c8262 fix test 2025-12-29 19:15:45 -03:00
Ezequiel Victorero
0c5c016844 Merge branch 'main' into evictorero/saved-queries-rbac-support 2025-12-29 15:25:26 -03:00
Ezequiel Victorero
42654a4b39 SavedQueries: Add RBAC support 2025-12-29 15:11:12 -03:00
4 changed files with 34 additions and 3 deletions

View File

@@ -59,8 +59,8 @@ The following tables list permissions associated with basic and fixed roles. Thi
| Grafana Admin | `basic_grafana_admin` |
| `fixed:authentication.config:writer`<br>`fixed:general.auth.config:writer`<br>`fixed:ldap:writer`<br>`fixed:licensing:writer`<br>`fixed:migrationassistant:migrator`<br>`fixed:org.users:writer`<br>`fixed:organization:maintainer`<br>`fixed:plugins:maintainer`<br>`fixed:provisioning:writer`<br>`fixed:roles:writer`<br>`fixed:settings:reader`<br>`fixed:settings:writer`<br>`fixed:stats:reader`<br>`fixed:support.bundles:writer`<br>`fixed:usagestats:reader`<br>`fixed:users:writer` | Default [Grafana server administrator](/docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/#grafana-server-administrators) assignments. |
| Admin | `basic_admin` | All roles assigned to Editor and `fixed:reports:writer` <br>`fixed:datasources:writer`<br>`fixed:organization:writer`<br>`fixed:datasources.permissions:writer`<br>`fixed:teams:writer`<br>`fixed:dashboards:writer`<br>`fixed:dashboards.permissions:writer`<br>`fixed:dashboards.public:writer`<br>`fixed:folders:writer`<br>`fixed:folders.permissions:writer`<br>`fixed:alerting:writer`<br>`fixed:alerting.provisioning.secrets:reader`<br>`fixed:alerting.provisioning:writer`<br>`fixed:datasources.caching:writer`<br>`fixed:plugins:writer`<br>`fixed:library.panels:writer` | Default [Grafana organization administrator](ref:rbac-basic-roles) assignments. |
| Editor | `basic_editor` | All roles assigned to Viewer and `fixed:datasources:explorer` <br>`fixed:dashboards:creator`<br>`fixed:folders:creator`<br>`fixed:annotations:writer`<br>`fixed:alerting:writer`<br>`fixed:library.panels:creator`<br>`fixed:library.panels:general.writer`<br>`fixed:alerting.provisioning.provenance:writer` | Default [Editor](ref:rbac-basic-roles) assignments. |
| Viewer | `basic_viewer` | `fixed:datasources.id:reader`<br>`fixed:organization:reader`<br>`fixed:annotations:reader`<br>`fixed:annotations.dashboard:writer`<br>`fixed:alerting:reader`<br>`fixed:plugins.app:reader`<br>`fixed:dashboards.insights:reader`<br>`fixed:datasources.insights:reader`<br>`fixed:library.panels:general.reader`<br>`fixed:folders.general:reader`<br>`fixed:datasources.builtin:reader` | Default [Viewer](ref:rbac-basic-roles) assignments. |
| Editor | `basic_editor` | All roles assigned to Viewer and `fixed:datasources:explorer` <br>`fixed:dashboards:creator`<br>`fixed:folders:creator`<br>`fixed:annotations:writer`<br>`fixed:alerting:writer`<br>`fixed:library.panels:creator`<br>`fixed:library.panels:general.writer`<br>`fixed:alerting.provisioning.provenance:writer`<br>`fixed:queries:writer` | Default [Editor](ref:rbac-basic-roles) assignments. |
| Viewer | `basic_viewer` | `fixed:datasources.id:reader`<br>`fixed:organization:reader`<br>`fixed:annotations:reader`<br>`fixed:annotations.dashboard:writer`<br>`fixed:alerting:reader`<br>`fixed:plugins.app:reader`<br>`fixed:dashboards.insights:reader`<br>`fixed:datasources.insights:reader`<br>`fixed:library.panels:general.reader`<br>`fixed:folders.general:reader`<br>`fixed:datasources.builtin:reader`<br>`fixed:queries:reader` | Default [Viewer](ref:rbac-basic-roles) assignments. |
| No Basic Role | n/a | | Default [No Basic Role](ref:rbac-basic-roles) |
## Fixed role definitions
@@ -135,6 +135,8 @@ To learn how to use the roles API to determine the role UUIDs, refer to [Manage
| `fixed:plugins:writer` | `fixed_MRYpGk7kpNNwt2VoVOXFiPnQziE` | `plugins:write` | Enable and disable plugins and edit plugins' settings. |
| `fixed:plugins.app:reader` | `fixed_AcZRiNYx7NueYkUqzw1o2OGGUAA` | `plugins.app:access` | Access application plugins (still enforcing the organization role). |
| `fixed:provisioning:writer` | `fixed_bgk1FCyR6OEDwhgirZlQgu5LlCA` | `provisioning:reload` | Reload provisioning. |
| `fixed:queries:reader` | `fixed_-rEsxR-pZg1-fQL-XDQaouEpK98` | `queries:read` | Read saved queries. |
| `fixed:queries:writer` | `fixed_7TMOlueweuPX_PhffesRB2FTQn4` | All permissions from `fixed:queries:reader` and<br>`queries:write` | Create, update, and delete saved queries. |
| `fixed:reports:reader` | `fixed_72_8LU_0ukfm6BdblOw8Z9q-GQ8` | `reports:read`<br>`reports:send`<br>`reports.settings:read` | Read all reports and shared report settings. |
| `fixed:reports:writer` | `fixed_jBW3_7g1EWOjGVBYeVRwtFxhUNw` | All permissions from `fixed:reports:reader` and <br>`reports:create`<br>`reports:write`<br>`reports:delete`<br>`reports.settings:write` | Create, read, update, or delete all reports and shared report settings. |
| `fixed:roles:reader` | `fixed_GkfG-1NSwEGb4hpK3-E3qHyNltc` | `roles:read`<br>`teams.roles:read`<br>`users.roles:read`<br>`users.permissions:read` | Read all access control roles, roles and permissions assigned to users, teams. |

View File

@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
import { noop } from 'lodash';
import { render } from '../../../test/test-utils';
import { contextSrv } from '../../core/services/context_srv';
import { QueriesDrawerContextProviderMock } from './QueriesDrawer/mocks';
import { QueryLibraryContextProviderMock } from './QueryLibrary/mocks';
@@ -17,7 +18,26 @@ jest.mock('@grafana/runtime', () => ({
}),
}));
jest.mock('app/core/services/context_srv', () => ({
contextSrv: {
user: {
uid: 'user123',
},
hasRole: jest.fn(),
hasPermission: jest.fn(),
isEditor: true,
isSignedIn: true,
},
}));
const mockContextSrv = contextSrv as jest.Mocked<typeof contextSrv>;
describe('SecondaryActions', () => {
afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
});
it('should render component with two buttons', () => {
render(
<QueryLibraryContextProviderMock>
@@ -65,6 +85,7 @@ describe('SecondaryActions', () => {
});
it('should disable both add query buttons when addQueryRowButtonDisabled=true and saved queries is enabled', () => {
mockContextSrv.hasPermission.mockReturnValue(true);
render(
<QueryLibraryContextProviderMock queryLibraryEnabled={true}>
<SecondaryActions

View File

@@ -4,6 +4,8 @@ import { CoreApp, GrafanaTheme2 } from '@grafana/data';
import { Components, selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { ToolbarButton, useTheme2 } from '@grafana/ui';
import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types/accessControl';
import { useQueriesDrawerContext } from './QueriesDrawer/QueriesDrawerContext';
import { useQueryLibraryContext } from './QueryLibrary/QueryLibraryContext';
@@ -43,6 +45,8 @@ export function SecondaryActions({
const styles = getStyles(theme);
const { queryLibraryEnabled, openDrawer: openQueryLibraryDrawer } = useQueryLibraryContext();
const { drawerOpened, setDrawerOpened } = useQueriesDrawerContext();
// TODO: contextSrv.isSignedIn is not needed but added to make the frontend retrocompatible, remove it after backend reaches rrcs.
const canReadQueries = contextSrv.isSignedIn || contextSrv.hasPermission(AccessControlAction.QueriesRead);
return (
<div className={styles.containerMargin}>
@@ -57,7 +61,7 @@ export function SecondaryActions({
>
<Trans i18nKey="explore.secondary-actions.query-add-button">Add query</Trans>
</ToolbarButton>
{queryLibraryEnabled && (
{queryLibraryEnabled && canReadQueries && (
<ToolbarButton
data-testid={selectors.pages.Explore.General.addFromQueryLibrary}
aria-label={t('explore.secondary-actions.add-from-query-library', 'Add from saved queries')}

View File

@@ -176,6 +176,10 @@ export enum AccessControlAction {
// Migration Assistant
MigrationAssistantMigrate = 'migrationassistant:migrate',
// Saved Queries
QueriesRead = 'queries:read',
QueriesWrite = 'queries:write',
}
export interface Role extends RoleDto {