From 8b0b3b07d6dcb99e699f79482c4cc34a26eec37b Mon Sep 17 00:00:00 2001 From: Asier Isayas Date: Fri, 9 Feb 2024 10:58:10 -0500 Subject: [PATCH] Add Mongo Proxy to Data Explorer (Standalone and Portal) (#1738) * Mongo Proxy backend API * merge main into current * allow mongo proxy endpoints to be constants * allow mongo proxy endpoints to be constants * fix test * check for allowed mongo proxy endpoint * check for allowed mongo proxy endpoint --------- Co-authored-by: Asier Isayas --- .eslintignore | 1 + src/Common/Constants.ts | 4 + src/Common/MongoProxyClient.ts | 340 +++++++++++++++++- src/ConfigContext.ts | 18 +- src/Contracts/ViewModels.ts | 1 + src/Explorer/Explorer.tsx | 2 +- src/Juno/JunoClient.ts | 4 +- src/Phoenix/PhoenixClient.ts | 2 +- ...EndpointValidation.ts => EndpointUtils.ts} | 16 + src/Utils/NetworkUtility.test.ts | 2 +- src/Utils/NetworkUtility.ts | 2 +- src/hooks/useKnockoutExplorer.ts | 1 + tsconfig.strict.json | 1 + 13 files changed, 376 insertions(+), 18 deletions(-) rename src/Utils/{EndpointValidation.ts => EndpointUtils.ts} (83%) diff --git a/.eslintignore b/.eslintignore index c188701b9..78e9b517e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -145,4 +145,5 @@ src/Explorer/Notebook/temp/inputs/connected-editors/codemirror.tsx src/Explorer/Tree/ResourceTreeAdapter.tsx __mocks__/monaco-editor.ts src/Explorer/Tree/ResourceTree.tsx +src/Utils/EndpointUtils.ts src/Utils/PriorityBasedExecutionUtils.ts \ No newline at end of file diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index 4d86f5ff7..bfecb27c1 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -211,6 +211,10 @@ export class HttpHeaders { public static migrateOfferToAutopilot: string = "x-ms-cosmos-migrate-offer-to-autopilot"; } +export class ContentType { + public static applicationJson: string = "application/json"; +} + export class ApiType { // Mapped to hexadecimal values in the backend public static readonly MongoDB: number = 1; diff --git a/src/Common/MongoProxyClient.ts b/src/Common/MongoProxyClient.ts index ea4103ff6..2a4d9fed7 100644 --- a/src/Common/MongoProxyClient.ts +++ b/src/Common/MongoProxyClient.ts @@ -1,6 +1,6 @@ import { Constants as CosmosSDKConstants } from "@azure/cosmos"; +import { MongoProxyEndpoints, allowedMongoProxyEndpoints_ToBeDeprecated, validateEndpoint } from "Utils/EndpointUtils"; import queryString from "querystring"; -import { allowedMongoProxyEndpoints, validateEndpoint } from "Utils/EndpointValidation"; import { AuthType } from "../AuthType"; import { configContext } from "../ConfigContext"; import * as DataModels from "../Contracts/DataModels"; @@ -10,7 +10,7 @@ import DocumentId from "../Explorer/Tree/DocumentId"; import { hasFlag } from "../Platform/Hosted/extractFeatures"; import { userContext } from "../UserContext"; import { logConsoleError } from "../Utils/NotificationConsoleUtils"; -import { ApiType, HttpHeaders, HttpStatusCodes } from "./Constants"; +import { ApiType, ContentType, HttpHeaders, HttpStatusCodes } from "./Constants"; import { MinimalQueryIterator } from "./IteratorUtilities"; import { sendMessage } from "./MessageHandler"; @@ -62,6 +62,73 @@ export function queryDocuments( isResourceList: boolean, query: string, continuationToken?: string, +): Promise { + if (!useMongoProxyEndpoint("resourcelist")) { + return queryDocuments_ToBeDeprecated(databaseId, collection, isResourceList, query, continuationToken); + } + + const { databaseAccount } = userContext; + const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; + const params = { + databaseID: databaseId, + collectionID: collection.id(), + resourceUrl: `${resourceEndpoint}dbs/${databaseId}/colls/${collection.id()}/docs/`, + resourceID: collection.rid, + resourceType: "docs", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: + collection && collection.partitionKey && !collection.partitionKey.systemKey + ? collection.partitionKeyProperties?.[0] + : "", + query, + }; + + const endpoint = getFeatureEndpointOrDefault("resourcelist") || ""; + + const headers = { + ...defaultHeaders, + ...authHeaders(), + [CosmosSDKConstants.HttpHeaders.IsQuery]: "true", + [CosmosSDKConstants.HttpHeaders.PopulateQueryMetrics]: "true", + [CosmosSDKConstants.HttpHeaders.EnableScanInQuery]: "true", + [CosmosSDKConstants.HttpHeaders.EnableCrossPartitionQuery]: "true", + [CosmosSDKConstants.HttpHeaders.ParallelizeCrossPartitionQuery]: "true", + [HttpHeaders.contentType]: "application/query+json", + }; + + if (continuationToken) { + headers[CosmosSDKConstants.HttpHeaders.Continuation] = continuationToken; + } + + const path = isResourceList ? "/resourcelist" : ""; + + return window + .fetch(`${endpoint}${path}`, { + method: "POST", + body: JSON.stringify(params), + headers, + }) + .then(async (response) => { + if (response.ok) { + return { + continuationToken: response.headers.get(CosmosSDKConstants.HttpHeaders.Continuation), + documents: (await response.json()).Documents as DataModels.DocumentId[], + headers: response.headers, + }; + } + await errorHandling(response, "querying documents", params); + return undefined; + }); +} + +function queryDocuments_ToBeDeprecated( + databaseId: string, + collection: Collection, + isResourceList: boolean, + query: string, + continuationToken?: string, ): Promise { const { databaseAccount } = userContext; const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; @@ -122,6 +189,54 @@ export function readDocument( databaseId: string, collection: Collection, documentId: DocumentId, +): Promise { + if (!useMongoProxyEndpoint("readDocument")) { + return readDocument_ToBeDeprecated(databaseId, collection, documentId); + } + const { databaseAccount } = userContext; + const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; + const idComponents = documentId.self.split("/"); + const path = idComponents.slice(0, 4).join("/"); + const rid = encodeURIComponent(idComponents[5]); + const params = { + databaseID: databaseId, + collectionID: collection.id(), + resourceUrl: `${resourceEndpoint}${path}/${rid}`, + resourceID: rid, + resourceType: "docs", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: + documentId && documentId.partitionKey && !documentId.partitionKey.systemKey + ? documentId.partitionKeyProperties?.[0] + : "", + }; + + const endpoint = getFeatureEndpointOrDefault("readDocument"); + + return window + .fetch(endpoint, { + method: "POST", + body: JSON.stringify(params), + headers: { + ...defaultHeaders, + ...authHeaders(), + [HttpHeaders.contentType]: ContentType.applicationJson, + }, + }) + .then(async (response) => { + if (response.ok) { + return response.json(); + } + return await errorHandling(response, "reading document", params); + }); +} + +export function readDocument_ToBeDeprecated( + databaseId: string, + collection: Collection, + documentId: DocumentId, ): Promise { const { databaseAccount } = userContext; const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; @@ -169,6 +284,51 @@ export function createDocument( collection: Collection, partitionKeyProperty: string, documentContent: unknown, +): Promise { + if (!useMongoProxyEndpoint("createDocument")) { + return createDocument_ToBeDeprecated(databaseId, collection, partitionKeyProperty, documentContent); + } + const { databaseAccount } = userContext; + const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; + const params = { + databaseID: databaseId, + collectionID: collection.id(), + resourceUrl: `${resourceEndpoint}dbs/${databaseId}/colls/${collection.id()}/docs/`, + resourceID: collection.rid, + resourceType: "docs", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: + collection && collection.partitionKey && !collection.partitionKey.systemKey ? partitionKeyProperty : "", + documentContent: JSON.stringify(documentContent), + }; + + const endpoint = getFeatureEndpointOrDefault("createDocument"); + + return window + .fetch(`${endpoint}/createDocument`, { + method: "POST", + body: JSON.stringify(params), + headers: { + ...defaultHeaders, + ...authHeaders(), + [HttpHeaders.contentType]: ContentType.applicationJson, + }, + }) + .then(async (response) => { + if (response.ok) { + return response.json(); + } + return await errorHandling(response, "creating document", params); + }); +} + +export function createDocument_ToBeDeprecated( + databaseId: string, + collection: Collection, + partitionKeyProperty: string, + documentContent: unknown, ): Promise { const { databaseAccount } = userContext; const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; @@ -208,6 +368,56 @@ export function updateDocument( collection: Collection, documentId: DocumentId, documentContent: string, +): Promise { + if (!useMongoProxyEndpoint("updateDocument")) { + return updateDocument_ToBeDeprecated(databaseId, collection, documentId, documentContent); + } + const { databaseAccount } = userContext; + const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; + const idComponents = documentId.self.split("/"); + const path = idComponents.slice(0, 5).join("/"); + const rid = encodeURIComponent(idComponents[5]); + const params = { + databaseID: databaseId, + collectionID: collection.id(), + resourceUrl: `${resourceEndpoint}${path}/${rid}`, + resourceID: rid, + resourceType: "docs", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: + documentId && documentId.partitionKey && !documentId.partitionKey.systemKey + ? documentId.partitionKeyProperties?.[0] + : "", + documentContent, + }; + const endpoint = getFeatureEndpointOrDefault("updateDocument"); + + return window + .fetch(endpoint, { + method: "PUT", + body: JSON.stringify(params), + headers: { + ...defaultHeaders, + ...authHeaders(), + [HttpHeaders.contentType]: ContentType.applicationJson, + [CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()), + }, + }) + .then(async (response) => { + if (response.ok) { + return response.json(); + } + return await errorHandling(response, "updating document", params); + }); +} + +export function updateDocument_ToBeDeprecated( + databaseId: string, + collection: Collection, + documentId: DocumentId, + documentContent: string, ): Promise { const { databaseAccount } = userContext; const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; @@ -237,7 +447,7 @@ export function updateDocument( headers: { ...defaultHeaders, ...authHeaders(), - [HttpHeaders.contentType]: "application/json", + [HttpHeaders.contentType]: ContentType.applicationJson, [CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()), }, }) @@ -250,6 +460,53 @@ export function updateDocument( } export function deleteDocument(databaseId: string, collection: Collection, documentId: DocumentId): Promise { + if (!useMongoProxyEndpoint("deleteDocument")) { + deleteDocument_ToBeDeprecated(databaseId, collection, documentId); + } + const { databaseAccount } = userContext; + const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; + const idComponents = documentId.self.split("/"); + const path = idComponents.slice(0, 5).join("/"); + const rid = encodeURIComponent(idComponents[5]); + const params = { + databaseID: databaseId, + collectionID: collection.id(), + resourceUrl: `${resourceEndpoint}${path}/${rid}`, + resourceID: rid, + resourceType: "docs", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: + documentId && documentId.partitionKey && !documentId.partitionKey.systemKey + ? documentId.partitionKeyProperties?.[0] + : "", + }; + const endpoint = getFeatureEndpointOrDefault("deleteDocument"); + + return window + .fetch(endpoint, { + method: "DELETE", + body: JSON.stringify(params), + headers: { + ...defaultHeaders, + ...authHeaders(), + [HttpHeaders.contentType]: ContentType.applicationJson, + }, + }) + .then(async (response) => { + if (response.ok) { + return undefined; + } + return await errorHandling(response, "deleting document", params); + }); +} + +export function deleteDocument_ToBeDeprecated( + databaseId: string, + collection: Collection, + documentId: DocumentId, +): Promise { const { databaseAccount } = userContext; const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; const idComponents = documentId.self.split("/"); @@ -277,7 +534,7 @@ export function deleteDocument(databaseId: string, collection: Collection, docum headers: { ...defaultHeaders, ...authHeaders(), - [HttpHeaders.contentType]: "application/json", + [HttpHeaders.contentType]: ContentType.applicationJson, [CosmosSDKConstants.HttpHeaders.PartitionKey]: JSON.stringify(documentId.partitionKeyHeader()), }, }) @@ -291,6 +548,52 @@ export function deleteDocument(databaseId: string, collection: Collection, docum export function createMongoCollectionWithProxy( params: DataModels.CreateCollectionParams, +): Promise { + if (!useMongoProxyEndpoint("createCollectionWithProxy")) { + createMongoCollectionWithProxy_ToBeDeprecated(params); + } + const { databaseAccount } = userContext; + const shardKey: string = params.partitionKey?.paths[0]; + + const createCollectionParams = { + databaseID: params.databaseId, + collectionID: params.collectionId, + resourceUrl: databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint, + resourceID: "", + resourceType: "colls", + subscriptionID: userContext.subscriptionId, + resourceGroup: userContext.resourceGroup, + databaseAccountName: databaseAccount.name, + partitionKey: shardKey, + isAutoscale: !!params.autoPilotMaxThroughput, + hasSharedThroughput: params.databaseLevelThroughput, + offerThroughput: params.autoPilotMaxThroughput || params.offerThroughput, + createDatabase: params.createNewDatabase, + isSharded: !!shardKey, + }; + + const endpoint = getFeatureEndpointOrDefault("createCollectionWithProxy"); + + return window + .fetch(`${endpoint}/createCollection`, { + method: "POST", + body: JSON.stringify(createCollectionParams), + headers: { + ...defaultHeaders, + ...authHeaders(), + [HttpHeaders.contentType]: ContentType.applicationJson, + }, + }) + .then(async (response) => { + if (response.ok) { + return response.json(); + } + return await errorHandling(response, "creating collection", createCollectionParams); + }); +} + +export function createMongoCollectionWithProxy_ToBeDeprecated( + params: DataModels.CreateCollectionParams, ): Promise { const { databaseAccount } = userContext; const shardKey: string = params.partitionKey?.paths[0]; @@ -334,13 +637,17 @@ export function createMongoCollectionWithProxy( return await errorHandling(response, "creating collection", mongoParams); }); } - export function getFeatureEndpointOrDefault(feature: string): string { - const endpoint = - hasFlag(userContext.features.mongoProxyAPIs, feature) && - validateEndpoint(userContext.features.mongoProxyEndpoint, allowedMongoProxyEndpoints) - ? userContext.features.mongoProxyEndpoint - : configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT; + let endpoint; + if (useMongoProxyEndpoint(feature)) { + endpoint = configContext.MONGO_PROXY_ENDPOINT; + } else { + endpoint = + hasFlag(userContext.features.mongoProxyAPIs, feature) && + validateEndpoint(userContext.features.mongoProxyEndpoint, allowedMongoProxyEndpoints_ToBeDeprecated) + ? userContext.features.mongoProxyEndpoint + : configContext.MONGO_BACKEND_ENDPOINT || configContext.BACKEND_ENDPOINT; + } return getEndpoint(endpoint); } @@ -349,7 +656,11 @@ export function getEndpoint(endpoint: string): string { let url = endpoint + "/api/mongo/explorer"; if (userContext.authType === AuthType.EncryptedToken) { - url = url.replace("api/mongo", "api/guest/mongo"); + if (endpoint === configContext.MONGO_PROXY_ENDPOINT) { + url = url.replace("api/mongo", "api/connectionstring/mongo"); + } else { + url = url.replace("api/mongo", "api/guest/mongo"); + } } return url; } @@ -370,3 +681,10 @@ async function errorHandling(response: Response, action: string, params: unknown export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameters): string { return `subscriptions/${params.sid}/resourceGroups/${params.rg}/providers/Microsoft.DocumentDB/databaseAccounts/${userContext.databaseAccount.name}/mongodbDatabases/${params.db}/collections/${params.coll}`; } + +function useMongoProxyEndpoint(api: string): boolean { + return ( + configContext.NEW_MONGO_APIS?.includes(api) && + [MongoProxyEndpoints.Development, MongoProxyEndpoints.MPAC].includes(configContext.MONGO_PROXY_ENDPOINT) + ); +} diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index 1679a3657..c04bc9671 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -7,11 +7,12 @@ import { allowedHostedExplorerEndpoints, allowedJunoOrigins, allowedMongoBackendEndpoints, + allowedMongoProxyEndpoints, allowedMsalRedirectEndpoints, defaultAllowedArmEndpoints, defaultAllowedBackendEndpoints, validateEndpoint, -} from "Utils/EndpointValidation"; +} from "Utils/EndpointUtils"; export enum Platform { Portal = "Portal", @@ -38,6 +39,8 @@ export interface ConfigContext { ARCADIA_LIVY_ENDPOINT_DNS_ZONE: string; BACKEND_ENDPOINT?: string; MONGO_BACKEND_ENDPOINT?: string; + MONGO_PROXY_ENDPOINT?: string; + NEW_MONGO_APIS?: string[]; PROXY_PATH?: string; JUNO_ENDPOINT: string; GITHUB_CLIENT_ID: string; @@ -82,6 +85,15 @@ let configContext: Readonly = { GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772 JUNO_ENDPOINT: JunoEndpoints.Prod, BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com", + MONGO_PROXY_ENDPOINT: "https://cdb-ms-prod-mp.cosmos.azure.com", + NEW_MONGO_APIS: [ + // "resourcelist", + // "createDocument", + // "readDocument", + // "updateDocument", + // "deleteDocument", + // "createCollectionWithProxy", + ], isTerminalEnabled: false, isPhoenixEnabled: false, }; @@ -127,6 +139,10 @@ export function updateConfigContext(newContext: Partial): void { delete newContext.BACKEND_ENDPOINT; } + if (!validateEndpoint(newContext.MONGO_PROXY_ENDPOINT, allowedMongoProxyEndpoints)) { + delete newContext.MONGO_PROXY_ENDPOINT; + } + if (!validateEndpoint(newContext.MONGO_BACKEND_ENDPOINT, allowedMongoBackendEndpoints)) { delete newContext.MONGO_BACKEND_ENDPOINT; } diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index d95d8ce05..885ebabd0 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -386,6 +386,7 @@ export interface DataExplorerInputsFrame { dnsSuffix?: string; serverId?: string; extensionEndpoint?: string; + mongoProxyEndpoint?: string; subscriptionType?: SubscriptionType; quotaId?: string; isTryCosmosDBSubscription?: boolean; diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 2aacbdf7e..3a945d3ed 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -7,7 +7,7 @@ import { getCopilotEnabled, isCopilotFeatureRegistered } from "Explorer/QueryCop import { IGalleryItem } from "Juno/JunoClient"; import { scheduleRefreshDatabaseResourceToken } from "Platform/Fabric/FabricUtil"; import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility"; -import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointValidation"; +import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointUtils"; import { useQueryCopilot } from "hooks/useQueryCopilot"; import * as ko from "knockout"; import React from "react"; diff --git a/src/Juno/JunoClient.ts b/src/Juno/JunoClient.ts index 7cef27da1..0b0618e72 100644 --- a/src/Juno/JunoClient.ts +++ b/src/Juno/JunoClient.ts @@ -1,6 +1,6 @@ -import ko from "knockout"; -import { allowedJunoOrigins, validateEndpoint } from "Utils/EndpointValidation"; +import { allowedJunoOrigins, validateEndpoint } from "Utils/EndpointUtils"; import { GetGithubClientId } from "Utils/GitHubUtils"; +import ko from "knockout"; import { HttpHeaders, HttpStatusCodes } from "../Common/Constants"; import { configContext } from "../ConfigContext"; import * as DataModels from "../Contracts/DataModels"; diff --git a/src/Phoenix/PhoenixClient.ts b/src/Phoenix/PhoenixClient.ts index 685bbbbb2..d5e304b8e 100644 --- a/src/Phoenix/PhoenixClient.ts +++ b/src/Phoenix/PhoenixClient.ts @@ -2,7 +2,7 @@ import { configContext } from "ConfigContext"; import { useDialog } from "Explorer/Controls/Dialog"; import { Action } from "Shared/Telemetry/TelemetryConstants"; import { userContext } from "UserContext"; -import { allowedJunoOrigins, validateEndpoint } from "Utils/EndpointValidation"; +import { allowedJunoOrigins, validateEndpoint } from "Utils/EndpointUtils"; import { useQueryCopilot } from "hooks/useQueryCopilot"; import promiseRetry, { AbortError } from "p-retry"; import { diff --git a/src/Utils/EndpointValidation.ts b/src/Utils/EndpointUtils.ts similarity index 83% rename from src/Utils/EndpointValidation.ts rename to src/Utils/EndpointUtils.ts index 0f9eb44ef..656f55903 100644 --- a/src/Utils/EndpointValidation.ts +++ b/src/Utils/EndpointUtils.ts @@ -67,7 +67,23 @@ export const PortalBackendIPs: { [key: string]: string[] } = { //usnat: ["7.28.202.68"], }; +export class MongoProxyEndpoints { + public static readonly Development: string = "https://localhost:7238"; + public static readonly MPAC: string = "https://cdb-ms-mpac-mp.cosmos.azure.com"; + public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com"; + public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us"; + public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn"; +} + export const allowedMongoProxyEndpoints: ReadonlyArray = [ + MongoProxyEndpoints.Development, + MongoProxyEndpoints.MPAC, + MongoProxyEndpoints.Prod, + MongoProxyEndpoints.Fairfax, + MongoProxyEndpoints.Mooncake, +]; + +export const allowedMongoProxyEndpoints_ToBeDeprecated: ReadonlyArray = [ "https://main.documentdb.ext.azure.com", "https://main.documentdb.ext.azure.cn", "https://main.documentdb.ext.azure.us", diff --git a/src/Utils/NetworkUtility.test.ts b/src/Utils/NetworkUtility.test.ts index ed22b502e..4ee4b5cd2 100644 --- a/src/Utils/NetworkUtility.test.ts +++ b/src/Utils/NetworkUtility.test.ts @@ -1,7 +1,7 @@ import { resetConfigContext, updateConfigContext } from "ConfigContext"; import { DatabaseAccount, IpRule } from "Contracts/DataModels"; import { updateUserContext } from "UserContext"; -import { PortalBackendIPs } from "Utils/EndpointValidation"; +import { PortalBackendIPs } from "Utils/EndpointUtils"; import { getNetworkSettingsWarningMessage } from "./NetworkUtility"; describe("NetworkUtility tests", () => { diff --git a/src/Utils/NetworkUtility.ts b/src/Utils/NetworkUtility.ts index 8f4624297..96f3ae124 100644 --- a/src/Utils/NetworkUtility.ts +++ b/src/Utils/NetworkUtility.ts @@ -1,7 +1,7 @@ import { configContext } from "ConfigContext"; import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules"; import { userContext } from "UserContext"; -import { PortalBackendIPs } from "Utils/EndpointValidation"; +import { PortalBackendIPs } from "Utils/EndpointUtils"; export const getNetworkSettingsWarningMessage = async ( setStateFunc: (warningMessage: string) => void, diff --git a/src/hooks/useKnockoutExplorer.ts b/src/hooks/useKnockoutExplorer.ts index 629bd0b7a..4de6d5fc2 100644 --- a/src/hooks/useKnockoutExplorer.ts +++ b/src/hooks/useKnockoutExplorer.ts @@ -478,6 +478,7 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) { updateConfigContext({ BACKEND_ENDPOINT: inputs.extensionEndpoint || configContext.BACKEND_ENDPOINT, ARM_ENDPOINT: normalizeArmEndpoint(inputs.csmEndpoint || configContext.ARM_ENDPOINT), + MONGO_PROXY_ENDPOINT: inputs.mongoProxyEndpoint, }); updateUserContext({ diff --git a/tsconfig.strict.json b/tsconfig.strict.json index be0195655..969c39d01 100644 --- a/tsconfig.strict.json +++ b/tsconfig.strict.json @@ -112,6 +112,7 @@ "./src/Utils/BlobUtils.ts", "./src/Utils/CapabilityUtils.ts", "./src/Utils/CloudUtils.ts", + "./src/Utils/EndpointUtils.ts", "./src/Utils/GitHubUtils.test.ts", "./src/Utils/GitHubUtils.ts", "./src/Utils/MessageValidation.test.ts",