Compare commits
6 Commits
5281165a0f
...
5fb016a679
Author | SHA1 | Date |
---|---|---|
Tudor Stanciu | 5fb016a679 | |
Tudor Stanciu | 06de0a7636 | |
Tudor Stanciu | 6f341415f0 | |
Tudor Stanciu | d992b5eedc | |
Tudor Stanciu | 3e9e9534e1 | |
Tudor Stanciu | fea35bab90 |
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "network-resurrector-frontend",
|
"name": "network-resurrector-frontend",
|
||||||
"version": "1.1.2",
|
"version": "1.2.1",
|
||||||
"description": "Frontend component of Network resurrector system",
|
"description": "Frontend component of Network resurrector system",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Tudor Stanciu",
|
"name": "Tudor Stanciu",
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from "react";
|
||||||
|
import { IconButton } from "@material-ui/core";
|
||||||
|
import {
|
||||||
|
Visibility as VisibilityIcon,
|
||||||
|
VisibilityOff as VisibilityOffIcon
|
||||||
|
} from "@material-ui/icons";
|
||||||
|
import { useSensitiveInfo } from "../../hooks";
|
||||||
|
|
||||||
|
const SensitiveInfoToggle = () => {
|
||||||
|
const { enabled, onSensitiveInfoEnabled } = useSensitiveInfo();
|
||||||
|
|
||||||
|
const handleChange = () => onSensitiveInfoEnabled(!enabled);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
aria-label="sensitive-info-toggle"
|
||||||
|
color="inherit"
|
||||||
|
onClick={handleChange}
|
||||||
|
>
|
||||||
|
{enabled ? <VisibilityOffIcon /> : <VisibilityIcon />}
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SensitiveInfoToggle;
|
|
@ -6,6 +6,7 @@ import { AppBar, Toolbar, Typography, IconButton } from "@material-ui/core";
|
||||||
import MenuIcon from "@material-ui/icons/Menu";
|
import MenuIcon from "@material-ui/icons/Menu";
|
||||||
import ProfileButton from "./ProfileButton";
|
import ProfileButton from "./ProfileButton";
|
||||||
import LightDarkToggle from "./LightDarkToggle";
|
import LightDarkToggle from "./LightDarkToggle";
|
||||||
|
import SensitiveInfoToggle from "./SensitiveInfoToggle";
|
||||||
import styles from "./styles";
|
import styles from "./styles";
|
||||||
|
|
||||||
const useStyles = makeStyles(styles);
|
const useStyles = makeStyles(styles);
|
||||||
|
@ -35,6 +36,7 @@ const TopBar = ({ open, handleDrawerOpen }) => {
|
||||||
<Typography variant="h6" noWrap className={classes.title}>
|
<Typography variant="h6" noWrap className={classes.title}>
|
||||||
Network resurrector
|
Network resurrector
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<SensitiveInfoToggle />
|
||||||
<LightDarkToggle />
|
<LightDarkToggle />
|
||||||
<ProfileButton />
|
<ProfileButton />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { KeyboardArrowDown, KeyboardArrowUp } from "@material-ui/icons";
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import MachineLog from "./MachineLog";
|
import MachineLog from "./MachineLog";
|
||||||
import WakeComponent from "./WakeComponent";
|
import WakeComponent from "./WakeComponent";
|
||||||
|
import { useSensitiveInfo } from "../../../hooks";
|
||||||
|
|
||||||
const useRowStyles = makeStyles({
|
const useRowStyles = makeStyles({
|
||||||
root: {
|
root: {
|
||||||
|
@ -62,6 +63,7 @@ const Machine = ({
|
||||||
}) => {
|
}) => {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const classes = useRowStyles();
|
const classes = useRowStyles();
|
||||||
|
const { mask, maskElements } = useSensitiveInfo();
|
||||||
|
|
||||||
const topActions = useMemo(
|
const topActions = useMemo(
|
||||||
() => actions.filter(a => a.top === true),
|
() => actions.filter(a => a.top === true),
|
||||||
|
@ -86,11 +88,11 @@ const Machine = ({
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell component="th" scope="row">
|
<TableCell component="th" scope="row">
|
||||||
{machine.fullMachineName}
|
{mask(machine.fullMachineName)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{machine.machineName}</TableCell>
|
<TableCell>{mask(machine.machineName)}</TableCell>
|
||||||
<TableCell>{machine.iPv4Address}</TableCell>
|
<TableCell>{mask(machine.iPv4Address)}</TableCell>
|
||||||
<TableCell>{machine.macAddress}</TableCell>
|
<TableCell>{mask(machine.macAddress)}</TableCell>
|
||||||
<TableCell align="right">
|
<TableCell align="right">
|
||||||
<WakeComponent machine={machine} addLog={addLog} />
|
<WakeComponent machine={machine} addLog={addLog} />
|
||||||
{topActions.map(action => (
|
{topActions.map(action => (
|
||||||
|
@ -120,7 +122,7 @@ const Machine = ({
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
||||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||||
<MachineLog logs={logs} />
|
<MachineLog logs={maskElements(logs)} />
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
|
@ -6,10 +6,12 @@ import {
|
||||||
import useApi from "../../../api";
|
import useApi from "../../../api";
|
||||||
import MachinesList from "./MachinesList";
|
import MachinesList from "./MachinesList";
|
||||||
import PageTitle from "../../../components/common/PageTitle";
|
import PageTitle from "../../../components/common/PageTitle";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const MachinesContainer = () => {
|
const MachinesContainer = () => {
|
||||||
const state = useContext(ApplicationStateContext);
|
const state = useContext(ApplicationStateContext);
|
||||||
const dispatchActions = useContext(ApplicationDispatchContext);
|
const dispatchActions = useContext(ApplicationDispatchContext);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ const MachinesContainer = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageTitle text="Machines" />
|
<PageTitle text={t("Menu.Machines")} />
|
||||||
<MachinesList dense={true} machines={state.network.machines} />
|
<MachinesList dense={true} machines={state.network.machines} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
export { useToast } from "./useToast";
|
import { useToast } from "./useToast";
|
||||||
|
import { useSensitiveInfo } from "../providers/SensitiveInfoProvider";
|
||||||
|
|
||||||
|
export { useToast, useSensitiveInfo };
|
||||||
|
|
|
@ -6,20 +6,23 @@ import App from "./components/App";
|
||||||
import { TuitioProvider } from "@flare/tuitio-client-react";
|
import { TuitioProvider } from "@flare/tuitio-client-react";
|
||||||
import ApplicationStateProvider from "./providers/ApplicationStateProvider";
|
import ApplicationStateProvider from "./providers/ApplicationStateProvider";
|
||||||
import ToastProvider from "./providers/ToastProvider";
|
import ToastProvider from "./providers/ToastProvider";
|
||||||
|
import SensitiveInfoProvider from "./providers/SensitiveInfoProvider";
|
||||||
import "./utils/i18n";
|
import "./utils/i18n";
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
|
<TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
|
||||||
<ApplicationStateProvider>
|
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
<SensitiveInfoProvider>
|
||||||
|
<ApplicationStateProvider>
|
||||||
<Suspense fallback={<div>Loading...</div>}>
|
<Suspense fallback={<div>Loading...</div>}>
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
<App />
|
<App />
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</ThemeProvider>
|
|
||||||
</ApplicationStateProvider>
|
</ApplicationStateProvider>
|
||||||
|
</SensitiveInfoProvider>
|
||||||
|
</ThemeProvider>
|
||||||
</TuitioProvider>,
|
</TuitioProvider>,
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import React, { useReducer, useMemo, useContext } from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { obfuscate } from "../utils/obfuscateStrings";
|
||||||
|
|
||||||
|
const SensitiveInfoContext = React.createContext();
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
enabled: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducer = (state = initialState, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case "onSensitiveInfoEnabled": {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
enabled: action.payload.enabled
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dispatchActions = dispatch => ({
|
||||||
|
onSensitiveInfoEnabled: enabled =>
|
||||||
|
dispatch({ type: "onSensitiveInfoEnabled", payload: { enabled } })
|
||||||
|
});
|
||||||
|
|
||||||
|
const useSensitiveInfo = () => {
|
||||||
|
const { state, actions } = useContext(SensitiveInfoContext);
|
||||||
|
const { enabled } = state;
|
||||||
|
const { onSensitiveInfoEnabled } = actions;
|
||||||
|
|
||||||
|
const mask = text => {
|
||||||
|
if (!enabled) return text;
|
||||||
|
return obfuscate(text, "#");
|
||||||
|
};
|
||||||
|
|
||||||
|
const maskElements = list => {
|
||||||
|
if (!enabled) return list;
|
||||||
|
const maskedList = list.map(z => obfuscate(z, "#"));
|
||||||
|
return maskedList;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { enabled, onSensitiveInfoEnabled, mask, maskElements };
|
||||||
|
};
|
||||||
|
|
||||||
|
const SensitiveInfoProvider = ({ children }) => {
|
||||||
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
const actions = useMemo(() => dispatchActions(dispatch), [dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SensitiveInfoContext.Provider
|
||||||
|
value={{
|
||||||
|
state,
|
||||||
|
actions
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SensitiveInfoContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SensitiveInfoProvider.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export { SensitiveInfoProvider, useSensitiveInfo };
|
||||||
|
export default SensitiveInfoProvider;
|
|
@ -0,0 +1,24 @@
|
||||||
|
const obfuscateForChars = (text, placeholder = "*") => {
|
||||||
|
const firstChar = text.substring(0, 1);
|
||||||
|
const lastChar = text.substring(text.length - 1);
|
||||||
|
const middleChars = text
|
||||||
|
.substring(1, text.length - 1)
|
||||||
|
.replace(/[a-zA-Z0-9]/g, placeholder);
|
||||||
|
return firstChar + middleChars + lastChar;
|
||||||
|
};
|
||||||
|
|
||||||
|
const obfuscate = (text, placeholder = "*") => {
|
||||||
|
if (text.length <= 2) return text;
|
||||||
|
if (text.length <= 5) {
|
||||||
|
return obfuscateForChars(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstTwoChars = text.substring(0, 2);
|
||||||
|
const lastChar = text.substring(text.length - 1);
|
||||||
|
const middleChars = text
|
||||||
|
.substring(2, text.length - 1)
|
||||||
|
.replace(/[a-zA-Z0-9]/g, placeholder);
|
||||||
|
return firstTwoChars + middleChars + lastChar;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { obfuscate };
|
Loading…
Reference in New Issue