mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-19 17:01:13 +00:00
Backend Migration - Remove Use of Legacy Backend from DE (#2043)
* Default to new backend endpoint if the endpoint in current context does not match existing set in constants. * Remove some env references. * Added comments with reasoning for selecting new backend by default. * Update comment. * Remove all references to useNewPortalBackendEndpoint now that old backend is disabled in all environments. * Resolve lint issues. * Removed references to old backend from Cassandra and Mongo Apis * fix unit tests --------- Co-authored-by: Asier Isayas <aisayas@microsoft.com>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
||||
import { PhoenixClient } from "Phoenix/PhoenixClient";
|
||||
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
||||
import { cloneDeep } from "lodash";
|
||||
import create, { UseStore } from "zustand";
|
||||
import { AuthType } from "../../AuthType";
|
||||
@@ -128,9 +127,7 @@ export const useNotebook: UseStore<NotebookState> = create((set, get) => ({
|
||||
userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo"
|
||||
? databaseAccount?.location
|
||||
: databaseAccount?.properties?.writeLocations?.[0]?.locationName.toLowerCase();
|
||||
const disallowedLocationsUri: string = useNewPortalBackendEndpoint(Constants.BackendApi.DisallowedLocations)
|
||||
? `${configContext.PORTAL_BACKEND_ENDPOINT}/api/disallowedlocations`
|
||||
: `${configContext.BACKEND_ENDPOINT}/api/disallowedLocations`;
|
||||
const disallowedLocationsUri: string = `${configContext.PORTAL_BACKEND_ENDPOINT}/api/disallowedlocations`;
|
||||
const authorizationHeader = getAuthorizationHeader();
|
||||
try {
|
||||
const response = await fetch(disallowedLocationsUri, {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { FeedOptions } from "@azure/cosmos";
|
||||
import {
|
||||
Areas,
|
||||
BackendApi,
|
||||
ConnectionStatusType,
|
||||
ContainerStatusType,
|
||||
HttpStatusCodes,
|
||||
@@ -32,7 +31,6 @@ import { Action } from "Shared/Telemetry/TelemetryConstants";
|
||||
import { traceFailure, traceStart, traceSuccess } from "Shared/Telemetry/TelemetryProcessor";
|
||||
import { userContext } from "UserContext";
|
||||
import { getAuthorizationHeader } from "Utils/AuthorizationUtils";
|
||||
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
||||
import { queryPagesUntilContentPresent } from "Utils/QueryUtils";
|
||||
import { QueryCopilotState, useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import { useTabs } from "hooks/useTabs";
|
||||
@@ -82,9 +80,7 @@ export const isCopilotFeatureRegistered = async (subscriptionId: string): Promis
|
||||
};
|
||||
|
||||
export const getCopilotEnabled = async (): Promise<boolean> => {
|
||||
const backendEndpoint: string = useNewPortalBackendEndpoint(BackendApi.PortalSettings)
|
||||
? configContext.PORTAL_BACKEND_ENDPOINT
|
||||
: configContext.BACKEND_ENDPOINT;
|
||||
const backendEndpoint: string = configContext.PORTAL_BACKEND_ENDPOINT;
|
||||
|
||||
const url = `${backendEndpoint}/api/portalsettings/querycopilot`;
|
||||
const authorizationHeader: AuthorizationTokenHeaderMetadata = getAuthorizationHeader();
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as ko from "knockout";
|
||||
import Q from "q";
|
||||
import { AuthType } from "../../AuthType";
|
||||
import * as Constants from "../../Common/Constants";
|
||||
import { CassandraProxyAPIs, CassandraProxyEndpoints } from "../../Common/Constants";
|
||||
import { CassandraProxyAPIs } from "../../Common/Constants";
|
||||
import { handleError } from "../../Common/ErrorHandlingUtils";
|
||||
import * as HeadersUtility from "../../Common/HeadersUtility";
|
||||
import { createDocument } from "../../Common/dataAccess/createDocument";
|
||||
@@ -264,9 +264,6 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
shouldNotify?: boolean,
|
||||
paginationToken?: string,
|
||||
): Promise<Entities.IListTableEntitiesResult> {
|
||||
if (!this.useCassandraProxyEndpoint("postQuery")) {
|
||||
return this.queryDocuments_ToBeDeprecated(collection, query, shouldNotify, paginationToken);
|
||||
}
|
||||
const clearMessage =
|
||||
shouldNotify && NotificationConsoleUtils.logConsoleProgress(`Querying rows for table ${collection.id()}`);
|
||||
try {
|
||||
@@ -309,55 +306,6 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
}
|
||||
}
|
||||
|
||||
public async queryDocuments_ToBeDeprecated(
|
||||
collection: ViewModels.Collection,
|
||||
query: string,
|
||||
shouldNotify?: boolean,
|
||||
paginationToken?: string,
|
||||
): Promise<Entities.IListTableEntitiesResult> {
|
||||
const clearMessage =
|
||||
shouldNotify && NotificationConsoleUtils.logConsoleProgress(`Querying rows for table ${collection.id()}`);
|
||||
try {
|
||||
const { authType, databaseAccount } = userContext;
|
||||
const apiEndpoint: string =
|
||||
authType === AuthType.EncryptedToken
|
||||
? Constants.CassandraBackend.guestQueryApi
|
||||
: Constants.CassandraBackend.queryApi;
|
||||
const data: any = await $.ajax(`${configContext.BACKEND_ENDPOINT}/${apiEndpoint}`, {
|
||||
type: "POST",
|
||||
data: {
|
||||
accountName: databaseAccount?.name,
|
||||
cassandraEndpoint: this.trimCassandraEndpoint(databaseAccount?.properties.cassandraEndpoint),
|
||||
resourceId: databaseAccount?.id,
|
||||
keyspaceId: collection.databaseId,
|
||||
tableId: collection.id(),
|
||||
query,
|
||||
paginationToken,
|
||||
},
|
||||
beforeSend: this.setAuthorizationHeader as any,
|
||||
cache: false,
|
||||
});
|
||||
shouldNotify &&
|
||||
NotificationConsoleUtils.logConsoleInfo(
|
||||
`Successfully fetched ${data.result.length} rows for table ${collection.id()}`,
|
||||
);
|
||||
return {
|
||||
Results: data.result,
|
||||
ContinuationToken: data.paginationToken,
|
||||
};
|
||||
} catch (error) {
|
||||
shouldNotify &&
|
||||
handleError(
|
||||
error,
|
||||
"QueryDocuments_ToBeDeprecated_Cassandra",
|
||||
`Failed to query rows for table ${collection.id()}`,
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
clearMessage?.();
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteDocuments(
|
||||
collection: ViewModels.Collection,
|
||||
entitiesToDelete: Entities.ITableEntity[],
|
||||
@@ -471,10 +419,6 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
}
|
||||
|
||||
public getTableKeys(collection: ViewModels.Collection): Q.Promise<CassandraTableKeys> {
|
||||
if (!this.useCassandraProxyEndpoint("getKeys")) {
|
||||
return this.getTableKeys_ToBeDeprecated(collection);
|
||||
}
|
||||
|
||||
if (!!collection.cassandraKeys) {
|
||||
return Q.resolve(collection.cassandraKeys);
|
||||
}
|
||||
@@ -515,52 +459,7 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
public getTableKeys_ToBeDeprecated(collection: ViewModels.Collection): Q.Promise<CassandraTableKeys> {
|
||||
if (!!collection.cassandraKeys) {
|
||||
return Q.resolve(collection.cassandraKeys);
|
||||
}
|
||||
const clearInProgressMessage = logConsoleProgress(`Fetching keys for table ${collection.id()}`);
|
||||
const { authType, databaseAccount } = userContext;
|
||||
const apiEndpoint: string =
|
||||
authType === AuthType.EncryptedToken
|
||||
? Constants.CassandraBackend.guestKeysApi
|
||||
: Constants.CassandraBackend.keysApi;
|
||||
let endpoint = `${configContext.BACKEND_ENDPOINT}/${apiEndpoint}`;
|
||||
const deferred = Q.defer<CassandraTableKeys>();
|
||||
|
||||
$.ajax(endpoint, {
|
||||
type: "POST",
|
||||
data: {
|
||||
accountName: databaseAccount?.name,
|
||||
cassandraEndpoint: this.trimCassandraEndpoint(databaseAccount?.properties.cassandraEndpoint),
|
||||
resourceId: databaseAccount?.id,
|
||||
keyspaceId: collection.databaseId,
|
||||
tableId: collection.id(),
|
||||
},
|
||||
beforeSend: this.setAuthorizationHeader as any,
|
||||
cache: false,
|
||||
})
|
||||
.then(
|
||||
(data: CassandraTableKeys) => {
|
||||
collection.cassandraKeys = data;
|
||||
logConsoleInfo(`Successfully fetched keys for table ${collection.id()}`);
|
||||
deferred.resolve(data);
|
||||
},
|
||||
(error: any) => {
|
||||
const errorText = error.responseJSON?.message ?? JSON.stringify(error);
|
||||
handleError(errorText, "FetchKeysCassandra", `Error fetching keys for table ${collection.id()}`);
|
||||
deferred.reject(errorText);
|
||||
},
|
||||
)
|
||||
.done(clearInProgressMessage);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
public getTableSchema(collection: ViewModels.Collection): Q.Promise<CassandraTableKey[]> {
|
||||
if (!this.useCassandraProxyEndpoint("getSchema")) {
|
||||
return this.getTableSchema_ToBeDeprecated(collection);
|
||||
}
|
||||
|
||||
if (!!collection.cassandraSchema) {
|
||||
return Q.resolve(collection.cassandraSchema);
|
||||
}
|
||||
@@ -602,52 +501,7 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
public getTableSchema_ToBeDeprecated(collection: ViewModels.Collection): Q.Promise<CassandraTableKey[]> {
|
||||
if (!!collection.cassandraSchema) {
|
||||
return Q.resolve(collection.cassandraSchema);
|
||||
}
|
||||
const clearInProgressMessage = logConsoleProgress(`Fetching schema for table ${collection.id()}`);
|
||||
const { databaseAccount, authType } = userContext;
|
||||
const apiEndpoint: string =
|
||||
authType === AuthType.EncryptedToken
|
||||
? Constants.CassandraBackend.guestSchemaApi
|
||||
: Constants.CassandraBackend.schemaApi;
|
||||
let endpoint = `${configContext.BACKEND_ENDPOINT}/${apiEndpoint}`;
|
||||
const deferred = Q.defer<CassandraTableKey[]>();
|
||||
|
||||
$.ajax(endpoint, {
|
||||
type: "POST",
|
||||
data: {
|
||||
accountName: databaseAccount?.name,
|
||||
cassandraEndpoint: this.trimCassandraEndpoint(databaseAccount?.properties.cassandraEndpoint),
|
||||
resourceId: databaseAccount?.id,
|
||||
keyspaceId: collection.databaseId,
|
||||
tableId: collection.id(),
|
||||
},
|
||||
beforeSend: this.setAuthorizationHeader as any,
|
||||
cache: false,
|
||||
})
|
||||
.then(
|
||||
(data: any) => {
|
||||
collection.cassandraSchema = data.columns;
|
||||
logConsoleInfo(`Successfully fetched schema for table ${collection.id()}`);
|
||||
deferred.resolve(data.columns);
|
||||
},
|
||||
(error: any) => {
|
||||
const errorText = error.responseJSON?.message ?? JSON.stringify(error);
|
||||
handleError(errorText, "FetchSchemaCassandra", `Error fetching schema for table ${collection.id()}`);
|
||||
deferred.reject(errorText);
|
||||
},
|
||||
)
|
||||
.done(clearInProgressMessage);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
private createOrDeleteQuery(cassandraEndpoint: string, resourceId: string, query: string): Q.Promise<any> {
|
||||
if (!this.useCassandraProxyEndpoint("createOrDelete")) {
|
||||
return this.createOrDeleteQuery_ToBeDeprecated(cassandraEndpoint, resourceId, query);
|
||||
}
|
||||
|
||||
const deferred = Q.defer();
|
||||
const { authType, databaseAccount } = userContext;
|
||||
const apiEndpoint: string =
|
||||
@@ -677,38 +531,6 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
private createOrDeleteQuery_ToBeDeprecated(
|
||||
cassandraEndpoint: string,
|
||||
resourceId: string,
|
||||
query: string,
|
||||
): Q.Promise<any> {
|
||||
const deferred = Q.defer();
|
||||
const { authType, databaseAccount } = userContext;
|
||||
const apiEndpoint: string =
|
||||
authType === AuthType.EncryptedToken
|
||||
? Constants.CassandraBackend.guestCreateOrDeleteApi
|
||||
: Constants.CassandraBackend.createOrDeleteApi;
|
||||
$.ajax(`${configContext.BACKEND_ENDPOINT}/${apiEndpoint}`, {
|
||||
type: "POST",
|
||||
data: {
|
||||
accountName: databaseAccount?.name,
|
||||
cassandraEndpoint: this.trimCassandraEndpoint(cassandraEndpoint),
|
||||
resourceId: resourceId,
|
||||
query: query,
|
||||
},
|
||||
beforeSend: this.setAuthorizationHeader as any,
|
||||
cache: false,
|
||||
}).then(
|
||||
(data: any) => {
|
||||
deferred.resolve();
|
||||
},
|
||||
(reason) => {
|
||||
deferred.reject(reason);
|
||||
},
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
private trimCassandraEndpoint(cassandraEndpoint: string): string {
|
||||
if (!cassandraEndpoint) {
|
||||
return cassandraEndpoint;
|
||||
@@ -747,23 +569,4 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
private getCassandraPartitionKeyProperty(collection: ViewModels.Collection): string {
|
||||
return collection.cassandraKeys.partitionKeys[0].property;
|
||||
}
|
||||
|
||||
private useCassandraProxyEndpoint(api: string): boolean {
|
||||
const activeCassandraProxyEndpoints: string[] = [
|
||||
CassandraProxyEndpoints.Development,
|
||||
CassandraProxyEndpoints.Mpac,
|
||||
CassandraProxyEndpoints.Prod,
|
||||
CassandraProxyEndpoints.Fairfax,
|
||||
CassandraProxyEndpoints.Mooncake,
|
||||
];
|
||||
|
||||
if (configContext.globallyEnabledCassandraAPIs.includes(api)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
configContext.NEW_CASSANDRA_APIS?.includes(api) &&
|
||||
activeCassandraProxyEndpoints.includes(configContext.CASSANDRA_PROXY_ENDPOINT)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1150,27 +1150,16 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
||||
deletePromise = _bulkDeleteNoSqlDocuments(_collection, toDeleteDocumentIds);
|
||||
}
|
||||
} else {
|
||||
if (isMongoBulkDeleteDisabled) {
|
||||
// TODO: Once new mongo proxy is available for all users, remove the call for MongoProxyClient.deleteDocument().
|
||||
// MongoProxyClient.deleteDocuments() should be called for all users.
|
||||
deletePromise = MongoProxyClient.deleteDocument(
|
||||
_collection.databaseId,
|
||||
_collection as ViewModels.Collection,
|
||||
toDeleteDocumentIds[0],
|
||||
).then(() => [toDeleteDocumentIds[0]]);
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
} else {
|
||||
deletePromise = MongoProxyClient.deleteDocuments(
|
||||
_collection.databaseId,
|
||||
_collection as ViewModels.Collection,
|
||||
toDeleteDocumentIds,
|
||||
).then(({ deletedCount, isAcknowledged }) => {
|
||||
if (deletedCount === toDeleteDocumentIds.length && isAcknowledged) {
|
||||
return toDeleteDocumentIds;
|
||||
}
|
||||
throw new Error(`Delete failed with deletedCount: ${deletedCount} and isAcknowledged: ${isAcknowledged}`);
|
||||
});
|
||||
}
|
||||
deletePromise = MongoProxyClient.deleteDocuments(
|
||||
_collection.databaseId,
|
||||
_collection as ViewModels.Collection,
|
||||
toDeleteDocumentIds,
|
||||
).then(({ deletedCount, isAcknowledged }) => {
|
||||
if (deletedCount === toDeleteDocumentIds.length && isAcknowledged) {
|
||||
return toDeleteDocumentIds;
|
||||
}
|
||||
throw new Error(`Delete failed with deletedCount: ${deletedCount} and isAcknowledged: ${isAcknowledged}`);
|
||||
});
|
||||
}
|
||||
|
||||
return deletePromise
|
||||
@@ -2054,11 +2043,8 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
|
||||
}
|
||||
}, [prevSelectedColumnIds, refreshDocumentsGrid, selectedColumnIds]);
|
||||
|
||||
// TODO: remove isMongoBulkDeleteDisabled when new mongo proxy is enabled for all users
|
||||
// TODO: remove partitionKey.systemKey when JS SDK bug is fixed
|
||||
const isMongoBulkDeleteDisabled = !MongoProxyClient.useMongoProxyEndpoint(Constants.MongoProxyApi.BulkDelete);
|
||||
const isBulkDeleteDisabled =
|
||||
(partitionKey.systemKey && !isPreferredApiMongoDB) || (isPreferredApiMongoDB && isMongoBulkDeleteDisabled);
|
||||
const isBulkDeleteDisabled = partitionKey.systemKey && !isPreferredApiMongoDB;
|
||||
// -------------------------------------------------------
|
||||
|
||||
const getFilterChoices = (): InputDatalistDropdownOptionSection[] => {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { useMongoProxyEndpoint } from "Common/MongoProxyClient";
|
||||
import React, { Component } from "react";
|
||||
import * as Constants from "../../../Common/Constants";
|
||||
import { configContext } from "../../../ConfigContext";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
@@ -50,15 +48,13 @@ export default class MongoShellTabComponent extends Component<
|
||||
IMongoShellTabComponentStates
|
||||
> {
|
||||
private _logTraces: Map<string, number>;
|
||||
private _useMongoProxyEndpoint: boolean;
|
||||
|
||||
constructor(props: IMongoShellTabComponentProps) {
|
||||
super(props);
|
||||
this._logTraces = new Map();
|
||||
this._useMongoProxyEndpoint = useMongoProxyEndpoint(Constants.MongoProxyApi.LegacyMongoShell);
|
||||
|
||||
this.state = {
|
||||
url: getMongoShellUrl(this._useMongoProxyEndpoint),
|
||||
url: getMongoShellUrl(),
|
||||
};
|
||||
|
||||
props.onMongoShellTabAccessor({
|
||||
@@ -113,17 +109,9 @@ export default class MongoShellTabComponent extends Component<
|
||||
const resourceId = databaseAccount?.id;
|
||||
const accountName = databaseAccount?.name;
|
||||
const documentEndpoint = databaseAccount?.properties.mongoEndpoint || databaseAccount?.properties.documentEndpoint;
|
||||
const mongoEndpoint =
|
||||
documentEndpoint.substr(
|
||||
Constants.MongoDBAccounts.protocol.length + 3,
|
||||
documentEndpoint.length -
|
||||
(Constants.MongoDBAccounts.protocol.length + 2 + Constants.MongoDBAccounts.defaultPort.length),
|
||||
) + Constants.MongoDBAccounts.defaultPort.toString();
|
||||
const databaseId = this.props.collection.databaseId;
|
||||
const collectionId = this.props.collection.id();
|
||||
const apiEndpoint = this._useMongoProxyEndpoint
|
||||
? configContext.MONGO_PROXY_ENDPOINT
|
||||
: configContext.BACKEND_ENDPOINT;
|
||||
const apiEndpoint = configContext.MONGO_PROXY_ENDPOINT;
|
||||
const encryptedAuthToken: string = userContext.accessToken;
|
||||
|
||||
shellIframe.contentWindow.postMessage(
|
||||
@@ -132,7 +120,7 @@ export default class MongoShellTabComponent extends Component<
|
||||
data: {
|
||||
resourceId: resourceId,
|
||||
accountName: accountName,
|
||||
mongoEndpoint: this._useMongoProxyEndpoint ? documentEndpoint : mongoEndpoint,
|
||||
mongoEndpoint: documentEndpoint,
|
||||
authorization: authorization,
|
||||
databaseId: databaseId,
|
||||
collectionId: collectionId,
|
||||
|
||||
@@ -2,8 +2,6 @@ import { Platform, resetConfigContext, updateConfigContext } from "../../../Conf
|
||||
import { updateUserContext, userContext } from "../../../UserContext";
|
||||
import { getMongoShellUrl } from "./getMongoShellUrl";
|
||||
|
||||
const mongoBackendEndpoint = "https://localhost:1234";
|
||||
|
||||
describe("getMongoShellUrl", () => {
|
||||
let queryString = "";
|
||||
|
||||
@@ -11,7 +9,6 @@ describe("getMongoShellUrl", () => {
|
||||
resetConfigContext();
|
||||
|
||||
updateConfigContext({
|
||||
BACKEND_ENDPOINT: mongoBackendEndpoint,
|
||||
platform: Platform.Hosted,
|
||||
});
|
||||
|
||||
@@ -37,12 +34,7 @@ describe("getMongoShellUrl", () => {
|
||||
queryString = `resourceId=${userContext.databaseAccount.id}&accountName=${userContext.databaseAccount.name}&mongoEndpoint=${userContext.databaseAccount.properties.documentEndpoint}`;
|
||||
});
|
||||
|
||||
it("should return /indexv2.html by default", () => {
|
||||
expect(getMongoShellUrl().toString()).toContain(`/indexv2.html?${queryString}`);
|
||||
});
|
||||
|
||||
it("should return /index.html when useMongoProxyEndpoint is true", () => {
|
||||
const useMongoProxyEndpoint: boolean = true;
|
||||
expect(getMongoShellUrl(useMongoProxyEndpoint).toString()).toContain(`/index.html?${queryString}`);
|
||||
it("should return /index.html by default", () => {
|
||||
expect(getMongoShellUrl().toString()).toContain(`/index.html?${queryString}`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { userContext } from "../../../UserContext";
|
||||
|
||||
export function getMongoShellUrl(useMongoProxyEndpoint?: boolean): string {
|
||||
export function getMongoShellUrl(): string {
|
||||
const { databaseAccount: account } = userContext;
|
||||
const resourceId = account?.id;
|
||||
const accountName = account?.name;
|
||||
const mongoEndpoint = account?.properties?.mongoEndpoint || account?.properties?.documentEndpoint;
|
||||
const queryString = `resourceId=${resourceId}&accountName=${accountName}&mongoEndpoint=${mongoEndpoint}`;
|
||||
|
||||
return useMongoProxyEndpoint ? `/mongoshell/index.html?${queryString}` : `/mongoshell/indexv2.html?${queryString}`;
|
||||
return `/mongoshell/index.html?${queryString}`;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import { IMessageBarStyles, MessageBar, MessageBarType } from "@fluentui/react";
|
||||
import { CassandraProxyEndpoints, MongoProxyEndpoints } from "Common/Constants";
|
||||
import { configContext } from "ConfigContext";
|
||||
import { IpRule } from "Contracts/DataModels";
|
||||
import { CollectionTabKind } from "Contracts/ViewModels";
|
||||
import Explorer from "Explorer/Explorer";
|
||||
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||
@@ -12,10 +8,8 @@ import { PostgresConnectTab } from "Explorer/Tabs/PostgresConnectTab";
|
||||
import { QuickstartTab } from "Explorer/Tabs/QuickstartTab";
|
||||
import { VcoreMongoConnectTab } from "Explorer/Tabs/VCoreMongoConnectTab";
|
||||
import { VcoreMongoQuickstartTab } from "Explorer/Tabs/VCoreMongoQuickstartTab";
|
||||
import { LayoutConstants } from "Explorer/Theme/ThemeUtil";
|
||||
import { KeyboardAction, KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
||||
import { userContext } from "UserContext";
|
||||
import { CassandraProxyOutboundIPs, MongoProxyOutboundIPs, PortalBackendIPs } from "Utils/EndpointUtils";
|
||||
import { useTeachingBubble } from "hooks/useTeachingBubble";
|
||||
import ko from "knockout";
|
||||
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||
@@ -34,10 +28,6 @@ interface TabsProps {
|
||||
|
||||
export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
||||
const { openedTabs, openedReactTabs, activeTab, activeReactTab } = useTabs();
|
||||
const [
|
||||
showMongoAndCassandraProxiesNetworkSettingsWarningState,
|
||||
setShowMongoAndCassandraProxiesNetworkSettingsWarningState,
|
||||
] = useState<boolean>(showMongoAndCassandraProxiesNetworkSettingsWarning());
|
||||
|
||||
const setKeyboardHandlers = useKeyboardActionGroup(KeyboardActionGroup.TABS);
|
||||
useEffect(() => {
|
||||
@@ -48,28 +38,8 @@ export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
||||
});
|
||||
}, [setKeyboardHandlers]);
|
||||
|
||||
const defaultMessageBarStyles: IMessageBarStyles = {
|
||||
root: {
|
||||
height: `${LayoutConstants.rowHeight}px`,
|
||||
overflow: "hidden",
|
||||
flexDirection: "row",
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="tabsManagerContainer">
|
||||
{showMongoAndCassandraProxiesNetworkSettingsWarningState && (
|
||||
<MessageBar
|
||||
messageBarType={MessageBarType.warning}
|
||||
styles={defaultMessageBarStyles}
|
||||
onDismiss={() => {
|
||||
setShowMongoAndCassandraProxiesNetworkSettingsWarningState(false);
|
||||
}}
|
||||
>
|
||||
{`We have migrated our middleware to new infrastructure. To avoid issues with Data Explorer access, please
|
||||
re-enable "Allow access from Azure Portal" on the Networking blade for your account.`}
|
||||
</MessageBar>
|
||||
)}
|
||||
<div className="nav-tabs-margin">
|
||||
<ul className="nav nav-tabs level navTabHeight" id="navTabs" role="tablist">
|
||||
{openedReactTabs.map((tab) => (
|
||||
@@ -314,57 +284,3 @@ const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): J
|
||||
throw Error(`Unsupported tab kind ${ReactTabKind[activeReactTab]}`);
|
||||
}
|
||||
};
|
||||
|
||||
const showMongoAndCassandraProxiesNetworkSettingsWarning = (): boolean => {
|
||||
const ipRules: IpRule[] = userContext.databaseAccount?.properties?.ipRules;
|
||||
if (
|
||||
((userContext.apiType === "Mongo" && configContext.MONGO_PROXY_ENDPOINT !== MongoProxyEndpoints.Development) ||
|
||||
(userContext.apiType === "Cassandra" &&
|
||||
configContext.CASSANDRA_PROXY_ENDPOINT !== CassandraProxyEndpoints.Development)) &&
|
||||
ipRules?.length
|
||||
) {
|
||||
const legacyPortalBackendIPs: string[] = PortalBackendIPs[configContext.BACKEND_ENDPOINT];
|
||||
const ipAddressesFromIPRules: string[] = ipRules.map((ipRule) => ipRule.ipAddressOrRange);
|
||||
const ipRulesIncludeLegacyPortalBackend: boolean = legacyPortalBackendIPs.every((legacyPortalBackendIP: string) =>
|
||||
ipAddressesFromIPRules.includes(legacyPortalBackendIP),
|
||||
);
|
||||
if (!ipRulesIncludeLegacyPortalBackend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (userContext.apiType === "Mongo") {
|
||||
const isProdOrMpacMongoProxyEndpoint: boolean = [MongoProxyEndpoints.Mpac, MongoProxyEndpoints.Prod].includes(
|
||||
configContext.MONGO_PROXY_ENDPOINT,
|
||||
);
|
||||
|
||||
const mongoProxyOutboundIPs: string[] = isProdOrMpacMongoProxyEndpoint
|
||||
? [...MongoProxyOutboundIPs[MongoProxyEndpoints.Mpac], ...MongoProxyOutboundIPs[MongoProxyEndpoints.Prod]]
|
||||
: MongoProxyOutboundIPs[configContext.MONGO_PROXY_ENDPOINT];
|
||||
|
||||
const ipRulesIncludeMongoProxy: boolean = mongoProxyOutboundIPs.every((mongoProxyOutboundIP: string) =>
|
||||
ipAddressesFromIPRules.includes(mongoProxyOutboundIP),
|
||||
);
|
||||
|
||||
return !ipRulesIncludeMongoProxy;
|
||||
} else if (userContext.apiType === "Cassandra") {
|
||||
const isProdOrMpacCassandraProxyEndpoint: boolean = [
|
||||
CassandraProxyEndpoints.Mpac,
|
||||
CassandraProxyEndpoints.Prod,
|
||||
].includes(configContext.CASSANDRA_PROXY_ENDPOINT);
|
||||
|
||||
const cassandraProxyOutboundIPs: string[] = isProdOrMpacCassandraProxyEndpoint
|
||||
? [
|
||||
...CassandraProxyOutboundIPs[CassandraProxyEndpoints.Mpac],
|
||||
...CassandraProxyOutboundIPs[CassandraProxyEndpoints.Prod],
|
||||
]
|
||||
: CassandraProxyOutboundIPs[configContext.CASSANDRA_PROXY_ENDPOINT];
|
||||
|
||||
const ipRulesIncludeCassandraProxy: boolean = cassandraProxyOutboundIPs.every(
|
||||
(cassandraProxyOutboundIP: string) => ipAddressesFromIPRules.includes(cassandraProxyOutboundIP),
|
||||
);
|
||||
|
||||
return !ipRulesIncludeCassandraProxy;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user