mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-09-01 10:36:55 +00:00
58
ui/package-lock.json
generated
58
ui/package-lock.json
generated
@@ -38,6 +38,7 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-graph-vis": "^1.0.7",
|
"react-graph-vis": "^1.0.7",
|
||||||
"react-lowlight": "^3.0.0",
|
"react-lowlight": "^3.0.0",
|
||||||
|
"react-router-dom": "^6.2.1",
|
||||||
"react-scrollable-feed-virtualized": "^1.4.9",
|
"react-scrollable-feed-virtualized": "^1.4.9",
|
||||||
"react-syntax-highlighter": "^15.4.3",
|
"react-syntax-highlighter": "^15.4.3",
|
||||||
"react-toastify": "^8.0.3",
|
"react-toastify": "^8.0.3",
|
||||||
@@ -11790,6 +11791,14 @@
|
|||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/history": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.7.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hmac-drbg": {
|
"node_modules/hmac-drbg": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||||
@@ -19663,6 +19672,30 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==",
|
||||||
|
"dependencies": {
|
||||||
|
"history": "^5.2.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==",
|
||||||
|
"dependencies": {
|
||||||
|
"history": "^5.2.0",
|
||||||
|
"react-router": "6.2.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-scripts": {
|
"node_modules/react-scripts": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",
|
||||||
@@ -35700,6 +35733,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.3.1.tgz",
|
||||||
"integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw=="
|
"integrity": "sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw=="
|
||||||
},
|
},
|
||||||
|
"history": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.7.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hmac-drbg": {
|
"hmac-drbg": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||||
@@ -41850,6 +41891,23 @@
|
|||||||
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==",
|
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==",
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
|
"react-router": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==",
|
||||||
|
"requires": {
|
||||||
|
"history": "^5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-router-dom": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==",
|
||||||
|
"requires": {
|
||||||
|
"history": "^5.2.0",
|
||||||
|
"react-router": "6.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-scripts": {
|
"react-scripts": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-graph-vis": "^1.0.7",
|
"react-graph-vis": "^1.0.7",
|
||||||
"react-lowlight": "^3.0.0",
|
"react-lowlight": "^3.0.0",
|
||||||
|
"react-router-dom": "^6.2.1",
|
||||||
"react-scrollable-feed-virtualized": "^1.4.9",
|
"react-scrollable-feed-virtualized": "^1.4.9",
|
||||||
"react-syntax-highlighter": "^15.4.3",
|
"react-syntax-highlighter": "^15.4.3",
|
||||||
"react-toastify": "^8.0.3",
|
"react-toastify": "^8.0.3",
|
||||||
|
@@ -1,41 +1,24 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import './App.sass';
|
import './App.sass';
|
||||||
import {TLSWarning} from "./components/TLSWarning/TLSWarning";
|
|
||||||
import {Header} from "./components/Header/Header";
|
import {Header} from "./components/Header/Header";
|
||||||
import {TrafficPage} from "./components/TrafficPage";
|
import {TrafficPage} from "./components/Pages/TrafficPage/TrafficPage";
|
||||||
import { ServiceMapModal } from './components/ServiceMapModal/ServiceMapModal';
|
import { ServiceMapModal } from './components/ServiceMapModal/ServiceMapModal';
|
||||||
|
import {useRecoilState} from "recoil";
|
||||||
|
import serviceMapModalOpenAtom from "./recoil/serviceMapModalOpen";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
const [analyzeStatus, setAnalyzeStatus] = useState(null);
|
const [analyzeStatus, setAnalyzeStatus] = useState(null);
|
||||||
const [showTLSWarning, setShowTLSWarning] = useState(false);
|
const [serviceMapModalOpen, setServiceMapModalOpen] = useRecoilState(serviceMapModalOpenAtom);
|
||||||
const [userDismissedTLSWarning, setUserDismissedTLSWarning] = useState(false);
|
|
||||||
const [addressesWithTLS, setAddressesWithTLS] = useState(new Set<string>());
|
|
||||||
const [openServiceMapModal, setOpenServiceMapModal] = useState(false);
|
|
||||||
|
|
||||||
const onTLSDetected = (destAddress: string) => {
|
|
||||||
addressesWithTLS.add(destAddress);
|
|
||||||
setAddressesWithTLS(new Set(addressesWithTLS));
|
|
||||||
|
|
||||||
if (!userDismissedTLSWarning) {
|
|
||||||
setShowTLSWarning(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mizuApp">
|
<div className="mizuApp">
|
||||||
<Header analyzeStatus={analyzeStatus} />
|
<Header analyzeStatus={analyzeStatus} />
|
||||||
<TrafficPage setAnalyzeStatus={setAnalyzeStatus} onTLSDetected={onTLSDetected} setOpenServiceMapModal={setOpenServiceMapModal} />
|
<TrafficPage setAnalyzeStatus={setAnalyzeStatus}/>
|
||||||
<TLSWarning showTLSWarning={showTLSWarning}
|
|
||||||
setShowTLSWarning={setShowTLSWarning}
|
|
||||||
addressesWithTLS={addressesWithTLS}
|
|
||||||
setAddressesWithTLS={setAddressesWithTLS}
|
|
||||||
userDismissedTLSWarning={userDismissedTLSWarning}
|
|
||||||
setUserDismissedTLSWarning={setUserDismissedTLSWarning} />
|
|
||||||
{window["isServiceMapEnabled"] && <ServiceMapModal
|
{window["isServiceMapEnabled"] && <ServiceMapModal
|
||||||
isOpen={openServiceMapModal}
|
isOpen={serviceMapModalOpen}
|
||||||
onOpen={() => setOpenServiceMapModal(true)}
|
onOpen={() => setServiceMapModalOpen(true)}
|
||||||
onClose={() => setOpenServiceMapModal(false)}
|
onClose={() => setServiceMapModalOpen(false)}
|
||||||
/>}
|
/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -1,97 +1,15 @@
|
|||||||
import React, {useCallback, useEffect, useState} from 'react';
|
import React from 'react';
|
||||||
import './App.sass';
|
import './App.sass';
|
||||||
import {TrafficPage} from "./components/TrafficPage";
|
import AppSwitchRoutes from "./components/AppSwitchRoutes";
|
||||||
import {TLSWarning} from "./components/TLSWarning/TLSWarning";
|
import {BrowserRouter} from "react-router-dom";
|
||||||
import {EntHeader} from "./components/Header/EntHeader";
|
|
||||||
import Api from "./helpers/api";
|
|
||||||
import {toast} from "react-toastify";
|
|
||||||
import InstallPage from "./components/InstallPage";
|
|
||||||
import LoginPage from "./components/LoginPage";
|
|
||||||
import LoadingOverlay from "./components/LoadingOverlay";
|
|
||||||
import AuthPageBase from './components/AuthPageBase';
|
|
||||||
import entPageAtom, {Page} from "./recoil/entPage";
|
|
||||||
import {useRecoilState} from "recoil";
|
|
||||||
import { ServiceMapModal } from './components/ServiceMapModal/ServiceMapModal';
|
|
||||||
|
|
||||||
const api = Api.getInstance();
|
|
||||||
|
|
||||||
const EntApp = () => {
|
const EntApp = () => {
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [showTLSWarning, setShowTLSWarning] = useState(false);
|
|
||||||
const [userDismissedTLSWarning, setUserDismissedTLSWarning] = useState(false);
|
|
||||||
const [addressesWithTLS, setAddressesWithTLS] = useState(new Set<string>());
|
|
||||||
const [entPage, setEntPage] = useRecoilState(entPageAtom);
|
|
||||||
const [isFirstLogin, setIsFirstLogin] = useState(false);
|
|
||||||
const [openServiceMapModal, setOpenServiceMapModal] = useState(false);
|
|
||||||
|
|
||||||
const determinePage = useCallback(async () => { // TODO: move to state management
|
|
||||||
try {
|
|
||||||
const isInstallNeeded = await api.isInstallNeeded();
|
|
||||||
if (isInstallNeeded) {
|
|
||||||
setEntPage(Page.Setup);
|
|
||||||
} else {
|
|
||||||
const isAuthNeeded = await api.isAuthenticationNeeded();
|
|
||||||
if(isAuthNeeded) {
|
|
||||||
setEntPage(Page.Login);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
toast.error("Error occured while checking Mizu API status, see console for mode details");
|
|
||||||
console.error(e);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
},[setEntPage]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
determinePage();
|
|
||||||
}, [determinePage]);
|
|
||||||
|
|
||||||
const onTLSDetected = (destAddress: string) => {
|
|
||||||
addressesWithTLS.add(destAddress);
|
|
||||||
setAddressesWithTLS(new Set(addressesWithTLS));
|
|
||||||
|
|
||||||
if (!userDismissedTLSWarning) {
|
|
||||||
setShowTLSWarning(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let pageComponent: any;
|
|
||||||
|
|
||||||
switch (entPage) { // TODO: move to state management / proper routing
|
|
||||||
case Page.Traffic:
|
|
||||||
pageComponent = <TrafficPage onTLSDetected={onTLSDetected} setOpenServiceMapModal={setOpenServiceMapModal} />;
|
|
||||||
break;
|
|
||||||
case Page.Setup:
|
|
||||||
pageComponent = <AuthPageBase><InstallPage onFirstLogin={() => setIsFirstLogin(true)}/></AuthPageBase>;
|
|
||||||
break;
|
|
||||||
case Page.Login:
|
|
||||||
pageComponent = <AuthPageBase><LoginPage/></AuthPageBase>;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pageComponent = <div>Unknown Error</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <LoadingOverlay/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mizuApp">
|
<div className="mizuApp">
|
||||||
{entPage === Page.Traffic && <EntHeader isFirstLogin={isFirstLogin} setIsFirstLogin={setIsFirstLogin} />}
|
<BrowserRouter>
|
||||||
{pageComponent}
|
<AppSwitchRoutes/>
|
||||||
{entPage === Page.Traffic && <TLSWarning showTLSWarning={showTLSWarning}
|
</BrowserRouter>
|
||||||
setShowTLSWarning={setShowTLSWarning}
|
|
||||||
addressesWithTLS={addressesWithTLS}
|
|
||||||
setAddressesWithTLS={setAddressesWithTLS}
|
|
||||||
userDismissedTLSWarning={userDismissedTLSWarning}
|
|
||||||
setUserDismissedTLSWarning={setUserDismissedTLSWarning} />}
|
|
||||||
{entPage === Page.Traffic && window["isServiceMapEnabled"] && <ServiceMapModal
|
|
||||||
isOpen={openServiceMapModal}
|
|
||||||
onOpen={() => setOpenServiceMapModal(true)}
|
|
||||||
onClose={() => setOpenServiceMapModal(false)}
|
|
||||||
/>}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
80
ui/src/components/AppSwitchRoutes.tsx
Normal file
80
ui/src/components/AppSwitchRoutes.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import React, {useCallback, useEffect, useState} from "react";
|
||||||
|
import {Route, Routes, useNavigate} from "react-router-dom";
|
||||||
|
import {RouterRoutes} from "../helpers/routes";
|
||||||
|
import {useRecoilState} from "recoil";
|
||||||
|
import entPageAtom, {Page} from "../recoil/entPage";
|
||||||
|
import {toast} from "react-toastify";
|
||||||
|
import AuthPageBase from "./Pages/AuthPage/AuthPageBase";
|
||||||
|
import InstallPage from "./Pages/AuthPage/InstallPage";
|
||||||
|
import LoginPage from "./Pages/AuthPage/LoginPage";
|
||||||
|
import LoadingOverlay from "./LoadingOverlay";
|
||||||
|
import SystemViewer from "./Pages/SystemViewer/SystemViewer";
|
||||||
|
import Api from "../helpers/api";
|
||||||
|
import {TrafficPage} from "./Pages/TrafficPage/TrafficPage";
|
||||||
|
|
||||||
|
const api = Api.getInstance();
|
||||||
|
|
||||||
|
const AppSwitchRoutes = () => {
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [entPage, setEntPage] = useRecoilState(entPageAtom);
|
||||||
|
const [isFirstLogin, setIsFirstLogin] = useState(false);
|
||||||
|
|
||||||
|
const determinePage = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
const isInstallNeeded = await api.isInstallNeeded();
|
||||||
|
if (isInstallNeeded) {
|
||||||
|
setEntPage(Page.Setup);
|
||||||
|
} else {
|
||||||
|
const isAuthNeeded = await api.isAuthenticationNeeded();
|
||||||
|
if(isAuthNeeded) {
|
||||||
|
setEntPage(Page.Login);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
toast.error("Error occured while checking Mizu API status, see console for mode details");
|
||||||
|
console.error(e);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
},[setEntPage]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
determinePage();
|
||||||
|
}, [determinePage]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
switch (entPage) {
|
||||||
|
case Page.Traffic:
|
||||||
|
navigate("/");
|
||||||
|
break;
|
||||||
|
case Page.Setup:
|
||||||
|
navigate(RouterRoutes.SETUP);
|
||||||
|
break;
|
||||||
|
case Page.Login:
|
||||||
|
navigate(RouterRoutes.LOGIN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
navigate(RouterRoutes.LOGIN);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
},[entPage])
|
||||||
|
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return <LoadingOverlay/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Routes>
|
||||||
|
<Route path={"/"} element={<SystemViewer isFirstLogin={isFirstLogin} setIsFirstLogin={setIsFirstLogin}/>}>
|
||||||
|
<Route path={"/"} element={<TrafficPage/>} />
|
||||||
|
<Route path={RouterRoutes.SETTINGS} element={<></>} /> {/*todo: set settings component*/}
|
||||||
|
</Route>
|
||||||
|
<Route path={RouterRoutes.LOGIN} element={<AuthPageBase><LoginPage/></AuthPageBase>}/>
|
||||||
|
<Route path={RouterRoutes.SETUP} element={<AuthPageBase><InstallPage onFirstLogin={() => setIsFirstLogin(true)}/></AuthPageBase>}/>
|
||||||
|
</Routes>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppSwitchRoutes;
|
@@ -11,6 +11,7 @@ import Api from "../../helpers/api";
|
|||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {useSetRecoilState} from "recoil";
|
import {useSetRecoilState} from "recoil";
|
||||||
import entPageAtom, {Page} from "../../recoil/entPage";
|
import entPageAtom, {Page} from "../../recoil/entPage";
|
||||||
|
import {useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
const api = Api.getInstance();
|
const api = Api.getInstance();
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ interface EntHeaderProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const EntHeader: React.FC<EntHeaderProps> = ({isFirstLogin, setIsFirstLogin}) => {
|
export const EntHeader: React.FC<EntHeaderProps> = ({isFirstLogin, setIsFirstLogin}) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
|
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -37,7 +38,7 @@ export const EntHeader: React.FC<EntHeaderProps> = ({isFirstLogin, setIsFirstLog
|
|||||||
return <div className="header">
|
return <div className="header">
|
||||||
<div>
|
<div>
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<img style={{height: 55}} src={logo} alt="logo"/>
|
<img className="entLogo" style={{height: 55}} src={logo} alt="logo" onClick={() => navigate("/")}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: "flex", alignItems: "center"}}>
|
<div style={{display: "flex", alignItems: "center"}}>
|
||||||
|
@@ -21,3 +21,6 @@
|
|||||||
|
|
||||||
.headerIcon
|
.headerIcon
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
|
||||||
|
.entLogo
|
||||||
|
cursor: pointer
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
@import "../../variables.module"
|
@import "src/variables.module"
|
||||||
|
|
||||||
.authContainer
|
.authContainer
|
||||||
height: 100vh
|
height: 100vh
|
@@ -1,8 +1,8 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import background from "./assets/authBackground.png";
|
import background from "../../assets/authBackground.png";
|
||||||
import logo from './assets/MizuEntLogoNoPowBy.svg';
|
import logo from '../../assets/MizuEntLogoNoPowBy.svg';
|
||||||
import poweredBy from './assets/powered-by.svg'
|
import poweredBy from '../../assets/powered-by.svg'
|
||||||
import "./style/AuthBasePage.sass";
|
import "./AuthBasePage.sass";
|
||||||
|
|
||||||
|
|
||||||
export const AuthPageBase: React.FC = ({children}) => {
|
export const AuthPageBase: React.FC = ({children}) => {
|
@@ -1,14 +1,14 @@
|
|||||||
import { Button } from "@material-ui/core";
|
import { Button } from "@material-ui/core";
|
||||||
import React, { useState,useRef } from "react";
|
import React, { useState,useRef } from "react";
|
||||||
import { adminUsername } from "../consts";
|
import { adminUsername } from "../../../consts";
|
||||||
import Api, { FormValidationErrorType } from "../helpers/api";
|
import Api, { FormValidationErrorType } from "../../../helpers/api";
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import LoadingOverlay from "./LoadingOverlay";
|
import LoadingOverlay from "../../LoadingOverlay";
|
||||||
import { useCommonStyles } from "../helpers/commonStyle";
|
import { useCommonStyles } from "../../../helpers/commonStyle";
|
||||||
import {useSetRecoilState} from "recoil";
|
import {useSetRecoilState} from "recoil";
|
||||||
import entPageAtom, {Page} from "../recoil/entPage";
|
import entPageAtom, {Page} from "../../../recoil/entPage";
|
||||||
import useKeyPress from "../hooks/useKeyPress"
|
import useKeyPress from "../../../hooks/useKeyPress"
|
||||||
import shortcutsKeyboard from "../configs/shortcutsKeyboard"
|
import shortcutsKeyboard from "../../../configs/shortcutsKeyboard"
|
||||||
|
|
||||||
|
|
||||||
const api = Api.getInstance();
|
const api = Api.getInstance();
|
@@ -1,13 +1,13 @@
|
|||||||
import { Button } from "@material-ui/core";
|
import { Button } from "@material-ui/core";
|
||||||
import React, { useState,useRef } from "react";
|
import React, { useState,useRef } from "react";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import Api from "../helpers/api";
|
import Api from "../../../helpers/api";
|
||||||
import { useCommonStyles } from "../helpers/commonStyle";
|
import { useCommonStyles } from "../../../helpers/commonStyle";
|
||||||
import LoadingOverlay from "./LoadingOverlay";
|
import LoadingOverlay from "../../LoadingOverlay";
|
||||||
import entPageAtom, {Page} from "../recoil/entPage";
|
import entPageAtom, {Page} from "../../../recoil/entPage";
|
||||||
import {useSetRecoilState} from "recoil";
|
import {useSetRecoilState} from "recoil";
|
||||||
import useKeyPress from "../hooks/useKeyPress"
|
import useKeyPress from "../../../hooks/useKeyPress"
|
||||||
import shortcutsKeyboard from "../configs/shortcutsKeyboard"
|
import shortcutsKeyboard from "../../../configs/shortcutsKeyboard"
|
||||||
|
|
||||||
|
|
||||||
const api = Api.getInstance();
|
const api = Api.getInstance();
|
23
ui/src/components/Pages/SystemViewer/SystemViewer.tsx
Normal file
23
ui/src/components/Pages/SystemViewer/SystemViewer.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {Outlet} from "react-router-dom";
|
||||||
|
import {ServiceMapModal} from "../../ServiceMapModal/ServiceMapModal";
|
||||||
|
import {EntHeader} from "../../Header/EntHeader";
|
||||||
|
import {useRecoilState} from "recoil";
|
||||||
|
import serviceMapModalOpenAtom from "../../../recoil/serviceMapModalOpen";
|
||||||
|
|
||||||
|
const SystemViewer = ({isFirstLogin, setIsFirstLogin}) => {
|
||||||
|
|
||||||
|
const [serviceMapModalOpen, setServiceMapModalOpen] = useRecoilState(serviceMapModalOpenAtom);
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<EntHeader isFirstLogin={isFirstLogin} setIsFirstLogin={setIsFirstLogin} />
|
||||||
|
<Outlet/>
|
||||||
|
{window["isServiceMapEnabled"] && <ServiceMapModal
|
||||||
|
isOpen={serviceMapModalOpen}
|
||||||
|
onOpen={() => setServiceMapModalOpen(true)}
|
||||||
|
onClose={() => setServiceMapModalOpen(false)}
|
||||||
|
/>}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SystemViewer;
|
@@ -1,4 +1,4 @@
|
|||||||
@import '../../variables.module.scss'
|
@import 'src/variables.module'
|
||||||
|
|
||||||
.TrafficPage
|
.TrafficPage
|
||||||
width: 100%
|
width: 100%
|
@@ -1,25 +1,27 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { Filters } from "./Filters";
|
import { Filters } from "../../Filters";
|
||||||
import { EntriesList } from "./EntriesList";
|
import { EntriesList } from "../../EntriesList";
|
||||||
import { makeStyles, Button } from "@material-ui/core";
|
import { makeStyles, Button } from "@material-ui/core";
|
||||||
import "./style/TrafficPage.sass";
|
import "./TrafficPage.sass";
|
||||||
import styles from './style/EntriesList.module.sass';
|
import styles from '../../style/EntriesList.module.sass';
|
||||||
import {EntryDetailed} from "./EntryDetailed";
|
import {EntryDetailed} from "../../EntryDetailed";
|
||||||
import playIcon from './assets/run.svg';
|
import playIcon from '../../assets/run.svg';
|
||||||
import pauseIcon from './assets/pause.svg';
|
import pauseIcon from '../../assets/pause.svg';
|
||||||
import variables from '../variables.module.scss';
|
import variables from '../../../variables.module.scss';
|
||||||
import {StatusBar} from "./UI/StatusBar";
|
import {StatusBar} from "../../UI/StatusBar";
|
||||||
import Api, {MizuWebsocketURL} from "../helpers/api";
|
import Api, {MizuWebsocketURL} from "../../../helpers/api";
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import {useRecoilState, useRecoilValue} from "recoil";
|
import {useRecoilState, useRecoilValue, useSetRecoilState} from "recoil";
|
||||||
import tappingStatusAtom from "../recoil/tappingStatus";
|
import tappingStatusAtom from "../../../recoil/tappingStatus";
|
||||||
import entriesAtom from "../recoil/entries";
|
import entriesAtom from "../../../recoil/entries";
|
||||||
import focusedEntryIdAtom from "../recoil/focusedEntryId";
|
import focusedEntryIdAtom from "../../../recoil/focusedEntryId";
|
||||||
import websocketConnectionAtom, {WsConnectionStatus} from "../recoil/wsConnection";
|
import websocketConnectionAtom, {WsConnectionStatus} from "../../../recoil/wsConnection";
|
||||||
import queryAtom from "../recoil/query";
|
import queryAtom from "../../../recoil/query";
|
||||||
import OasModal from "./OasModal/OasModal";
|
import OasModal from "../../OasModal/OasModal";
|
||||||
import {useCommonStyles} from "../helpers/commonStyle"
|
import {useCommonStyles} from "../../../helpers/commonStyle"
|
||||||
|
import {TLSWarning} from "../../TLSWarning/TLSWarning";
|
||||||
|
import serviceMapModalOpenAtom from "../../../recoil/serviceMapModalOpen";
|
||||||
|
|
||||||
const useLayoutStyles = makeStyles(() => ({
|
const useLayoutStyles = makeStyles(() => ({
|
||||||
details: {
|
details: {
|
||||||
@@ -43,19 +45,18 @@ const useLayoutStyles = makeStyles(() => ({
|
|||||||
|
|
||||||
interface TrafficPageProps {
|
interface TrafficPageProps {
|
||||||
setAnalyzeStatus?: (status: any) => void;
|
setAnalyzeStatus?: (status: any) => void;
|
||||||
onTLSDetected: (destAddress: string) => void;
|
|
||||||
setOpenServiceMapModal?: (open: boolean) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = Api.getInstance();
|
const api = Api.getInstance();
|
||||||
|
|
||||||
export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSDetected, setOpenServiceMapModal}) => {
|
export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus}) => {
|
||||||
const commonClasses = useCommonStyles();
|
const commonClasses = useCommonStyles();
|
||||||
const classes = useLayoutStyles();
|
const classes = useLayoutStyles();
|
||||||
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
|
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
|
||||||
const [entries, setEntries] = useRecoilState(entriesAtom);
|
const [entries, setEntries] = useRecoilState(entriesAtom);
|
||||||
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
|
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
|
||||||
const [wsConnection, setWsConnection] = useRecoilState(websocketConnectionAtom);
|
const [wsConnection, setWsConnection] = useRecoilState(websocketConnectionAtom);
|
||||||
|
const setServiceMapModalOpen = useSetRecoilState(serviceMapModalOpenAtom);
|
||||||
const query = useRecoilValue(queryAtom);
|
const query = useRecoilValue(queryAtom);
|
||||||
|
|
||||||
const [noMoreDataTop, setNoMoreDataTop] = useState(false);
|
const [noMoreDataTop, setNoMoreDataTop] = useState(false);
|
||||||
@@ -76,6 +77,10 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSD
|
|||||||
const handleOpenModal = () => setOpenOasModal(true);
|
const handleOpenModal = () => setOpenOasModal(true);
|
||||||
const handleCloseModal = () => setOpenOasModal(false);
|
const handleCloseModal = () => setOpenOasModal(false);
|
||||||
|
|
||||||
|
const [showTLSWarning, setShowTLSWarning] = useState(false);
|
||||||
|
const [userDismissedTLSWarning, setUserDismissedTLSWarning] = useState(false);
|
||||||
|
const [addressesWithTLS, setAddressesWithTLS] = useState(new Set<string>());
|
||||||
|
|
||||||
const handleQueryChange = useMemo(
|
const handleQueryChange = useMemo(
|
||||||
() =>
|
() =>
|
||||||
debounce(async (query: string) => {
|
debounce(async (query: string) => {
|
||||||
@@ -216,6 +221,15 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onTLSDetected = (destAddress: string) => {
|
||||||
|
addressesWithTLS.add(destAddress);
|
||||||
|
setAddressesWithTLS(new Set(addressesWithTLS));
|
||||||
|
|
||||||
|
if (!userDismissedTLSWarning) {
|
||||||
|
setShowTLSWarning(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getConnectionStatusClass = (isContainer) => {
|
const getConnectionStatusClass = (isContainer) => {
|
||||||
const container = isContainer ? "Container" : "";
|
const container = isContainer ? "Container" : "";
|
||||||
switch (wsConnection) {
|
switch (wsConnection) {
|
||||||
@@ -225,7 +239,7 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSD
|
|||||||
return "redIndicator" + container;
|
return "redIndicator" + container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getConnectionTitle = () => {
|
const getConnectionTitle = () => {
|
||||||
switch (wsConnection) {
|
switch (wsConnection) {
|
||||||
case WsConnectionStatus.Connected:
|
case WsConnectionStatus.Connected:
|
||||||
@@ -243,7 +257,7 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSD
|
|||||||
}
|
}
|
||||||
|
|
||||||
const openServiceMapModalDebounce = debounce(() => {
|
const openServiceMapModalDebounce = debounce(() => {
|
||||||
setOpenServiceMapModal(true)
|
setServiceMapModalOpen(true)
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -320,6 +334,12 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus,onTLSD
|
|||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
{tappingStatus && !openOasModal && <StatusBar />}
|
{tappingStatus && !openOasModal && <StatusBar />}
|
||||||
|
<TLSWarning showTLSWarning={showTLSWarning}
|
||||||
|
setShowTLSWarning={setShowTLSWarning}
|
||||||
|
addressesWithTLS={addressesWithTLS}
|
||||||
|
setAddressesWithTLS={setAddressesWithTLS}
|
||||||
|
userDismissedTLSWarning={userDismissedTLSWarning}
|
||||||
|
setUserDismissedTLSWarning={setUserDismissedTLSWarning} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
5
ui/src/helpers/routes.ts
Normal file
5
ui/src/helpers/routes.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export enum RouterRoutes {
|
||||||
|
LOGIN = "/login",
|
||||||
|
SETUP = "/setup",
|
||||||
|
SETTINGS = "/settings"
|
||||||
|
}
|
@@ -6,23 +6,20 @@ import 'react-toastify/dist/ReactToastify.css';
|
|||||||
import {RecoilRoot} from "recoil";
|
import {RecoilRoot} from "recoil";
|
||||||
import AppChooser from "./AppChooser";
|
import AppChooser from "./AppChooser";
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render( <>
|
||||||
<React.StrictMode>
|
<RecoilRoot>
|
||||||
<>
|
<AppChooser/>
|
||||||
<RecoilRoot>
|
<ToastContainer
|
||||||
<AppChooser/>
|
position="bottom-right"
|
||||||
<ToastContainer
|
autoClose={5000}
|
||||||
position="bottom-right"
|
hideProgressBar={false}
|
||||||
autoClose={5000}
|
newestOnTop={false}
|
||||||
hideProgressBar={false}
|
closeOnClick
|
||||||
newestOnTop={false}
|
rtl={false}
|
||||||
closeOnClick
|
pauseOnFocusLoss
|
||||||
rtl={false}
|
draggable
|
||||||
pauseOnFocusLoss
|
pauseOnHover
|
||||||
draggable
|
/>
|
||||||
pauseOnHover
|
</RecoilRoot>
|
||||||
/>
|
</>,
|
||||||
</RecoilRoot>
|
|
||||||
</>
|
|
||||||
</React.StrictMode>,
|
|
||||||
document.getElementById('root'));
|
document.getElementById('root'));
|
||||||
|
8
ui/src/recoil/serviceMapModalOpen/atom.ts
Normal file
8
ui/src/recoil/serviceMapModalOpen/atom.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { atom } from "recoil"
|
||||||
|
|
||||||
|
const serviceMapModalOpenAtom = atom({
|
||||||
|
key: "serviceMapModalOpenAtom",
|
||||||
|
default: false
|
||||||
|
})
|
||||||
|
|
||||||
|
export default serviceMapModalOpenAtom;
|
2
ui/src/recoil/serviceMapModalOpen/index.ts
Normal file
2
ui/src/recoil/serviceMapModalOpen/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import atom from "./atom";
|
||||||
|
export default atom;
|
Reference in New Issue
Block a user