mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-25 15:06:55 +00:00
Add check and guidance for networking settings (#1348)
This commit is contained in:
parent
5b1db2778c
commit
5dde66b032
@ -34,6 +34,7 @@ export interface DatabaseAccountExtendedProperties {
|
||||
capacity?: { totalThroughputLimit: number };
|
||||
locations?: DatabaseAccountResponseLocation[];
|
||||
postgresqlEndpoint?: string;
|
||||
publicNetworkAccess?: string;
|
||||
}
|
||||
|
||||
export interface DatabaseAccountResponseLocation {
|
||||
|
@ -37,6 +37,7 @@ export enum MessageTypes {
|
||||
OpenQuickstartBlade,
|
||||
OpenPostgreSQLPasswordReset,
|
||||
OpenPostgresNetworkingBlade,
|
||||
OpenCosmosDBNetworkingBlade,
|
||||
}
|
||||
|
||||
export { Versions, ActionContracts, Diagnostics };
|
||||
|
@ -186,7 +186,6 @@ export interface Collection extends CollectionBase {
|
||||
onDrop(source: Collection, event: { originalEvent: DragEvent }): void;
|
||||
uploadFiles(fileList: FileList): Promise<{ data: UploadDetailsRecord[] }>;
|
||||
|
||||
getLabel(): string;
|
||||
getPendingThroughputSplitNotification(): Promise<DataModels.Notification>;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { MessageBar, MessageBarButton, MessageBarType } from "@fluentui/react";
|
||||
import { sendMessage } from "Common/MessageHandler";
|
||||
import { MessageTypes } from "Contracts/ExplorerContracts";
|
||||
import { CollectionTabKind } from "Contracts/ViewModels";
|
||||
import Explorer from "Explorer/Explorer";
|
||||
import { SplashScreen } from "Explorer/SplashScreen/SplashScreen";
|
||||
@ -21,10 +24,24 @@ interface TabsProps {
|
||||
}
|
||||
|
||||
export const Tabs = ({ explorer }: TabsProps): JSX.Element => {
|
||||
const { openedTabs, openedReactTabs, activeTab, activeReactTab } = useTabs();
|
||||
const { openedTabs, openedReactTabs, activeTab, activeReactTab, showNetworkSettingsWarning } = useTabs();
|
||||
|
||||
return (
|
||||
<div className="tabsManagerContainer">
|
||||
{showNetworkSettingsWarning && (
|
||||
<MessageBar
|
||||
messageBarType={MessageBarType.warning}
|
||||
actions={
|
||||
<MessageBarButton onClick={() => sendMessage({ type: MessageTypes.OpenCosmosDBNetworkingBlade })}>
|
||||
Change network settings
|
||||
</MessageBarButton>
|
||||
}
|
||||
messageBarIconProps={{ iconName: "WarningSolid", className: "messageBarWarningIcon" }}
|
||||
>
|
||||
The Network settings for this account are preventing access from Data Explorer. Please allow access from Azure
|
||||
Portal to proceed.
|
||||
</MessageBar>
|
||||
)}
|
||||
<div id="content" className="flexContainer hideOverflows">
|
||||
<div className="nav-tabs-margin">
|
||||
<ul className="nav nav-tabs level navTabHeight" id="navTabs" role="tablist">
|
||||
|
@ -1160,23 +1160,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
this.onDocumentDBDocumentsClick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get correct collection label depending on account API
|
||||
*/
|
||||
public getLabel(): string {
|
||||
if (userContext.apiType === "Tables") {
|
||||
return "Entities";
|
||||
} else if (userContext.apiType === "Cassandra") {
|
||||
return "Rows";
|
||||
} else if (userContext.apiType === "Gremlin") {
|
||||
return "Graph";
|
||||
} else if (userContext.apiType === "Mongo") {
|
||||
return "Documents";
|
||||
}
|
||||
|
||||
return "Items";
|
||||
}
|
||||
|
||||
public getDatabase(): ViewModels.Database {
|
||||
return useDatabases.getState().findDatabaseWithId(this.databaseId);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Callout, DirectionalHint, ICalloutProps, ILinkProps, Link, Stack, Text } from "@fluentui/react";
|
||||
import * as React from "react";
|
||||
import { getItemName } from "Utils/APITypeUtils";
|
||||
import shallow from "zustand/shallow";
|
||||
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
||||
import DeleteIcon from "../../../images/delete.svg";
|
||||
@ -497,7 +498,7 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ container }: Resourc
|
||||
const buildCollectionNode = (database: ViewModels.Database, collection: ViewModels.Collection): TreeNode => {
|
||||
const children: TreeNode[] = [];
|
||||
children.push({
|
||||
label: collection.getLabel(),
|
||||
label: getItemName(),
|
||||
id: collection.isSampleCollection ? "sampleItems" : "",
|
||||
onClick: () => {
|
||||
collection.openTab();
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Callout, DirectionalHint, ICalloutProps, ILinkProps, Link, Stack, Text } from "@fluentui/react";
|
||||
import * as ko from "knockout";
|
||||
import * as React from "react";
|
||||
import { getItemName } from "Utils/APITypeUtils";
|
||||
import CosmosDBIcon from "../../../images/Azure-Cosmos-DB.svg";
|
||||
import DeleteIcon from "../../../images/delete.svg";
|
||||
import GalleryIcon from "../../../images/GalleryIcon.svg";
|
||||
@ -254,7 +255,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
private buildCollectionNode(database: ViewModels.Database, collection: ViewModels.Collection): TreeNode {
|
||||
const children: TreeNode[] = [];
|
||||
children.push({
|
||||
label: collection.getLabel(),
|
||||
label: getItemName(),
|
||||
onClick: () => {
|
||||
collection.openTab();
|
||||
// push to most recent
|
||||
|
@ -74,3 +74,18 @@ export const getApiShortDisplayName = (): string => {
|
||||
return "Table API";
|
||||
}
|
||||
};
|
||||
|
||||
export const getItemName = (): string => {
|
||||
switch (userContext.apiType) {
|
||||
case "Tables":
|
||||
return "Entities";
|
||||
case "Cassandra":
|
||||
return "Rows";
|
||||
case "Gremlin":
|
||||
return "Graph";
|
||||
case "Mongo":
|
||||
return "Documents";
|
||||
default:
|
||||
return "Items";
|
||||
}
|
||||
};
|
||||
|
40
src/Utils/NetworkUtility.ts
Normal file
40
src/Utils/NetworkUtility.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { userContext } from "UserContext";
|
||||
|
||||
const PortalIPs: { [key: string]: string[] } = {
|
||||
prod1: ["104.42.195.92", "40.76.54.131"],
|
||||
prod2: ["104.42.196.69"],
|
||||
mooncake: ["139.217.8.252"],
|
||||
blackforest: ["51.4.229.218"],
|
||||
fairfax: ["52.244.48.71"],
|
||||
ussec: ["29.26.26.67", "29.26.26.66"],
|
||||
usnat: ["7.28.202.68"],
|
||||
};
|
||||
|
||||
export const doNetworkSettingsAllowDataExplorerAccess = (): boolean => {
|
||||
const accountProperties = userContext.databaseAccount?.properties;
|
||||
|
||||
if (!accountProperties) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// public network access is disabled
|
||||
if (accountProperties.publicNetworkAccess !== "Enabled") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ipRules = accountProperties.ipRules;
|
||||
// public network access is set to "All networks"
|
||||
if (ipRules.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const portalIPs = PortalIPs[userContext.portalEnv];
|
||||
let numberOfMatches = 0;
|
||||
ipRules.forEach((ipRule) => {
|
||||
if (portalIPs.indexOf(ipRule.ipAddressOrRange) !== -1) {
|
||||
numberOfMatches++;
|
||||
}
|
||||
});
|
||||
|
||||
return numberOfMatches === portalIPs.length;
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||
import { useEffect, useState } from "react";
|
||||
import { doNetworkSettingsAllowDataExplorerAccess } from "Utils/NetworkUtility";
|
||||
import { applyExplorerBindings } from "../applyExplorerBindings";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { AccountKind, Flights } from "../Common/Constants";
|
||||
@ -381,6 +382,8 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
|
||||
}
|
||||
}
|
||||
|
||||
useTabs.getState().setShowNetworkSettingsWarning(!doNetworkSettingsAllowDataExplorerAccess());
|
||||
|
||||
if (inputs.features) {
|
||||
Object.assign(userContext.features, extractFeatures(new URLSearchParams(inputs.features)));
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ interface TabsState {
|
||||
openedReactTabs: ReactTabKind[];
|
||||
activeTab: TabsBase | undefined;
|
||||
activeReactTab: ReactTabKind | undefined;
|
||||
showNetworkSettingsWarning: boolean;
|
||||
activateTab: (tab: TabsBase) => void;
|
||||
activateNewTab: (tab: TabsBase) => void;
|
||||
activateReactTab: (tabkind: ReactTabKind) => void;
|
||||
@ -20,6 +21,7 @@ interface TabsState {
|
||||
closeAllNotebookTabs: (hardClose: boolean) => void;
|
||||
openAndActivateReactTab: (tabKind: ReactTabKind) => void;
|
||||
closeReactTab: (tabKind: ReactTabKind) => void;
|
||||
setShowNetworkSettingsWarning: (showWarning: boolean) => void;
|
||||
}
|
||||
|
||||
export enum ReactTabKind {
|
||||
@ -33,6 +35,7 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
||||
openedReactTabs: [ReactTabKind.Home],
|
||||
activeTab: undefined,
|
||||
activeReactTab: ReactTabKind.Home,
|
||||
showNetworkSettingsWarning: false,
|
||||
activateTab: (tab: TabsBase): void => {
|
||||
if (get().openedTabs.some((openedTab) => openedTab.tabId === tab.tabId)) {
|
||||
set({ activeTab: tab, activeReactTab: undefined });
|
||||
@ -142,4 +145,5 @@ export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
||||
|
||||
set({ openedReactTabs: updatedOpenedReactTabs });
|
||||
},
|
||||
setShowNetworkSettingsWarning: (showWarning: boolean) => set({ showNetworkSettingsWarning: showWarning }),
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user