From 57c51f462abec92a5d099e061fe560a6315a26ae Mon Sep 17 00:00:00 2001 From: Bikram Choudhury Date: Tue, 25 Nov 2025 17:12:44 +0530 Subject: [PATCH] update account only if allVersion feature is not enabled --- src/Contracts/DataModels.ts | 1 + .../ContainerCopy/Actions/CopyJobActions.tsx | 4 +++- .../ContainerCopy/ContainerCopyMessages.ts | 20 +++++++++++----- .../AddReadPermissionToDefaultIdentity.tsx | 1 - .../AssignPermissions/OnlineCopyEnabled.tsx | 24 +++++++++++++------ .../hooks/useManagedIdentity.tsx | 1 - .../hooks/usePermissionsSection.tsx | 19 +++++++++------ src/Utils/arm/databaseAccountUtils.ts | 2 +- 8 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index 0c02ae5fa..dd731a0f8 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -73,6 +73,7 @@ export interface DatabaseAccountExtendedProperties { publicNetworkAccess?: string; enablePriorityBasedExecution?: boolean; vcoreMongoEndpoint?: string; + enableAllVersionsAndDeletesChangeFeed?: boolean; } export interface DatabaseAccountResponseLocation { diff --git a/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx b/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx index 7668fa3e6..030ad57be 100644 --- a/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx +++ b/src/Explorer/ContainerCopy/Actions/CopyJobActions.tsx @@ -23,6 +23,7 @@ import { extractErrorMessage, formatUTCDateTime, getAccountDetailsFromResourceId, + isIntraAccountCopy, } from "../CopyJobUtils"; import CreateCopyJobScreensProvider from "../CreateCopyJob/Screens/CreateCopyJobScreensProvider"; import { CopyJobActions, CopyJobStatusType } from "../Enums/CopyJobEnums"; @@ -138,11 +139,12 @@ export const submitCreateCopyJob = async (state: CopyJobContextState, onSuccess: const { subscriptionId, resourceGroup, accountName } = getAccountDetailsFromResourceId( userContext.databaseAccount?.id || "", ); + const isSameAccount = isIntraAccountCopy(source?.account?.id, target?.account?.id); const body = { properties: { source: { component: "CosmosDBSql", - remoteAccountName: source?.account?.name, + ...(isSameAccount ? {} : { accountName: source?.account?.name }), databaseName: source?.databaseId, containerName: source?.containerId, }, diff --git a/src/Explorer/ContainerCopy/ContainerCopyMessages.ts b/src/Explorer/ContainerCopy/ContainerCopyMessages.ts index 5e2d4d8cf..fdc4e38c6 100644 --- a/src/Explorer/ContainerCopy/ContainerCopyMessages.ts +++ b/src/Explorer/ContainerCopy/ContainerCopyMessages.ts @@ -55,13 +55,15 @@ export default { "To copy data from the source to the destination container, ensure that the managed identity of the destination account has read access to the source account by completing the following steps.", intraAccountOnlineDescription: (accountName: string) => `Follow the steps below to enable online copy on your "${accountName}" account.`, - commonConfiguration: { - title: "Common configuration", - description: "Basic permissions required for copy operations", + crossAccountConfiguration: { + title: "Cross-account container copy", + description: (sourceAccount: string, destinationAccount: string) => + `Please follow the instruction below to grant requisite permissions to copy data from "${sourceAccount}" to "${destinationAccount}".`, }, onlineConfiguration: { - title: "Online copy configuration", - description: "Additional permissions required for online copy operations", + title: "Online container copy", + description: (accountName: string) => + `Please follow the instructions below to enable online copy on your "${accountName}" account.`, }, }, toggleBtn: { @@ -130,10 +132,16 @@ export default { onlineCopyEnabled: { title: "Online copy enabled", description: (accountName: string) => - `"To enable the online copy feature on your ${accountName} account, proceed with the action below.`, + `Enable online container copy by clicking the button below on your "${accountName}" account.`, hrefText: "Learn more about online copy jobs", href: "https://learn.microsoft.com/en-us/azure/cosmos-db/container-copy?tabs=online-copy&pivots=api-nosql#enable-online-copy", buttonText: "Enable Online Copy", + validateAllVersionsAndDeletesChangeFeedSpinnerLabel: + "Validating All versions and deletes change feed mode (preview)...", + enablingAllVersionsAndDeletesChangeFeedSpinnerLabel: + "Enabling All versions and deletes change feed mode (preview)...", + enablingOnlineCopySpinnerLabel: (accountName: string) => + `Enabling online copy on your "${accountName}" account ...`, }, MonitorJobs: { Columns: { diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx index 075257644..1c4b0a85d 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/AddReadPermissionToDefaultIdentity.tsx @@ -53,7 +53,6 @@ const AddReadPermissionToDefaultIdentity: React.FC { const [loading, setLoading] = React.useState(false); + const [loaderMessage, setLoaderMessage] = React.useState(""); const [showRefreshButton, setShowRefreshButton] = React.useState(false); const intervalRef = React.useRef(null); const timeoutRef = React.useRef(null); @@ -75,12 +76,21 @@ const OnlineCopyEnabled: React.FC = () => { setShowRefreshButton(false); try { - await updateDatabaseAccount(sourceSubscriptionId, sourceResourceGroup, sourceAccountName, { - properties: { - enableAllVersionsAndDeletesChangeFeed: true, - }, - }); - + setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.validateAllVersionsAndDeletesChangeFeedSpinnerLabel); + const sourAccountBeforeUpdate = await fetchDatabaseAccount( + sourceSubscriptionId, + sourceResourceGroup, + sourceAccountName, + ); + if (!sourAccountBeforeUpdate?.properties.enableAllVersionsAndDeletesChangeFeed) { + setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.enablingAllVersionsAndDeletesChangeFeedSpinnerLabel); + await updateDatabaseAccount(sourceSubscriptionId, sourceResourceGroup, sourceAccountName, { + properties: { + enableAllVersionsAndDeletesChangeFeed: true, + }, + }); + } + setLoaderMessage(ContainerCopyMessages.onlineCopyEnabled.enablingOnlineCopySpinnerLabel(sourceAccountName)); await updateDatabaseAccount(sourceSubscriptionId, sourceResourceGroup, sourceAccountName, { properties: { capabilities: [...sourceAccountCapabilities, { name: CapabilityNames.EnableOnlineCopyFeature }], @@ -120,7 +130,7 @@ const OnlineCopyEnabled: React.FC = () => { return ( - + {ContainerCopyMessages.onlineCopyEnabled.description(source?.account?.name || "")}  diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/useManagedIdentity.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/useManagedIdentity.tsx index 559789191..c054421f5 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/useManagedIdentity.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/useManagedIdentity.tsx @@ -44,7 +44,6 @@ const useManagedIdentity = ( const errorMessage = error.message || "Error enabling system-assigned managed identity. Please try again later."; logError(errorMessage, "CopyJob/useManagedIdentity.handleAddSystemIdentity"); setContextError(errorMessage); - } finally { setLoading(false); } }, [updateIdentityFn]); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx index 8ee6d8355..747635e6d 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx @@ -186,15 +186,20 @@ const usePermissionSections = (state: CopyJobContextState): PermissionGroupConfi const groupsToValidate = useMemo(() => { const isSameAccount = isIntraAccountCopy(sourceAccount.accountId, targetAccount.accountId); - const commonSections = isSameAccount ? [] : [...PERMISSION_SECTIONS_CONFIG]; + const crossAccountSections = isSameAccount ? [] : [...PERMISSION_SECTIONS_CONFIG]; const groups: PermissionGroupConfig[] = []; + const sourceAccountName = state.source?.account?.name || ""; + const targetAccountName = state.target?.account?.name || ""; - if (commonSections.length > 0) { + if (crossAccountSections.length > 0) { groups.push({ - id: "commonConfigs", - title: ContainerCopyMessages.assignPermissions.commonConfiguration.title, - description: ContainerCopyMessages.assignPermissions.commonConfiguration.description, - sections: commonSections, + id: "crossAccountConfigs", + title: ContainerCopyMessages.assignPermissions.crossAccountConfiguration.title, + description: ContainerCopyMessages.assignPermissions.crossAccountConfiguration.description( + sourceAccountName, + targetAccountName, + ), + sections: crossAccountSections, }); } @@ -202,7 +207,7 @@ const usePermissionSections = (state: CopyJobContextState): PermissionGroupConfi groups.push({ id: "onlineConfigs", title: ContainerCopyMessages.assignPermissions.onlineConfiguration.title, - description: ContainerCopyMessages.assignPermissions.onlineConfiguration.description, + description: ContainerCopyMessages.assignPermissions.onlineConfiguration.description(sourceAccountName), sections: [...PERMISSION_SECTIONS_FOR_ONLINE_JOBS], }); } diff --git a/src/Utils/arm/databaseAccountUtils.ts b/src/Utils/arm/databaseAccountUtils.ts index c7eb756b0..c689eccec 100644 --- a/src/Utils/arm/databaseAccountUtils.ts +++ b/src/Utils/arm/databaseAccountUtils.ts @@ -2,7 +2,7 @@ import { DatabaseAccount } from "Contracts/DataModels"; import { userContext } from "UserContext"; import { buildArmUrl } from "Utils/arm/armUtils"; -const apiVersion = "2025-04-15"; +const apiVersion = "2025-05-01-preview"; export type FetchAccountDetailsParams = { subscriptionId: string; resourceGroupName: string;