mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-06-14 00:17:36 +01:00
remove arm token dependency
This commit is contained in:
Vendored
+10
-1
@@ -24,5 +24,14 @@
|
|||||||
"source.organizeImports": "explicit"
|
"source.organizeImports": "explicit"
|
||||||
},
|
},
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ export interface DatabaseAccountSystemData {
|
|||||||
|
|
||||||
export interface DatabaseAccountBackupPolicy {
|
export interface DatabaseAccountBackupPolicy {
|
||||||
type: string;
|
type: string;
|
||||||
|
/* periodicModeProperties?: {
|
||||||
|
backupIntervalInMinutes: number;
|
||||||
|
backupRetentionIntervalInHours: number;
|
||||||
|
backupStorageRedundancy: string;
|
||||||
|
};
|
||||||
|
continuousModeProperties?: {
|
||||||
|
tier: string;
|
||||||
|
}; */
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DatabaseAccountExtendedProperties {
|
export interface DatabaseAccountExtendedProperties {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { userContext } from "UserContext";
|
import { userContext } from "UserContext";
|
||||||
import { useAADAuth } from "../../../hooks/useAADAuth";
|
|
||||||
import { useConfig } from "../../../hooks/useConfig";
|
|
||||||
import { CopyJobMigrationType } from "../Enums";
|
import { CopyJobMigrationType } from "../Enums";
|
||||||
import { CopyJobContextProviderType, CopyJobContextState, CopyJobFlowType } from "../Types";
|
import { CopyJobContextProviderType, CopyJobContextState, CopyJobFlowType } from "../Types";
|
||||||
|
|
||||||
@@ -39,24 +37,15 @@ const getInitialCopyJobState = (): CopyJobContextState => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CopyJobContextProvider: React.FC<CopyJobContextProviderProps> = (props) => {
|
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 [copyJobState, setCopyJobState] = React.useState<CopyJobContextState>(getInitialCopyJobState());
|
||||||
const [flow, setFlow] = React.useState<CopyJobFlowType | null>(null);
|
const [flow, setFlow] = React.useState<CopyJobFlowType | null>(null);
|
||||||
|
|
||||||
if (!isLoggedIn || !armToken) {
|
|
||||||
// Add a shimmer or loader here
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetCopyJobState = () => {
|
const resetCopyJobState = () => {
|
||||||
setCopyJobState(getInitialCopyJobState());
|
setCopyJobState(getInitialCopyJobState());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CopyJobContext.Provider value={{ principalId, armToken, copyJobState, setCopyJobState, flow, setFlow, resetCopyJobState }}>
|
<CopyJobContext.Provider value={{ copyJobState, setCopyJobState, flow, setFlow, resetCopyJobState }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</CopyJobContext.Provider>
|
</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 };
|
||||||
|
}
|
||||||
+5
-10
@@ -25,7 +25,7 @@ export interface PermissionSectionConfig {
|
|||||||
Component: React.ComponentType
|
Component: React.ComponentType
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
completed?: boolean;
|
completed?: boolean;
|
||||||
validate?: (state: CopyJobContextState, armToken?: string) => boolean | Promise<boolean>;
|
validate?: (state: CopyJobContextState) => boolean | Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section IDs for maintainability
|
// Section IDs for maintainability
|
||||||
@@ -66,10 +66,9 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [
|
|||||||
title: ContainerCopyMessages.readPermissionAssigned.title,
|
title: ContainerCopyMessages.readPermissionAssigned.title,
|
||||||
Component: AddReadPermissionToDefaultIdentity,
|
Component: AddReadPermissionToDefaultIdentity,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
validate: async (state: CopyJobContextState, armToken?: string) => {
|
validate: async (state: CopyJobContextState) => {
|
||||||
const principalId = state?.target?.account?.identity?.principalId;
|
const principalId = state?.target?.account?.identity?.principalId;
|
||||||
const rolesAssigned = await fetchRoleAssignments(
|
const rolesAssigned = await fetchRoleAssignments(
|
||||||
armToken,
|
|
||||||
state.source?.subscription?.subscriptionId,
|
state.source?.subscription?.subscriptionId,
|
||||||
state.source?.account?.resourceGroup,
|
state.source?.account?.resourceGroup,
|
||||||
state.source?.account?.name,
|
state.source?.account?.name,
|
||||||
@@ -77,7 +76,6 @@ const PERMISSION_SECTIONS_CONFIG: PermissionSectionConfig[] = [
|
|||||||
);
|
);
|
||||||
|
|
||||||
const roleDefinitions = await fetchRoleDefinitions(
|
const roleDefinitions = await fetchRoleDefinitions(
|
||||||
armToken,
|
|
||||||
rolesAssigned ?? []
|
rolesAssigned ?? []
|
||||||
);
|
);
|
||||||
return checkTargetHasReaderRoleOnSource(roleDefinitions ?? []);
|
return checkTargetHasReaderRoleOnSource(roleDefinitions ?? []);
|
||||||
@@ -127,10 +125,7 @@ export function checkTargetHasReaderRoleOnSource(roleDefinitions: RoleDefinition
|
|||||||
* Returns the permission sections configuration for the Assign Permissions screen.
|
* Returns the permission sections configuration for the Assign Permissions screen.
|
||||||
* Memoizes derived values for performance and decouples logic for testability.
|
* Memoizes derived values for performance and decouples logic for testability.
|
||||||
*/
|
*/
|
||||||
const usePermissionSections = (
|
const usePermissionSections = (state: CopyJobContextState): PermissionSectionConfig[] => {
|
||||||
state: CopyJobContextState,
|
|
||||||
armToken: string,
|
|
||||||
): PermissionSectionConfig[] => {
|
|
||||||
const { validationCache, setValidationCache } = useCopyJobPrerequisitesCache();
|
const { validationCache, setValidationCache } = useCopyJobPrerequisitesCache();
|
||||||
const [permissionSections, setPermissionSections] = useState<PermissionSectionConfig[] | null>(null);
|
const [permissionSections, setPermissionSections] = useState<PermissionSectionConfig[] | null>(null);
|
||||||
const isValidatingRef = useRef(false);
|
const isValidatingRef = useRef(false);
|
||||||
@@ -169,7 +164,7 @@ const usePermissionSections = (
|
|||||||
}
|
}
|
||||||
// We've reached the first non-cached section - validate it
|
// We've reached the first non-cached section - validate it
|
||||||
if (section.validate) {
|
if (section.validate) {
|
||||||
const isValid = await section.validate(state, armToken);
|
const isValid = await section.validate(state);
|
||||||
newValidationCache.set(section.id, isValid);
|
newValidationCache.set(section.id, isValid);
|
||||||
result.push({ ...section, completed: isValid });
|
result.push({ ...section, completed: isValid });
|
||||||
// Stop validation if current section failed
|
// Stop validation if current section failed
|
||||||
@@ -197,7 +192,7 @@ const usePermissionSections = (
|
|||||||
return () => {
|
return () => {
|
||||||
isValidatingRef.current = false;
|
isValidatingRef.current = false;
|
||||||
}
|
}
|
||||||
}, [state, armToken, sectionToValidate]);
|
}, [state, sectionToValidate]);
|
||||||
|
|
||||||
return permissionSections ?? [];
|
return permissionSections ?? [];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ const PermissionSection: React.FC<PermissionSectionConfig> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const AssignPermissions = () => {
|
const AssignPermissions = () => {
|
||||||
const { armToken, copyJobState } = useCopyJobContext();
|
const { copyJobState } = useCopyJobContext();
|
||||||
const permissionSections = usePermissionSections(copyJobState, armToken);
|
const permissionSections = usePermissionSections(copyJobState);
|
||||||
const [openItems, setOpenItems] = React.useState<string[]>([]);
|
const [openItems, setOpenItems] = React.useState<string[]>([]);
|
||||||
|
|
||||||
const indentLevels = React.useMemo<IndentLevel[]>(
|
const indentLevels = React.useMemo<IndentLevel[]>(
|
||||||
@@ -48,10 +48,6 @@ const AssignPermissions = () => {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
/* const onMoveToNextSection: AccordionToggleEventHandler<string> = useCallback((_event, data) => {
|
|
||||||
setOpenItems(data.openItems);
|
|
||||||
}, []); */
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const firstIncompleteSection = permissionSections.find(section => !section.completed);
|
const firstIncompleteSection = permissionSections.find(section => !section.completed);
|
||||||
const nextOpenItems = firstIncompleteSection ? [firstIncompleteSection.id] : [];
|
const nextOpenItems = firstIncompleteSection ? [firstIncompleteSection.id] : [];
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ interface SelectAccountProps { }
|
|||||||
|
|
||||||
const SelectAccount = React.memo(
|
const SelectAccount = React.memo(
|
||||||
(_props: SelectAccountProps) => {
|
(_props: SelectAccountProps) => {
|
||||||
const { armToken, copyJobState, setCopyJobState } = useCopyJobContext();
|
const { copyJobState, setCopyJobState } = useCopyJobContext();
|
||||||
const selectedSubscriptionId = copyJobState?.source?.subscription?.subscriptionId;
|
const selectedSubscriptionId = copyJobState?.source?.subscription?.subscriptionId;
|
||||||
|
|
||||||
const subscriptions: Subscription[] = useSubscriptions(armToken);
|
const subscriptions: Subscription[] = useSubscriptions();
|
||||||
const allAccounts: DatabaseAccount[] = useDatabaseAccounts(selectedSubscriptionId, armToken);
|
const allAccounts: DatabaseAccount[] = useDatabaseAccounts(selectedSubscriptionId);
|
||||||
const sqlApiOnlyAccounts: DatabaseAccount[] = allAccounts?.filter(account => account.type === "SQL" || account.kind === "GlobalDocumentDB");
|
const sqlApiOnlyAccounts: DatabaseAccount[] = allAccounts?.filter(account => account.type === "SQL" || account.kind === "GlobalDocumentDB");
|
||||||
|
|
||||||
const { subscriptionOptions, accountOptions } = useDropdownOptions(subscriptions, sqlApiOnlyAccounts);
|
const { subscriptionOptions, accountOptions } = useDropdownOptions(subscriptions, sqlApiOnlyAccounts);
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ import { useMemoizedSourceAndTargetData } from "./memoizedData";
|
|||||||
interface SelectSourceAndTargetContainersProps { }
|
interface SelectSourceAndTargetContainersProps { }
|
||||||
|
|
||||||
const SelectSourceAndTargetContainers = (_props: SelectSourceAndTargetContainersProps) => {
|
const SelectSourceAndTargetContainers = (_props: SelectSourceAndTargetContainersProps) => {
|
||||||
const { armToken, copyJobState, setCopyJobState } = useCopyJobContext();
|
const { copyJobState, setCopyJobState } = useCopyJobContext();
|
||||||
const {
|
const {
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
@@ -19,7 +19,7 @@ const SelectSourceAndTargetContainers = (_props: SelectSourceAndTargetContainers
|
|||||||
sourceContainerParams,
|
sourceContainerParams,
|
||||||
targetDbParams,
|
targetDbParams,
|
||||||
targetContainerParams
|
targetContainerParams
|
||||||
} = useMemoizedSourceAndTargetData(copyJobState, armToken);
|
} = useMemoizedSourceAndTargetData(copyJobState);
|
||||||
|
|
||||||
// Custom hooks
|
// Custom hooks
|
||||||
const sourceDatabases = useDatabases(...sourceDbParams) || [];
|
const sourceDatabases = useDatabases(...sourceDbParams) || [];
|
||||||
|
|||||||
+28
-21
@@ -1,57 +1,64 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { getAccountDetailsFromResourceId } from "../../../CopyJobUtils";
|
||||||
import { CopyJobContextState, DatabaseParams, DataContainerParams } from "../../../Types";
|
import { CopyJobContextState, DatabaseParams, DataContainerParams } from "../../../Types";
|
||||||
|
|
||||||
export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState, armToken: string) {
|
export function useMemoizedSourceAndTargetData(copyJobState: CopyJobContextState) {
|
||||||
const { source, target } = copyJobState ?? {};
|
const { source, target } = copyJobState ?? {};
|
||||||
const selectedSourceAccount = source?.account;
|
const selectedSourceAccount = source?.account;
|
||||||
const selectedTargetAccount = target?.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(
|
const sourceDbParams = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
[
|
[
|
||||||
armToken,
|
sourceSubscriptionId,
|
||||||
source?.subscription?.subscriptionId,
|
sourceResourceGroup,
|
||||||
selectedSourceAccount?.resourceGroup,
|
sourceAccountName,
|
||||||
selectedSourceAccount?.name,
|
|
||||||
'SQL',
|
'SQL',
|
||||||
] as DatabaseParams,
|
] as DatabaseParams,
|
||||||
[armToken, source?.subscription?.subscriptionId, selectedSourceAccount]
|
[sourceSubscriptionId, sourceResourceGroup, sourceAccountName]
|
||||||
);
|
);
|
||||||
|
|
||||||
const sourceContainerParams = React.useMemo(
|
const sourceContainerParams = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
[
|
[
|
||||||
armToken,
|
sourceSubscriptionId,
|
||||||
source?.subscription?.subscriptionId,
|
sourceResourceGroup,
|
||||||
selectedSourceAccount?.resourceGroup,
|
sourceAccountName,
|
||||||
selectedSourceAccount?.name,
|
|
||||||
source?.databaseId,
|
source?.databaseId,
|
||||||
'SQL',
|
'SQL',
|
||||||
] as DataContainerParams,
|
] as DataContainerParams,
|
||||||
[armToken, source?.subscription?.subscriptionId, selectedSourceAccount, source?.databaseId]
|
[sourceSubscriptionId, sourceResourceGroup, sourceAccountName, source?.databaseId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const targetDbParams = React.useMemo(
|
const targetDbParams = React.useMemo(
|
||||||
() => [
|
() => [
|
||||||
armToken,
|
targetSubscriptionId,
|
||||||
target?.subscriptionId,
|
targetResourceGroup,
|
||||||
selectedTargetAccount?.resourceGroup,
|
targetAccountName,
|
||||||
selectedTargetAccount?.name,
|
|
||||||
'SQL',
|
'SQL',
|
||||||
] as DatabaseParams,
|
] as DatabaseParams,
|
||||||
[armToken, target?.subscriptionId, selectedTargetAccount]
|
[targetSubscriptionId, targetResourceGroup, targetAccountName]
|
||||||
);
|
);
|
||||||
|
|
||||||
const targetContainerParams = React.useMemo(
|
const targetContainerParams = React.useMemo(
|
||||||
() => [
|
() => [
|
||||||
armToken,
|
targetSubscriptionId,
|
||||||
target?.subscriptionId,
|
targetResourceGroup,
|
||||||
selectedTargetAccount?.resourceGroup,
|
targetAccountName,
|
||||||
selectedTargetAccount?.name,
|
|
||||||
target?.databaseId,
|
target?.databaseId,
|
||||||
'SQL',
|
'SQL',
|
||||||
] as DataContainerParams,
|
] as DataContainerParams,
|
||||||
[armToken, target?.subscriptionId, selectedTargetAccount, target?.databaseId]
|
[targetSubscriptionId, targetResourceGroup, targetAccountName, target?.databaseId]
|
||||||
);
|
);
|
||||||
|
|
||||||
return { source, target, sourceDbParams, sourceContainerParams, targetDbParams, targetContainerParams };
|
return { source, target, sourceDbParams, sourceContainerParams, targetDbParams, targetContainerParams };
|
||||||
|
|||||||
@@ -28,14 +28,12 @@ export type DropdownOptionType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type DatabaseParams = [
|
export type DatabaseParams = [
|
||||||
string,
|
|
||||||
string | undefined,
|
string | undefined,
|
||||||
string | undefined,
|
string | undefined,
|
||||||
string | undefined,
|
string | undefined,
|
||||||
ApiType
|
ApiType
|
||||||
];
|
];
|
||||||
export type DataContainerParams = [
|
export type DataContainerParams = [
|
||||||
string,
|
|
||||||
string | undefined,
|
string | undefined,
|
||||||
string | undefined,
|
string | undefined,
|
||||||
string | undefined,
|
string | undefined,
|
||||||
@@ -80,8 +78,6 @@ export interface CopyJobFlowType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CopyJobContextProviderType {
|
export interface CopyJobContextProviderType {
|
||||||
principalId: string;
|
|
||||||
armToken: string;
|
|
||||||
flow: CopyJobFlowType;
|
flow: CopyJobFlowType;
|
||||||
setFlow: React.Dispatch<React.SetStateAction<CopyJobFlowType>>;
|
setFlow: React.Dispatch<React.SetStateAction<CopyJobFlowType>>;
|
||||||
copyJobState: CopyJobContextState | null;
|
copyJobState: CopyJobContextState | null;
|
||||||
|
|||||||
+3
-3
@@ -78,13 +78,13 @@ const App: React.FunctionComponent = () => {
|
|||||||
}
|
}
|
||||||
StyleConstants.updateStyles();
|
StyleConstants.updateStyles();
|
||||||
const explorer = useKnockoutExplorer(config?.platform);
|
const explorer = useKnockoutExplorer(config?.platform);
|
||||||
// console.log("Using config: ", config);
|
console.log("Using config: ", config);
|
||||||
|
|
||||||
if (!explorer) {
|
if (!explorer) {
|
||||||
return <LoadingExplorer />;
|
return <LoadingExplorer />;
|
||||||
}
|
}
|
||||||
// console.log("Using explorer: ", explorer);
|
console.log("Using explorer: ", explorer);
|
||||||
// console.log("Using userContext: ", userContext);
|
console.log("Using userContext: ", userContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardShortcutRoot>
|
<KeyboardShortcutRoot>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { configContext } from "ConfigContext";
|
import { configContext } from "ConfigContext";
|
||||||
import { armRequest } from "Utils/arm/request";
|
import { armRequest } from "Utils/arm/request";
|
||||||
|
import { getCopyJobAuthorizationHeader } from "../CopyJobAuthUtils";
|
||||||
|
|
||||||
export type FetchAccountDetailsParams = {
|
export type FetchAccountDetailsParams = {
|
||||||
armToken: string;
|
|
||||||
subscriptionId: string;
|
subscriptionId: string;
|
||||||
resourceGroupName: string;
|
resourceGroupName: string;
|
||||||
accountName: string;
|
accountName: string;
|
||||||
@@ -43,13 +43,6 @@ const getArmBaseUrl = (): string => {
|
|||||||
return base.endsWith("/") ? base.slice(0, -1) : base;
|
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 =>
|
const buildArmUrl = (path: string): string =>
|
||||||
`${getArmBaseUrl()}${path}?api-version=${apiVersion}`;
|
`${getArmBaseUrl()}${path}?api-version=${apiVersion}`;
|
||||||
|
|
||||||
@@ -64,7 +57,6 @@ const handleResponse = async (response: Response, context: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchRoleAssignments = async (
|
export const fetchRoleAssignments = async (
|
||||||
armToken: string,
|
|
||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroupName: string,
|
resourceGroupName: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
@@ -74,7 +66,7 @@ export const fetchRoleAssignments = async (
|
|||||||
`/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlRoleAssignments`
|
`/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");
|
const data = await handleResponse(response, "role assignments");
|
||||||
|
|
||||||
return (data.value || []).filter(
|
return (data.value || []).filter(
|
||||||
@@ -84,13 +76,12 @@ export const fetchRoleAssignments = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchRoleDefinitions = async (
|
export const fetchRoleDefinitions = async (
|
||||||
armToken: string,
|
|
||||||
roleAssignments: RoleAssignmentType[]
|
roleAssignments: RoleAssignmentType[]
|
||||||
): Promise<RoleDefinitionType[]> => {
|
): Promise<RoleDefinitionType[]> => {
|
||||||
const roleDefinitionIds = roleAssignments.map(assignment => assignment.properties.roleDefinitionId);
|
const roleDefinitionIds = roleAssignments.map(assignment => assignment.properties.roleDefinitionId);
|
||||||
const uniqueRoleDefinitionIds = Array.from(new Set(roleDefinitionIds));
|
const uniqueRoleDefinitionIds = Array.from(new Set(roleDefinitionIds));
|
||||||
|
|
||||||
const headers = createAuthHeaders(armToken);
|
const headers = getCopyJobAuthorizationHeader();
|
||||||
const roleDefinitionUris = uniqueRoleDefinitionIds.map((id) => buildArmUrl(id));
|
const roleDefinitionUris = uniqueRoleDefinitionIds.map((id) => buildArmUrl(id));
|
||||||
|
|
||||||
const promises = roleDefinitionUris.map((url) => fetch(url, { method: "GET", headers }));
|
const promises = roleDefinitionUris.map((url) => fetch(url, { method: "GET", headers }));
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import useSWR from "swr";
|
|||||||
import { getCollectionEndpoint, getDatabaseEndpoint } from "../Common/DatabaseAccountUtility";
|
import { getCollectionEndpoint, getDatabaseEndpoint } from "../Common/DatabaseAccountUtility";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext } from "../ConfigContext";
|
||||||
import { ApiType } from "../UserContext";
|
import { ApiType } from "../UserContext";
|
||||||
|
import { getCopyJobAuthorizationHeader } from "../Utils/CopyJobAuthUtils";
|
||||||
|
|
||||||
const apiVersion = "2023-09-15";
|
const apiVersion = "2023-09-15";
|
||||||
export interface FetchDataContainersListParams {
|
export interface FetchDataContainersListParams {
|
||||||
armToken: string;
|
|
||||||
subscriptionId: string;
|
subscriptionId: string;
|
||||||
resourceGroupName: string;
|
resourceGroupName: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
@@ -27,7 +27,6 @@ const buildReadDataContainersListUrl = (params: FetchDataContainersListParams):
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fetchDataContainersList = async (
|
const fetchDataContainersList = async (
|
||||||
armToken: string,
|
|
||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroupName: string,
|
resourceGroupName: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
@@ -35,17 +34,13 @@ const fetchDataContainersList = async (
|
|||||||
apiType: ApiType
|
apiType: ApiType
|
||||||
): Promise<DatabaseModel[]> => {
|
): Promise<DatabaseModel[]> => {
|
||||||
const uri = buildReadDataContainersListUrl({
|
const uri = buildReadDataContainersListUrl({
|
||||||
armToken,
|
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroupName,
|
resourceGroupName,
|
||||||
accountName,
|
accountName,
|
||||||
databaseName,
|
databaseName,
|
||||||
apiType
|
apiType
|
||||||
});
|
});
|
||||||
const headers = new Headers();
|
const headers = getCopyJobAuthorizationHeader();
|
||||||
const bearer = `Bearer ${armToken}`;
|
|
||||||
headers.append("Authorization", bearer);
|
|
||||||
headers.append("Content-Type", "application/json");
|
|
||||||
|
|
||||||
const response = await fetch(uri, {
|
const response = await fetch(uri, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -61,7 +56,6 @@ const fetchDataContainersList = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function useDataContainers(
|
export function useDataContainers(
|
||||||
armToken: string,
|
|
||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroupName: string,
|
resourceGroupName: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
@@ -70,13 +64,12 @@ export function useDataContainers(
|
|||||||
): DatabaseModel[] | undefined {
|
): DatabaseModel[] | undefined {
|
||||||
const { data } = useSWR(
|
const { data } = useSWR(
|
||||||
() => (
|
() => (
|
||||||
armToken && subscriptionId && resourceGroupName && accountName && databaseName && apiType ? [
|
subscriptionId && resourceGroupName && accountName && databaseName && apiType ? [
|
||||||
"fetchContainersLinkedToDatabases",
|
"fetchContainersLinkedToDatabases",
|
||||||
armToken, subscriptionId, resourceGroupName, accountName, databaseName, apiType
|
subscriptionId, resourceGroupName, accountName, databaseName, apiType
|
||||||
] : undefined
|
] : undefined
|
||||||
),
|
),
|
||||||
(_, armToken, subscriptionId, resourceGroupName, accountName, databaseName, apiType) => fetchDataContainersList(
|
(_, subscriptionId, resourceGroupName, accountName, databaseName, apiType) => fetchDataContainersList(
|
||||||
armToken,
|
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroupName,
|
resourceGroupName,
|
||||||
accountName,
|
accountName,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { HttpHeaders } from "Common/Constants";
|
import { HttpHeaders } from "Common/Constants";
|
||||||
import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph";
|
import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
import { userContext } from "UserContext";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext } from "../ConfigContext";
|
||||||
import { DatabaseAccount } from "../Contracts/DataModels";
|
import { DatabaseAccount } from "../Contracts/DataModels";
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
@@ -10,9 +11,12 @@ interface AccountListResult {
|
|||||||
value: DatabaseAccount[];
|
value: DatabaseAccount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDatabaseAccounts(subscriptionId: string, accessToken: string): Promise<DatabaseAccount[]> {
|
export async function fetchDatabaseAccounts(subscriptionId: string, accessToken: string = ""): Promise<DatabaseAccount[]> {
|
||||||
|
if (!accessToken && !userContext.authorizationToken) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
const bearer = `Bearer ${accessToken}`;
|
const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken;
|
||||||
|
|
||||||
headers.append("Authorization", bearer);
|
headers.append("Authorization", bearer);
|
||||||
|
|
||||||
@@ -35,10 +39,13 @@ export async function fetchDatabaseAccounts(subscriptionId: string, accessToken:
|
|||||||
|
|
||||||
export async function fetchDatabaseAccountsFromGraph(
|
export async function fetchDatabaseAccountsFromGraph(
|
||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
accessToken: string,
|
accessToken: string = "",
|
||||||
): Promise<DatabaseAccount[]> {
|
): Promise<DatabaseAccount[]> {
|
||||||
|
if (!accessToken && !userContext.authorizationToken) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
const bearer = `Bearer ${accessToken}`;
|
const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken;
|
||||||
|
|
||||||
headers.append("Authorization", bearer);
|
headers.append("Authorization", bearer);
|
||||||
headers.append(HttpHeaders.contentType, "application/json");
|
headers.append(HttpHeaders.contentType, "application/json");
|
||||||
@@ -54,15 +61,15 @@ export async function fetchDatabaseAccountsFromGraph(
|
|||||||
subscriptions: [subscriptionId],
|
subscriptions: [subscriptionId],
|
||||||
...(skipToken
|
...(skipToken
|
||||||
? {
|
? {
|
||||||
options: {
|
options: {
|
||||||
$skipToken: skipToken,
|
$skipToken: skipToken,
|
||||||
} as QueryRequestOptions,
|
} as QueryRequestOptions,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
options: {
|
options: {
|
||||||
$top: 150,
|
$top: 150,
|
||||||
} as QueryRequestOptions,
|
} as QueryRequestOptions,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(managementResourceGraphAPIURL, {
|
const response = await fetch(managementResourceGraphAPIURL, {
|
||||||
@@ -85,9 +92,9 @@ export async function fetchDatabaseAccountsFromGraph(
|
|||||||
return databaseAccounts.sort((a, b) => a.name.localeCompare(b.name));
|
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(
|
const { data } = useSWR(
|
||||||
() => (armToken && subscriptionId ? ["databaseAccounts", subscriptionId, armToken] : undefined),
|
() => (subscriptionId ? ["databaseAccounts", subscriptionId, armToken] : undefined),
|
||||||
(_, subscriptionId, armToken) => fetchDatabaseAccountsFromGraph(subscriptionId, armToken),
|
(_, subscriptionId, armToken) => fetchDatabaseAccountsFromGraph(subscriptionId, armToken),
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import useSWR from "swr";
|
|||||||
import { getDatabaseEndpoint } from "../Common/DatabaseAccountUtility";
|
import { getDatabaseEndpoint } from "../Common/DatabaseAccountUtility";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext } from "../ConfigContext";
|
||||||
import { ApiType } from "../UserContext";
|
import { ApiType } from "../UserContext";
|
||||||
|
import { getCopyJobAuthorizationHeader } from "../Utils/CopyJobAuthUtils";
|
||||||
|
|
||||||
const apiVersion = "2023-09-15";
|
const apiVersion = "2023-09-15";
|
||||||
export interface FetchDatabasesListParams {
|
export interface FetchDatabasesListParams {
|
||||||
armToken: string;
|
|
||||||
subscriptionId: string;
|
subscriptionId: string;
|
||||||
resourceGroupName: string;
|
resourceGroupName: string;
|
||||||
accountName: 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}`;
|
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<DatabaseModel[]> => {
|
const fetchDatabasesList = async (subscriptionId: string, resourceGroupName: string, accountName: string, apiType: ApiType): Promise<DatabaseModel[]> => {
|
||||||
const uri = buildReadDatabasesListUrl({ armToken, subscriptionId, resourceGroupName, accountName, apiType });
|
const uri = buildReadDatabasesListUrl({ subscriptionId, resourceGroupName, accountName, apiType });
|
||||||
const headers = new Headers();
|
const headers = getCopyJobAuthorizationHeader();
|
||||||
const bearer = `Bearer ${armToken}`;
|
|
||||||
headers.append("Authorization", bearer);
|
|
||||||
headers.append("Content-Type", "application/json");
|
|
||||||
|
|
||||||
const response = await fetch(uri, {
|
const response = await fetch(uri, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -45,7 +42,6 @@ const fetchDatabasesList = async (armToken: string, subscriptionId: string, reso
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function useDatabases(
|
export function useDatabases(
|
||||||
armToken: string,
|
|
||||||
subscriptionId: string,
|
subscriptionId: string,
|
||||||
resourceGroupName: string,
|
resourceGroupName: string,
|
||||||
accountName: string,
|
accountName: string,
|
||||||
@@ -53,13 +49,12 @@ export function useDatabases(
|
|||||||
): DatabaseModel[] | undefined {
|
): DatabaseModel[] | undefined {
|
||||||
const { data } = useSWR(
|
const { data } = useSWR(
|
||||||
() => (
|
() => (
|
||||||
armToken && subscriptionId && resourceGroupName && accountName && apiType ? [
|
subscriptionId && resourceGroupName && accountName && apiType ? [
|
||||||
"fetchDatabasesLinkedToResource",
|
"fetchDatabasesLinkedToResource",
|
||||||
armToken, subscriptionId, resourceGroupName, accountName, apiType
|
subscriptionId, resourceGroupName, accountName, apiType
|
||||||
] : undefined
|
] : undefined
|
||||||
),
|
),
|
||||||
(_, armToken, subscriptionId, resourceGroupName, accountName, apiType) => fetchDatabasesList(
|
(_, subscriptionId, resourceGroupName, accountName, apiType) => fetchDatabasesList(
|
||||||
armToken,
|
|
||||||
subscriptionId,
|
subscriptionId,
|
||||||
resourceGroupName,
|
resourceGroupName,
|
||||||
accountName,
|
accountName,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { HttpHeaders } from "Common/Constants";
|
import { HttpHeaders } from "Common/Constants";
|
||||||
import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph";
|
import { QueryRequestOptions, QueryResponse } from "Contracts/AzureResourceGraph";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
import { userContext } from "UserContext";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext } from "../ConfigContext";
|
||||||
import { Subscription } from "../Contracts/DataModels";
|
import { Subscription } from "../Contracts/DataModels";
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
@@ -10,9 +11,12 @@ interface SubscriptionListResult {
|
|||||||
value: Subscription[];
|
value: Subscription[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSubscriptions(accessToken: string): Promise<Subscription[]> {
|
export async function fetchSubscriptions(accessToken: string = ""): Promise<Subscription[]> {
|
||||||
|
if (!accessToken && !userContext.authorizationToken) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
const bearer = `Bearer ${accessToken}`;
|
const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken;
|
||||||
|
|
||||||
headers.append("Authorization", bearer);
|
headers.append("Authorization", bearer);
|
||||||
|
|
||||||
@@ -35,9 +39,12 @@ export async function fetchSubscriptions(accessToken: string): Promise<Subscript
|
|||||||
return subscriptions.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
return subscriptions.sort((a, b) => a.displayName.localeCompare(b.displayName));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSubscriptionsFromGraph(accessToken: string): Promise<Subscription[]> {
|
export async function fetchSubscriptionsFromGraph(accessToken: string = ""): Promise<Subscription[]> {
|
||||||
|
if (!accessToken && !userContext.authorizationToken) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
const bearer = `Bearer ${accessToken}`;
|
const bearer = accessToken ? `Bearer ${accessToken}` : userContext.authorizationToken;
|
||||||
|
|
||||||
headers.append("Authorization", bearer);
|
headers.append("Authorization", bearer);
|
||||||
headers.append(HttpHeaders.contentType, "application/json");
|
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));
|
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(
|
const { data } = useSWR(
|
||||||
() => (armToken ? ["subscriptions", armToken] : undefined),
|
() => ["subscriptions", armToken],
|
||||||
(_, armToken) => fetchSubscriptionsFromGraph(armToken),
|
(_, armToken) => fetchSubscriptionsFromGraph(armToken),
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
Reference in New Issue
Block a user