mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-23 10:51:30 +00:00
Compare commits
1 Commits
documentdb
...
cloudshell
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac137c994b |
@@ -44,12 +44,6 @@ export interface DatabaseAccountExtendedProperties {
|
||||
publicNetworkAccess?: string;
|
||||
enablePriorityBasedExecution?: boolean;
|
||||
vcoreMongoEndpoint?: string;
|
||||
apiProperties?: ApiProperties;
|
||||
}
|
||||
|
||||
export interface ApiProperties {
|
||||
/* Describes the version of the MongoDB account. */
|
||||
serverVersion?: "3.2" | "3.6" | "4.0" | "4.2" | "5.0" | "6.0" | "7.0";
|
||||
}
|
||||
|
||||
export interface DatabaseAccountResponseLocation {
|
||||
|
||||
@@ -18,7 +18,6 @@ import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||
import { acquireMsalTokenForAccount } from "Utils/AuthorizationUtils";
|
||||
import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointUtils";
|
||||
import { featureRegistered } from "Utils/FeatureRegistrationUtils";
|
||||
import { getVSCodeUrl } from "Utils/VSCodeExtensionUtils";
|
||||
import { update } from "Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import * as ko from "knockout";
|
||||
@@ -290,8 +289,40 @@ export default class Explorer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a VS Code DocumentDB connection URL using the current user's MongoDB connection parameters.
|
||||
* Double-encodes the updated connection string for safe usage in VS Code URLs.
|
||||
*
|
||||
* The DocumentDB VS Code extension requires double encoding for connection strings.
|
||||
* See: https://microsoft.github.io/vscode-documentdb/manual/how-to-construct-url.html#double-encoding
|
||||
*
|
||||
* @returns {string} The encoded VS Code DocumentDB connection URL.
|
||||
*/
|
||||
private getDocumentDbUrl() {
|
||||
const { adminLogin: adminLoginuserName = "", connectionString = "" } = userContext.vcoreMongoConnectionParams;
|
||||
const updatedConnectionString = connectionString.replace(/<(user|username)>:<password>/i, adminLoginuserName);
|
||||
const encodedUpdatedConnectionString = encodeURIComponent(encodeURIComponent(updatedConnectionString));
|
||||
const documentDbUrl = `vscode://ms-azuretools.vscode-documentdb?connectionString=${encodedUpdatedConnectionString}`;
|
||||
return documentDbUrl;
|
||||
}
|
||||
|
||||
private getCosmosDbUrl() {
|
||||
const activeTab = useTabs.getState().activeTab;
|
||||
const resourceId = encodeURIComponent(userContext.databaseAccount.id);
|
||||
const database = encodeURIComponent(activeTab?.collection?.databaseId);
|
||||
const container = encodeURIComponent(activeTab?.collection?.id());
|
||||
const baseUrl = `vscode://ms-azuretools.vscode-cosmosdb?resourceId=${resourceId}`;
|
||||
const vscodeUrl = activeTab ? `${baseUrl}&database=${database}&container=${container}` : baseUrl;
|
||||
return vscodeUrl;
|
||||
}
|
||||
|
||||
private getVSCodeUrl(): string {
|
||||
const isvCore = (userContext.apiType || userContext.databaseAccount.kind) === "VCoreMongo";
|
||||
return isvCore ? this.getDocumentDbUrl() : this.getCosmosDbUrl();
|
||||
}
|
||||
|
||||
public openInVsCode(): void {
|
||||
const vscodeUrl = getVSCodeUrl();
|
||||
const vscodeUrl = this.getVSCodeUrl();
|
||||
const openVSCodeDialogProps: DialogProps = {
|
||||
linkProps: {
|
||||
linkText: "Download Visual Studio Code",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* Accordion top class
|
||||
*/
|
||||
import { Link, makeStyles, tokens } from "@fluentui/react-components";
|
||||
import { DocumentAddRegular, LinkMultipleRegular, OpenRegular } from "@fluentui/react-icons";
|
||||
import { makeStyles, tokens } from "@fluentui/react-components";
|
||||
import { DocumentAddRegular, LinkMultipleRegular } from "@fluentui/react-icons";
|
||||
import { SampleDataImportDialog } from "Explorer/SplashScreen/SampleDataImportDialog";
|
||||
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
|
||||
import { isFabricNative, isFabricNativeReadOnly } from "Platform/Fabric/FabricUtil";
|
||||
@@ -119,7 +119,7 @@ const FabricHomeScreenButton: React.FC<FabricHomeScreenButtonProps & { className
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
return (
|
||||
<div role="button" className={`${styles.buttonContainer} ${className}`} onClick={onClick} tabIndex={0}>
|
||||
<div role="button" className={`${styles.buttonContainer} ${className}`} onClick={onClick}>
|
||||
<div className={styles.buttonUpperPart}>{icon}</div>
|
||||
<div aria-label={title} className={styles.buttonLowerPart}>
|
||||
<div>{title}</div>
|
||||
@@ -147,7 +147,7 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
|
||||
{
|
||||
title: "Sample data",
|
||||
description: "Automatically load sample data in your database",
|
||||
icon: <img src={CosmosDbBlackIcon} alt={"Azure Cosmos DB icon"} aria-hidden="true" />,
|
||||
icon: <img src={CosmosDbBlackIcon} />,
|
||||
onClick: () => setOpenSampleDataImportDialog(true),
|
||||
},
|
||||
{
|
||||
@@ -181,18 +181,16 @@ export const FabricHomeScreen: React.FC<SplashScreenProps> = (props: SplashScree
|
||||
explorer={props.explorer}
|
||||
databaseName={userContext.fabricContext?.databaseName}
|
||||
/>
|
||||
<div className={styles.title} role="heading" aria-label={title} aria-level={1}>
|
||||
<div className={styles.title} role="heading" aria-label={title}>
|
||||
{title}
|
||||
</div>
|
||||
{getSplashScreenButtons()}
|
||||
{
|
||||
<div className={styles.footer}>
|
||||
Need help?{" "}
|
||||
<Link href="https://learn.microsoft.com/fabric/database/cosmos-db/overview" target="_blank">
|
||||
Learn more <OpenRegular />
|
||||
</Link>
|
||||
</div>
|
||||
}
|
||||
{/* <div className={styles.footer}>
|
||||
Need help?{" "}
|
||||
<Link href="https://aka.ms/cosmosdbfabricdocs" target="_blank">
|
||||
Learn more <img src={LinkIcon} alt="Learn more" />
|
||||
</Link>
|
||||
</div> */}
|
||||
</CosmosFluentProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -14,11 +14,6 @@ export const DISABLE_HISTORY = `set +o history`;
|
||||
* Used when shell initialization or connection fails.
|
||||
*/
|
||||
export const EXIT_COMMAND = ` printf "\\033[1;31mSession ended. Please close this tab and initiate a new shell session if needed.\\033[0m\\n" && disown -a && exit`;
|
||||
/**
|
||||
* Command that displays error message with MongoDB networking guidance and exits the shell session.
|
||||
* Used when MongoDB shell connection fails due to networking issues.
|
||||
*/
|
||||
export const EXIT_COMMAND_MONGO = ` printf "\\033[1;31mSession ended. Please close this tab and initiate a new shell session if needed.\\033[0m\\n" && printf "\\033[1;36mPlease use the 'Add Azure Cloud Shell IPs' button in the Networking blade to allow Cloud Shell access, if not already configured.\\033[0m\\n" && disown -a && exit`;
|
||||
|
||||
/**
|
||||
* This command runs mongosh in no-database and quiet mode,
|
||||
@@ -45,14 +40,6 @@ export abstract class AbstractShellHandler {
|
||||
abstract getTerminalSuppressedData(): string[];
|
||||
updateTerminalData?(data: string): string;
|
||||
|
||||
/**
|
||||
* Gets the exit command to use when connection fails.
|
||||
* Can be overridden by subclasses to provide custom exit commands.
|
||||
*/
|
||||
protected getExitCommand(): string {
|
||||
return EXIT_COMMAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the complete initialization command sequence for the shell.
|
||||
*
|
||||
@@ -77,7 +64,7 @@ export abstract class AbstractShellHandler {
|
||||
START_MARKER,
|
||||
DISABLE_HISTORY,
|
||||
...setupCommands,
|
||||
`{ ${connectionCommand}; } || true;${this.getExitCommand()}`,
|
||||
`{ ${connectionCommand}; } || true;${EXIT_COMMAND}`,
|
||||
];
|
||||
|
||||
return allCommands.join("\n").concat("\n");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { userContext } from "../../../../UserContext";
|
||||
import { filterAndCleanTerminalOutput, getHostFromUrl, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||
|
||||
export class MongoShellHandler extends AbstractShellHandler {
|
||||
private _key: string;
|
||||
@@ -48,10 +48,6 @@ export class MongoShellHandler extends AbstractShellHandler {
|
||||
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||
}
|
||||
|
||||
protected getExitCommand(): string {
|
||||
return EXIT_COMMAND_MONGO;
|
||||
}
|
||||
|
||||
updateTerminalData(data: string): string {
|
||||
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { userContext } from "../../../../UserContext";
|
||||
import { filterAndCleanTerminalOutput, getMongoShellRemoveInfoText } from "../Utils/CommonUtils";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND, EXIT_COMMAND_MONGO } from "./AbstractShellHandler";
|
||||
import { AbstractShellHandler, DISABLE_TELEMETRY_COMMAND } from "./AbstractShellHandler";
|
||||
|
||||
export class VCoreMongoShellHandler extends AbstractShellHandler {
|
||||
private _endpoint: string | undefined;
|
||||
@@ -35,13 +35,6 @@ export class VCoreMongoShellHandler extends AbstractShellHandler {
|
||||
return ["Warning: Non-Genuine MongoDB Detected", "Telemetry is now disabled."];
|
||||
}
|
||||
|
||||
/**
|
||||
* Override getExitCommand to include MongoDB networking guidance
|
||||
*/
|
||||
protected getExitCommand(): string {
|
||||
return EXIT_COMMAND_MONGO;
|
||||
}
|
||||
|
||||
updateTerminalData(data: string): string {
|
||||
return filterAndCleanTerminalOutput(data, this._removeInfoText);
|
||||
}
|
||||
|
||||
13
src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts
Normal file
13
src/Explorer/Tabs/CloudShellTab/Utils/CloudShellIPUtils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export const CLOUDSHELL_IP_RECOMMENDATIONS = {
|
||||
centralindia: ["4.247.135.109", "74.225.207.63"],
|
||||
southeastasia: ["4.194.56.6", "4.194.213.10", "4.194.144.127", "4.194.5.74"],
|
||||
centraluseuap: ["52.158.186.182", "172.215.26.246", "134.138.154.177", "134.138.129.52", "172.215.31.177"],
|
||||
eastus2euap: ["135.18.43.51", "20.252.175.33", "40.89.88.111", "135.18.17.187", "135.18.67.251"],
|
||||
eastus: ["40.71.199.151", "20.42.18.188", "52.190.17.9", "20.120.96.152"],
|
||||
northeurope: ["74.234.65.146", "52.169.70.113"],
|
||||
southcentralus: ["4.151.247.81", "20.225.211.35", "4.151.48.133", "4.151.247.225"],
|
||||
westeurope: ["52.166.126.216", "108.142.162.20", "52.178.13.125", "172.201.33.160"],
|
||||
westus: ["20.245.161.131", "57.154.182.51", "40.118.133.244", "20.253.192.12", "20.43.245.209", "20.66.22.66"],
|
||||
usgovarizona: ["62.10.232.179"],
|
||||
usgovvirginia: ["62.10.26.85"],
|
||||
};
|
||||
@@ -7,8 +7,11 @@ const validCloudShellRegions = new Set([
|
||||
"westeurope",
|
||||
"centralindia",
|
||||
"southeastasia",
|
||||
"westcentralus",
|
||||
"usgovvirginia",
|
||||
"usgovarizona",
|
||||
"centraluseuap",
|
||||
"eastus2euap",
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -40,7 +43,8 @@ export const getNormalizedRegion = (region: string, defaultCloudshellRegion: str
|
||||
}
|
||||
|
||||
const regionMap: Record<string, string> = {
|
||||
eastus2: "eastus",
|
||||
centralus: "centraluseuap",
|
||||
eastus2: "eastus2euap",
|
||||
};
|
||||
|
||||
const normalizedRegion = regionMap[region.toLowerCase()] || region;
|
||||
|
||||
40
src/Explorer/Tabs/Shared/CloudShellIPChecker.ts
Normal file
40
src/Explorer/Tabs/Shared/CloudShellIPChecker.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { configContext } from "ConfigContext";
|
||||
import * as DataModels from "Contracts/DataModels";
|
||||
import { userContext } from "UserContext";
|
||||
import { armRequest } from "Utils/arm/request";
|
||||
import { CLOUDSHELL_IP_RECOMMENDATIONS } from "../CloudShellTab/Utils/CloudShellIPUtils";
|
||||
import { getNormalizedRegion } from "../CloudShellTab/Utils/RegionUtils";
|
||||
|
||||
export async function checkCloudShellIPsConfigured() {
|
||||
const databaseRegion = userContext.databaseAccount?.location;
|
||||
console.log("db region", databaseRegion);
|
||||
const normalizedRegion = getNormalizedRegion(databaseRegion, "westus");
|
||||
const cloudShellIPs = getCloudShellIPsForRegion(normalizedRegion);
|
||||
console.log("CloudShell IPs for region", normalizedRegion, cloudShellIPs);
|
||||
if (!cloudShellIPs || cloudShellIPs.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const firewallRules = await getFirewallRules();
|
||||
console.log("firewall rules", firewallRules);
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCloudShellIPsForRegion(region: string): string[] {
|
||||
const regionKey = region.toLowerCase();
|
||||
const ips = CLOUDSHELL_IP_RECOMMENDATIONS[regionKey as keyof typeof CLOUDSHELL_IP_RECOMMENDATIONS];
|
||||
return ips ? [...ips] : [];
|
||||
}
|
||||
|
||||
async function getFirewallRules(): Promise<DataModels.FirewallRule[]> {
|
||||
const firewallRulesUri = `${userContext.databaseAccount.id}/firewallRules`;
|
||||
|
||||
const response: any = await armRequest({
|
||||
host: configContext.ARM_ENDPOINT,
|
||||
path: firewallRulesUri,
|
||||
method: "GET",
|
||||
apiVersion: "2023-03-01-preview",
|
||||
});
|
||||
|
||||
return response?.data?.value || response?.value || [];
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { QuickstartFirewallNotification } from "Explorer/Quickstart/QuickstartFi
|
||||
import { getShellNameForDisplay } from "Explorer/Tabs/CloudShellTab/Utils/CommonUtils";
|
||||
import * as React from "react";
|
||||
import FirewallRuleScreenshot from "../../../../images/firewallRule.png";
|
||||
import VcoreFirewallRuleScreenshot from "../../../../images/vcoreMongoFirewallRule.png";
|
||||
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
@@ -21,18 +22,28 @@ export abstract class BaseTerminalComponentAdapter implements ReactAdapter {
|
||||
protected getUsername: () => string,
|
||||
protected isAllPublicIPAddressesEnabled: ko.Observable<boolean>,
|
||||
protected kind: ViewModels.TerminalKind,
|
||||
) {}
|
||||
protected isCloudShellIPsConfigured?: ko.Observable<boolean>,
|
||||
) { }
|
||||
|
||||
public renderComponent(): JSX.Element {
|
||||
if (this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo) {
|
||||
return this.renderTerminalComponent();
|
||||
if (this.kind === ViewModels.TerminalKind.VCoreMongo && this.isCloudShellIPsConfigured && !this.isCloudShellIPsConfigured()) {
|
||||
return (
|
||||
<QuickstartFirewallNotification
|
||||
messageType={this.getMessageType()}
|
||||
screenshot={VcoreFirewallRuleScreenshot}
|
||||
shellName={getShellNameForDisplay(this.kind)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.isAllPublicIPAddressesEnabled()) {
|
||||
return (
|
||||
<QuickstartFirewallNotification
|
||||
messageType={this.getMessageType()}
|
||||
screenshot={FirewallRuleScreenshot}
|
||||
screenshot={
|
||||
this.kind === ViewModels.TerminalKind.Mongo || this.kind === ViewModels.TerminalKind.VCoreMongo
|
||||
? VcoreFirewallRuleScreenshot
|
||||
: FirewallRuleScreenshot
|
||||
}
|
||||
shellName={getShellNameForDisplay(this.kind)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { userContext } from "../../UserContext";
|
||||
import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent";
|
||||
import Explorer from "../Explorer";
|
||||
import { useNotebook } from "../Notebook/useNotebook";
|
||||
import { checkCloudShellIPsConfigured } from "./Shared/CloudShellIPChecker";
|
||||
import { NotebookTerminalComponentAdapter } from "./ShellAdapters/NotebookTerminalComponentAdapter";
|
||||
import TabsBase from "./TabsBase";
|
||||
|
||||
@@ -23,11 +24,13 @@ export default class TerminalTab extends TabsBase {
|
||||
private container: Explorer;
|
||||
private notebookTerminalComponentAdapter: ReactAdapter;
|
||||
private isAllPublicIPAddressesEnabled: ko.Observable<boolean>;
|
||||
private isCloudShellIPsConfigured: ko.Observable<boolean>;
|
||||
|
||||
constructor(options: TerminalTabOptions) {
|
||||
super(options);
|
||||
this.container = options.container;
|
||||
this.isAllPublicIPAddressesEnabled = ko.observable(true);
|
||||
this.isCloudShellIPsConfigured = ko.observable(true);
|
||||
|
||||
const commonArgs: [
|
||||
() => DataModels.DatabaseAccount,
|
||||
@@ -36,19 +39,37 @@ export default class TerminalTab extends TabsBase {
|
||||
ko.Observable<boolean>,
|
||||
ViewModels.TerminalKind,
|
||||
] = [
|
||||
() => userContext?.databaseAccount,
|
||||
() => this.tabId,
|
||||
() => this.getUsername(),
|
||||
this.isAllPublicIPAddressesEnabled,
|
||||
options.kind,
|
||||
];
|
||||
() => userContext?.databaseAccount,
|
||||
() => this.tabId,
|
||||
() => this.getUsername(),
|
||||
this.isAllPublicIPAddressesEnabled,
|
||||
options.kind,
|
||||
];
|
||||
|
||||
if (userContext.features.enableCloudShell) {
|
||||
this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(...commonArgs);
|
||||
this.notebookTerminalComponentAdapter = new CloudShellTerminalComponentAdapter(
|
||||
() => userContext?.databaseAccount,
|
||||
() => this.tabId,
|
||||
() => this.getUsername(),
|
||||
this.isAllPublicIPAddressesEnabled,
|
||||
options.kind,
|
||||
options.kind === ViewModels.TerminalKind.VCoreMongo ? this.isCloudShellIPsConfigured : undefined,
|
||||
);
|
||||
|
||||
this.notebookTerminalComponentAdapter.parameters = ko.computed<boolean>(() => {
|
||||
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
|
||||
const cloudShellConfigured = this.isCloudShellIPsConfigured();
|
||||
return this.isTemplateReady() && cloudShellConfigured;
|
||||
}
|
||||
return this.isTemplateReady() && this.isAllPublicIPAddressesEnabled();
|
||||
});
|
||||
|
||||
if (options.kind === ViewModels.TerminalKind.VCoreMongo) {
|
||||
(async () => {
|
||||
const result = await checkCloudShellIPsConfigured();
|
||||
this.isCloudShellIPsConfigured(result);
|
||||
})();
|
||||
}
|
||||
} else {
|
||||
this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter(
|
||||
() => this.getNotebookServerInfo(options),
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { useTabs } from "hooks/useTabs";
|
||||
import { userContext } from "UserContext";
|
||||
import { getHostFromUrl } from "./../Explorer/Tabs/CloudShellTab/Utils/CommonUtils";
|
||||
|
||||
export const DOCUMENTDB_VSCODE_EXTENSION_BASEURL = "vscode://ms-azuretools.vscode-documentdb";
|
||||
export const COSMOSDB_VSCODE_EXTENSION_BASEURL = "vscode://ms-azuretools.vscode-cosmosdb";
|
||||
|
||||
/**
|
||||
* Generates a VS Code DocumentDB connection URL using the current user's MongoDB connection parameters.
|
||||
* Double-encodes the updated connection string for safe usage in VS Code URLs.
|
||||
*
|
||||
* The DocumentDB VS Code extension requires double encoding for connection strings.
|
||||
* See: https://microsoft.github.io/vscode-documentdb/manual/how-to-construct-url.html#double-encoding
|
||||
*
|
||||
* @returns {string} The encoded VS Code DocumentDB connection URL.
|
||||
*/
|
||||
export const getVSCodeUrl = (): string => {
|
||||
const isvCore = (userContext.apiType || userContext.databaseAccount.kind) === "VCoreMongo";
|
||||
const isMongo =
|
||||
userContext.apiType === "Mongo" && userContext.databaseAccount?.properties?.apiProperties?.serverVersion !== "3.2";
|
||||
return isvCore ? getDocumentDbUrl() : isMongo ? getMongoRUUrl() : getCosmosDbUrl();
|
||||
};
|
||||
|
||||
export const getCosmosDbUrl = () => {
|
||||
const activeTab = useTabs.getState().activeTab;
|
||||
const resourceId = encodeURIComponent(userContext.databaseAccount.id);
|
||||
const database = encodeURIComponent(activeTab?.collection?.databaseId);
|
||||
const container = encodeURIComponent(activeTab?.collection?.id());
|
||||
const baseUrl = `${COSMOSDB_VSCODE_EXTENSION_BASEURL}?resourceId=${resourceId}`;
|
||||
const vscodeUrl = activeTab ? `${baseUrl}&database=${database}&container=${container}` : baseUrl;
|
||||
return vscodeUrl;
|
||||
};
|
||||
|
||||
export const getMongoRUUrl = () => {
|
||||
const activeTab = useTabs.getState().activeTab;
|
||||
const databaseAccount = userContext.databaseAccount;
|
||||
const host = getHostFromUrl(databaseAccount.properties?.mongoEndpoint);
|
||||
const port = 10255;
|
||||
const database = activeTab?.collection?.databaseId;
|
||||
const container = activeTab?.collection?.id();
|
||||
const encodedUpdatedConnectionString = encodeURIComponent(`mongodb://${databaseAccount?.name}@${host}:${port}`);
|
||||
const documentDbUrl = `${DOCUMENTDB_VSCODE_EXTENSION_BASEURL}?connectionString=${encodedUpdatedConnectionString}${
|
||||
database ? `&database=${database}` : ""
|
||||
}${container ? `&collection=${container}` : ""}`;
|
||||
|
||||
return documentDbUrl;
|
||||
};
|
||||
|
||||
export const getDocumentDbUrl = () => {
|
||||
const { adminLogin: adminLoginuserName = "", connectionString = "" } = userContext.vcoreMongoConnectionParams;
|
||||
const updatedConnectionString = connectionString.replace(/<(user|username)>:<password>/i, adminLoginuserName);
|
||||
const encodedUpdatedConnectionString = encodeURIComponent(encodeURIComponent(updatedConnectionString));
|
||||
const documentDbUrl = `${DOCUMENTDB_VSCODE_EXTENSION_BASEURL}?connectionString=${encodedUpdatedConnectionString}`;
|
||||
return documentDbUrl;
|
||||
};
|
||||
Reference in New Issue
Block a user