Add basic token rights editor
This commit is contained in:
parent
c7f72882a7
commit
e68569b9b4
@ -1,7 +1,9 @@
|
||||
import { APIClient } from "./ApiClient";
|
||||
|
||||
export type RightVerb = "POST" | "GET" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
export interface TokenRight {
|
||||
verb: "POST" | "GET" | "PUT" | "DELETE" | "PATCH";
|
||||
verb: RightVerb;
|
||||
path: string;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,8 @@ import { EditSection } from "../forms/EditSection";
|
||||
import { IPInputWithMask } from "../forms/IPInput";
|
||||
import { RadioGroupInput } from "../forms/RadioGroupInput";
|
||||
import { TextInput } from "../forms/TextInput";
|
||||
import { RawRightsEditor } from "./RawRightsEditor";
|
||||
import { TokenRawRightsEditor } from "./TokenRawRightsEditor";
|
||||
import { TokenRightsEditor } from "./TokenRightsEditor";
|
||||
|
||||
const SECS_PER_DAY = 3600 * 24;
|
||||
|
||||
@ -106,7 +107,7 @@ function APITokenDetailsInner(p: DetailsInnerProps): React.ReactElement {
|
||||
]}
|
||||
/>
|
||||
{currTab === TokenTab.General && <APITokenTabGeneral {...p} />}
|
||||
{/* todo: rights */}
|
||||
{currTab === TokenTab.Rights && <APITokenRights {...p} />}
|
||||
{currTab === TokenTab.RawRights && <APITokenRawRights {...p} />}
|
||||
{currTab === TokenTab.Danger && <APITokenTabDanger {...p} />}
|
||||
</>
|
||||
@ -198,10 +199,24 @@ function APITokenTabGeneral(p: DetailsInnerProps): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
function APITokenRights(p: DetailsInnerProps): React.ReactElement {
|
||||
return (
|
||||
<div style={{ padding: "30px" }}>
|
||||
<TokenRightsEditor
|
||||
{...p}
|
||||
editable={p.status !== TokenWidgetStatus.Read}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function APITokenRawRights(p: DetailsInnerProps): React.ReactElement {
|
||||
return (
|
||||
<div style={{ padding: "30px" }}>
|
||||
<RawRightsEditor {...p} editable={p.status !== TokenWidgetStatus.Read} />
|
||||
<TokenRawRightsEditor
|
||||
{...p}
|
||||
editable={p.status !== TokenWidgetStatus.Read}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import { APIToken } from "../../api/TokensApi";
|
||||
import { SelectInput } from "../forms/SelectInput";
|
||||
import { TextInput } from "../forms/TextInput";
|
||||
|
||||
export function RawRightsEditor(p: {
|
||||
export function TokenRawRightsEditor(p: {
|
||||
token: APIToken;
|
||||
editable: boolean;
|
||||
onChange?: () => void;
|
151
virtweb_frontend/src/widgets/tokens/TokenRightsEditor.tsx
Normal file
151
virtweb_frontend/src/widgets/tokens/TokenRightsEditor.tsx
Normal file
@ -0,0 +1,151 @@
|
||||
import {
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
Paper,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
import { NWFilter } from "../../api/NWFilterApi";
|
||||
import { NetworkInfo } from "../../api/NetworksApi";
|
||||
import { APIToken, TokenRight } from "../../api/TokensApi";
|
||||
import { VMInfo } from "../../api/VMApi";
|
||||
|
||||
export function TokenRightsEditor(p: {
|
||||
token: APIToken;
|
||||
editable: boolean;
|
||||
onChange?: () => void;
|
||||
vms: VMInfo[];
|
||||
networks: NetworkInfo[];
|
||||
nwFilters: NWFilter[];
|
||||
tokens: APIToken[];
|
||||
}): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
{/* ISO files */}
|
||||
<RightsSection label="ISO files">
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "POST", path: "/api/iso/upload" }}
|
||||
label="Upload a new ISO file"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "POST", path: "/api/iso/upload_from_url" }}
|
||||
label="Upload a new ISO file from a given URL"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/iso/list" }}
|
||||
label="Get the list of ISO files"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/iso/*" }}
|
||||
label="Download ISO files"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "DELETE", path: "/api/iso/*" }}
|
||||
label="Delete ISO files"
|
||||
/>
|
||||
</RightsSection>
|
||||
|
||||
{/* Server general information */}
|
||||
<RightsSection label="Server">
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/server/static_config" }}
|
||||
label="Get static server configuration"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/server/info" }}
|
||||
label="Get server information"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/server/network_hook_status" }}
|
||||
label="Get network hook status"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/server/number_vcpus" }}
|
||||
label="Get number of vCPU"
|
||||
/>
|
||||
<RouteRight
|
||||
{...p}
|
||||
right={{ verb: "GET", path: "/api/server/networks" }}
|
||||
label="Get list of network cards"
|
||||
/>
|
||||
</RightsSection>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function RightsSection(
|
||||
p: React.PropsWithChildren<{ label: string }>
|
||||
): React.ReactElement {
|
||||
return (
|
||||
<Paper style={{ padding: "20px" }}>
|
||||
<Typography variant="h5">{p.label}</Typography>
|
||||
{p.children}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
function RouteRight(p: {
|
||||
right: TokenRight;
|
||||
label?: string;
|
||||
editable: boolean;
|
||||
token: APIToken;
|
||||
onChange?: () => void;
|
||||
parent?: TokenRight;
|
||||
}): React.ReactElement {
|
||||
const activated =
|
||||
p.token.rights.find(
|
||||
(r) => r.verb === p.right.verb && r.path === p.right.path
|
||||
) !== undefined;
|
||||
|
||||
const toggle = (a: boolean) => {
|
||||
if (a) {
|
||||
p.token.rights.push(p.right);
|
||||
} else {
|
||||
p.token.rights.splice(p.token.rights.indexOf(p.right), 1);
|
||||
}
|
||||
p.onChange?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Tooltip
|
||||
title={`${p.right.verb} ${p.right.path}`}
|
||||
arrow
|
||||
placement="left"
|
||||
slotProps={{
|
||||
popper: {
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, -14],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={activated}
|
||||
disabled={!p.editable}
|
||||
onChange={(_e, a) => toggle(a)}
|
||||
/>
|
||||
}
|
||||
label={p.label}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user