Started to create rules editor

This commit is contained in:
Pierre HUBERT 2024-01-04 11:30:20 +01:00
parent aafa4bf145
commit 7d7a052f5f
4 changed files with 162 additions and 0 deletions

View File

@ -47,6 +47,7 @@ struct ServerConstraints {
nwfilter_name_size: LenConstraints, nwfilter_name_size: LenConstraints,
nwfilter_comment_size: LenConstraints, nwfilter_comment_size: LenConstraints,
nwfilter_priority: SLenConstraints, nwfilter_priority: SLenConstraints,
nwfilter_selectors_count: LenConstraints,
} }
pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder { pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
@ -89,6 +90,7 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
min: -1000, min: -1000,
max: 1000, max: 1000,
}, },
nwfilter_selectors_count: LenConstraints { min: 0, max: 1 },
}, },
}) })
} }

View File

@ -25,6 +25,7 @@ export interface ServerConstraints {
nwfilter_name_size: LenConstraint; nwfilter_name_size: LenConstraint;
nwfilter_comment_size: LenConstraint; nwfilter_comment_size: LenConstraint;
nwfilter_priority: LenConstraint; nwfilter_priority: LenConstraint;
nwfilter_selectors_count: LenConstraint;
} }
export interface LenConstraint { export interface LenConstraint {

View File

@ -0,0 +1,146 @@
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
import DeleteIcon from "@mui/icons-material/Delete";
import {
Button,
Card,
CardActions,
CardContent,
IconButton,
} from "@mui/material";
import { NWFilterRule } from "../../api/NWFilterApi";
import { EditSection } from "./EditSection";
import { SelectInput } from "./SelectInput";
import { TextInput } from "./TextInput";
import { ServerApi } from "../../api/ServerApi";
export function NWFilterRules(p: {
editable: boolean;
rules: NWFilterRule[];
onChange?: () => void;
}): React.ReactElement {
const addRule = () => {
p.rules.push({
action: "drop",
direction: "inout",
selectors: [],
});
p.onChange?.();
};
const swapRules = (f: number, s: number) => {
const swap = p.rules[f];
p.rules[f] = p.rules[s];
p.rules[s] = swap;
p.onChange?.();
};
const deleteRule = (num: number) => {
p.rules.splice(num, 1);
p.onChange?.();
};
return (
<EditSection title="Rules">
{p.rules.map((r, n) => (
<NWRuleEdit
key={n}
rule={r}
onDelete={() => {
deleteRule(n);
}}
onGoDown={
n < p.rules.length - 1 ? () => swapRules(n, n + 1) : undefined
}
onGoUp={n > 0 ? () => swapRules(n, n - 1) : undefined}
{...p}
/>
))}
<div style={{ textAlign: "right" }}>
{p.editable && <Button onClick={addRule}>Add a new rule</Button>}
</div>
</EditSection>
);
}
function NWRuleEdit(p: {
editable: boolean;
rule: NWFilterRule;
onChange?: () => void;
onGoUp?: () => void;
onGoDown?: () => void;
onDelete: () => void;
}): React.ReactElement {
return (
<Card style={{ margin: "30px" }} elevation={3}>
<CardContent>
<div style={{ display: "flex" }}>
<SelectInput
editable={p.editable}
label="Action"
value={p.rule.action}
onValueChange={(v) => {
p.rule.action = v as any;
p.onChange?.();
}}
options={[
{ label: "drop", value: "drop" },
{ label: "reject", value: "reject" },
{ label: "accept", value: "accept" },
{ label: "return", value: "return" },
{ label: "continue", value: "continue" },
]}
/>
<span style={{ width: "20px" }}></span>
<SelectInput
editable={p.editable}
label="Direction"
value={p.rule.direction}
onValueChange={(v) => {
p.rule.direction = v as any;
p.onChange?.();
}}
options={[
{ label: "in", value: "in" },
{ label: "out", value: "out" },
{ label: "inout", value: "inout" },
]}
/>
<span style={{ width: "20px" }}></span>
<TextInput
label="Priority"
editable={p.editable}
value={p.rule.priority?.toString()}
type="number"
onValueChange={(v) => {
p.rule.priority = v && v !== "" ? Number(v) : undefined;
p.onChange?.();
}}
size={ServerApi.Config.constraints.nwfilter_priority}
/>
</div>
</CardContent>
<CardActions>
{p.editable && (
<div style={{ display: "flex", width: "100%" }}>
<IconButton color="error" onClick={p.onDelete}>
<DeleteIcon />
</IconButton>
<span style={{ flex: 1 }}></span>
{p.onGoUp && (
<IconButton onClick={p.onGoUp}>
<ArrowUpwardIcon />
</IconButton>
)}
{p.onGoDown && (
<IconButton onClick={p.onGoDown}>
<ArrowDownwardIcon />
</IconButton>
)}
</div>
)}
</CardActions>
</Card>
);
}

View File

@ -17,6 +17,7 @@ import { TextInput } from "../forms/TextInput";
import { ServerApi } from "../../api/ServerApi"; import { ServerApi } from "../../api/ServerApi";
import { SelectInput } from "../forms/SelectInput"; import { SelectInput } from "../forms/SelectInput";
import { NWFSelectReferencedFilters } from "../forms/NWFSelectReferencedFilters"; import { NWFSelectReferencedFilters } from "../forms/NWFSelectReferencedFilters";
import { NWFilterRules } from "../forms/NWFilterRules";
interface DetailsProps { interface DetailsProps {
nwfilter: NWFilter; nwfilter: NWFilter;
@ -159,6 +160,18 @@ function NetworkFilterDetailsTabGeneral(
); );
} }
function NetworkFilterDetailsTabRules(
p: InnerDetailsProps
): React.ReactElement {
return (
<NWFilterRules
editable={p.editable}
rules={p.nwfilter.rules}
onChange={p.onChange}
/>
);
}
function NetworkFilterDetailsTabXML(p: InnerDetailsProps): React.ReactElement { function NetworkFilterDetailsTabXML(p: InnerDetailsProps): React.ReactElement {
return ( return (
<XMLAsyncWidget <XMLAsyncWidget