diff --git a/public/apps/configuration/panels/permission-list/permission-list.tsx b/public/apps/configuration/panels/permission-list/permission-list.tsx
index 96f0c425b..ec90dd7d5 100644
--- a/public/apps/configuration/panels/permission-list/permission-list.tsx
+++ b/public/apps/configuration/panels/permission-list/permission-list.tsx
@@ -34,7 +34,14 @@ import {
Query,
} from '@elastic/eui';
import { difference } from 'lodash';
-import React, { Dispatch, ReactNode, SetStateAction, useCallback, useState } from 'react';
+import React, {
+ Dispatch,
+ ReactNode,
+ SetStateAction,
+ useCallback,
+ useState,
+ useContext,
+} from 'react';
import { AppDependencies } from '../../../types';
import { Action, DataObject, ActionGroupItem, ExpandedRowMapInterface } from '../../types';
import {
@@ -54,6 +61,9 @@ import { useDeleteConfirmState } from '../../utils/delete-confirm-modal-utils';
import { useContextMenuState } from '../../utils/context-menu';
import { generateResourceName } from '../../utils/resource-utils';
import { DocLinks } from '../../constants';
+import { SecurityPluginTopNavMenu } from '../../top-nav-menu';
+import { DataSourceContext } from '../../app-router';
+import { createDataSourceQuery } from '../../../../utils/datasource-utils';
export function renderBooleanToCheckMark(value: boolean): React.ReactNode {
return value ? : '';
@@ -77,7 +87,7 @@ export function toggleRowDetails(
});
}
-export function renderRowExpanstionArrow(
+export function renderRowExpansionArrow(
itemIdToExpandedRowMap: ExpandedRowMapInterface,
actionGroupDict: DataObject,
setItemIdToExpandedRowMap: Dispatch>
@@ -129,7 +139,7 @@ function getColumns(
align: RIGHT_ALIGNMENT,
width: '40px',
isExpander: true,
- render: renderRowExpanstionArrow(
+ render: renderRowExpansionArrow(
itemIdToExpandedRowMap,
actionGroupDict,
setItemIdToExpandedRowMap
@@ -182,6 +192,8 @@ export function PermissionList(props: AppDependencies) {
const [selection, setSelection] = React.useState([]);
const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState({});
+ const { dataSource, setDataSource } = useContext(DataSourceContext)!;
+
// Modal state
const [editModal, setEditModal] = useState(null);
@@ -194,7 +206,10 @@ export function PermissionList(props: AppDependencies) {
const fetchData = useCallback(async () => {
try {
setLoading(true);
- const actionGroups = await fetchActionGroups(props.coreStart.http);
+ const actionGroups = await fetchActionGroups(
+ props.coreStart.http,
+ createDataSourceQuery(dataSource.id)
+ );
setActionGroupDict(actionGroups);
setPermissionList(await mergeAllPermissions(actionGroups));
} catch (e) {
@@ -203,16 +218,20 @@ export function PermissionList(props: AppDependencies) {
} finally {
setLoading(false);
}
- }, [props.coreStart.http]);
+ }, [props.coreStart.http, dataSource.id]);
React.useEffect(() => {
fetchData();
- }, [props.coreStart.http, fetchData]);
+ }, [props.coreStart.http, fetchData, dataSource.id]);
const handleDelete = async () => {
const groupsToDelete: string[] = selection.map((r) => r.name);
try {
- await requestDeleteActionGroups(props.coreStart.http, groupsToDelete);
+ await requestDeleteActionGroups(
+ props.coreStart.http,
+ groupsToDelete,
+ createDataSourceQuery(dataSource.id)
+ );
setPermissionList(difference(permissionList, selection));
setSelection([]);
} catch (e) {
@@ -276,9 +295,12 @@ export function PermissionList(props: AppDependencies) {
handleClose={() => setEditModal(null)}
handleSave={async (groupName, allowedAction) => {
try {
- await updateActionGroup(props.coreStart.http, groupName, {
- allowed_actions: allowedAction,
- });
+ await updateActionGroup(
+ props.coreStart.http,
+ groupName,
+ { allowed_actions: allowedAction },
+ createDataSourceQuery(dataSource.id)
+ );
setEditModal(null);
fetchData();
addToast({
@@ -301,7 +323,11 @@ export function PermissionList(props: AppDependencies) {
};
const createActionGroupMenuItems = [
- showEditModal('', Action.create, [])}>
+ showEditModal('', Action.create, [])}
+ >
Create from blank
,
+
Permissions
diff --git a/public/apps/configuration/panels/permission-list/test/permission-list.test.tsx b/public/apps/configuration/panels/permission-list/test/permission-list.test.tsx
index 965ccea01..856a3e8fb 100644
--- a/public/apps/configuration/panels/permission-list/test/permission-list.test.tsx
+++ b/public/apps/configuration/panels/permission-list/test/permission-list.test.tsx
@@ -19,7 +19,7 @@ import {
PermissionList,
renderBooleanToCheckMark,
toggleRowDetails,
- renderRowExpanstionArrow,
+ renderRowExpansionArrow,
} from '../permission-list';
import { EuiInMemoryTable, EuiButtonIcon } from '@elastic/eui';
import {
@@ -49,6 +49,11 @@ jest.mock('../../../utils/toast-utils', () => ({
useToastState: jest.fn().mockReturnValue([[], jest.fn(), jest.fn()]),
}));
+jest.mock('react', () => ({
+ ...jest.requireActual('react'),
+ useContext: jest.fn().mockReturnValue({ dataSource: { id: 'test' }, setDataSource: jest.fn() }), // Mock the useContext hook to return dummy datasource and setdatasource function
+}));
+
describe('Permission list page ', () => {
const sampleActionGroup: PermissionListingItem = {
name: 'group',
@@ -73,7 +78,7 @@ describe('Permission list page ', () => {
describe('renderRowExpanstionArrow', () => {
it('should render down arrow when collapsed', () => {
- const renderFunc = renderRowExpanstionArrow({}, {}, jest.fn());
+ const renderFunc = renderRowExpansionArrow({}, {}, jest.fn());
const Wrapper = () => <>{renderFunc(sampleActionGroup)}>;
const component = shallow();
@@ -81,7 +86,7 @@ describe('Permission list page ', () => {
});
it('should render up arrow when expanded', () => {
- const renderFunc = renderRowExpanstionArrow(
+ const renderFunc = renderRowExpansionArrow(
{ [sampleActionGroup.name]: sampleActionGroup },
{},
jest.fn()
@@ -94,6 +99,12 @@ describe('Permission list page ', () => {
});
describe('PermissionList', () => {
+ const mockCoreStart = {
+ http: 1,
+ };
+ const dataSourceQuery = {
+ dataSourceId: 'test',
+ };
it('render empty', () => {
const component = shallow(
{
jest.spyOn(React, 'useEffect').mockImplementationOnce((f) => f());
shallow(
);
- expect(fetchActionGroups).toBeCalled();
+ expect(fetchActionGroups).toBeCalledWith(mockCoreStart.http, dataSourceQuery);
});
it('fetch data error', () => {
@@ -147,7 +158,7 @@ describe('Permission list page ', () => {
it('submit change', () => {
const component = shallow(
{
const submitFunc = component.find(PermissionEditModal).prop('handleSave');
submitFunc('group1', []);
- expect(updateActionGroup).toBeCalled();
+ expect(updateActionGroup).toBeCalledWith(
+ mockCoreStart.http,
+ 'group1',
+ { allowed_actions: [] },
+ dataSourceQuery
+ );
});
it('submit change error', () => {
@@ -186,7 +202,7 @@ describe('Permission list page ', () => {
it('delete action group', (done) => {
shallow(
{
deleteFunc();
process.nextTick(() => {
- expect(requestDeleteActionGroups).toBeCalled();
+ expect(requestDeleteActionGroups).toBeCalledWith(mockCoreStart.http, [], dataSourceQuery);
done();
});
});
diff --git a/public/apps/configuration/panels/test/__snapshots__/role-list.test.tsx.snap b/public/apps/configuration/panels/test/__snapshots__/role-list.test.tsx.snap
index 9826ce5c9..a9cbacb15 100644
--- a/public/apps/configuration/panels/test/__snapshots__/role-list.test.tsx.snap
+++ b/public/apps/configuration/panels/test/__snapshots__/role-list.test.tsx.snap
@@ -17,6 +17,7 @@ exports[`Role list Render columns render Customization column 1`] = `
>
Reserved
diff --git a/public/apps/configuration/utils/action-groups-utils.tsx b/public/apps/configuration/utils/action-groups-utils.tsx
index 048448ead..7852f86ba 100644
--- a/public/apps/configuration/utils/action-groups-utils.tsx
+++ b/public/apps/configuration/utils/action-groups-utils.tsx
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-import { HttpStart } from 'opensearch-dashboards/public';
+import { HttpStart, HttpFetchQuery } from 'opensearch-dashboards/public';
import { map } from 'lodash';
import { API_ENDPOINT_ACTIONGROUPS, CLUSTER_PERMISSIONS, INDEX_PERMISSIONS } from '../constants';
import { DataObject, ActionGroupItem, ActionGroupUpdate, ObjectsMessage } from '../types';
@@ -29,10 +29,14 @@ export interface PermissionListingItem {
hasIndexPermission: boolean;
}
-export async function fetchActionGroups(http: HttpStart): Promise> {
+export async function fetchActionGroups(
+ http: HttpStart,
+ query: HttpFetchQuery
+): Promise> {
const actiongroups = await httpGet>({
http,
url: API_ENDPOINT_ACTIONGROUPS,
+ query,
});
return actiongroups.data;
}
@@ -50,8 +54,11 @@ export function transformActionGroupsToListingFormat(
}));
}
-export async function fetchActionGroupListing(http: HttpStart): Promise {
- return transformActionGroupsToListingFormat(await fetchActionGroups(http));
+export async function fetchActionGroupListing(
+ http: HttpStart,
+ query: HttpFetchQuery
+): Promise {
+ return transformActionGroupsToListingFormat(await fetchActionGroups(http, query));
}
function getClusterSinglePermissions(): PermissionListingItem[] {
@@ -76,8 +83,11 @@ function getIndexSinglePermissions(): PermissionListingItem[] {
}));
}
-export async function getAllPermissionsListing(http: HttpStart): Promise {
- return mergeAllPermissions(await fetchActionGroups(http));
+export async function getAllPermissionsListing(
+ http: HttpStart,
+ query: HttpFetchQuery
+): Promise {
+ return mergeAllPermissions(await fetchActionGroups(http, query));
}
export async function mergeAllPermissions(
@@ -91,17 +101,23 @@ export async function mergeAllPermissions(
export async function updateActionGroup(
http: HttpStart,
groupName: string,
- updateObject: ActionGroupUpdate
+ updateObject: ActionGroupUpdate,
+ query: HttpFetchQuery
): Promise {
return await httpPost({
http,
url: getResourceUrl(API_ENDPOINT_ACTIONGROUPS, groupName),
body: updateObject,
+ query,
});
}
-export async function requestDeleteActionGroups(http: HttpStart, groups: string[]) {
+export async function requestDeleteActionGroups(
+ http: HttpStart,
+ groups: string[],
+ query: HttpFetchQuery
+) {
for (const group of groups) {
- await httpDelete({ http, url: getResourceUrl(API_ENDPOINT_ACTIONGROUPS, group) });
+ await httpDelete({ http, url: getResourceUrl(API_ENDPOINT_ACTIONGROUPS, group), query });
}
}
diff --git a/public/apps/configuration/utils/display-utils.tsx b/public/apps/configuration/utils/display-utils.tsx
index d4b33fb62..f11584ab4 100644
--- a/public/apps/configuration/utils/display-utils.tsx
+++ b/public/apps/configuration/utils/display-utils.tsx
@@ -70,7 +70,14 @@ export function renderCustomization(reserved: boolean, props: UIProps) {
- {reserved ? 'Reserved' : 'Custom'}
+
+ {reserved ? 'Reserved' : 'Custom'}
+
);
diff --git a/public/apps/configuration/utils/test/__snapshots__/display-utils.test.tsx.snap b/public/apps/configuration/utils/test/__snapshots__/display-utils.test.tsx.snap
index f81deee72..f1795f2a5 100644
--- a/public/apps/configuration/utils/test/__snapshots__/display-utils.test.tsx.snap
+++ b/public/apps/configuration/utils/test/__snapshots__/display-utils.test.tsx.snap
@@ -16,6 +16,7 @@ exports[`Display utils Render Customization column when reserved = False 1`] = `
>
Custom
@@ -39,6 +40,7 @@ exports[`Display utils Render Customization column when reserved = True 1`] = `
>
Reserved
diff --git a/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js b/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js
index 93a810243..8026c3da7 100644
--- a/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js
+++ b/test/cypress/e2e/multi-datasources/multi_datasources_enabled.spec.js
@@ -22,8 +22,8 @@ const createDataSource = () => {
},
body: {
attributes: {
- title: `9202`,
- endpoint: `https://localhost:9202`,
+ title: '9202',
+ endpoint: 'https://localhost:9202',
auth: {
type: 'username_password',
credentials: {
@@ -36,6 +36,15 @@ const createDataSource = () => {
});
};
+const closeToast = () => {
+ // remove browser incompatibiltiy toast causing flakyness (cause it has higher z-index than Create button making it invisible)
+ cy.get('body').then((body) => {
+ if (body.find('[data-test-subj="toastCloseButton"]').length > 0) {
+ cy.get('[data-test-subj="toastCloseButton"]').click();
+ }
+ });
+};
+
const deleteAllDataSources = () => {
cy.request(
'GET',
@@ -77,7 +86,7 @@ describe('Multi-datasources enabled', () => {
cy.get('.euiToastHeader__title').should('contain', 'successful for Local cluster');
// Remote cluster purge cache
cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
- cy.contains('li.euiSelectableListItem', '9202').click();
+ cy.get('[title="9202"]').click();
cy.get('[data-test-subj="purge-cache"]').click();
cy.get('.euiToastHeader__title').should('contain', 'successful for 9202');
cy.visit('http://localhost:5601/app/security-dashboards-plugin#/auth');
@@ -91,21 +100,23 @@ describe('Multi-datasources enabled', () => {
cy.get('.panel-header-count').first().invoke('text').should('contain', '(6)');
// Remote cluster auth
cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
- cy.contains('li.euiSelectableListItem', '9202').click();
- cy.get('.panel-header-count').first().invoke('text').should('contain', '(2)');
- cy.visit('http://localhost:5601/app/security-dashboards-plugin#/users');
- // Data source persisted across tabs
- cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').contains('9202');
+ cy.get('[title="9202"]').click();
+ cy.get('.panel-header-count').first().invoke('text').should('contain', '(6)');
});
- it.skip('Checks Users Tab', () => {
+ it('Checks Users Tab', () => {
cy.visit('http://localhost:5601/app/security-dashboards-plugin#/users');
// Create an internal user in the remote cluster
cy.contains('h3', 'Internal users');
cy.contains('a', 'admin');
- // TODO replace these with navigating to urls that get read to determine datasource, since these are flaky
+
+ closeToast();
+
+ // select remote data source
cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
- cy.contains('li.euiSelectableListItem', '9202').click();
+ cy.get('[title="9202"]').click();
+
+ // create a user on remote data source
cy.get('[data-test-subj="create-user"]').click();
cy.get('[data-test-subj="name-text"]').focus().type('9202-user');
cy.get('[data-test-subj="password"]').focus().type('myStrongPassword123!');
@@ -113,12 +124,59 @@ describe('Multi-datasources enabled', () => {
cy.get('[data-test-subj="submit-save-user"]').click();
// Internal user exists on the remote
- cy.visit('http://localhost:5601/app/security-dashboards-plugin#/users');
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').should(
+ 'contain',
+ '9202'
+ );
cy.get('[data-test-subj="checkboxSelectRow-9202-user"]').should('exist');
// Internal user doesn't exist on local cluster
cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
- cy.contains('li.euiSelectableListItem', 'Local cluster').click();
+ cy.get('[title="Local cluster"]').click();
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').should(
+ 'contain',
+ 'Local cluster'
+ );
cy.get('[data-test-subj="checkboxSelectRow-9202-user"]').should('not.exist');
});
+
+ it('Checks Permissions Tab', () => {
+ cy.visit('http://localhost:5601/app/security-dashboards-plugin#/permissions');
+ // Create a permission in the remote cluster
+ cy.contains('h3', 'Permissions');
+
+ closeToast();
+
+ // Select remote cluster
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
+ cy.get('[title="9202"]').click();
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').should(
+ 'contain',
+ '9202'
+ );
+
+ // Create an action group
+ cy.get('[id="Create action group"]').click();
+ cy.get('[id="create-from-blank"]').click();
+ cy.get('[data-test-subj="name-text"]')
+ .focus()
+ .type('test_permission_ag', { force: true })
+ .should('have.value', 'test_permission_ag');
+ cy.get('[data-test-subj="comboBoxInput"]').focus().type('some_permission');
+ cy.get('[id="submit"]').click();
+
+ // Permission exists on the remote data source
+ cy.get('[data-text="Customization"]').click();
+ cy.get('[data-test-subj="filter-custom-action-groups"]').click();
+ cy.get('[data-test-subj="checkboxSelectRow-test_permission_ag"]').should('exist');
+
+ // Permission doesn't exist on local cluster
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').click();
+ cy.get('[title="Local cluster"]').click();
+ cy.get('[data-test-subj="dataSourceSelectableContextMenuHeaderLink"]').should(
+ 'contain',
+ 'Local cluster'
+ );
+ cy.get('[data-test-subj="checkboxSelectRow-test_permission_ag"]').should('not.exist');
+ });
});
diff --git a/test/helper/entity_operation.ts b/test/helper/entity_operation.ts
index aabdfbd8a..aad5da56f 100644
--- a/test/helper/entity_operation.ts
+++ b/test/helper/entity_operation.ts
@@ -57,3 +57,24 @@ export async function getEntityAsAdminWithDataSource(
.get(root, `/api/v1/configuration/${entityType}/${entityId}?dataSourceId=${dataSourceId}`)
.set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
}
+
+export async function getAllEntitiesAsAdminWithDataSource(
+ root: Root,
+ entityType: string,
+ dataSourceId: string
+) {
+ return await osdTestServer.request
+ .get(root, `/api/v1/configuration/${entityType}?dataSourceId=${dataSourceId}`)
+ .set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
+}
+
+export async function deleteEntityAsAdminWithDataSource(
+ root: Root,
+ entityType: string,
+ entityId: string,
+ dataSourceId: string
+) {
+ return await osdTestServer.request
+ .delete(root, `/api/v1/configuration/${entityType}/${entityId}?dataSourceId=${dataSourceId}`)
+ .set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
+}
diff --git a/test/jest_integration/security_entity_api.test.ts b/test/jest_integration/security_entity_api.test.ts
index c3ca21986..4f745c9de 100644
--- a/test/jest_integration/security_entity_api.test.ts
+++ b/test/jest_integration/security_entity_api.test.ts
@@ -29,6 +29,8 @@ import { extractAuthCookie, getAuthCookie } from '../helper/cookie';
import {
createOrUpdateEntityAsAdmin,
createOrUpdateEntityAsAdminWithDataSource,
+ deleteEntityAsAdminWithDataSource,
+ getAllEntitiesAsAdminWithDataSource,
getEntityAsAdmin,
getEntityAsAdminWithDataSource,
} from '../helper/entity_operation';
@@ -478,6 +480,7 @@ describe('start OpenSearch Dashboards server multi datasources enabled', () => {
},
},
});
+ expect(createDataSource.status).toEqual(200);
dataSourceId = createDataSource.body.id;
});
@@ -541,10 +544,11 @@ describe('start OpenSearch Dashboards server multi datasources enabled', () => {
it('create/get/update/list/delete internal user for external datasource', async () => {
const testUsername = `test_user_${Date.now()}`;
const testUserPassword = 'testUserPassword123';
+ const entityType = 'internalusers';
const createUserResponse = await createOrUpdateEntityAsAdminWithDataSource(
root,
- 'internalusers',
+ entityType,
testUsername,
{
description: 'test user description',
@@ -557,7 +561,7 @@ describe('start OpenSearch Dashboards server multi datasources enabled', () => {
const getUserResponse = await getEntityAsAdminWithDataSource(
root,
- 'internalusers',
+ entityType,
testUsername,
dataSourceId
);
@@ -565,16 +569,18 @@ describe('start OpenSearch Dashboards server multi datasources enabled', () => {
expect(getUserResponse.body.description).toEqual('test user description');
expect(getUserResponse.body.backend_roles).toContain('arbitrary_backend_role');
- const listUserResponse = await osdTestServer.request
- .get(root, `/api/v1/configuration/internalusers?dataSourceId=${dataSourceId}`)
- .set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
+ const listUserResponse = await getAllEntitiesAsAdminWithDataSource(
+ root,
+ entityType,
+ dataSourceId
+ );
expect(listUserResponse.status).toEqual(200);
expect(listUserResponse.body.total).toBeGreaterThan(2);
expect(listUserResponse.body.data[testUsername]).toBeTruthy();
const updateUserResponse = await createOrUpdateEntityAsAdminWithDataSource(
root,
- 'internalusers',
+ entityType,
testUsername,
{
description: 'new description',
@@ -587,27 +593,107 @@ describe('start OpenSearch Dashboards server multi datasources enabled', () => {
const getUpdatedUserResponse = await getEntityAsAdminWithDataSource(
root,
- 'internalusers',
+ entityType,
testUsername,
dataSourceId
);
expect(getUpdatedUserResponse.status).toEqual(200);
expect(getUpdatedUserResponse.body.description).toEqual('new description');
- const deleteUserResponse = await osdTestServer.request
- .delete(
- root,
- `/api/v1/configuration/internalusers/${testUsername}?dataSourceId=${dataSourceId}`
- )
- .set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
+ const deleteUserResponse = await deleteEntityAsAdminWithDataSource(
+ root,
+ entityType,
+ testUsername,
+ dataSourceId
+ );
expect(deleteUserResponse.status).toEqual(200);
const getDeletedUserResponse = await getEntityAsAdminWithDataSource(
root,
- 'internalusers',
+ entityType,
testUsername,
dataSourceId
);
expect(getDeletedUserResponse.status).toEqual(404);
});
+
+ it('CRUD Permissions for external datasource', async () => {
+ const entityType = 'actiongroups';
+ const testActionGroupName = `test_action_group_${Date.now()}`;
+
+ const createActionGroupResponse = await createOrUpdateEntityAsAdminWithDataSource(
+ root,
+ entityType,
+ testActionGroupName,
+ {
+ allowed_actions: ['some_allowed_action'],
+ },
+ dataSourceId
+ );
+ expect(createActionGroupResponse.status).toEqual(200);
+
+ const getActionGroupsResponse = await getAllEntitiesAsAdminWithDataSource(
+ root,
+ entityType,
+ dataSourceId
+ );
+ expect(getActionGroupsResponse.status).toEqual(200);
+ expect(getActionGroupsResponse.body.data?.hasOwnProperty(testActionGroupName)).toBe(true);
+ expect(getActionGroupsResponse.body.data[testActionGroupName].allowed_actions).toContain(
+ 'some_allowed_action'
+ );
+
+ // verify that this AG is not created in Local Cluster
+ const getActionGroupsResponseLocalCluster = await getAllEntitiesAsAdminWithDataSource(
+ root,
+ entityType,
+ ''
+ );
+ expect(getActionGroupsResponseLocalCluster.status).toEqual(200);
+ expect(getActionGroupsResponseLocalCluster.body.data?.hasOwnProperty(testActionGroupName)).toBe(
+ false
+ );
+
+ const updatePermissionResponse = await createOrUpdateEntityAsAdminWithDataSource(
+ root,
+ entityType,
+ testActionGroupName,
+ {
+ allowed_actions: ['some_allowed_action', 'another_permission'],
+ },
+ dataSourceId
+ );
+ expect(updatePermissionResponse.status).toEqual(200);
+
+ const getUpdatedActionGroupsResponse = await getAllEntitiesAsAdminWithDataSource(
+ root,
+ entityType,
+ dataSourceId
+ );
+ expect(getUpdatedActionGroupsResponse.status).toEqual(200);
+ expect(getUpdatedActionGroupsResponse.body.data?.hasOwnProperty(testActionGroupName)).toBe(
+ true
+ );
+ expect(getUpdatedActionGroupsResponse.body.data[testActionGroupName].allowed_actions).toContain(
+ 'another_permission'
+ );
+
+ const deleteActionGroupResponse = await deleteEntityAsAdminWithDataSource(
+ root,
+ entityType,
+ testActionGroupName,
+ dataSourceId
+ );
+ expect(deleteActionGroupResponse.status).toEqual(200);
+
+ const getDeletedActionGroupsResponse = await getAllEntitiesAsAdminWithDataSource(
+ root,
+ entityType,
+ dataSourceId
+ );
+ expect(getDeletedActionGroupsResponse.status).toEqual(200);
+ expect(getDeletedActionGroupsResponse.body.data?.hasOwnProperty(testActionGroupName)).toBe(
+ false
+ );
+ });
});