[Fix] Backfill missing command menu items conditional availability expression (#20852)
## Description Following [report in discord](https://discord.com/channels/1130383047699738754/1498690477044793386/1506602927412744242) Some command menu items were showing to all users because they had no conditional availability expression, whereas users did not actually have access to the page or feature behind. For instance: "Go to Admin panel", "Go to AI settings", "Send email" etc. <img width="833" height="1245" alt="image" src="https://github.com/user-attachments/assets/8d2a9404-9b81-4d58-9522-558e9924c457" /> ## Fix - Add conditional availability expressions - Backfill expressions for existing workspaces as they are stored in db (commandMenuItems table) --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+6
@@ -1,3 +1,4 @@
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { objectPermissionsFamilySelector } from '@/auth/states/objectPermissionsFamilySelector';
|
||||
@@ -27,6 +28,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
const commandMenuItems = useAtomStateValue(commandMenuItemsSelector);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const currentUserWorkspace = useAtomStateValue(currentUserWorkspaceState);
|
||||
const currentUser = useAtomStateValue(currentUserState);
|
||||
const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
|
||||
const isLayoutCustomizationModeEnabled = useAtomStateValue(
|
||||
isLayoutCustomizationModeEnabledState,
|
||||
@@ -85,12 +87,16 @@ export const StandalonePageCommandMenu = () => {
|
||||
permissionFlags,
|
||||
targetObjectReadPermissions,
|
||||
targetObjectWritePermissions,
|
||||
canImpersonate: currentUser?.canImpersonate === true,
|
||||
canAccessFullAdminPanel: currentUser?.canAccessFullAdminPanel === true,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
};
|
||||
}, [
|
||||
currentWorkspace?.featureFlags,
|
||||
currentUserWorkspace?.permissionFlags,
|
||||
currentUser?.canImpersonate,
|
||||
currentUser?.canAccessFullAdminPanel,
|
||||
isLayoutCustomizationModeEnabled,
|
||||
objectMetadataItems,
|
||||
store,
|
||||
|
||||
+2
@@ -27,6 +27,8 @@ export const EMPTY_COMMAND_MENU_CONTEXT_API: CommandMenuContextApi = {
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
canImpersonate: false,
|
||||
canAccessFullAdminPanel: false,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
};
|
||||
|
||||
+2
@@ -67,6 +67,8 @@ const getWrapper =
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
canImpersonate: false,
|
||||
canAccessFullAdminPanel: false,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
},
|
||||
|
||||
+7
@@ -1,3 +1,4 @@
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { objectPermissionsFamilySelector } from '@/auth/states/objectPermissionsFamilySelector';
|
||||
@@ -151,6 +152,10 @@ export const useCurrentCommandMenuContextApi = (): CommandMenuContextApi => {
|
||||
permissionFlags[flag] = true;
|
||||
}
|
||||
|
||||
const currentUser = useAtomStateValue(currentUserState);
|
||||
const canImpersonate = currentUser?.canImpersonate === true;
|
||||
const canAccessFullAdminPanel = currentUser?.canAccessFullAdminPanel === true;
|
||||
|
||||
const targetObjectReadPermissions: Record<string, boolean> = {};
|
||||
const targetObjectWritePermissions: Record<string, boolean> = {};
|
||||
|
||||
@@ -188,6 +193,8 @@ export const useCurrentCommandMenuContextApi = (): CommandMenuContextApi => {
|
||||
permissionFlags,
|
||||
targetObjectReadPermissions,
|
||||
targetObjectWritePermissions,
|
||||
canImpersonate,
|
||||
canAccessFullAdminPanel,
|
||||
objectMetadataItem: objectMetadataItem ?? {},
|
||||
objectMetadataLabel,
|
||||
};
|
||||
|
||||
+2
@@ -39,6 +39,8 @@ const buildMockCommandMenuContextApi = (
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
canImpersonate: false,
|
||||
canAccessFullAdminPanel: false,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
...overrides,
|
||||
|
||||
+4
@@ -25,6 +25,10 @@ export const targetObjectReadPermissions =
|
||||
null as unknown as CommandMenuContextApi['targetObjectReadPermissions'];
|
||||
export const targetObjectWritePermissions =
|
||||
null as unknown as CommandMenuContextApi['targetObjectWritePermissions'];
|
||||
export const canImpersonate =
|
||||
null as unknown as CommandMenuContextApi['canImpersonate'];
|
||||
export const canAccessFullAdminPanel =
|
||||
null as unknown as CommandMenuContextApi['canAccessFullAdminPanel'];
|
||||
|
||||
export const objectMetadataItem =
|
||||
null as unknown as CommandMenuContextApi['objectMetadataItem'];
|
||||
|
||||
@@ -12,6 +12,8 @@ export {
|
||||
featureFlags,
|
||||
targetObjectReadPermissions,
|
||||
targetObjectWritePermissions,
|
||||
canImpersonate,
|
||||
canAccessFullAdminPanel,
|
||||
isDefined,
|
||||
isNonEmptyString,
|
||||
includes,
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { Module } from '@nestjs/common';
|
||||
import { WorkspaceIteratorModule } from 'src/database/commands/command-runners/workspace-iterator.module';
|
||||
import { DropChannelStandardObjectsCommand } from 'src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798000050000-drop-channel-standard-objects.command';
|
||||
import { BackfillRelationJoinColumnIndexesCommand } from 'src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command';
|
||||
import { GateDefaultCommandMenuItemsByPermissionFlagCommand } from 'src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100010000-gate-default-command-menu-items-by-permission-flag.command';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
@@ -19,6 +20,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
providers: [
|
||||
DropChannelStandardObjectsCommand,
|
||||
BackfillRelationJoinColumnIndexesCommand,
|
||||
GateDefaultCommandMenuItemsByPermissionFlagCommand,
|
||||
],
|
||||
})
|
||||
export class V2_8_UpgradeVersionCommandModule {}
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
import { Command } from 'nest-commander';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ActiveOrSuspendedWorkspaceCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspace.command-runner';
|
||||
import { WorkspaceIteratorService } from 'src/database/commands/command-runners/workspace-iterator.service';
|
||||
import { type RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspace.command-runner';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { RegisteredWorkspaceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-workspace-command.decorator';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { STANDARD_COMMAND_MENU_ITEMS } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-command-menu-item.constant';
|
||||
import { computeTwentyStandardApplicationAllFlatEntityMaps } from 'src/engine/workspace-manager/twenty-standard-application/utils/twenty-standard-application-all-flat-entity-maps.constant';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
const UNIVERSAL_IDENTIFIERS_TO_FIX = new Set<string>([
|
||||
STANDARD_COMMAND_MENU_ITEMS.askAi.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.viewPreviousAiChats.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.composeEmail.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.composeEmailToPerson.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.composeEmailToCompany.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.composeEmailToOpportunity.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsAccounts.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsAccountsEmails.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsAccountsCalendars.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsGeneral.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsObjects.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsMembers.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsRoles.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsDomains.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsBilling.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsApiWebhooks.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsApplications.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsAI.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsSecurity.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsUpdates.universalIdentifier,
|
||||
STANDARD_COMMAND_MENU_ITEMS.goToSettingsAdminPanel.universalIdentifier,
|
||||
]);
|
||||
|
||||
@RegisteredWorkspaceCommand('2.8.0', 1798100010000)
|
||||
@Command({
|
||||
name: 'upgrade:2-8:gate-default-command-menu-items-by-permission-flag',
|
||||
description:
|
||||
'Gate default command menu items (Ask AI, settings navigation, compose email) behind their relevant permission flags so members without permission no longer see them',
|
||||
})
|
||||
export class GateDefaultCommandMenuItemsByPermissionFlagCommand extends ActiveOrSuspendedWorkspaceCommandRunner {
|
||||
constructor(
|
||||
protected readonly workspaceIteratorService: WorkspaceIteratorService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {
|
||||
super(workspaceIteratorService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options.dryRun ?? false;
|
||||
|
||||
this.logger.log(
|
||||
`${isDryRun ? '[DRY RUN] ' : ''}Gating default command menu items by permission flag for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatCommandMenuItemMaps',
|
||||
]);
|
||||
|
||||
const { allFlatEntityMaps: standardAllFlatEntityMaps } =
|
||||
computeTwentyStandardApplicationAllFlatEntityMaps({
|
||||
now: new Date().toISOString(),
|
||||
workspaceId,
|
||||
twentyStandardApplicationId: twentyStandardFlatApplication.id,
|
||||
});
|
||||
|
||||
const itemsToUpdate = [...UNIVERSAL_IDENTIFIERS_TO_FIX]
|
||||
.map((universalIdentifier) => {
|
||||
const standardItem =
|
||||
standardAllFlatEntityMaps.flatCommandMenuItemMaps
|
||||
.byUniversalIdentifier[universalIdentifier];
|
||||
const existingItem =
|
||||
existingFlatCommandMenuItemMaps.byUniversalIdentifier[
|
||||
universalIdentifier
|
||||
];
|
||||
|
||||
if (
|
||||
!isDefined(standardItem) ||
|
||||
!isDefined(existingItem) ||
|
||||
existingItem.conditionalAvailabilityExpression ===
|
||||
standardItem.conditionalAvailabilityExpression
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...existingItem,
|
||||
conditionalAvailabilityExpression:
|
||||
standardItem.conditionalAvailabilityExpression,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
if (itemsToUpdate.length === 0) {
|
||||
this.logger.log(
|
||||
`Default command menu item expressions already up to date for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Found ${itemsToUpdate.length} command menu item(s) to update for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (isDryRun) {
|
||||
this.logger.log(
|
||||
`[DRY RUN] Would update ${itemsToUpdate.length} command menu item availability expression(s) for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
commandMenuItem: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: itemsToUpdate,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
this.logger.error(
|
||||
`Failed to update command menu item availability expressions:\n${JSON.stringify(validateAndBuildResult, null, 2)}`,
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Failed to gate default command menu items by permission flag for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Successfully updated ${itemsToUpdate.length} command menu item availability expression(s) for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+24
-20
@@ -644,7 +644,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 42,
|
||||
shortLabel: 'Ask AI',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.AI',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.ASK_AI,
|
||||
@@ -658,7 +658,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 43,
|
||||
shortLabel: 'Previous AI Chats',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.AI',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.VIEW_PREVIOUS_AI_CHATS,
|
||||
@@ -687,7 +687,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 45,
|
||||
shortLabel: 'Compose',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.SEND_EMAIL_TOOL',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.COMPOSE_EMAIL,
|
||||
@@ -731,7 +731,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 48,
|
||||
shortLabel: 'Accounts',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -746,7 +746,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 49,
|
||||
shortLabel: 'Emails',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -761,7 +761,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 50,
|
||||
shortLabel: 'Calendars',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.CONNECTED_ACCOUNTS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -776,7 +776,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 51,
|
||||
shortLabel: 'General',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -791,7 +791,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 52,
|
||||
shortLabel: 'Data Model',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.DATA_MODEL',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -806,7 +806,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 53,
|
||||
shortLabel: 'Members',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE_MEMBERS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -821,7 +821,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 54,
|
||||
shortLabel: 'Roles',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE_MEMBERS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -836,7 +836,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 55,
|
||||
shortLabel: 'Domains',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -851,7 +851,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 56,
|
||||
shortLabel: 'Billing',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -866,7 +866,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 57,
|
||||
shortLabel: 'APIs & Webhooks',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.API_KEYS_AND_WEBHOOKS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -881,7 +881,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 58,
|
||||
shortLabel: 'Apps',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.APPLICATIONS',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -896,7 +896,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 59,
|
||||
shortLabel: 'AI',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.WORKSPACE',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -911,7 +911,7 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 60,
|
||||
shortLabel: 'Security',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression: 'permissionFlags.SECURITY',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -926,7 +926,8 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 61,
|
||||
shortLabel: 'Admin Panel',
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
conditionalAvailabilityExpression:
|
||||
'canImpersonate or canAccessFullAdminPanel',
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
engineComponentKey: EngineComponentKey.NAVIGATION,
|
||||
@@ -956,7 +957,8 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 63,
|
||||
shortLabel: 'Send Email',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression: 'numberOfSelectedRecords >= 1',
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords >= 1 and permissionFlags.SEND_EMAIL_TOOL',
|
||||
availabilityObjectMetadataUniversalIdentifier:
|
||||
STANDARD_OBJECTS.person.universalIdentifier,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
@@ -971,7 +973,8 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 64,
|
||||
shortLabel: 'Send Email',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression: 'numberOfSelectedRecords == 1',
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords == 1 and permissionFlags.SEND_EMAIL_TOOL',
|
||||
availabilityObjectMetadataUniversalIdentifier:
|
||||
STANDARD_OBJECTS.company.universalIdentifier,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
@@ -986,7 +989,8 @@ export const STANDARD_COMMAND_MENU_ITEMS = {
|
||||
position: 65,
|
||||
shortLabel: 'Send Email',
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
conditionalAvailabilityExpression: 'numberOfSelectedRecords == 1',
|
||||
conditionalAvailabilityExpression:
|
||||
'numberOfSelectedRecords == 1 and permissionFlags.SEND_EMAIL_TOOL',
|
||||
availabilityObjectMetadataUniversalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.universalIdentifier,
|
||||
frontComponentUniversalIdentifier: null,
|
||||
|
||||
@@ -17,6 +17,8 @@ export type CommandMenuContextApi = {
|
||||
permissionFlags: Record<string, boolean>;
|
||||
targetObjectReadPermissions: Record<string, boolean>;
|
||||
targetObjectWritePermissions: Record<string, boolean>;
|
||||
canImpersonate: boolean;
|
||||
canAccessFullAdminPanel: boolean;
|
||||
objectMetadataItem: Record<string, unknown>;
|
||||
objectMetadataLabel: string;
|
||||
};
|
||||
|
||||
+2
@@ -27,6 +27,8 @@ const buildContext = (
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
canImpersonate: false,
|
||||
canAccessFullAdminPanel: false,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
...overrides,
|
||||
|
||||
+2
@@ -27,6 +27,8 @@ const buildContext = (
|
||||
permissionFlags: {},
|
||||
targetObjectReadPermissions: {},
|
||||
targetObjectWritePermissions: {},
|
||||
canImpersonate: false,
|
||||
canAccessFullAdminPanel: false,
|
||||
objectMetadataItem: {},
|
||||
objectMetadataLabel: '',
|
||||
...overrides,
|
||||
|
||||
Reference in New Issue
Block a user