From e002a4505c9644634188663b81d851076f20acdd Mon Sep 17 00:00:00 2001 From: Bikram Choudhury Date: Mon, 27 Oct 2025 16:12:54 +0530 Subject: [PATCH] remove arm token dependency --- .vscode/settings.json | 11 ++++- src/Contracts/DataModels.ts | 8 +++ .../ContainerCopy/Context/CopyJobContext.tsx | 13 +---- src/Explorer/ContainerCopy/CopyJobUtils.ts | 9 ++++ .../hooks/usePermissionsSection.tsx | 15 ++---- .../Screens/AssignPermissions/index.tsx | 8 +-- .../Screens/SelectAccount/index.tsx | 6 +-- .../SelectSourceAndTargetContainers/index.tsx | 4 +- .../memoizedData.tsx | 49 +++++++++++-------- src/Explorer/ContainerCopy/Types/index.ts | 4 -- src/Main.tsx | 6 +-- src/Utils/CopyJobAuthUtils.ts | 9 ++++ src/Utils/arm/RbacUtils.ts | 15 ++---- src/hooks/useDataContainers.tsx | 17 ++----- src/hooks/useDatabaseAccounts.tsx | 35 +++++++------ src/hooks/useDatabases.tsx | 19 +++---- src/hooks/useSubscriptions.tsx | 19 ++++--- 17 files changed, 129 insertions(+), 118 deletions(-) create mode 100644 src/Utils/CopyJobAuthUtils.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index a57d40961..bf6c96252 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,5 +24,14 @@ "source.organizeImports": "explicit" }, "typescript.preferences.importModuleSpecifier": "non-relative", - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[typescriptreact]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[json]": { + "editor.defaultFormatter": "vscode.json-language-features" + } } diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index b0bb8eb29..b05d7ebac 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -36,6 +36,14 @@ export interface DatabaseAccountSystemData { export interface DatabaseAccountBackupPolicy { type: string; + /* periodicModeProperties?: { + backupIntervalInMinutes: number; + backupRetentionIntervalInHours: number; + backupStorageRedundancy: string; + }; + continuousModeProperties?: { + tier: string; + }; */ } export interface DatabaseAccountExtendedProperties { diff --git a/src/Explorer/ContainerCopy/Context/CopyJobContext.tsx b/src/Explorer/ContainerCopy/Context/CopyJobContext.tsx index 6af75fd38..e3834a980 100644 --- a/src/Explorer/ContainerCopy/Context/CopyJobContext.tsx +++ b/src/Explorer/ContainerCopy/Context/CopyJobContext.tsx @@ -1,7 +1,5 @@ import React from "react"; import { userContext } from "UserContext"; -import { useAADAuth } from "../../../hooks/useAADAuth"; -import { useConfig } from "../../../hooks/useConfig"; import { CopyJobMigrationType } from "../Enums"; import { CopyJobContextProviderType, CopyJobContextState, CopyJobFlowType } from "../Types"; @@ -39,24 +37,15 @@ const getInitialCopyJobState = (): CopyJobContextState => { } const CopyJobContextProvider: React.FC = (props) => { - const config = useConfig(); - const { isLoggedIn, armToken, account } = useAADAuth(config); - const principalId = account?.localAccountId ?? ""; - const [copyJobState, setCopyJobState] = React.useState(getInitialCopyJobState()); const [flow, setFlow] = React.useState(null); - if (!isLoggedIn || !armToken) { - // Add a shimmer or loader here - return null; - } - const resetCopyJobState = () => { setCopyJobState(getInitialCopyJobState()); } return ( - + {props.children} ); diff --git a/src/Explorer/ContainerCopy/CopyJobUtils.ts b/src/Explorer/ContainerCopy/CopyJobUtils.ts index c9bcaddd2..6e436ab0d 100644 --- a/src/Explorer/ContainerCopy/CopyJobUtils.ts +++ b/src/Explorer/ContainerCopy/CopyJobUtils.ts @@ -79,3 +79,12 @@ export function extractErrorMessage(error: CopyJobErrorType): CopyJobErrorType { } } +export function getAccountDetailsFromResourceId(accountId: string | undefined) { + if (!accountId) { + return null; + } + const pattern = new RegExp('/subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/Microsoft\\.DocumentDB/databaseAccounts/([^/]+)', 'i'); + const matches = accountId.match(pattern); + const [_, subscriptionId, resourceGroup, accountName] = matches || []; + return { subscriptionId, resourceGroup, accountName }; +} \ No newline at end of file diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx index 8e2917a86..ed2a5588f 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/hooks/usePermissionsSection.tsx @@ -25,7 +25,7 @@ export interface PermissionSectionConfig { Component: React.ComponentType disabled: boolean; completed?: boolean; - validate?: (state: CopyJobContextState, armToken?: string) => boolean | Promise; + validate?: (state: CopyJobContextState) => boolean | Promise; } // Section IDs for maintainability @@ -66,10 +66,9 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [ title: ContainerCopyMessages.readPermissionAssigned.title, Component: AddReadPermissionToDefaultIdentity, disabled: true, - validate: async (state: CopyJobContextState, armToken?: string) => { + validate: async (state: CopyJobContextState) => { const principalId = state?.target?.account?.identity?.principalId; const rolesAssigned = await fetchRoleAssignments( - armToken, state.source?.subscription?.subscriptionId, state.source?.account?.resourceGroup, state.source?.account?.name, @@ -77,7 +76,6 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [ ); const roleDefinitions = await fetchRoleDefinitions( - armToken, rolesAssigned ?? [] ); return checkTargetHasReaderRoleOnSource(roleDefinitions ?? []); @@ -127,10 +125,7 @@ export function checkTargetHasReaderRoleOnSource(roleDefinitions: RoleDefinition * Returns the permission sections configuration for the Assign Permissions screen. * Memoizes derived values for performance and decouples logic for testability. */ -const usePermissionSections = ( - state: CopyJobContextState, - armToken: string, -): PermissionSectionConfig[] => { +const usePermissionSections = (state: CopyJobContextState): PermissionSectionConfig[] => { const { validationCache, setValidationCache } = useCopyJobPrerequisitesCache(); const [permissionSections, setPermissionSections] = useState(null); const isValidatingRef = useRef(false); @@ -169,7 +164,7 @@ const usePermissionSections = ( } // We've reached the first non-cached section - validate it if (section.validate) { - const isValid = await section.validate(state, armToken); + const isValid = await section.validate(state); newValidationCache.set(section.id, isValid); result.push({ ...section, completed: isValid }); // Stop validation if current section failed @@ -197,7 +192,7 @@ const usePermissionSections = ( return () => { isValidatingRef.current = false; } - }, [state, armToken, sectionToValidate]); + }, [state, sectionToValidate]); return permissionSections ?? []; }; diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/index.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/index.tsx index b3fee3fb4..4cec74262 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/index.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/AssignPermissions/index.tsx @@ -39,8 +39,8 @@ const PermissionSection: React.FC = ({ ); const AssignPermissions = () => { - const { armToken, copyJobState } = useCopyJobContext(); - const permissionSections = usePermissionSections(copyJobState, armToken); + const { copyJobState } = useCopyJobContext(); + const permissionSections = usePermissionSections(copyJobState); const [openItems, setOpenItems] = React.useState([]); const indentLevels = React.useMemo( @@ -48,10 +48,6 @@ const AssignPermissions = () => { [] ); - /* const onMoveToNextSection: AccordionToggleEventHandler = useCallback((_event, data) => { - setOpenItems(data.openItems); - }, []); */ - useEffect(() => { const firstIncompleteSection = permissionSections.find(section => !section.completed); const nextOpenItems = firstIncompleteSection ? [firstIncompleteSection.id] : []; diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/index.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/index.tsx index bf070e413..0dd4cdc73 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/index.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectAccount/index.tsx @@ -15,11 +15,11 @@ interface SelectAccountProps { } const SelectAccount = React.memo( (_props: SelectAccountProps) => { - const { armToken, copyJobState, setCopyJobState } = useCopyJobContext(); + const { copyJobState, setCopyJobState } = useCopyJobContext(); const selectedSubscriptionId = copyJobState?.source?.subscription?.subscriptionId; - const subscriptions: Subscription[] = useSubscriptions(armToken); - const allAccounts: DatabaseAccount[] = useDatabaseAccounts(selectedSubscriptionId, armToken); + const subscriptions: Subscription[] = useSubscriptions(); + const allAccounts: DatabaseAccount[] = useDatabaseAccounts(selectedSubscriptionId); const sqlApiOnlyAccounts: DatabaseAccount[] = allAccounts?.filter(account => account.type === "SQL" || account.kind === "GlobalDocumentDB"); const { subscriptionOptions, accountOptions } = useDropdownOptions(subscriptions, sqlApiOnlyAccounts); diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/index.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/index.tsx index 88d642755..e6435205d 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/index.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/index.tsx @@ -11,7 +11,7 @@ import { useMemoizedSourceAndTargetData } from "./memoizedData"; interface SelectSourceAndTargetContainersProps { } const SelectSourceAndTargetContainers = (_props: SelectSourceAndTargetContainersProps) => { - const { armToken, copyJobState, setCopyJobState } = useCopyJobContext(); + const { copyJobState, setCopyJobState } = useCopyJobContext(); const { source, target, @@ -19,7 +19,7 @@ const SelectSourceAndTargetContainers = (_props: SelectSourceAndTargetContainers sourceContainerParams, targetDbParams, targetContainerParams - } = useMemoizedSourceAndTargetData(copyJobState, armToken); + } = useMemoizedSourceAndTargetData(copyJobState); // Custom hooks const sourceDatabases = useDatabases(...sourceDbParams) || []; diff --git a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/memoizedData.tsx b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/memoizedData.tsx index 077b0fad7..6cb246826 100644 --- a/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/memoizedData.tsx +++ b/src/Explorer/ContainerCopy/CreateCopyJob/Screens/SelectSourceAndTargetContainers/memoizedData.tsx @@ -1,57 +1,64 @@ import React from "react"; +import { getAccountDetailsFromResourceId } from "../../../CopyJobUtils"; import { CopyJobContextState, DatabaseParams, DataContainerParams } from "../../../Types"; -export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState, armToken: string) { +export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState) { const { source, target } = copyJobState ?? {}; const selectedSourceAccount = source?.account; const selectedTargetAccount = target?.account; + const { + subscriptionId: sourceSubscriptionId, + resourceGroup: sourceResourceGroup, + accountName: sourceAccountName + } = getAccountDetailsFromResourceId(selectedSourceAccount?.id); + const { + subscriptionId: targetSubscriptionId, + resourceGroup: targetResourceGroup, + accountName: targetAccountName + } = getAccountDetailsFromResourceId(selectedTargetAccount?.id); const sourceDbParams = React.useMemo( () => [ - armToken, - source?.subscription?.subscriptionId, - selectedSourceAccount?.resourceGroup, - selectedSourceAccount?.name, + sourceSubscriptionId, + sourceResourceGroup, + sourceAccountName, 'SQL', ] as DatabaseParams, - [armToken, source?.subscription?.subscriptionId, selectedSourceAccount] + [sourceSubscriptionId, sourceResourceGroup, sourceAccountName] ); const sourceContainerParams = React.useMemo( () => [ - armToken, - source?.subscription?.subscriptionId, - selectedSourceAccount?.resourceGroup, - selectedSourceAccount?.name, + sourceSubscriptionId, + sourceResourceGroup, + sourceAccountName, source?.databaseId, 'SQL', ] as DataContainerParams, - [armToken, source?.subscription?.subscriptionId, selectedSourceAccount, source?.databaseId] + [sourceSubscriptionId, sourceResourceGroup, sourceAccountName, source?.databaseId] ); const targetDbParams = React.useMemo( () => [ - armToken, - target?.subscriptionId, - selectedTargetAccount?.resourceGroup, - selectedTargetAccount?.name, + targetSubscriptionId, + targetResourceGroup, + targetAccountName, 'SQL', ] as DatabaseParams, - [armToken, target?.subscriptionId, selectedTargetAccount] + [targetSubscriptionId, targetResourceGroup, targetAccountName] ); const targetContainerParams = React.useMemo( () => [ - armToken, - target?.subscriptionId, - selectedTargetAccount?.resourceGroup, - selectedTargetAccount?.name, + targetSubscriptionId, + targetResourceGroup, + targetAccountName, target?.databaseId, 'SQL', ] as DataContainerParams, - [armToken, target?.subscriptionId, selectedTargetAccount, target?.databaseId] + [targetSubscriptionId, targetResourceGroup, targetAccountName, target?.databaseId] ); return { source, target, sourceDbParams, sourceContainerParams, targetDbParams, targetContainerParams }; diff --git a/src/Explorer/ContainerCopy/Types/index.ts b/src/Explorer/ContainerCopy/Types/index.ts index 3d9cd3ff2..54fbc2dce 100644 --- a/src/Explorer/ContainerCopy/Types/index.ts +++ b/src/Explorer/ContainerCopy/Types/index.ts @@ -28,14 +28,12 @@ export type DropdownOptionType = { }; export type DatabaseParams = [ - string, string | undefined, string | undefined, string | undefined, ApiType ]; export type DataContainerParams = [ - string, string | undefined, string | undefined, string | undefined, @@ -80,8 +78,6 @@ export interface CopyJobFlowType { } export interface CopyJobContextProviderType { - principalId: string; - armToken: string; flow: CopyJobFlowType; setFlow: React.Dispatch>; copyJobState: CopyJobContextState | null; diff --git a/src/Main.tsx b/src/Main.tsx index a61a7699a..2b61c594e 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -78,13 +78,13 @@ const App: React.FunctionComponent = () => { } StyleConstants.updateStyles(); const explorer = useKnockoutExplorer(config?.platform); - // console.log("Using config: ", config); + console.log("Using config: ", config); if (!explorer) { return ; } - // console.log("Using explorer: ", explorer); - // console.log("Using userContext: ", userContext); + console.log("Using explorer: ", explorer); + console.log("Using userContext: ", userContext); return ( diff --git a/src/Utils/CopyJobAuthUtils.ts b/src/Utils/CopyJobAuthUtils.ts new file mode 100644 index 000000000..f18212741 --- /dev/null +++ b/src/Utils/CopyJobAuthUtils.ts @@ -0,0 +1,9 @@ +import { userContext } from "UserContext"; + +export function getCopyJobAuthorizationHeader(token: string = ""): Headers { + const headers = new Headers(); + const authToken = token ? `Bearer ${token}` : userContext.authorizationToken; + headers.append("Authorization", authToken); + headers.append("Content-Type", "application/json"); + return headers; +} \ No newline at end of file diff --git a/src/Utils/arm/RbacUtils.ts b/src/Utils/arm/RbacUtils.ts index 6275f2019..1ee14007d 100644 --- a/src/Utils/arm/RbacUtils.ts +++ b/src/Utils/arm/RbacUtils.ts @@ -1,8 +1,8 @@ import { configContext } from "ConfigContext"; import { armRequest } from "Utils/arm/request"; +import { getCopyJobAuthorizationHeader } from "../CopyJobAuthUtils"; export type FetchAccountDetailsParams = { - armToken: string; subscriptionId: string; resourceGroupName: string; accountName: string; @@ -43,13 +43,6 @@ const getArmBaseUrl = (): string => { return base.endsWith("/") ? base.slice(0, -1) : base; }; -const createAuthHeaders = (armToken: string): Headers => { - const headers = new Headers(); - headers.append("Authorization", `Bearer ${armToken}`); - headers.append("Content-Type", "application/json"); - return headers; -}; - const buildArmUrl = (path: string): string => `${getArmBaseUrl()}${path}?api-version=${apiVersion}`; @@ -64,7 +57,6 @@ const handleResponse = async (response: Response, context: string) => { }; export const fetchRoleAssignments = async ( - armToken: string, subscriptionId: string, resourceGroupName: string, accountName: string, @@ -74,7 +66,7 @@ export const fetchRoleAssignments = async ( `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlRoleAssignments` ); - const response = await fetch(uri, { method: "GET", headers: createAuthHeaders(armToken) }); + const response = await fetch(uri, { method: "GET", headers: getCopyJobAuthorizationHeader() }); const data = await handleResponse(response, "role assignments"); return (data.value || []).filter( @@ -84,13 +76,12 @@ export const fetchRoleAssignments = async ( }; export const fetchRoleDefinitions = async ( - armToken: string, roleAssignments: RoleAssignmentType[] ): Promise => { const roleDefinitionIds = roleAssignments.map(assignment => assignment.properties.roleDefinitionId); const uniqueRoleDefinitionIds = Array.from(new Set(roleDefinitionIds)); - const headers = createAuthHeaders(armToken); + const headers = getCopyJobAuthorizationHeader(); const roleDefinitionUris = uniqueRoleDefinitionIds.map((id) => buildArmUrl(id)); const promises = roleDefinitionUris.map((url) => fetch(url, { method: "GET", headers })); diff --git a/src/hooks/useDataContainers.tsx b/src/hooks/useDataContainers.tsx index 16ba491d9..d79a94fcc 100644 --- a/src/hooks/useDataContainers.tsx +++ b/src/hooks/useDataContainers.tsx @@ -3,10 +3,10 @@ import useSWR from "swr"; import { getCollectionEndpoint, getDatabaseEndpoint } from "../Common/DatabaseAccountUtility"; import { configContext } from "../ConfigContext"; import { ApiType } from "../UserContext"; +import { getCopyJobAuthorizationHeader } from "../Utils/CopyJobAuthUtils"; const apiVersion = "2023-09-15"; export interface FetchDataContainersListParams { - armToken: string; subscriptionId: string; resourceGroupName: string; databaseName: string; @@ -27,7 +27,6 @@ const buildReadDataContainersListUrl = (params: FetchDataContainersListParams): } const fetchDataContainersList = async ( - armToken: string, subscriptionId: string, resourceGroupName: string, accountName: string, @@ -35,17 +34,13 @@ const fetchDataContainersList = async ( apiType: ApiType ): Promise => { const uri = buildReadDataContainersListUrl({ - armToken, subscriptionId, resourceGroupName, accountName, databaseName, apiType }); - const headers = new Headers(); - const bearer = `Bearer ${armToken}`; - headers.append("Authorization", bearer); - headers.append("Content-Type", "application/json"); + const headers = getCopyJobAuthorizationHeader(); const response = await fetch(uri, { method: "GET", @@ -61,7 +56,6 @@ const fetchDataContainersList = async ( }; export function useDataContainers( - armToken: string, subscriptionId: string, resourceGroupName: string, accountName: string, @@ -70,13 +64,12 @@ export function useDataContainers( ): DatabaseModel[] | undefined { const { data } = useSWR( () => ( - armToken && subscriptionId && resourceGroupName && accountName && databaseName && apiType ? [ + subscriptionId && resourceGroupName && accountName && databaseName && apiType ? [ "fetchContainersLinkedToDatabases", - armToken, subscriptionId, resourceGroupName, accountName, databaseName, apiType + subscriptionId, resourceGroupName, accountName, databaseName, apiType ] : undefined ), - (_, armToken, subscriptionId, resourceGroupName, accountName, databaseName, apiType) => fetchDataContainersList( - armToken, + (_, subscriptionId, resourceGroupName, accountName, databaseName, apiType) => fetchDataContainersList( subscriptionId, resourceGroupName, accountName, diff --git a/src/hooks/useDatabaseAccounts.tsx b/src/hooks/useDatabaseAccounts.tsx index f517b2e30..efa36137a 100644 --- a/src/hooks/useDatabaseAccounts.tsx +++ b/src/hooks/useDatabaseAccounts.tsx @@ -1,6 +1,7 @@ import { HttpHeaders } from "Common/Constants"; import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph"; import useSWR from "swr"; +import { userContext } from "UserContext"; import { configContext } from "../ConfigContext"; import { DatabaseAccount } from "../Contracts/DataModels"; /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -10,9 +11,12 @@ interface AccountListResult { value: DatabaseAccount[]; } -export async function fetchDatabaseAccounts(subscriptionId: string, accessToken: string): Promise { +export async function fetchDatabaseAccounts(subscriptionId: string, accessToken: string = ""): Promise { + if (!accessToken && !userContext.authorizationToken) { + return []; + } const headers = new Headers(); - const bearer = `Bearer ${accessToken}`; + const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken; headers.append("Authorization", bearer); @@ -35,10 +39,13 @@ export async function fetchDatabaseAccounts(subscriptionId: string, accessToken: export async function fetchDatabaseAccountsFromGraph( subscriptionId: string, - accessToken: string, + accessToken: string = "", ): Promise { + if (!accessToken && !userContext.authorizationToken) { + return []; + } const headers = new Headers(); - const bearer = `Bearer ${accessToken}`; + const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken; headers.append("Authorization", bearer); headers.append(HttpHeaders.contentType, "application/json"); @@ -54,15 +61,15 @@ export async function fetchDatabaseAccountsFromGraph( subscriptions: [subscriptionId], ...(skipToken ? { - options: { - $skipToken: skipToken, - } as QueryRequestOptions, - } + options: { + $skipToken: skipToken, + } as QueryRequestOptions, + } : { - options: { - $top: 150, - } as QueryRequestOptions, - }), + options: { + $top: 150, + } as QueryRequestOptions, + }), }; const response = await fetch(managementResourceGraphAPIURL, { @@ -85,9 +92,9 @@ export async function fetchDatabaseAccountsFromGraph( return databaseAccounts.sort((a, b) => a.name.localeCompare(b.name)); } -export function useDatabaseAccounts(subscriptionId: string, armToken: string): DatabaseAccount[] | undefined { +export function useDatabaseAccounts(subscriptionId: string, armToken: string = ""): DatabaseAccount[] | undefined { const { data } = useSWR( - () => (armToken && subscriptionId ? ["databaseAccounts", subscriptionId, armToken] : undefined), + () => (subscriptionId ? ["databaseAccounts", subscriptionId, armToken] : undefined), (_, subscriptionId, armToken) => fetchDatabaseAccountsFromGraph(subscriptionId, armToken), ); return data; diff --git a/src/hooks/useDatabases.tsx b/src/hooks/useDatabases.tsx index a0d8f4823..a9f0237c3 100644 --- a/src/hooks/useDatabases.tsx +++ b/src/hooks/useDatabases.tsx @@ -3,10 +3,10 @@ import useSWR from "swr"; import { getDatabaseEndpoint } from "../Common/DatabaseAccountUtility"; import { configContext } from "../ConfigContext"; import { ApiType } from "../UserContext"; +import { getCopyJobAuthorizationHeader } from "../Utils/CopyJobAuthUtils"; const apiVersion = "2023-09-15"; export interface FetchDatabasesListParams { - armToken: string; subscriptionId: string; resourceGroupName: string; accountName: string; @@ -24,12 +24,9 @@ const buildReadDatabasesListUrl = (params: FetchDatabasesListParams): string => return `${armEndpoint}/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/${databaseEndpoint}?api-version=${apiVersion}`; } -const fetchDatabasesList = async (armToken: string, subscriptionId: string, resourceGroupName: string, accountName: string, apiType: ApiType): Promise => { - const uri = buildReadDatabasesListUrl({ armToken, subscriptionId, resourceGroupName, accountName, apiType }); - const headers = new Headers(); - const bearer = `Bearer ${armToken}`; - headers.append("Authorization", bearer); - headers.append("Content-Type", "application/json"); +const fetchDatabasesList = async (subscriptionId: string, resourceGroupName: string, accountName: string, apiType: ApiType): Promise => { + const uri = buildReadDatabasesListUrl({ subscriptionId, resourceGroupName, accountName, apiType }); + const headers = getCopyJobAuthorizationHeader(); const response = await fetch(uri, { method: "GET", @@ -45,7 +42,6 @@ const fetchDatabasesList = async (armToken: string, subscriptionId: string, reso }; export function useDatabases( - armToken: string, subscriptionId: string, resourceGroupName: string, accountName: string, @@ -53,13 +49,12 @@ export function useDatabases( ): DatabaseModel[] | undefined { const { data } = useSWR( () => ( - armToken && subscriptionId && resourceGroupName && accountName && apiType ? [ + subscriptionId && resourceGroupName && accountName && apiType ? [ "fetchDatabasesLinkedToResource", - armToken, subscriptionId, resourceGroupName, accountName, apiType + subscriptionId, resourceGroupName, accountName, apiType ] : undefined ), - (_, armToken, subscriptionId, resourceGroupName, accountName, apiType) => fetchDatabasesList( - armToken, + (_, subscriptionId, resourceGroupName, accountName, apiType) => fetchDatabasesList( subscriptionId, resourceGroupName, accountName, diff --git a/src/hooks/useSubscriptions.tsx b/src/hooks/useSubscriptions.tsx index ca80a87f5..5977ac911 100644 --- a/src/hooks/useSubscriptions.tsx +++ b/src/hooks/useSubscriptions.tsx @@ -1,6 +1,7 @@ import { HttpHeaders } from "Common/Constants"; import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph"; import useSWR from "swr"; +import { userContext } from "UserContext"; import { configContext } from "../ConfigContext"; import { Subscription } from "../Contracts/DataModels"; /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -10,9 +11,12 @@ interface SubscriptionListResult { value: Subscription[]; } -export async function fetchSubscriptions(accessToken: string): Promise { +export async function fetchSubscriptions(accessToken: string = ""): Promise { + if (!accessToken && !userContext.authorizationToken) { + return []; + } const headers = new Headers(); - const bearer = `Bearer ${accessToken}`; + const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken; headers.append("Authorization", bearer); @@ -35,9 +39,12 @@ export async function fetchSubscriptions(accessToken: string): Promise a.displayName.localeCompare(b.displayName)); } -export async function fetchSubscriptionsFromGraph(accessToken: string): Promise { +export async function fetchSubscriptionsFromGraph(accessToken: string = ""): Promise { + if (!accessToken && !userContext.authorizationToken) { + return []; + } const headers = new Headers(); - const bearer = `Bearer ${accessToken}`; + const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken; headers.append("Authorization", bearer); headers.append(HttpHeaders.contentType, "application/json"); @@ -85,9 +92,9 @@ export async function fetchSubscriptionsFromGraph(accessToken: string): Promise< return subscriptions.sort((a, b) => a.displayName.localeCompare(b.displayName)); } -export function useSubscriptions(armToken: string): Subscription[] | undefined { +export function useSubscriptions(armToken: string = ""): Subscription[] | undefined { const { data } = useSWR( - () => (armToken ? ["subscriptions", armToken] : undefined), + () => ["subscriptions", armToken], (_, armToken) => fetchSubscriptionsFromGraph(armToken), ); return data;