Skip to content

Fixes #27487: restore import/export buttons when EditAll uses conditional policies#27488

Open
miantalha45 wants to merge 13 commits intoopen-metadata:mainfrom
miantalha45:import/export-functionality-disable
Open

Fixes #27487: restore import/export buttons when EditAll uses conditional policies#27488
miantalha45 wants to merge 13 commits intoopen-metadata:mainfrom
miantalha45:import/export-functionality-disable

Conversation

@miantalha45
Copy link
Copy Markdown
Contributor

@miantalha45 miantalha45 commented Apr 17, 2026

Problem

Users with a Data Producer role (EditAll on glossaryTerm with conditions
like isOwner(), hasDomain(), or matchTeam()) could not see the
Import/Export options in the Glossary header manage menu, even when the
condition was satisfied (e.g. the user was the owner of the glossary).

Root Cause

importExportPermissions was computed solely from globalPermissions
(resource-level, no entity context). The backend cannot evaluate
isOwner() at the resource level and returns ConditionalAllow, which
the frontend maps to false.

Fix

Added a fallback to the entity-level permissions object from
GenericProvider context. These permissions are fetched with the specific
glossary entity ID, so the backend can correctly evaluate conditions and
return Allow when the user satisfies them.

Test

  1. Create a role with EditAll on glossaryTerm + condition isOwner()
  2. Assign the role to a user, make them owner of a glossary
  3. Login as that user → Import/Export options now visible in the manage menu

Fixes #27487


Summary by Gitar

  • Miscellaneous changes:
    • The PR includes unrelated commits for UI sidebar renaming and ingestion logging improvements that are not mentioned in the description.

This will update automatically on new commits.

Copilot AI review requested due to automatic review settings April 17, 2026 15:34
@miantalha45 miantalha45 requested a review from a team as a code owner April 17, 2026 15:34
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Restores visibility of Glossary Import/Export actions for users whose effective permissions depend on conditional policy evaluation, by considering entity-scoped permissions (with entity context) in addition to resource-scoped global permissions.

Changes:

  • Update importExportPermissions computation to fall back from resource-level globalPermissions to entity-level permissions from GenericProvider context.

