mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-03-06 18:07:11 +00:00
Update to V3 messaging
This commit is contained in:
parent
36c0bf7392
commit
8cfd951c31
@ -1,5 +1,6 @@
|
|||||||
import * as Cosmos from "@azure/cosmos";
|
import * as Cosmos from "@azure/cosmos";
|
||||||
import { getAuthorizationTokenUsingResourceTokens } from "Common/getAuthorizationTokenUsingResourceTokens";
|
import { getAuthorizationTokenUsingResourceTokens } from "Common/getAuthorizationTokenUsingResourceTokens";
|
||||||
|
import { CosmosDbArtifactType } from "Contracts/FabricMessagesContract";
|
||||||
import { AuthorizationToken } from "Contracts/FabricMessageTypes";
|
import { AuthorizationToken } from "Contracts/FabricMessageTypes";
|
||||||
import { checkDatabaseResourceTokensValidity, isFabricMirrored } from "Platform/Fabric/FabricUtil";
|
import { checkDatabaseResourceTokensValidity, isFabricMirrored } from "Platform/Fabric/FabricUtil";
|
||||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
@ -8,7 +9,7 @@ import { AuthType } from "../AuthType";
|
|||||||
import { BackendApi, PriorityLevel } from "../Common/Constants";
|
import { BackendApi, PriorityLevel } from "../Common/Constants";
|
||||||
import * as Logger from "../Common/Logger";
|
import * as Logger from "../Common/Logger";
|
||||||
import { Platform, configContext } from "../ConfigContext";
|
import { Platform, configContext } from "../ConfigContext";
|
||||||
import { updateUserContext, userContext } from "../UserContext";
|
import { FabricArtifactInfo, updateUserContext, userContext } from "../UserContext";
|
||||||
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
import { logConsoleError } from "../Utils/NotificationConsoleUtils";
|
||||||
import * as PriorityBasedExecutionUtils from "../Utils/PriorityBasedExecutionUtils";
|
import * as PriorityBasedExecutionUtils from "../Utils/PriorityBasedExecutionUtils";
|
||||||
import { EmulatorMasterKey, HttpHeaders } from "./Constants";
|
import { EmulatorMasterKey, HttpHeaders } from "./Constants";
|
||||||
@ -54,8 +55,13 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
|||||||
// User resource tokens
|
// User resource tokens
|
||||||
// TODO userContext.fabricContext.databaseConnectionInfo can be undefined
|
// TODO userContext.fabricContext.databaseConnectionInfo can be undefined
|
||||||
headers[HttpHeaders.msDate] = new Date().toUTCString();
|
headers[HttpHeaders.msDate] = new Date().toUTCString();
|
||||||
const resourceTokens = userContext.fabricContext.mirroredConnectionInfo.resourceTokens;
|
const resourceTokens = (
|
||||||
checkDatabaseResourceTokensValidity(userContext.fabricContext.mirroredConnectionInfo.resourceTokensTimestamp);
|
userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]
|
||||||
|
).resourceTokenInfo.resourceTokens;
|
||||||
|
checkDatabaseResourceTokensValidity(
|
||||||
|
(userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY])
|
||||||
|
.resourceTokenInfo.resourceTokensTimestamp,
|
||||||
|
);
|
||||||
return getAuthorizationTokenUsingResourceTokens(resourceTokens, requestInfo.path, requestInfo.resourceId);
|
return getAuthorizationTokenUsingResourceTokens(resourceTokens, requestInfo.path, requestInfo.resourceId);
|
||||||
|
|
||||||
case Cosmos.ResourceType.none:
|
case Cosmos.ResourceType.none:
|
||||||
@ -66,7 +72,9 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
|||||||
// For now, these operations aren't used, so fetching the authorization token is commented out.
|
// For now, these operations aren't used, so fetching the authorization token is commented out.
|
||||||
// This provider must return a real token to pass validation by the client, so we return the cached resource token
|
// This provider must return a real token to pass validation by the client, so we return the cached resource token
|
||||||
// (which is a valid token, but won't work for these operations).
|
// (which is a valid token, but won't work for these operations).
|
||||||
const resourceTokens2 = userContext.fabricContext.mirroredConnectionInfo.resourceTokens;
|
const resourceTokens2 = (
|
||||||
|
userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]
|
||||||
|
).resourceTokenInfo.resourceTokens;
|
||||||
return getAuthorizationTokenUsingResourceTokens(resourceTokens2, requestInfo.path, requestInfo.resourceId);
|
return getAuthorizationTokenUsingResourceTokens(resourceTokens2, requestInfo.path, requestInfo.resourceId);
|
||||||
|
|
||||||
/* ************** TODO: Uncomment this code if we need to support these operations **************
|
/* ************** TODO: Uncomment this code if we need to support these operations **************
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { ContainerResponse } from "@azure/cosmos";
|
import { ContainerResponse } from "@azure/cosmos";
|
||||||
import { Queries } from "Common/Constants";
|
import { Queries } from "Common/Constants";
|
||||||
|
import { CosmosDbArtifactType } from "Contracts/FabricMessagesContract";
|
||||||
import { isFabricMirrored } from "Platform/Fabric/FabricUtil";
|
import { isFabricMirrored } from "Platform/Fabric/FabricUtil";
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { FabricArtifactInfo, userContext } from "../../UserContext";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { listCassandraTables } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
import { listCassandraTables } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
||||||
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
||||||
@ -16,11 +17,13 @@ import { handleError } from "../ErrorHandlingUtils";
|
|||||||
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
|
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
|
||||||
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
|
||||||
|
|
||||||
if (isFabricMirrored() && userContext.fabricContext?.mirroredConnectionInfo.databaseId === databaseId) {
|
if (isFabricMirrored() && userContext.fabricContext?.databaseName === databaseId) {
|
||||||
const collections: DataModels.Collection[] = [];
|
const collections: DataModels.Collection[] = [];
|
||||||
const promises: Promise<ContainerResponse>[] = [];
|
const promises: Promise<ContainerResponse>[] = [];
|
||||||
|
|
||||||
for (const collectionResourceId in userContext.fabricContext.mirroredConnectionInfo.resourceTokens) {
|
for (const collectionResourceId in (
|
||||||
|
userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]
|
||||||
|
).resourceTokenInfo.resourceTokens) {
|
||||||
// Dictionary key looks like this: dbs/SampleDB/colls/Container
|
// Dictionary key looks like this: dbs/SampleDB/colls/Container
|
||||||
const resourceIdObj = collectionResourceId.split("/");
|
const resourceIdObj = collectionResourceId.split("/");
|
||||||
const tokenDatabaseId = resourceIdObj[1];
|
const tokenDatabaseId = resourceIdObj[1];
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import { CosmosDbArtifactType } from "Contracts/FabricMessagesContract";
|
||||||
import { isFabricMirrored, isFabricNative } from "Platform/Fabric/FabricUtil";
|
import { isFabricMirrored, isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import { userContext } from "../../UserContext";
|
import { FabricArtifactInfo, userContext } from "../../UserContext";
|
||||||
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
|
||||||
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
|
||||||
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
|
||||||
@ -14,8 +15,13 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
|
|||||||
let databases: DataModels.Database[];
|
let databases: DataModels.Database[];
|
||||||
const clearMessage = logConsoleProgress(`Querying databases`);
|
const clearMessage = logConsoleProgress(`Querying databases`);
|
||||||
|
|
||||||
if (isFabricMirrored() && userContext.fabricContext?.mirroredConnectionInfo.resourceTokens) {
|
if (
|
||||||
const tokensData = userContext.fabricContext.mirroredConnectionInfo;
|
isFabricMirrored() &&
|
||||||
|
(userContext.fabricContext?.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]).resourceTokenInfo
|
||||||
|
.resourceTokens
|
||||||
|
) {
|
||||||
|
const tokensData = (userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY])
|
||||||
|
.resourceTokenInfo;
|
||||||
|
|
||||||
const databaseIdsSet = new Set<string>(); // databaseId
|
const databaseIdsSet = new Set<string>(); // databaseId
|
||||||
|
|
||||||
@ -46,8 +52,8 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
|
|||||||
}));
|
}));
|
||||||
clearMessage();
|
clearMessage();
|
||||||
return databases;
|
return databases;
|
||||||
} else if (isFabricNative() && userContext.fabricContext?.nativeConnectionInfo.databaseName) {
|
} else if (isFabricNative() && userContext.fabricContext?.databaseName) {
|
||||||
const databaseId = userContext.fabricContext.nativeConnectionInfo.databaseName;
|
const databaseId = userContext.fabricContext.databaseName;
|
||||||
databases = [
|
databases = [
|
||||||
{
|
{
|
||||||
_rid: "",
|
_rid: "",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AuthorizationToken } from "./FabricMessageTypes";
|
import { AuthorizationToken } from "./FabricMessageTypes";
|
||||||
|
|
||||||
// This is the version of these messages
|
// This is the version of these messages
|
||||||
export const FABRIC_RPC_VERSION = "2";
|
export const FABRIC_RPC_VERSION = "FabricMessageV3";
|
||||||
|
|
||||||
// Fabric to Data Explorer
|
// Fabric to Data Explorer
|
||||||
export type FabricMessageV2 =
|
export type FabricMessageV2 =
|
||||||
@ -16,11 +16,6 @@ export type FabricMessageV2 =
|
|||||||
message: {
|
message: {
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
isReadOnly: boolean;
|
|
||||||
artifactType: CosmosDbArtifactType;
|
|
||||||
|
|
||||||
// For Native artifacts
|
|
||||||
nativeConnectionInfo?: FabricNativeDatabaseConnectionInfo;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@ -36,7 +31,41 @@ export type FabricMessageV2 =
|
|||||||
message: {
|
message: {
|
||||||
id: string;
|
id: string;
|
||||||
error: string | undefined;
|
error: string | undefined;
|
||||||
data: FabricMirroredDatabaseConnectionInfo | undefined;
|
data: ResourceTokenInfo | undefined;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "explorerVisible";
|
||||||
|
message: {
|
||||||
|
visible: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FabricMessageV3 =
|
||||||
|
| {
|
||||||
|
type: "newContainer";
|
||||||
|
databaseName: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "initialize";
|
||||||
|
version: string;
|
||||||
|
id: string;
|
||||||
|
message: InitializeMessageV3<CosmosDbArtifactType>;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "authorizationToken";
|
||||||
|
message: {
|
||||||
|
id: string;
|
||||||
|
error: string | undefined;
|
||||||
|
data: AuthorizationToken | undefined;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "allResourceTokens_v2";
|
||||||
|
message: {
|
||||||
|
id: string;
|
||||||
|
error: string | undefined;
|
||||||
|
data: ResourceTokenInfo | undefined;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@ -47,27 +76,38 @@ export type FabricMessageV2 =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export enum CosmosDbArtifactType {
|
export enum CosmosDbArtifactType {
|
||||||
MIRRORED = "MIRRORED",
|
MIRRORED_KEY = "MIRRORED_KEY",
|
||||||
|
MIRRORED_AAD = "MIRRORED_AAD",
|
||||||
NATIVE = "NATIVE",
|
NATIVE = "NATIVE",
|
||||||
}
|
}
|
||||||
|
export interface ArtifactConnectionInfo {
|
||||||
|
[CosmosDbArtifactType.MIRRORED_KEY]: { connectionId: string };
|
||||||
|
[CosmosDbArtifactType.MIRRORED_AAD]: AccessTokenConnectionInfo;
|
||||||
|
[CosmosDbArtifactType.NATIVE]: AccessTokenConnectionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FabricNativeDatabaseConnectionInfo {
|
export interface AccessTokenConnectionInfo {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
accountEndpoint: string;
|
accountEndpoint: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CosmosDBTokenResponse {
|
export interface InitializeMessageV3<T extends CosmosDbArtifactType> {
|
||||||
token: string;
|
connectionId: string;
|
||||||
date: string;
|
isVisible: boolean;
|
||||||
|
isReadOnly: boolean;
|
||||||
|
artifactType: T;
|
||||||
|
artifactConnectionInfo: ArtifactConnectionInfo[T];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CosmosDBConnectionInfoResponse {
|
export interface CosmosDBConnectionInfoResponse {
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
databaseId: string;
|
databaseId: string;
|
||||||
resourceTokens: Record<string, string>;
|
resourceTokens: Record<string, string> | undefined;
|
||||||
|
accessToken: string | undefined;
|
||||||
|
isReadOnly: boolean;
|
||||||
|
credentialType: "Key" | "OAuth2" | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FabricMirroredDatabaseConnectionInfo extends CosmosDBConnectionInfoResponse {
|
export interface ResourceTokenInfo extends CosmosDBConnectionInfoResponse {
|
||||||
resourceTokensTimestamp: number;
|
resourceTokensTimestamp: number;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils";
|
|||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../Utils/NotificationConsoleUtils";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../Utils/NotificationConsoleUtils";
|
||||||
import { useSidePanel } from "../hooks/useSidePanel";
|
import { useSidePanel } from "../hooks/useSidePanel";
|
||||||
import { useTabs } from "../hooks/useTabs";
|
import { ReactTabKind, useTabs } from "../hooks/useTabs";
|
||||||
import "./ComponentRegisterer";
|
import "./ComponentRegisterer";
|
||||||
import { DialogProps, useDialog } from "./Controls/Dialog";
|
import { DialogProps, useDialog } from "./Controls/Dialog";
|
||||||
import { GalleryTab as GalleryTabKind } from "./Controls/NotebookGallery/GalleryViewerComponent";
|
import { GalleryTab as GalleryTabKind } from "./Controls/NotebookGallery/GalleryViewerComponent";
|
||||||
@ -187,6 +187,10 @@ export default class Explorer {
|
|||||||
useNotebook.getState().setNotebookBasePath(userContext.features.notebookBasePath);
|
useNotebook.getState().setNotebookBasePath(userContext.features.notebookBasePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFabricMirrored()) {
|
||||||
|
useTabs.getState().closeReactTab(ReactTabKind.Home);
|
||||||
|
}
|
||||||
|
|
||||||
this.refreshExplorer();
|
this.refreshExplorer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,9 +133,7 @@ const GlobalCommands: React.FC<GlobalCommandsProps> = ({ explorer }) => {
|
|||||||
label: `New ${getCollectionName()}`,
|
label: `New ${getCollectionName()}`,
|
||||||
icon: <Add16Regular />,
|
icon: <Add16Regular />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const databaseId = isFabricNative()
|
const databaseId = isFabricNative() ? userContext.fabricContext?.databaseName : undefined;
|
||||||
? userContext.fabricContext?.nativeConnectionInfo?.databaseName
|
|
||||||
: undefined;
|
|
||||||
explorer.onNewCollectionClicked({ databaseId });
|
explorer.onNewCollectionClicked({ databaseId });
|
||||||
},
|
},
|
||||||
keyboardAction: KeyboardAction.NEW_COLLECTION,
|
keyboardAction: KeyboardAction.NEW_COLLECTION,
|
||||||
|
@ -130,9 +130,7 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
|
|||||||
description: "Create a destination container to store your data",
|
description: "Create a destination container to store your data",
|
||||||
icon: <DocumentAddRegular />,
|
icon: <DocumentAddRegular />,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const databaseId = isFabricNative()
|
const databaseId = isFabricNative() ? userContext.fabricContext?.databaseName : undefined;
|
||||||
? userContext.fabricContext?.nativeConnectionInfo?.databaseName
|
|
||||||
: undefined;
|
|
||||||
props.explorer.onNewCollectionClicked({ databaseId });
|
props.explorer.onNewCollectionClicked({ databaseId });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -342,12 +342,15 @@ describe("Documents tab (noSql API)", () => {
|
|||||||
updateConfigContext({ platform: Platform.Fabric });
|
updateConfigContext({ platform: Platform.Fabric });
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
fabricContext: {
|
fabricContext: {
|
||||||
connectionId: "test",
|
databaseName: "database",
|
||||||
mirroredConnectionInfo: undefined,
|
artifactInfo: {
|
||||||
nativeConnectionInfo: undefined,
|
connectionId: "test",
|
||||||
artifactType: CosmosDbArtifactType.MIRRORED,
|
resourceTokenInfo: undefined,
|
||||||
|
},
|
||||||
|
artifactType: CosmosDbArtifactType.MIRRORED_KEY,
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
fabricClientRpcVersion: "rpcVersion",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -557,7 +557,9 @@ describe("createDatabaseTreeNodes", () => {
|
|||||||
() => {
|
() => {
|
||||||
updateConfigContext({ platform: Platform.Fabric });
|
updateConfigContext({ platform: Platform.Fabric });
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
fabricContext: { artifactType: CosmosDbArtifactType.MIRRORED } as FabricContext,
|
fabricContext: {
|
||||||
|
artifactType: CosmosDbArtifactType.MIRRORED_KEY,
|
||||||
|
} as FabricContext<CosmosDbArtifactType>,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { sendCachedDataMessage } from "Common/MessageHandler";
|
import { sendCachedDataMessage } from "Common/MessageHandler";
|
||||||
import { configContext, Platform } from "ConfigContext";
|
import { configContext, Platform } from "ConfigContext";
|
||||||
import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
|
import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
|
||||||
import { CosmosDbArtifactType, FabricMirroredDatabaseConnectionInfo } from "Contracts/FabricMessagesContract";
|
import { CosmosDbArtifactType, ResourceTokenInfo } from "Contracts/FabricMessagesContract";
|
||||||
import { updateUserContext, userContext } from "UserContext";
|
import { updateUserContext, userContext } from "UserContext";
|
||||||
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
||||||
|
|
||||||
@ -19,21 +19,25 @@ const requestDatabaseResourceTokens = async (): Promise<void> => {
|
|||||||
|
|
||||||
lastRequestTimestamp = Date.now();
|
lastRequestTimestamp = Date.now();
|
||||||
try {
|
try {
|
||||||
const fabricDatabaseConnectionInfo = await sendCachedDataMessage<FabricMirroredDatabaseConnectionInfo>(
|
const resourceTokenInfo = await sendCachedDataMessage<ResourceTokenInfo>(
|
||||||
FabricMessageTypes.GetAllResourceTokens,
|
FabricMessageTypes.GetAllResourceTokens,
|
||||||
[],
|
[],
|
||||||
userContext.fabricContext.connectionId,
|
userContext.fabricContext.artifactInfo.connectionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!userContext.databaseAccount.properties.documentEndpoint) {
|
if (!userContext.databaseAccount.properties.documentEndpoint) {
|
||||||
userContext.databaseAccount.properties.documentEndpoint = fabricDatabaseConnectionInfo.endpoint;
|
userContext.databaseAccount.properties.documentEndpoint = resourceTokenInfo.endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
fabricContext: {
|
fabricContext: {
|
||||||
...userContext.fabricContext,
|
...userContext.fabricContext,
|
||||||
mirroredConnectionInfo: fabricDatabaseConnectionInfo,
|
databaseName: resourceTokenInfo.databaseId,
|
||||||
isReadOnly: true,
|
artifactInfo: {
|
||||||
|
...userContext.fabricContext.artifactInfo,
|
||||||
|
resourceTokenInfo,
|
||||||
|
},
|
||||||
|
isReadOnly: resourceTokenInfo.isReadOnly ?? userContext.fabricContext.isReadOnly,
|
||||||
},
|
},
|
||||||
databaseAccount: { ...userContext.databaseAccount },
|
databaseAccount: { ...userContext.databaseAccount },
|
||||||
});
|
});
|
||||||
@ -75,7 +79,8 @@ export const checkDatabaseResourceTokensValidity = (tokenTimestamp: number): voi
|
|||||||
|
|
||||||
export const isFabricMirrored = (): boolean =>
|
export const isFabricMirrored = (): boolean =>
|
||||||
configContext.platform === Platform.Fabric &&
|
configContext.platform === Platform.Fabric &&
|
||||||
userContext.fabricContext?.artifactType === CosmosDbArtifactType.MIRRORED;
|
(userContext.fabricContext?.artifactType === CosmosDbArtifactType.MIRRORED_KEY ||
|
||||||
|
userContext.fabricContext?.artifactType === CosmosDbArtifactType.MIRRORED_AAD);
|
||||||
|
|
||||||
export const isFabricNative = (): boolean =>
|
export const isFabricNative = (): boolean =>
|
||||||
configContext.platform === Platform.Fabric && userContext.fabricContext?.artifactType === CosmosDbArtifactType.NATIVE;
|
configContext.platform === Platform.Fabric && userContext.fabricContext?.artifactType === CosmosDbArtifactType.NATIVE;
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { CosmosDbArtifactType, ResourceTokenInfo } from "Contracts/FabricMessagesContract";
|
||||||
CosmosDbArtifactType,
|
|
||||||
FabricMirroredDatabaseConnectionInfo,
|
|
||||||
FabricNativeDatabaseConnectionInfo,
|
|
||||||
} from "Contracts/FabricMessagesContract";
|
|
||||||
import { ParsedResourceTokenConnectionString } from "Platform/Hosted/Helpers/ResourceTokenUtils";
|
import { ParsedResourceTokenConnectionString } from "Platform/Hosted/Helpers/ResourceTokenUtils";
|
||||||
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||||
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
|
import { traceOpen } from "Shared/Telemetry/TelemetryProcessor";
|
||||||
@ -51,13 +47,21 @@ export interface VCoreMongoConnectionParams {
|
|||||||
connectionString: string;
|
connectionString: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FabricContext {
|
export interface FabricArtifactInfo {
|
||||||
connectionId: string;
|
[CosmosDbArtifactType.MIRRORED_KEY]: {
|
||||||
|
connectionId: string;
|
||||||
|
resourceTokenInfo: ResourceTokenInfo | undefined;
|
||||||
|
};
|
||||||
|
[CosmosDbArtifactType.MIRRORED_AAD]: undefined;
|
||||||
|
[CosmosDbArtifactType.NATIVE]: undefined;
|
||||||
|
}
|
||||||
|
export interface FabricContext<T extends CosmosDbArtifactType> {
|
||||||
|
fabricClientRpcVersion: string;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
|
databaseName: string;
|
||||||
artifactType: CosmosDbArtifactType;
|
artifactType: CosmosDbArtifactType;
|
||||||
mirroredConnectionInfo: FabricMirroredDatabaseConnectionInfo | undefined;
|
artifactInfo: FabricArtifactInfo[T];
|
||||||
nativeConnectionInfo: FabricNativeDatabaseConnectionInfo | undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AdminFeedbackControlPolicy =
|
export type AdminFeedbackControlPolicy =
|
||||||
@ -76,7 +80,7 @@ export type AdminFeedbackPolicySettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface UserContext {
|
export interface UserContext {
|
||||||
readonly fabricContext?: FabricContext;
|
readonly fabricContext?: FabricContext<CosmosDbArtifactType>;
|
||||||
readonly authType?: AuthType;
|
readonly authType?: AuthType;
|
||||||
readonly masterKey?: string;
|
readonly masterKey?: string;
|
||||||
readonly subscriptionId?: string;
|
readonly subscriptionId?: string;
|
||||||
|
@ -3,11 +3,14 @@ import { createUri } from "Common/UrlUtility";
|
|||||||
import { DATA_EXPLORER_RPC_VERSION } from "Contracts/DataExplorerMessagesContract";
|
import { DATA_EXPLORER_RPC_VERSION } from "Contracts/DataExplorerMessagesContract";
|
||||||
import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
|
import { FabricMessageTypes } from "Contracts/FabricMessageTypes";
|
||||||
import {
|
import {
|
||||||
|
ArtifactConnectionInfo,
|
||||||
CosmosDbArtifactType,
|
CosmosDbArtifactType,
|
||||||
FABRIC_RPC_VERSION,
|
FABRIC_RPC_VERSION,
|
||||||
FabricMessageV2,
|
FabricMessageV2,
|
||||||
FabricNativeDatabaseConnectionInfo,
|
FabricMessageV3,
|
||||||
|
InitializeMessageV3,
|
||||||
} from "Contracts/FabricMessagesContract";
|
} from "Contracts/FabricMessagesContract";
|
||||||
|
import { useDialog } from "Explorer/Controls/Dialog";
|
||||||
import Explorer from "Explorer/Explorer";
|
import Explorer from "Explorer/Explorer";
|
||||||
import { useDataPlaneRbac } from "Explorer/Panes/SettingsPane/SettingsPane";
|
import { useDataPlaneRbac } from "Explorer/Panes/SettingsPane/SettingsPane";
|
||||||
import { useSelectedNode } from "Explorer/useSelectedNode";
|
import { useSelectedNode } from "Explorer/useSelectedNode";
|
||||||
@ -49,7 +52,7 @@ import {
|
|||||||
} from "../Platform/Hosted/HostedUtils";
|
} from "../Platform/Hosted/HostedUtils";
|
||||||
import { extractFeatures } from "../Platform/Hosted/extractFeatures";
|
import { extractFeatures } from "../Platform/Hosted/extractFeatures";
|
||||||
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
||||||
import { Node, PortalEnv, updateUserContext, userContext } from "../UserContext";
|
import { FabricArtifactInfo, Node, PortalEnv, updateUserContext, userContext } from "../UserContext";
|
||||||
import {
|
import {
|
||||||
acquireMsalTokenForAccount,
|
acquireMsalTokenForAccount,
|
||||||
acquireTokenWithMsal,
|
acquireTokenWithMsal,
|
||||||
@ -109,7 +112,7 @@ export function useKnockoutExplorer(platform: Platform): Explorer {
|
|||||||
|
|
||||||
async function configureFabric(): Promise<Explorer> {
|
async function configureFabric(): Promise<Explorer> {
|
||||||
// These are the versions of Fabric that Data Explorer supports.
|
// These are the versions of Fabric that Data Explorer supports.
|
||||||
const SUPPORTED_FABRIC_VERSIONS = [FABRIC_RPC_VERSION];
|
const SUPPORTED_FABRIC_VERSIONS = ["2", FABRIC_RPC_VERSION];
|
||||||
|
|
||||||
let firstContainerOpened = false;
|
let firstContainerOpened = false;
|
||||||
let explorer: Explorer;
|
let explorer: Explorer;
|
||||||
@ -125,7 +128,7 @@ async function configureFabric(): Promise<Explorer> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: FabricMessageV2 = event.data?.data;
|
const data: FabricMessageV2 | FabricMessageV3 = event.data?.data;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -134,30 +137,51 @@ async function configureFabric(): Promise<Explorer> {
|
|||||||
case "initialize": {
|
case "initialize": {
|
||||||
const fabricVersion = data.version;
|
const fabricVersion = data.version;
|
||||||
if (!SUPPORTED_FABRIC_VERSIONS.includes(fabricVersion)) {
|
if (!SUPPORTED_FABRIC_VERSIONS.includes(fabricVersion)) {
|
||||||
// TODO Surface error to user
|
// TODO Surface error to user and log to telemetry
|
||||||
|
useDialog
|
||||||
|
.getState()
|
||||||
|
.showOkModalDialog("Unsupported Fabric version", `Unsupported Fabric version: ${fabricVersion}`);
|
||||||
|
Logger.logError(`Unsupported Fabric version: ${fabricVersion}`, "Explorer/configureFabric");
|
||||||
console.error(`Unsupported Fabric version: ${fabricVersion}`);
|
console.error(`Unsupported Fabric version: ${fabricVersion}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Default values points to MIRRORED. This is for old fabric clients to explitly settings these values
|
if (fabricVersion === "2") {
|
||||||
data.message.artifactType = data.message.artifactType ?? CosmosDbArtifactType.MIRRORED;
|
// ----------------- TODO: Remove this when FabricMessageV2 is deprecated -----------------
|
||||||
data.message.isReadOnly = data.message.isReadOnly ?? true;
|
const initializationMessage = data.message as {
|
||||||
|
connectionId: string;
|
||||||
|
isVisible: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
explorer = createExplorerFabric(data.message);
|
explorer = createExplorerFabricLegacy(initializationMessage, data.version);
|
||||||
|
|
||||||
if (data.message.artifactType === CosmosDbArtifactType.MIRRORED) {
|
|
||||||
// Do not show Home tab for Mirrored
|
|
||||||
useTabs.getState().closeReactTab(ReactTabKind.Home);
|
|
||||||
await scheduleRefreshDatabaseResourceToken(true);
|
await scheduleRefreshDatabaseResourceToken(true);
|
||||||
|
resolve(explorer);
|
||||||
|
await explorer.refreshAllDatabases();
|
||||||
|
if (userContext.fabricContext.isVisible) {
|
||||||
|
firstContainerOpened = true;
|
||||||
|
openFirstContainer(explorer, userContext.fabricContext.databaseName);
|
||||||
|
}
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
} else if (fabricVersion === FABRIC_RPC_VERSION) {
|
||||||
|
const initializationMessage = data.message as InitializeMessageV3<CosmosDbArtifactType>;
|
||||||
|
explorer = createExplorerFabric(initializationMessage, data.version);
|
||||||
|
|
||||||
|
if (initializationMessage.artifactType === CosmosDbArtifactType.MIRRORED_KEY) {
|
||||||
|
// Do not show Home tab for Mirrored
|
||||||
|
useTabs.getState().closeReactTab(ReactTabKind.Home);
|
||||||
|
await scheduleRefreshDatabaseResourceToken(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(explorer);
|
||||||
|
await explorer.refreshAllDatabases();
|
||||||
|
|
||||||
|
const { databaseName } = userContext.fabricContext;
|
||||||
|
if (userContext.fabricContext.isVisible && databaseName) {
|
||||||
|
firstContainerOpened = true;
|
||||||
|
openFirstContainer(explorer, databaseName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(explorer);
|
|
||||||
await explorer.refreshAllDatabases();
|
|
||||||
|
|
||||||
if (userContext.fabricContext.isVisible && userContext.fabricContext.mirroredConnectionInfo?.databaseId) {
|
|
||||||
firstContainerOpened = true;
|
|
||||||
openFirstContainer(explorer, userContext.fabricContext.mirroredConnectionInfo.databaseId);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "newContainer":
|
case "newContainer":
|
||||||
@ -170,13 +194,12 @@ async function configureFabric(): Promise<Explorer> {
|
|||||||
}
|
}
|
||||||
case "explorerVisible": {
|
case "explorerVisible": {
|
||||||
userContext.fabricContext.isVisible = data.message.visible;
|
userContext.fabricContext.isVisible = data.message.visible;
|
||||||
if (
|
if (userContext.fabricContext.isVisible && !firstContainerOpened) {
|
||||||
userContext.fabricContext.isVisible &&
|
const { databaseName } = userContext.fabricContext;
|
||||||
!firstContainerOpened &&
|
if (databaseName !== undefined) {
|
||||||
userContext?.fabricContext?.mirroredConnectionInfo?.databaseId !== undefined
|
firstContainerOpened = true;
|
||||||
) {
|
openFirstContainer(explorer, databaseName);
|
||||||
firstContainerOpened = true;
|
}
|
||||||
openFirstContainer(explorer, userContext.fabricContext.mirroredConnectionInfo.databaseId);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -431,25 +454,67 @@ function configureHostedWithResourceToken(config: ResourceToken): Explorer {
|
|||||||
return explorer;
|
return explorer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createExplorerFabric = (params: {
|
/**
|
||||||
connectionId: string;
|
* Initialization for FabricMessageV2
|
||||||
isVisible: boolean;
|
* TODO: delete when FabricMessageV2 is deprecated
|
||||||
isReadOnly?: boolean;
|
* @param params
|
||||||
artifactType?: CosmosDbArtifactType;
|
* @returns
|
||||||
nativeConnectionInfo?: FabricNativeDatabaseConnectionInfo;
|
*/
|
||||||
}): Explorer => {
|
function createExplorerFabricLegacy(
|
||||||
|
params: { connectionId: string; isVisible: boolean },
|
||||||
|
fabricClientRpcVersion: string,
|
||||||
|
): Explorer {
|
||||||
|
const artifactInfo: FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY] = {
|
||||||
|
connectionId: params.connectionId,
|
||||||
|
resourceTokenInfo: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
fabricContext: {
|
fabricContext: {
|
||||||
connectionId: params.connectionId,
|
fabricClientRpcVersion,
|
||||||
mirroredConnectionInfo: undefined, // Set with resource token response
|
isReadOnly: true,
|
||||||
isReadOnly: params.isReadOnly,
|
isVisible: params.isVisible ?? true,
|
||||||
|
databaseName: undefined,
|
||||||
|
artifactType: CosmosDbArtifactType.MIRRORED_KEY,
|
||||||
|
artifactInfo,
|
||||||
|
},
|
||||||
|
authType: AuthType.ConnectionString,
|
||||||
|
databaseAccount: {
|
||||||
|
id: "",
|
||||||
|
location: "",
|
||||||
|
type: "",
|
||||||
|
name: "Mounted",
|
||||||
|
kind: AccountKind.Default,
|
||||||
|
properties: {
|
||||||
|
documentEndpoint: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const explorer = new Explorer();
|
||||||
|
return explorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization for FabricMessageV3 and above
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const createExplorerFabric = (
|
||||||
|
params: InitializeMessageV3<CosmosDbArtifactType>,
|
||||||
|
fabricClientRpcVersion: string,
|
||||||
|
): Explorer => {
|
||||||
|
updateUserContext({
|
||||||
|
fabricContext: {
|
||||||
|
fabricClientRpcVersion,
|
||||||
|
databaseName: undefined,
|
||||||
isVisible: params.isVisible,
|
isVisible: params.isVisible,
|
||||||
|
isReadOnly: params.isReadOnly,
|
||||||
artifactType: params.artifactType,
|
artifactType: params.artifactType,
|
||||||
nativeConnectionInfo: params.nativeConnectionInfo,
|
artifactInfo: undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (params.artifactType === CosmosDbArtifactType.MIRRORED) {
|
if (params.artifactType === CosmosDbArtifactType.MIRRORED_KEY) {
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
authType: AuthType.ConnectionString, // TODO: will need its own type and Mirroring could be using AAD
|
authType: AuthType.ConnectionString, // TODO: will need its own type and Mirroring could be using AAD
|
||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
@ -462,8 +527,17 @@ const createExplorerFabric = (params: {
|
|||||||
documentEndpoint: undefined,
|
documentEndpoint: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
fabricContext: {
|
||||||
|
...userContext.fabricContext,
|
||||||
|
artifactInfo: {
|
||||||
|
connectionId: (params.artifactConnectionInfo as ArtifactConnectionInfo[CosmosDbArtifactType.MIRRORED_KEY])
|
||||||
|
.connectionId,
|
||||||
|
resourceTokenInfo: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} else if (params.artifactType === CosmosDbArtifactType.NATIVE) {
|
} else if (params.artifactType === CosmosDbArtifactType.NATIVE) {
|
||||||
|
const nativeParams = params as InitializeMessageV3<CosmosDbArtifactType.NATIVE>;
|
||||||
// Make it behave like Hosted/AAD/RBAC
|
// Make it behave like Hosted/AAD/RBAC
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
@ -473,14 +547,20 @@ const createExplorerFabric = (params: {
|
|||||||
name: "Native", // TODO: not used?
|
name: "Native", // TODO: not used?
|
||||||
kind: AccountKind.Default,
|
kind: AccountKind.Default,
|
||||||
properties: {
|
properties: {
|
||||||
documentEndpoint: params.nativeConnectionInfo.accountEndpoint,
|
documentEndpoint: nativeParams.artifactConnectionInfo.accountEndpoint,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authType: AuthType.AAD,
|
authType: AuthType.AAD,
|
||||||
dataPlaneRbacEnabled: true,
|
dataPlaneRbacEnabled: true,
|
||||||
aadToken: params.nativeConnectionInfo.accessToken,
|
aadToken: nativeParams.artifactConnectionInfo.accessToken,
|
||||||
masterKey: undefined,
|
masterKey: undefined,
|
||||||
|
fabricContext: {
|
||||||
|
...userContext.fabricContext,
|
||||||
|
databaseName: nativeParams.artifactConnectionInfo.databaseName,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
} else if (params.artifactType === CosmosDbArtifactType.MIRRORED_AAD) {
|
||||||
|
throw new Error("Mirrored AAD is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
const explorer = new Explorer();
|
const explorer = new Explorer();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user