mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-26 13:14:04 +00:00
remove arm token dependency
This commit is contained in:
@@ -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<CopyJobContextProviderProps> = (props) => {
|
||||
const config = useConfig();
|
||||
const { isLoggedIn, armToken, account } = useAADAuth(config);
|
||||
const principalId = account?.localAccountId ?? "";
|
||||
|
||||
const [copyJobState, setCopyJobState] = React.useState<CopyJobContextState>(getInitialCopyJobState());
|
||||
const [flow, setFlow] = React.useState<CopyJobFlowType | null>(null);
|
||||
|
||||
if (!isLoggedIn || !armToken) {
|
||||
// Add a shimmer or loader here
|
||||
return null;
|
||||
}
|
||||
|
||||
const resetCopyJobState = () => {
|
||||
setCopyJobState(getInitialCopyJobState());
|
||||
}
|
||||
|
||||
return (
|
||||
<CopyJobContext.Provider value={{ principalId, armToken, copyJobState, setCopyJobState, flow, setFlow, resetCopyJobState }}>
|
||||
<CopyJobContext.Provider value={{ copyJobState, setCopyJobState, flow, setFlow, resetCopyJobState }}>
|
||||
{props.children}
|
||||
</CopyJobContext.Provider>
|
||||
);
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export interface PermissionSectionConfig {
|
||||
Component: React.ComponentType
|
||||
disabled: boolean;
|
||||
completed?: boolean;
|
||||
validate?: (state: CopyJobContextState, armToken?: string) => boolean | Promise<boolean>;
|
||||
validate?: (state: CopyJobContextState) => boolean | Promise<boolean>;
|
||||
}
|
||||
|
||||
// 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<PermissionSectionConfig[] | null>(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 ?? [];
|
||||
};
|
||||
|
||||
@@ -39,8 +39,8 @@ const PermissionSection: React.FC<PermissionSectionConfig> = ({
|
||||
);
|
||||
|
||||
const AssignPermissions = () => {
|
||||
const { armToken, copyJobState } = useCopyJobContext();
|
||||
const permissionSections = usePermissionSections(copyJobState, armToken);
|
||||
const { copyJobState } = useCopyJobContext();
|
||||
const permissionSections = usePermissionSections(copyJobState);
|
||||
const [openItems, setOpenItems] = React.useState<string[]>([]);
|
||||
|
||||
const indentLevels = React.useMemo<IndentLevel[]>(
|
||||
@@ -48,10 +48,6 @@ const AssignPermissions = () => {
|
||||
[]
|
||||
);
|
||||
|
||||
/* const onMoveToNextSection: AccordionToggleEventHandler<string> = useCallback((_event, data) => {
|
||||
setOpenItems(data.openItems);
|
||||
}, []); */
|
||||
|
||||
useEffect(() => {
|
||||
const firstIncompleteSection = permissionSections.find(section => !section.completed);
|
||||
const nextOpenItems = firstIncompleteSection ? [firstIncompleteSection.id] : [];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) || [];
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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<React.SetStateAction<CopyJobFlowType>>;
|
||||
copyJobState: CopyJobContextState | null;
|
||||
|
||||
Reference in New Issue
Block a user