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",
|
||||
"version": "1.1.2",
|
||||
"version": "1.2.1",
|
||||
"description": "Frontend component of Network resurrector system",
|
||||
"author": {
|
||||
"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 ProfileButton from "./ProfileButton";
|
||||
import LightDarkToggle from "./LightDarkToggle";
|
||||
import SensitiveInfoToggle from "./SensitiveInfoToggle";
|
||||
import styles from "./styles";
|
||||
|
||||
const useStyles = makeStyles(styles);
|
||||
|
@ -35,6 +36,7 @@ const TopBar = ({ open, handleDrawerOpen }) => {
|
|||
<Typography variant="h6" noWrap className={classes.title}>
|
||||
Network resurrector
|
||||
</Typography>
|
||||
<SensitiveInfoToggle />
|
||||
<LightDarkToggle />
|
||||
<ProfileButton />
|
||||
</Toolbar>
|
||||
|
|
|
@ -12,6 +12,7 @@ import { KeyboardArrowDown, KeyboardArrowUp } from "@material-ui/icons";
|
|||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import MachineLog from "./MachineLog";
|
||||
import WakeComponent from "./WakeComponent";
|
||||
import { useSensitiveInfo } from "../../../hooks";
|
||||
|
||||
const useRowStyles = makeStyles({
|
||||
root: {
|
||||
|
@ -62,6 +63,7 @@ const Machine = ({
|
|||
}) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const classes = useRowStyles();
|
||||
const { mask, maskElements } = useSensitiveInfo();
|
||||
|
||||
const topActions = useMemo(
|
||||
() => actions.filter(a => a.top === true),
|
||||
|
@ -86,11 +88,11 @@ const Machine = ({
|
|||
</IconButton>
|
||||
</TableCell>
|
||||
<TableCell component="th" scope="row">
|
||||
{machine.fullMachineName}
|
||||
{mask(machine.fullMachineName)}
|
||||
</TableCell>
|
||||
<TableCell>{machine.machineName}</TableCell>
|
||||
<TableCell>{machine.iPv4Address}</TableCell>
|
||||
<TableCell>{machine.macAddress}</TableCell>
|
||||
<TableCell>{mask(machine.machineName)}</TableCell>
|
||||
<TableCell>{mask(machine.iPv4Address)}</TableCell>
|
||||
<TableCell>{mask(machine.macAddress)}</TableCell>
|
||||
<TableCell align="right">
|
||||
<WakeComponent machine={machine} addLog={addLog} />
|
||||
{topActions.map(action => (
|
||||
|
@ -120,7 +122,7 @@ const Machine = ({
|
|||
<TableRow>
|
||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<MachineLog logs={logs} />
|
||||
<MachineLog logs={maskElements(logs)} />
|
||||
</Collapse>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
|
@ -6,10 +6,12 @@ import {
|
|||
import useApi from "../../../api";
|
||||
import MachinesList from "./MachinesList";
|
||||
import PageTitle from "../../../components/common/PageTitle";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const MachinesContainer = () => {
|
||||
const state = useContext(ApplicationStateContext);
|
||||
const dispatchActions = useContext(ApplicationDispatchContext);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const api = useApi();
|
||||
|
||||
|
@ -30,7 +32,7 @@ const MachinesContainer = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<PageTitle text="Machines" />
|
||||
<PageTitle text={t("Menu.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 ApplicationStateProvider from "./providers/ApplicationStateProvider";
|
||||
import ToastProvider from "./providers/ToastProvider";
|
||||
import SensitiveInfoProvider from "./providers/SensitiveInfoProvider";
|
||||
import "./utils/i18n";
|
||||
|
||||
ReactDOM.render(
|
||||
<TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
|
||||
<ApplicationStateProvider>
|
||||
<ThemeProvider>
|
||||
<CssBaseline />
|
||||
<SensitiveInfoProvider>
|
||||
<ApplicationStateProvider>
|
||||
<Suspense fallback={<div>Loading...</div>}>
|
||||
<ToastProvider>
|
||||
<App />
|
||||
</ToastProvider>
|
||||
</Suspense>
|
||||
</ThemeProvider>
|
||||
</ApplicationStateProvider>
|
||||
</SensitiveInfoProvider>
|
||||
</ThemeProvider>
|
||||
</TuitioProvider>,
|
||||
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