Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
* limitations under the License.
*/

import { Page, test as base } from '@playwright/test';
import { expect, Page, test as base } from '@playwright/test';
import { PolicyClass } from '../../../support/access-control/PoliciesClass';
import { RolesClass } from '../../../support/access-control/RolesClass';
import { EntityClass } from '../../../support/entity/EntityClass';
import { TableClass } from '../../../support/entity/TableClass';
import { UserClass } from '../../../support/user/UserClass';
import { performAdminLogin } from '../../../utils/admin';
import { getApiContext } from '../../../utils/common';
Expand All @@ -26,8 +29,75 @@ import {
assignRoleToUser,
cleanupPermissions,
initializePermissions,
setupUserWithPolicy,
} from '../../../utils/permission';

const EDIT_ALL_ALLOW_SPECIFIC_DENY_RULES = [
{
name: 'ViewAll-Rule',
resources: ['All'],
operations: ['ViewAll'],
effect: 'allow',
},
{
name: 'EditAll-Allow-Rule',
resources: ['All'],
operations: ['EditAll'],
effect: 'allow',
},
{
name: 'EditTier-Deny-Rule',
resources: ['All'],
operations: ['EditTier'],
effect: 'deny',
},
{
name: 'EditOwners-Deny-Rule',
resources: ['All'],
operations: ['EditOwners'],
effect: 'deny',
},
{
name: 'EditCertification-Deny-Rule',
resources: ['All'],
operations: ['EditCertification'],
effect: 'deny',
},
];

const SPECIFIC_ALLOW_EDIT_ALL_DENY_RULES = [
{
name: 'ViewAll-Rule',
resources: ['All'],
operations: ['ViewAll'],
effect: 'allow',
},
{
name: 'EditAll-Deny-Rule',
resources: ['All'],
operations: ['EditAll'],
effect: 'deny',
},
{
name: 'EditTier-Allow-Rule',
resources: ['All'],
operations: ['EditTier'],
effect: 'allow',
},
{
name: 'EditOwners-Allow-Rule',
resources: ['All'],
operations: ['EditOwners'],
effect: 'allow',
},
{
name: 'EditCertification-Allow-Rule',
resources: ['All'],
operations: ['EditCertification'],
effect: 'allow',
},
];

const adminUser = new UserClass();
const testUser = new UserClass();

Expand Down Expand Up @@ -70,6 +140,111 @@ test.afterAll('Cleanup pre-requests', async ({ browser }) => {
await afterAction();
});

let editAllUser: UserClass;
let editAllPolicy: PolicyClass;
let editAllRole: RolesClass;

let specificEditsUser: UserClass;
let specificEditsPolicy: PolicyClass;
let specificEditsRole: RolesClass;

let headerPermTable: TableClass;

const headerPermTest = base.extend<{
editAllPage: Page;
specificEditsPage: Page;
denyAllPage: Page;
}>({
editAllPage: async ({ browser }, use) => {
const page = await browser.newPage();
try {
await editAllUser.login(page);
await use(page);
} finally {
await page.close();
}
},
specificEditsPage: async ({ browser }, use) => {
const page = await browser.newPage();
try {
await specificEditsUser.login(page);
await use(page);
} finally {
await page.close();
}
},
});