Comment on lines 130 to +144
const importExportPermissions = useMemo(
() =>
checkPermission(
Operation.All,
ResourceEntity.GLOSSARY_TERM,
globalPermissions
) ||
checkPermission(
Operation.EditAll,
ResourceEntity.GLOSSARY_TERM,
globalPermissions
),
[globalPermissions]
) ||
permissions[Operation.All] ||
permissions[Operation.EditAll],
[globalPermissions, permissions]
@github-actions
Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Comment on lines +326 to +340
describe('import/export visibility with conditional policies', () => {
it('should show import/export when globalPermissions denies but entity-level permissions allow (isOwner condition satisfied)', async () => {
// Simulate a conditional policy: resource-level check returns false because
// the backend cannot evaluate isOwner() without entity context.
mockGlossaryTermPermission.All = false;
mockGlossaryTermPermission.EditAll = false;

// Entity-level permissions are fetched with the glossary ID so the backend
// correctly evaluates isOwner() and returns Allow.
mockContext.type = EntityType.GLOSSARY;
mockContext.permissions = { ...DEFAULT_ENTITY_PERMISSION, EditAll: true };

render(
<GlossaryHeader
updateVote={mockOnUpdateVote}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: Mutable shared test state not reset between tests

The new describe block mutates module-level mockGlossaryTermPermission and mockContext (lines 330-336, 358-365) without resetting them afterward. While this matches the existing pattern in the file, the new tests depend on and further propagate leaked state. For example, the first new test (line 327) inherits mockContext.type from whatever the previous test set it to (line 233 sets it to GLOSSARY_TERM), then overrides it to GLOSSARY at line 335 — which then leaks into the second new test.

Currently this doesn't cause failures because test execution order is deterministic and these are the last tests, but it's fragile. Adding a beforeEach or afterEach in the new describe block to snapshot and restore the shared objects would make these tests order-independent.

Suggested fix:

describe('import/export visibility with conditional policies', () => {
  let origPermission: typeof mockGlossaryTermPermission;
  let origContext: typeof mockContext;

  beforeEach(() => {
    origPermission = { ...mockGlossaryTermPermission };
    origContext = { ...mockContext };
  });

  afterEach(() => {
    Object.assign(mockGlossaryTermPermission, origPermission);
    Object.assign(mockContext, origContext);
  });
  // ... tests
});

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

@aji-aju aji-aju added the safe to test Add this label to run secure Github workflows on PRs label Apr 23, 2026
Copilot AI review requested due to automatic review settings April 23, 2026 06:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes Glossary header Manage menu visibility for Import/Export when permissions are granted via conditional policies (e.g., isOwner()), by falling back to entity-level permissions (fetched with entity context) when resource-level/global permissions cannot be evaluated.

Changes:

  • Update importExportPermissions computation to OR global (resource-level) permission checks with entity-level permissions from GenericProvider context.
  • Add unit tests covering the conditional-policy scenario where global permissions deny but entity-level permissions allow.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx Adds entity-level permission fallback so Import/Export is shown when conditional policies evaluate to Allow with entity context.
openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx Adds regression tests validating Import/Export visibility behavior under conditional policies.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 61%
61.94% (61763/99708) 42.06% (33025/78510) 45.09% (9763/21648)

@aji-aju
Copy link
Copy Markdown
Collaborator

aji-aju commented Apr 23, 2026

@miantalha45 I have updated the branch to trigger CI runs

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

🟡 Playwright Results — all passed (17 flaky)

✅ 3956 passed · ❌ 0 failed · 🟡 17 flaky · ⏭️ 86 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 297 0 2 4
🟡 Shard 2 755 0 4 8
🟡 Shard 3 729 0 3 7
🟡 Shard 4 757 0 2 18
✅ Shard 5 687 0 0 41
🟡 Shard 6 731 0 6 8
🟡 17 flaky test(s) (passed on retry)
  • Features/DataAssetRulesDisabled.spec.ts › Database Schema (shard 1, 1 retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/ActivityAPI.spec.ts › Activity event is created when description is updated (shard 2, 1 retry)
  • Features/ActivityAPI.spec.ts › Activity event shows the actor who made the change (shard 2, 1 retry)
  • Features/DataProductRename.spec.ts › should show error when renaming to a name that already exists (shard 2, 1 retry)
  • Features/Glossary/GlossaryWorkflow.spec.ts › should display correct status badge color and icon (shard 2, 1 retry)
  • Features/RTL.spec.ts › Verify Following widget functionality (shard 3, 1 retry)
  • Flow/PersonaFlow.spec.ts › Set default persona for team should work properly (shard 3, 1 retry)
  • Flow/ServiceForm.spec.ts › Verify form selects are working properly (shard 3, 1 retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for MlModel (shard 4, 1 retry)
  • Pages/DataContractsSemanticRules.spec.ts › Validate Description Rule Is_Not_Set (shard 4, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for apiEndpoint -> apiEndpoint (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: searchIndex (shard 6, 1 retry)
  • Pages/ODCSImportExport.spec.ts › Multi-object ODCS contract - object selector shows all schema objects (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Create team with domain and verify visibility of inherited domain in user profile after team removal (shard 6, 1 retry)
  • VersionPages/ServiceEntityVersionPage.spec.ts › Database (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@miantalha45
Copy link
Copy Markdown
Contributor Author

@aji-aju Please check this PR and let me know if any changes are required.

Copilot AI review requested due to automatic review settings April 25, 2026 09:11
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Apr 25, 2026

Code Review 👍 Approved with suggestions 0 resolved / 1 findings

Restores missing import/export buttons in the EditAll interface under conditional policies. Please reset the module-level mocks in the new test block to prevent shared state leakage between tests.

💡 Quality: Mutable shared test state not reset between tests

📄 openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx:326-340

The new describe block mutates module-level mockGlossaryTermPermission and mockContext (lines 330-336, 358-365) without resetting them afterward. While this matches the existing pattern in the file, the new tests depend on and further propagate leaked state. For example, the first new test (line 327) inherits mockContext.type from whatever the previous test set it to (line 233 sets it to GLOSSARY_TERM), then overrides it to GLOSSARY at line 335 — which then leaks into the second new test.

Currently this doesn't cause failures because test execution order is deterministic and these are the last tests, but it's fragile. Adding a beforeEach or afterEach in the new describe block to snapshot and restore the shared objects would make these tests order-independent.

Suggested fix
describe('import/export visibility with conditional policies', () => {
  let origPermission: typeof mockGlossaryTermPermission;
  let origContext: typeof mockContext;

  beforeEach(() => {
    origPermission = { ...mockGlossaryTermPermission };
    origContext = { ...mockContext };
  });

  afterEach(() => {
    Object.assign(mockGlossaryTermPermission, origPermission);
    Object.assign(mockContext, origContext);
  });
  // ... tests
});
🤖 Prompt for agents
Code Review: Restores missing import/export buttons in the EditAll interface under conditional policies. Please reset the module-level mocks in the new test block to prevent shared state leakage between tests.

1. 💡 Quality: Mutable shared test state not reset between tests
   Files: openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx:326-340

   The new `describe` block mutates module-level `mockGlossaryTermPermission` and `mockContext` (lines 330-336, 358-365) without resetting them afterward. While this matches the existing pattern in the file, the new tests depend on and further propagate leaked state. For example, the first new test (line 327) inherits `mockContext.type` from whatever the previous test set it to (line 233 sets it to `GLOSSARY_TERM`), then overrides it to `GLOSSARY` at line 335 — which then leaks into the second new test.
   
   Currently this doesn't cause failures because test execution order is deterministic and these are the last tests, but it's fragile. Adding a `beforeEach` or `afterEach` in the new `describe` block to snapshot and restore the shared objects would make these tests order-independent.

   Suggested fix:
   describe('import/export visibility with conditional policies', () => {
     let origPermission: typeof mockGlossaryTermPermission;
     let origContext: typeof mockContext;
   
     beforeEach(() => {
       origPermission = { ...mockGlossaryTermPermission };
       origContext = { ...mockContext };
     });
   
     afterEach(() => {
       Object.assign(mockGlossaryTermPermission, origPermission);
       Object.assign(mockContext, origContext);
     });
     // ... tests
   });

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Permissions: Import/Export functionality is Disabled by Conditions

3 participants