Create network filters route
This commit is contained in:
		@@ -26,6 +26,7 @@ import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
 | 
			
		||||
import { BaseLoginPage } from "./widgets/BaseLoginPage";
 | 
			
		||||
import { ViewNetworkRoute } from "./routes/ViewNetworkRoute";
 | 
			
		||||
import { HomeRoute } from "./routes/HomeRoute";
 | 
			
		||||
import { NetworkFiltersListRoute } from "./routes/NetworkFiltersListRoute";
 | 
			
		||||
 | 
			
		||||
interface AuthContext {
 | 
			
		||||
  signedIn: boolean;
 | 
			
		||||
@@ -61,6 +62,8 @@ export function App() {
 | 
			
		||||
          <Route path="net/:uuid" element={<ViewNetworkRoute />} />
 | 
			
		||||
          <Route path="net/:uuid/edit" element={<EditNetworkRoute />} />
 | 
			
		||||
 | 
			
		||||
          <Route path="nwfilter" element={<NetworkFiltersListRoute />} />
 | 
			
		||||
 | 
			
		||||
          <Route path="sysinfo" element={<SysInfoRoute />} />
 | 
			
		||||
          <Route path="*" element={<NotFoundRoute />} />
 | 
			
		||||
        </Route>
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@ export interface NWFilter {
 | 
			
		||||
  rules: NWFilterRule[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function NWFilterURL(n: NWFilter, edit: boolean = false): string {
 | 
			
		||||
  return `/nwfilter/${n.uuid}${edit ? "/edit" : ""}`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class NWFilterApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the entire list of networks
 | 
			
		||||
 
 | 
			
		||||
@@ -39,10 +39,6 @@ export function NetworkURL(n: NetworkInfo, edit: boolean = false): string {
 | 
			
		||||
  return `/net/${n.uuid}${edit ? "/edit" : ""}`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function NetworkXMLURL(n: NetworkInfo): string {
 | 
			
		||||
  return `/net/${n.uuid}/xml`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class NetworkApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new network
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ export interface ServerConfig {
 | 
			
		||||
  iso_mimetypes: string[];
 | 
			
		||||
  net_mac_prefix: string;
 | 
			
		||||
  constraints: ServerConstraints;
 | 
			
		||||
  builtin_nwfilter_rules: string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ServerConstraints {
 | 
			
		||||
 
 | 
			
		||||
@@ -133,10 +133,6 @@ export class VMInfo implements VMInfoInterface {
 | 
			
		||||
  get VNCURL(): string {
 | 
			
		||||
    return `/vm/${this.uuid}/vnc`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get XMLURL(): string {
 | 
			
		||||
    return `/vm/${this.uuid}/xml`;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class VMApi {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										153
									
								
								virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								virtweb_frontend/src/routes/NetworkFiltersListRoute.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
import VisibilityIcon from "@mui/icons-material/Visibility";
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
  IconButton,
 | 
			
		||||
  Paper,
 | 
			
		||||
  Table,
 | 
			
		||||
  TableBody,
 | 
			
		||||
  TableCell,
 | 
			
		||||
  TableContainer,
 | 
			
		||||
  TableHead,
 | 
			
		||||
  TableRow,
 | 
			
		||||
  ToggleButton,
 | 
			
		||||
  ToggleButtonGroup,
 | 
			
		||||
  Typography,
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { NWFilter, NWFilterApi, NWFilterURL } from "../api/NWFilterApi";
 | 
			
		||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
import { RouterLink } from "../widgets/RouterLink";
 | 
			
		||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
			
		||||
import { ServerApi } from "../api/ServerApi";
 | 
			
		||||
 | 
			
		||||
export function NetworkFiltersListRoute(): React.ReactElement {
 | 
			
		||||
  const [list, setList] = React.useState<NWFilter[] | undefined>();
 | 
			
		||||
 | 
			
		||||
  const [count] = React.useState(1);
 | 
			
		||||
 | 
			
		||||
  const load = async () => {
 | 
			
		||||
    setList(await NWFilterApi.GetList());
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <AsyncWidget
 | 
			
		||||
      loadKey={count}
 | 
			
		||||
      load={load}
 | 
			
		||||
      ready={list !== undefined}
 | 
			
		||||
      errMsg="Failed to load the list of networks!"
 | 
			
		||||
      build={() => <NetworkFiltersListRouteInner list={list!} />}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum VisibleFilters {
 | 
			
		||||
  All,
 | 
			
		||||
  Builtin,
 | 
			
		||||
  Custom,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NetworkFiltersListRouteInner(p: {
 | 
			
		||||
  list: NWFilter[];
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const [visibleFilters, setVisibleFilters] = React.useState(
 | 
			
		||||
    VisibleFilters.All
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const filteredList = React.useMemo(() => {
 | 
			
		||||
    if (visibleFilters === VisibleFilters.All) return p.list;
 | 
			
		||||
 | 
			
		||||
    const onlyBuiltin = visibleFilters === VisibleFilters.Builtin;
 | 
			
		||||
 | 
			
		||||
    return p.list.filter(
 | 
			
		||||
      (f) =>
 | 
			
		||||
        ServerApi.Config.builtin_nwfilter_rules.includes(f.name) === onlyBuiltin
 | 
			
		||||
    );
 | 
			
		||||
  }, [visibleFilters]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <VirtWebRouteContainer
 | 
			
		||||
      label="Network filters"
 | 
			
		||||
      actions={
 | 
			
		||||
        <>
 | 
			
		||||
          <span style={{ flex: 10 }}></span>
 | 
			
		||||
          <ToggleButtonGroup
 | 
			
		||||
            size="small"
 | 
			
		||||
            value={visibleFilters}
 | 
			
		||||
            exclusive
 | 
			
		||||
            onChange={(_ev, v) => setVisibleFilters(v)}
 | 
			
		||||
            aria-label="visible filters"
 | 
			
		||||
          >
 | 
			
		||||
            <ToggleButton value={VisibleFilters.All}>All</ToggleButton>
 | 
			
		||||
            <ToggleButton value={VisibleFilters.Builtin}>Builtin</ToggleButton>
 | 
			
		||||
            <ToggleButton value={VisibleFilters.Custom}>Custom</ToggleButton>
 | 
			
		||||
          </ToggleButtonGroup>
 | 
			
		||||
          <span style={{ flex: 2 }}></span>
 | 
			
		||||
 | 
			
		||||
          <RouterLink to="/nwfilter/new">
 | 
			
		||||
            <Button>New</Button>
 | 
			
		||||
          </RouterLink>
 | 
			
		||||
        </>
 | 
			
		||||
      }
 | 
			
		||||
    >
 | 
			
		||||
      <TableContainer component={Paper}>
 | 
			
		||||
        <Table>
 | 
			
		||||
          <TableHead>
 | 
			
		||||
            <TableRow>
 | 
			
		||||
              <TableCell>Name</TableCell>
 | 
			
		||||
              <TableCell>Chain</TableCell>
 | 
			
		||||
              <TableCell>Priority</TableCell>
 | 
			
		||||
              <TableCell>Referenced filters</TableCell>
 | 
			
		||||
              <TableCell># of rules</TableCell>
 | 
			
		||||
              <TableCell>Actions</TableCell>
 | 
			
		||||
            </TableRow>
 | 
			
		||||
          </TableHead>
 | 
			
		||||
          <TableBody>
 | 
			
		||||
            {filteredList.map((t) => {
 | 
			
		||||
              return (
 | 
			
		||||
                <TableRow
 | 
			
		||||
                  key={t.uuid}
 | 
			
		||||
                  hover
 | 
			
		||||
                  onDoubleClick={() => navigate(NWFilterURL(t))}
 | 
			
		||||
                >
 | 
			
		||||
                  <TableCell>{t.name}</TableCell>
 | 
			
		||||
                  <TableCell>
 | 
			
		||||
                    {t.chain?.protocol ?? (
 | 
			
		||||
                      <Typography style={{ fontStyle: "italic" }}>
 | 
			
		||||
                        None
 | 
			
		||||
                      </Typography>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </TableCell>
 | 
			
		||||
                  <TableCell>
 | 
			
		||||
                    {t.priority ?? (
 | 
			
		||||
                      <Typography style={{ fontStyle: "italic" }}>
 | 
			
		||||
                        None
 | 
			
		||||
                      </Typography>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </TableCell>
 | 
			
		||||
                  <TableCell>
 | 
			
		||||
                    <ul>
 | 
			
		||||
                      {t.join_filters.map((f, n) => (
 | 
			
		||||
                        <li key={n}>{f}</li>
 | 
			
		||||
                      ))}
 | 
			
		||||
                    </ul>
 | 
			
		||||
                  </TableCell>
 | 
			
		||||
                  <TableCell>{t.rules.length}</TableCell>
 | 
			
		||||
                  <TableCell>
 | 
			
		||||
                    <RouterLink to={NWFilterURL(t)}>
 | 
			
		||||
                      <IconButton>
 | 
			
		||||
                        <VisibilityIcon />
 | 
			
		||||
                      </IconButton>
 | 
			
		||||
                    </RouterLink>
 | 
			
		||||
                  </TableCell>
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              );
 | 
			
		||||
            })}
 | 
			
		||||
          </TableBody>
 | 
			
		||||
        </Table>
 | 
			
		||||
      </TableContainer>
 | 
			
		||||
    </VirtWebRouteContainer>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								virtweb_frontend/src/utils/DebugUtils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								virtweb_frontend/src/utils/DebugUtils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
export function isDebug(): boolean {
 | 
			
		||||
  return (
 | 
			
		||||
    !import.meta.env.NODE_ENV || import.meta.env.NODE_ENV === "development"
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,9 @@ import {
 | 
			
		||||
  mdiDisc,
 | 
			
		||||
  mdiHome,
 | 
			
		||||
  mdiInformation,
 | 
			
		||||
  mdiLan
 | 
			
		||||
  mdiLan,
 | 
			
		||||
  mdiSecurity,
 | 
			
		||||
  mdiSecurityNetwork,
 | 
			
		||||
} from "@mdi/js";
 | 
			
		||||
import Icon from "@mdi/react";
 | 
			
		||||
import {
 | 
			
		||||
@@ -17,6 +19,7 @@ import {
 | 
			
		||||
import { Outlet, useLocation } from "react-router-dom";
 | 
			
		||||
import { RouterLink } from "./RouterLink";
 | 
			
		||||
import { VirtWebAppBar } from "./VirtWebAppBar";
 | 
			
		||||
import { isDebug } from "../utils/DebugUtils";
 | 
			
		||||
 | 
			
		||||
export function BaseAuthenticatedPage(): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
@@ -60,6 +63,14 @@ export function BaseAuthenticatedPage(): React.ReactElement {
 | 
			
		||||
            uri="/net"
 | 
			
		||||
            icon={<Icon path={mdiLan} size={1} />}
 | 
			
		||||
          />
 | 
			
		||||
          {/* TODO : remove debug marker */}
 | 
			
		||||
          {isDebug() && (
 | 
			
		||||
            <NavLink
 | 
			
		||||
              label="Network filters"
 | 
			
		||||
              uri="/nwfilter"
 | 
			
		||||
              icon={<Icon path={mdiSecurityNetwork} size={1} />}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
          <NavLink
 | 
			
		||||
            label="ISO files"
 | 
			
		||||
            uri="/iso"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user