mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 09:20:16 +00:00
Test Explorer Improvements (#541)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { applyExplorerBindings } from "../applyExplorerBindings";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { AccountKind, DefaultAccountExperience } from "../Common/Constants";
|
||||
@@ -32,53 +32,65 @@ import { isInvalidParentFrameOrigin } from "../Utils/MessageValidation";
|
||||
// This hook will create a new instance of Explorer.ts and bind it to the DOM
|
||||
// This hook has a LOT of magic, but ideally we can delete it once we have removed KO and switched entirely to React
|
||||
// Pleas tread carefully :)
|
||||
let explorer: Explorer;
|
||||
|
||||
export function useKnockoutExplorer(platform: Platform, explorerParams: ExplorerParams): Explorer {
|
||||
explorer = explorer || new Explorer(explorerParams);
|
||||
const [explorer, setExplorer] = useState<Explorer>();
|
||||
|
||||
useEffect(() => {
|
||||
const effect = async () => {
|
||||
if (platform) {
|
||||
if (platform === Platform.Hosted) {
|
||||
await configureHosted();
|
||||
applyExplorerBindings(explorer);
|
||||
const explorer = await configureHosted(explorerParams);
|
||||
setExplorer(explorer);
|
||||
} else if (platform === Platform.Emulator) {
|
||||
configureEmulator();
|
||||
applyExplorerBindings(explorer);
|
||||
const explorer = configureEmulator(explorerParams);
|
||||
setExplorer(explorer);
|
||||
} else if (platform === Platform.Portal) {
|
||||
configurePortal();
|
||||
const explorer = await configurePortal(explorerParams);
|
||||
setExplorer(explorer);
|
||||
}
|
||||
}
|
||||
};
|
||||
effect();
|
||||
}, [platform]);
|
||||
|
||||
useEffect(() => {
|
||||
if (explorer) {
|
||||
applyExplorerBindings(explorer);
|
||||
}
|
||||
}, [explorer]);
|
||||
|
||||
return explorer;
|
||||
}
|
||||
|
||||
async function configureHosted() {
|
||||
async function configureHosted(explorerParams: ExplorerParams): Promise<Explorer> {
|
||||
const win = (window as unknown) as HostedExplorerChildFrame;
|
||||
if (win.hostedConfig.authType === AuthType.EncryptedToken) {
|
||||
configureHostedWithEncryptedToken(win.hostedConfig);
|
||||
return configureHostedWithEncryptedToken(win.hostedConfig, explorerParams);
|
||||
} else if (win.hostedConfig.authType === AuthType.ResourceToken) {
|
||||
configureHostedWithResourceToken(win.hostedConfig);
|
||||
return configureHostedWithResourceToken(win.hostedConfig, explorerParams);
|
||||
} else if (win.hostedConfig.authType === AuthType.ConnectionString) {
|
||||
configureHostedWithConnectionString(win.hostedConfig);
|
||||
return configureHostedWithConnectionString(win.hostedConfig, explorerParams);
|
||||
} else if (win.hostedConfig.authType === AuthType.AAD) {
|
||||
await configureHostedWithAAD(win.hostedConfig);
|
||||
return configureHostedWithAAD(win.hostedConfig, explorerParams);
|
||||
}
|
||||
throw new Error(`Unknown hosted config: ${win.hostedConfig}`);
|
||||
}
|
||||
|
||||
async function configureHostedWithAAD(config: AAD) {
|
||||
async function configureHostedWithAAD(config: AAD, explorerParams: ExplorerParams): Promise<Explorer> {
|
||||
const account = config.databaseAccount;
|
||||
const accountResourceId = account.id;
|
||||
const subscriptionId = accountResourceId && accountResourceId.split("subscriptions/")[1].split("/")[0];
|
||||
const resourceGroup = accountResourceId && accountResourceId.split("resourceGroups/")[1].split("/")[0];
|
||||
updateUserContext({
|
||||
subscriptionId,
|
||||
resourceGroup,
|
||||
authType: AuthType.AAD,
|
||||
authorizationToken: `Bearer ${config.authorizationToken}`,
|
||||
databaseAccount: config.databaseAccount,
|
||||
});
|
||||
const keys = await listKeys(subscriptionId, resourceGroup, account.name);
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.configure({
|
||||
databaseAccount: account,
|
||||
subscriptionId,
|
||||
@@ -87,9 +99,10 @@ async function configureHostedWithAAD(config: AAD) {
|
||||
authorizationToken: `Bearer ${config.authorizationToken}`,
|
||||
features: extractFeatures(),
|
||||
});
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureHostedWithConnectionString(config: ConnectionString) {
|
||||
function configureHostedWithConnectionString(config: ConnectionString, explorerParams: ExplorerParams): Explorer {
|
||||
const apiExperience = DefaultExperienceUtility.getDefaultExperienceFromApiKind(config.encryptedTokenMetadata.apiKind);
|
||||
const databaseAccount = {
|
||||
id: "",
|
||||
@@ -106,14 +119,16 @@ function configureHostedWithConnectionString(config: ConnectionString) {
|
||||
accessToken: encodeURIComponent(config.encryptedToken),
|
||||
databaseAccount,
|
||||
});
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.configure({
|
||||
databaseAccount,
|
||||
masterKey: config.masterKey,
|
||||
features: extractFeatures(),
|
||||
});
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureHostedWithResourceToken(config: ResourceToken) {
|
||||
function configureHostedWithResourceToken(config: ResourceToken, explorerParams: ExplorerParams): Explorer {
|
||||
const parsedResourceToken = parseResourceTokenConnectionString(config.resourceToken);
|
||||
const databaseAccount = {
|
||||
id: "",
|
||||
@@ -131,6 +146,7 @@ function configureHostedWithResourceToken(config: ResourceToken) {
|
||||
resourceToken: parsedResourceToken.resourceToken,
|
||||
endpoint: parsedResourceToken.accountEndpoint,
|
||||
});
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.resourceTokenDatabaseId(parsedResourceToken.databaseId);
|
||||
explorer.resourceTokenCollectionId(parsedResourceToken.collectionId);
|
||||
if (parsedResourceToken.partitionKey) {
|
||||
@@ -142,9 +158,10 @@ function configureHostedWithResourceToken(config: ResourceToken) {
|
||||
isAuthWithresourceToken: true,
|
||||
});
|
||||
explorer.isRefreshingExplorer(false);
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureHostedWithEncryptedToken(config: EncryptedToken) {
|
||||
function configureHostedWithEncryptedToken(config: EncryptedToken, explorerParams: ExplorerParams): Explorer {
|
||||
updateUserContext({
|
||||
authType: AuthType.EncryptedToken,
|
||||
accessToken: encodeURIComponent(config.encryptedToken),
|
||||
@@ -152,6 +169,7 @@ function configureHostedWithEncryptedToken(config: EncryptedToken) {
|
||||
const apiExperience: string = DefaultExperienceUtility.getDefaultExperienceFromApiKind(
|
||||
config.encryptedTokenMetadata.apiKind
|
||||
);
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.configure({
|
||||
databaseAccount: {
|
||||
id: "",
|
||||
@@ -162,91 +180,98 @@ function configureHostedWithEncryptedToken(config: EncryptedToken) {
|
||||
},
|
||||
features: extractFeatures(),
|
||||
});
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configureEmulator() {
|
||||
function configureEmulator(explorerParams: ExplorerParams): Explorer {
|
||||
updateUserContext({
|
||||
databaseAccount: emulatorAccount,
|
||||
authType: AuthType.MasterKey,
|
||||
});
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.databaseAccount(emulatorAccount);
|
||||
explorer.isAccountReady(true);
|
||||
return explorer;
|
||||
}
|
||||
|
||||
function configurePortal() {
|
||||
async function configurePortal(explorerParams: ExplorerParams): Promise<Explorer> {
|
||||
updateUserContext({
|
||||
authType: AuthType.AAD,
|
||||
});
|
||||
// In development mode, try to load the iframe message from session storage.
|
||||
// This allows webpack hot reload to function properly in the portal
|
||||
if (process.env.NODE_ENV === "development" && !window.location.search.includes("disablePortalInitCache")) {
|
||||
const initMessage = sessionStorage.getItem("portalDataExplorerInitMessage");
|
||||
if (initMessage) {
|
||||
const message = JSON.parse(initMessage);
|
||||
console.warn(
|
||||
"Loaded cached portal iframe message from session storage. Do a full page refresh to get a new message"
|
||||
);
|
||||
console.dir(message);
|
||||
explorer.configure(message);
|
||||
applyExplorerBindings(explorer);
|
||||
return new Promise((resolve) => {
|
||||
// In development mode, try to load the iframe message from session storage.
|
||||
// This allows webpack hot reload to function properly in the portal
|
||||
if (process.env.NODE_ENV === "development" && !window.location.search.includes("disablePortalInitCache")) {
|
||||
const initMessage = sessionStorage.getItem("portalDataExplorerInitMessage");
|
||||
if (initMessage) {
|
||||
const message = JSON.parse(initMessage);
|
||||
console.warn(
|
||||
"Loaded cached portal iframe message from session storage. Do a full page refresh to get a new message"
|
||||
);
|
||||
console.dir(message);
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.configure(message);
|
||||
resolve(explorer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the Portal, configuration of Explorer happens via iframe message
|
||||
window.addEventListener(
|
||||
"message",
|
||||
(event) => {
|
||||
if (isInvalidParentFrameOrigin(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldProcessMessage(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for init message
|
||||
const message: PortalMessage = event.data?.data;
|
||||
const inputs = message?.inputs;
|
||||
const openAction = message?.openAction;
|
||||
if (inputs) {
|
||||
if (
|
||||
configContext.BACKEND_ENDPOINT &&
|
||||
configContext.platform === Platform.Portal &&
|
||||
process.env.NODE_ENV === "development"
|
||||
) {
|
||||
inputs.extensionEndpoint = configContext.PROXY_PATH;
|
||||
// In the Portal, configuration of Explorer happens via iframe message
|
||||
window.addEventListener(
|
||||
"message",
|
||||
(event) => {
|
||||
if (isInvalidParentFrameOrigin(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authorizationToken = inputs.authorizationToken || "";
|
||||
const masterKey = inputs.masterKey || "";
|
||||
const databaseAccount = inputs.databaseAccount;
|
||||
|
||||
updateConfigContext({
|
||||
BACKEND_ENDPOINT: inputs.extensionEndpoint || configContext.BACKEND_ENDPOINT,
|
||||
ARM_ENDPOINT: normalizeArmEndpoint(inputs.csmEndpoint || configContext.ARM_ENDPOINT),
|
||||
});
|
||||
|
||||
updateUserContext({
|
||||
authorizationToken,
|
||||
masterKey,
|
||||
databaseAccount,
|
||||
resourceGroup: inputs.resourceGroup,
|
||||
subscriptionId: inputs.subscriptionId,
|
||||
subscriptionType: inputs.subscriptionType,
|
||||
quotaId: inputs.quotaId,
|
||||
});
|
||||
|
||||
explorer.configure(inputs);
|
||||
applyExplorerBindings(explorer);
|
||||
if (openAction) {
|
||||
handleOpenAction(openAction, explorer.nonSystemDatabases(), explorer);
|
||||
if (!shouldProcessMessage(event)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
sendMessage("ready");
|
||||
// Check for init message
|
||||
const message: PortalMessage = event.data?.data;
|
||||
const inputs = message?.inputs;
|
||||
const openAction = message?.openAction;
|
||||
if (inputs) {
|
||||
if (
|
||||
configContext.BACKEND_ENDPOINT &&
|
||||
configContext.platform === Platform.Portal &&
|
||||
process.env.NODE_ENV === "development"
|
||||
) {
|
||||
inputs.extensionEndpoint = configContext.PROXY_PATH;
|
||||
}
|
||||
|
||||
const authorizationToken = inputs.authorizationToken || "";
|
||||
const masterKey = inputs.masterKey || "";
|
||||
const databaseAccount = inputs.databaseAccount;
|
||||
|
||||
updateConfigContext({
|
||||
BACKEND_ENDPOINT: inputs.extensionEndpoint || configContext.BACKEND_ENDPOINT,
|
||||
ARM_ENDPOINT: normalizeArmEndpoint(inputs.csmEndpoint || configContext.ARM_ENDPOINT),
|
||||
});
|
||||
|
||||
updateUserContext({
|
||||
authorizationToken,
|
||||
masterKey,
|
||||
databaseAccount,
|
||||
resourceGroup: inputs.resourceGroup,
|
||||
subscriptionId: inputs.subscriptionId,
|
||||
subscriptionType: inputs.subscriptionType,
|
||||
quotaId: inputs.quotaId,
|
||||
});
|
||||
|
||||
const explorer = new Explorer(explorerParams);
|
||||
explorer.configure(inputs);
|
||||
resolve(explorer);
|
||||
if (openAction) {
|
||||
handleOpenAction(openAction, explorer.nonSystemDatabases(), explorer);
|
||||
}
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
sendMessage("ready");
|
||||
});
|
||||
}
|
||||
|
||||
function shouldProcessMessage(event: MessageEvent): boolean {
|
||||
|
||||
Reference in New Issue
Block a user