Create network filters route
This commit is contained in:
parent
706bce0fd8
commit
22f5acd0ff
19
virtweb_backend/Cargo.lock
generated
19
virtweb_backend/Cargo.lock
generated
@ -2159,18 +2159,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-xml-rs"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.193"
|
||||
@ -2677,7 +2665,6 @@ dependencies = [
|
||||
"reqwest",
|
||||
"rust-embed",
|
||||
"serde",
|
||||
"serde-xml-rs",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
"tempfile",
|
||||
@ -2981,12 +2968,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.31"
|
||||
|
@ -22,7 +22,6 @@ actix-web-actors = "4.2.0"
|
||||
actix-http = "3.4.0"
|
||||
serde = { version = "1.0.193", features = ["derive"] }
|
||||
serde_json = "1.0.108"
|
||||
serde-xml-rs = "0.6.0"
|
||||
quick-xml = { version = "0.31.0", features = ["serialize", "overlapped-lists"] }
|
||||
futures-util = "0.3.28"
|
||||
anyhow = "1.0.75"
|
||||
|
@ -16,7 +16,7 @@ struct StaticConfig {
|
||||
iso_mimetypes: &'static [&'static str],
|
||||
net_mac_prefix: &'static str,
|
||||
constraints: ServerConstraints,
|
||||
builtin_network_rules: &'static [&'static str],
|
||||
builtin_nwfilter_rules: &'static [&'static str],
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
@ -46,7 +46,7 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
|
||||
oidc_auth_enabled: !AppConfig::get().disable_oidc,
|
||||
iso_mimetypes: &constants::ALLOWED_ISO_MIME_TYPES,
|
||||
net_mac_prefix: constants::NET_MAC_ADDR_PREFIX,
|
||||
builtin_network_rules: &constants::BUILTIN_NETWORK_FILTER_RULES,
|
||||
builtin_nwfilter_rules: &constants::BUILTIN_NETWORK_FILTER_RULES,
|
||||
constraints: ServerConstraints {
|
||||
iso_max_size: constants::ISO_MAX_SIZE,
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user