headerPermTest.describe(
'DataAsset Header – EditTier / EditOwners / EditCertification permissions',
() => {
headerPermTest.beforeAll(
'Setup users, roles, and table',
async ({ browser }) => {
editAllUser = new UserClass();
editAllPolicy = new PolicyClass();
editAllRole = new RolesClass();

specificEditsUser = new UserClass();
specificEditsPolicy = new PolicyClass();
specificEditsRole = new RolesClass();

headerPermTable = new TableClass();

const { apiContext, afterAction } = await performAdminLogin(browser);

await headerPermTable.create(apiContext);

await setupUserWithPolicy(
apiContext,
editAllUser,
editAllPolicy,
editAllRole,
EDIT_ALL_ALLOW_SPECIFIC_DENY_RULES
);
await setupUserWithPolicy(
apiContext,
specificEditsUser,
specificEditsPolicy,
specificEditsRole,
SPECIFIC_ALLOW_EDIT_ALL_DENY_RULES
);
await afterAction();
}
);

headerPermTest(
'EditAll allowed but EditTier, EditOwners, EditCertification denied – edit buttons not visible',
async ({ editAllPage }) => {
await headerPermTable.visitEntityPage(editAllPage);

await expect(editAllPage.getByTestId('edit-tier')).not.toBeVisible();
await expect(editAllPage.getByTestId('edit-owner')).not.toBeVisible();
await expect(
editAllPage.getByTestId('edit-certification')
).not.toBeVisible();
}
);

headerPermTest(
'EditTier, EditOwners, EditCertification allowed but EditAll denied – edit buttons not visible',
async ({ specificEditsPage }) => {
await headerPermTable.visitEntityPage(specificEditsPage);

await expect(
specificEditsPage.getByTestId('edit-tier')
).not.toBeVisible();
await expect(
specificEditsPage.getByTestId('edit-owner')
).not.toBeVisible();
await expect(
specificEditsPage.getByTestId('edit-certification')
).not.toBeVisible();
}
Comment on lines +229 to +243
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Edge Case: E2E test expects specific-allow + EditAll-deny to hide buttons

The test 'EditTier, EditOwners, EditCertification allowed but EditAll denied – edit buttons not visible' (line 229-244) uses SPECIFIC_ALLOW_EDIT_ALL_DENY_RULES which sets EditTier/EditOwners/EditCertification to allow and EditAll to deny. Since getPrioritizedEditPermission now returns permissions[Operation.EditTier] directly (the key always exists), if the backend resolves EditTier as true despite EditAll being denied, the button would be visible and the test would fail.

This test passing depends on the backend's policy resolution cascading the EditAll deny to specific operations (i.e., deny always wins). If that's the intended backend behavior, this is fine — but it means this test is actually testing backend policy resolution rather than the frontend logic change. Please confirm the test passes in CI.

Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion

);
}
);

Object.entries(entityConfig).forEach(([, config]) => {
const entity = new config.class();
const entityType = entity.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
} from '../../../generated/entity/data/dataContract';
import { EntityStatus } from '../../../generated/entity/data/glossaryTerm';
import { Table } from '../../../generated/entity/data/table';
import { Operation } from '../../../generated/entity/policies/policy';
import { EntityReference } from '../../../generated/type/entityReference';
import { useApplicationStore } from '../../../hooks/useApplicationStore';
import { useCustomPages } from '../../../hooks/useCustomPages';
Expand Down Expand Up @@ -83,6 +84,7 @@ import {
getEntityName,
getEntityVoteStatus,
} from '../../../utils/EntityUtils';
import { getPrioritizedEditPermission } from '../../../utils/PermissionsUtils';
import { getEntityDetailsPath } from '../../../utils/RouterUtils';
import serviceUtilClassBase from '../../../utils/ServiceUtilClassBase';
import { getEntityTypeFromServiceCategory } from '../../../utils/ServiceUtils';
Expand Down Expand Up @@ -463,12 +465,16 @@ export const DataAssetsHeader = ({
() => ({
editDomainPermission: permissions.EditAll && !dataAsset.deleted,
editOwnerPermission:
(permissions.EditAll || permissions.EditOwners) && !dataAsset.deleted,
getPrioritizedEditPermission(permissions, Operation.EditOwners) &&
!dataAsset.deleted,
editTierPermission:
(permissions.EditAll || permissions.EditTier) && !dataAsset.deleted,
editCertificationPermission:
(permissions.EditAll || permissions.EditCertification) &&
getPrioritizedEditPermission(permissions, Operation.EditTier) &&
!dataAsset.deleted,
editCertificationPermission:
getPrioritizedEditPermission(
permissions,
Operation.EditCertification
) && !dataAsset.deleted,
}),
[permissions, dataAsset]
);
Expand Down
Loading