mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-02-23 12:37:25 +00:00
Remove Network Warning banner from Data Explorer. (#2019)
This commit is contained in:
parent
abf061089d
commit
4b75e86b74
@ -1,9 +1,7 @@
|
|||||||
import { IMessageBarStyles, MessageBar, MessageBarButton, MessageBarType } from "@fluentui/react";
|
import { IMessageBarStyles, MessageBar, MessageBarType } from "@fluentui/react";
|
||||||
import { CassandraProxyEndpoints, MongoProxyEndpoints } from "Common/Constants";
|
import { CassandraProxyEndpoints, MongoProxyEndpoints } from "Common/Constants";
|
||||||
import { sendMessage } from "Common/MessageHandler";
|
|
||||||
import { configContext } from "ConfigContext";
|
import { configContext } from "ConfigContext";
|
||||||
import { IpRule } from "Contracts/DataModels";
|
import { IpRule } from "Contracts/DataModels";
|
||||||
import { MessageTypes } from "Contracts/ExplorerContracts";
|
|
||||||
import { CollectionTabKind } from "Contracts/ViewModels";
|
import { CollectionTabKind } from "Contracts/ViewModels";
|
||||||
import Explorer from "Explorer/Explorer";
|
import Explorer from "Explorer/Explorer";
|
||||||
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
@ -35,7 +33,7 @@ interface TabsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
||||||
const { openedTabs, openedReactTabs, activeTab, activeReactTab, networkSettingsWarning } = useTabs();
|
const { openedTabs, openedReactTabs, activeTab, activeReactTab } = useTabs();
|
||||||
const [
|
const [
|
||||||
showMongoAndCassandraProxiesNetworkSettingsWarningState,
|
showMongoAndCassandraProxiesNetworkSettingsWarningState,
|
||||||
setShowMongoAndCassandraProxiesNetworkSettingsWarningState,
|
setShowMongoAndCassandraProxiesNetworkSettingsWarningState,
|
||||||
@ -60,29 +58,6 @@ export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tabsManagerContainer">
|
<div className="tabsManagerContainer">
|
||||||
{networkSettingsWarning && (
|
|
||||||
<MessageBar
|
|
||||||
messageBarType={MessageBarType.warning}
|
|
||||||
styles={defaultMessageBarStyles}
|
|
||||||
actions={
|
|
||||||
<MessageBarButton
|
|
||||||
onClick={() =>
|
|
||||||
sendMessage({
|
|
||||||
type:
|
|
||||||
userContext.apiType === "VCoreMongo"
|
|
||||||
? MessageTypes.OpenVCoreMongoNetworkingBlade
|
|
||||||
: MessageTypes.OpenPostgresNetworkingBlade,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Change network settings
|
|
||||||
</MessageBarButton>
|
|
||||||
}
|
|
||||||
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
|
|
||||||
>
|
|
||||||
{networkSettingsWarning}
|
|
||||||
</MessageBar>
|
|
||||||
)}
|
|
||||||
{showMongoAndCassandraProxiesNetworkSettingsWarningState && (
|
{showMongoAndCassandraProxiesNetworkSettingsWarningState && (
|
||||||
<MessageBar
|
<MessageBar
|
||||||
messageBarType={MessageBarType.warning}
|
messageBarType={MessageBarType.warning}
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
import { MongoProxyEndpoints, PortalBackendEndpoints } from "Common/Constants";
|
|
||||||
import { resetConfigContext, updateConfigContext } from "ConfigContext";
|
|
||||||
import { DatabaseAccount, IpRule } from "Contracts/DataModels";
|
|
||||||
import { updateUserContext } from "UserContext";
|
|
||||||
import { MongoProxyOutboundIPs, PortalBackendOutboundIPs } from "Utils/EndpointUtils";
|
|
||||||
import { getNetworkSettingsWarningMessage } from "./NetworkUtility";
|
|
||||||
|
|
||||||
describe("NetworkUtility tests", () => {
|
|
||||||
describe("getNetworkSettingsWarningMessage", () => {
|
|
||||||
const publicAccessMessagePart = "Please enable public access to proceed";
|
|
||||||
const accessMessagePart = "Please allow access from Azure Portal to proceed";
|
|
||||||
let warningMessageResult: string;
|
|
||||||
const warningMessageFunc = (msg: string) => (warningMessageResult = msg);
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
warningMessageResult = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
resetConfigContext();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return no message when publicNetworkAccess is enabled", async () => {
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
properties: {
|
|
||||||
publicNetworkAccess: "Enabled",
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(warningMessageFunc);
|
|
||||||
expect(warningMessageResult).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return publicAccessMessage when publicNetworkAccess is disabled", async () => {
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
properties: {
|
|
||||||
publicNetworkAccess: "Disabled",
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(warningMessageFunc);
|
|
||||||
expect(warningMessageResult).toContain(publicAccessMessagePart);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should return no message when the appropriate ip rules are added to mongo/cassandra account per endpoint`, async () => {
|
|
||||||
const portalBackendOutboundIPs: string[] = [
|
|
||||||
...PortalBackendOutboundIPs[PortalBackendEndpoints.Mpac],
|
|
||||||
...PortalBackendOutboundIPs[PortalBackendEndpoints.Prod],
|
|
||||||
...MongoProxyOutboundIPs[MongoProxyEndpoints.Mpac],
|
|
||||||
...MongoProxyOutboundIPs[MongoProxyEndpoints.Prod],
|
|
||||||
];
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
kind: "MongoDB",
|
|
||||||
properties: {
|
|
||||||
ipRules: portalBackendOutboundIPs.map((ip: string) => ({ ipAddressOrRange: ip }) as IpRule),
|
|
||||||
publicNetworkAccess: "Enabled",
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateConfigContext({
|
|
||||||
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Mpac,
|
|
||||||
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Mpac,
|
|
||||||
});
|
|
||||||
|
|
||||||
let asyncWarningMessageResult: string;
|
|
||||||
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
|
||||||
expect(asyncWarningMessageResult).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return accessMessage when incorrent ip rule is added to mongo/cassandra account per endpoint", async () => {
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
kind: "MongoDB",
|
|
||||||
properties: {
|
|
||||||
ipRules: [{ ipAddressOrRange: "1.1.1.1" }],
|
|
||||||
publicNetworkAccess: "Enabled",
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateConfigContext({
|
|
||||||
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Mpac,
|
|
||||||
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Mpac,
|
|
||||||
});
|
|
||||||
|
|
||||||
let asyncWarningMessageResult: string;
|
|
||||||
const asyncWarningMessageFunc = (msg: string) => (asyncWarningMessageResult = msg);
|
|
||||||
|
|
||||||
await getNetworkSettingsWarningMessage(asyncWarningMessageFunc);
|
|
||||||
expect(asyncWarningMessageResult).toContain(accessMessagePart);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Postgres and vcore mongo account checks basically pass through to CheckFirewallRules so those
|
|
||||||
// tests are omitted here and included in CheckFirewallRules.test.ts
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,99 +0,0 @@
|
|||||||
import { CassandraProxyEndpoints, MongoProxyEndpoints, PortalBackendEndpoints } from "Common/Constants";
|
|
||||||
import { configContext } from "ConfigContext";
|
|
||||||
import { checkFirewallRules } from "Explorer/Tabs/Shared/CheckFirewallRules";
|
|
||||||
import { userContext } from "UserContext";
|
|
||||||
import { CassandraProxyOutboundIPs, MongoProxyOutboundIPs, PortalBackendOutboundIPs } from "Utils/EndpointUtils";
|
|
||||||
|
|
||||||
export const getNetworkSettingsWarningMessage = async (
|
|
||||||
setStateFunc: (warningMessage: string) => void,
|
|
||||||
): Promise<void> => {
|
|
||||||
const accountProperties = userContext.databaseAccount?.properties;
|
|
||||||
const accessMessage =
|
|
||||||
"The Network settings for this account are preventing access from Data Explorer. Please allow access from Azure Portal to proceed.";
|
|
||||||
const publicAccessMessage =
|
|
||||||
"The Network settings for this account are preventing access from Data Explorer. Please enable public access to proceed.";
|
|
||||||
|
|
||||||
if (userContext.apiType === "Postgres") {
|
|
||||||
checkFirewallRules(
|
|
||||||
"2022-11-08",
|
|
||||||
(rule) => rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255",
|
|
||||||
undefined,
|
|
||||||
setStateFunc,
|
|
||||||
accessMessage,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} else if (userContext.apiType === "VCoreMongo") {
|
|
||||||
checkFirewallRules(
|
|
||||||
"2023-03-01-preview",
|
|
||||||
(rule) =>
|
|
||||||
rule.name.startsWith("AllowAllAzureServicesAndResourcesWithinAzureIps") ||
|
|
||||||
(rule.properties.startIpAddress === "0.0.0.0" && rule.properties.endIpAddress === "255.255.255.255"),
|
|
||||||
undefined,
|
|
||||||
setStateFunc,
|
|
||||||
accessMessage,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
} else if (accountProperties) {
|
|
||||||
// public network access is disabled
|
|
||||||
if (
|
|
||||||
accountProperties.publicNetworkAccess !== "Enabled" &&
|
|
||||||
accountProperties.publicNetworkAccess !== "SecuredByPerimeter"
|
|
||||||
) {
|
|
||||||
setStateFunc(publicAccessMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipRules = accountProperties.ipRules;
|
|
||||||
// public network access is NOT set to "All networks"
|
|
||||||
if (ipRules?.length > 0) {
|
|
||||||
const isProdOrMpacPortalBackendEndpoint: boolean = [
|
|
||||||
PortalBackendEndpoints.Mpac,
|
|
||||||
PortalBackendEndpoints.Prod,
|
|
||||||
].includes(configContext.PORTAL_BACKEND_ENDPOINT);
|
|
||||||
const portalBackendOutboundIPs: string[] = isProdOrMpacPortalBackendEndpoint
|
|
||||||
? [
|
|
||||||
...PortalBackendOutboundIPs[PortalBackendEndpoints.Mpac],
|
|
||||||
...PortalBackendOutboundIPs[PortalBackendEndpoints.Prod],
|
|
||||||
]
|
|
||||||
: PortalBackendOutboundIPs[configContext.PORTAL_BACKEND_ENDPOINT];
|
|
||||||
let portalIPs: string[] = [...portalBackendOutboundIPs];
|
|
||||||
|
|
||||||
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];
|
|
||||||
|
|
||||||
portalIPs = [...portalIPs, ...mongoProxyOutboundIPs];
|
|
||||||
} 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];
|
|
||||||
|
|
||||||
portalIPs = [...portalIPs, ...cassandraProxyOutboundIPs];
|
|
||||||
}
|
|
||||||
|
|
||||||
let numberOfMatches = 0;
|
|
||||||
ipRules.forEach((ipRule) => {
|
|
||||||
if (portalIPs.indexOf(ipRule.ipAddressOrRange) !== -1) {
|
|
||||||
numberOfMatches++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (numberOfMatches !== portalIPs.length) {
|
|
||||||
setStateFunc(accessMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -14,7 +14,6 @@ import {
|
|||||||
} from "Shared/AppStatePersistenceUtility";
|
} from "Shared/AppStatePersistenceUtility";
|
||||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||||
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
import { useNewPortalBackendEndpoint } from "Utils/EndpointUtils";
|
||||||
import { getNetworkSettingsWarningMessage } from "Utils/NetworkUtility";
|
|
||||||
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
import { logConsoleError } from "Utils/NotificationConsoleUtils";
|
||||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||||
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||||
@ -742,8 +741,6 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkSettingsWarningMessage(useTabs.getState().setNetworkSettingsWarning);
|
|
||||||
|
|
||||||
if (inputs.features) {
|
if (inputs.features) {
|
||||||
Object.assign(userContext.features, extractFeatures(new URLSearchParams(inputs.features)));
|
Object.assign(userContext.features, extractFeatures(new URLSearchParams(inputs.features)));
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ export interface TabsState {
|
|||||||
openedReactTabs: ReactTabKind[];
|
openedReactTabs: ReactTabKind[];
|
||||||
activeTab: TabsBase | undefined;
|
activeTab: TabsBase | undefined;
|
||||||
activeReactTab: ReactTabKind | undefined;
|
activeReactTab: ReactTabKind | undefined;
|
||||||
networkSettingsWarning: string;
|
|
||||||
queryCopilotTabInitialInput: string;
|
queryCopilotTabInitialInput: string;
|
||||||
isTabExecuting: boolean;
|
isTabExecuting: boolean;
|
||||||
isQueryErrorThrown: boolean;
|
isQueryErrorThrown: boolean;
|
||||||
@ -33,7 +32,6 @@ export interface TabsState {
|
|||||||
closeAllNotebookTabs: (hardClose: boolean) => void;
|
closeAllNotebookTabs: (hardClose: boolean) => void;
|
||||||
openAndActivateReactTab: (tabKind: ReactTabKind) => void;
|
openAndActivateReactTab: (tabKind: ReactTabKind) => void;
|
||||||
closeReactTab: (tabKind: ReactTabKind) => void;
|
closeReactTab: (tabKind: ReactTabKind) => void;
|
||||||
setNetworkSettingsWarning: (warningMessage: string) => void;
|
|
||||||
setQueryCopilotTabInitialInput: (input: string) => void;
|
setQueryCopilotTabInitialInput: (input: string) => void;
|
||||||
setIsTabExecuting: (state: boolean) => void;
|
setIsTabExecuting: (state: boolean) => void;
|
||||||
setIsQueryErrorThrown: (state: boolean) => void;
|
setIsQueryErrorThrown: (state: boolean) => void;
|
||||||
@ -69,7 +67,6 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
|||||||
openedReactTabs: !isPlatformFabric ? [ReactTabKind.Home] : [],
|
openedReactTabs: !isPlatformFabric ? [ReactTabKind.Home] : [],
|
||||||
activeTab: undefined,
|
activeTab: undefined,
|
||||||
activeReactTab: !isPlatformFabric ? ReactTabKind.Home : undefined,
|
activeReactTab: !isPlatformFabric ? ReactTabKind.Home : undefined,
|
||||||
networkSettingsWarning: "",
|
|
||||||
queryCopilotTabInitialInput: "",
|
queryCopilotTabInitialInput: "",
|
||||||
isTabExecuting: false,
|
isTabExecuting: false,
|
||||||
isQueryErrorThrown: false,
|
isQueryErrorThrown: false,
|
||||||
@ -190,7 +187,6 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
|||||||
|
|
||||||
set({ openedReactTabs: updatedOpenedReactTabs });
|
set({ openedReactTabs: updatedOpenedReactTabs });
|
||||||
},
|
},
|
||||||
setNetworkSettingsWarning: (warningMessage: string) => set({ networkSettingsWarning: warningMessage }),
|
|
||||||
setQueryCopilotTabInitialInput: (input: string) => set({ queryCopilotTabInitialInput: input }),
|
setQueryCopilotTabInitialInput: (input: string) => set({ queryCopilotTabInitialInput: input }),
|
||||||
setIsTabExecuting: (state: boolean) => {
|
setIsTabExecuting: (state: boolean) => {
|
||||||
set({ isTabExecuting: state });
|
set({ isTabExecuting: state });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user