Gate export/import command menu items by permission flag (#19991)
## Summary - Hides the `exportRecords`, `exportView`, and `importRecords` command menu actions from users whose role does not hold the matching `EXPORT_CSV` / `IMPORT_CSV` permission flag. - Exposes the current user's role permission flags to `conditionalAvailabilityExpression` by adding `permissionFlags: Record<string, boolean>` to `CommandMenuContextApi`, mirroring how `featureFlags` is already accessible. - Adds a `2.1.0` workspace upgrade command that rewrites the three existing rows on every active/suspended workspace. ## Before <img width="1294" height="287" alt="Screenshot 2026-04-22 at 19 37 40" src="https://github.com/user-attachments/assets/11ca8635-14d7-40a0-9ca0-76329c54e3c6" /> ## After <img width="1283" height="285" alt="Screenshot 2026-04-22 at 19 32 25" src="https://github.com/user-attachments/assets/5e49fa8a-4541-42ee-96da-4c1de7d00aae" />
This commit is contained in:
+55
@@ -24,6 +24,7 @@ const buildContext = (
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags: {},
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
objectMetadataItem: {},
|
||||
@@ -456,4 +457,58 @@ describe('evaluateConditionalAvailabilityExpression', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('permissionFlags gating', () => {
|
||||
it('should hide exportRecords when EXPORT_CSV permission flag is missing', () => {
|
||||
const context = buildContext({ permissionFlags: {} });
|
||||
|
||||
expect(
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
'permissionFlags.EXPORT_CSV',
|
||||
context,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should show exportRecords when EXPORT_CSV permission flag is present', () => {
|
||||
const context = buildContext({
|
||||
permissionFlags: { EXPORT_CSV: true },
|
||||
});
|
||||
|
||||
expect(
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
'permissionFlags.EXPORT_CSV',
|
||||
context,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should hide importRecords when IMPORT_CSV permission flag is missing even if soft-delete filter is off', () => {
|
||||
const context = buildContext({
|
||||
hasAnySoftDeleteFilterOnView: false,
|
||||
permissionFlags: {},
|
||||
});
|
||||
|
||||
expect(
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
'not hasAnySoftDeleteFilterOnView and permissionFlags.IMPORT_CSV',
|
||||
context,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should show importRecords when IMPORT_CSV permission flag is present and soft-delete filter is off', () => {
|
||||
const context = buildContext({
|
||||
hasAnySoftDeleteFilterOnView: false,
|
||||
permissionFlags: { IMPORT_CSV: true },
|
||||
});
|
||||
|
||||
expect(
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
'not hasAnySoftDeleteFilterOnView and permissionFlags.IMPORT_CSV',
|
||||
context,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ const buildContext = (
|
||||
},
|
||||
selectedRecords: [],
|
||||
featureFlags: {},
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
objectMetadataItem: {},
|
||||
|
||||
Reference in New Issue
Block a user