From 91127ea61fd16fabe494768b67ce6296f86628d9 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Wed, 17 Apr 2024 22:20:01 +0200 Subject: [PATCH] List the tokens from the WebUI --- .../src/controllers/api_tokens_controller.rs | 1 + virtweb_frontend/package-lock.json | 30 ++--- virtweb_frontend/package.json | 1 + virtweb_frontend/src/App.tsx | 3 + virtweb_frontend/src/api/TokensApi.ts | 36 ++++++ .../src/routes/TokensListRoute.tsx | 118 ++++++++++++++++++ .../src/widgets/BaseAuthenticatedPage.tsx | 6 + virtweb_frontend/src/widgets/TimeWidget.tsx | 64 ++++++++++ 8 files changed, 240 insertions(+), 19 deletions(-) create mode 100644 virtweb_frontend/src/api/TokensApi.ts create mode 100644 virtweb_frontend/src/routes/TokensListRoute.tsx create mode 100644 virtweb_frontend/src/widgets/TimeWidget.tsx diff --git a/virtweb_backend/src/controllers/api_tokens_controller.rs b/virtweb_backend/src/controllers/api_tokens_controller.rs index 3f40161..fa32fbd 100644 --- a/virtweb_backend/src/controllers/api_tokens_controller.rs +++ b/virtweb_backend/src/controllers/api_tokens_controller.rs @@ -14,6 +14,7 @@ mod rest_token { #[derive(serde::Serialize)] pub struct RestToken { + #[serde(flatten)] token: Token, } diff --git a/virtweb_frontend/package-lock.json b/virtweb_frontend/package-lock.json index 1ccdb12..09ef043 100644 --- a/virtweb_frontend/package-lock.json +++ b/virtweb_frontend/package-lock.json @@ -27,6 +27,7 @@ "@types/react-syntax-highlighter": "^15.5.11", "@types/uuid": "^9.0.5", "@vitejs/plugin-react": "^4.2.1", + "date-and-time": "^3.1.1", "filesize": "^10.0.12", "humanize-duration": "^3.29.0", "mui-file-input": "^4.0.4", @@ -35,7 +36,7 @@ "react-router-dom": "^6.15.0", "react-syntax-highlighter": "^15.5.0", "react-vnc": "^1.0.0", - "typescript": "^4.1.6", + "typescript": "^5.0.0", "uuid": "^9.0.1", "vite": "^5.0.8", "vite-tsconfig-paths": "^4.2.2", @@ -8877,6 +8878,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-and-time": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-3.1.1.tgz", + "integrity": "sha512-N9kstidT3P0VUk1iKOFilOZ6251r6iTUNx9M9kvgL2jqOk9mljWZUq5CjAtYwCnppWHbERk5YFQUrSbY7FQOpA==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -21890,15 +21896,15 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -22231,20 +22237,6 @@ } } }, - "node_modules/vite-tsconfig-paths/node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/virtweb_frontend/package.json b/virtweb_frontend/package.json index 1c4f96d..55e1ee2 100644 --- a/virtweb_frontend/package.json +++ b/virtweb_frontend/package.json @@ -23,6 +23,7 @@ "@types/react-syntax-highlighter": "^15.5.11", "@types/uuid": "^9.0.5", "@vitejs/plugin-react": "^4.2.1", + "date-and-time": "^3.1.1", "filesize": "^10.0.12", "humanize-duration": "^3.29.0", "mui-file-input": "^4.0.4", diff --git a/virtweb_frontend/src/App.tsx b/virtweb_frontend/src/App.tsx index f4dcc20..14f3f57 100644 --- a/virtweb_frontend/src/App.tsx +++ b/virtweb_frontend/src/App.tsx @@ -32,6 +32,7 @@ import { CreateNWFilterRoute, EditNWFilterRoute, } from "./routes/EditNWFilterRoute"; +import { TokensListRoute } from "./routes/TokensListRoute"; interface AuthContext { signedIn: boolean; @@ -72,6 +73,8 @@ export function App() { } /> } /> + } /> + } /> } /> diff --git a/virtweb_frontend/src/api/TokensApi.ts b/virtweb_frontend/src/api/TokensApi.ts new file mode 100644 index 0000000..d593a31 --- /dev/null +++ b/virtweb_frontend/src/api/TokensApi.ts @@ -0,0 +1,36 @@ +import { APIClient } from "./ApiClient"; + +export interface TokenRight { + verb: "POST" | "GET" | "PUT" | "DELETE" | "PATCH"; + path: string; +} + +export interface APIToken { + id: string; + name: string; + description: string; + created: number; + updated: number; + rights: TokenRight[]; + last_used: number; + ip_restriction?: string; + max_inactivity?: number; +} + +export function APITokenURL(t: APIToken, edit: boolean = false): string { + return `/tokens/${t.id}${edit ? "/edit" : ""}`; +} + +export class TokensApi { + /** + * Get the full list of tokens + */ + static async GetList(): Promise { + return ( + await APIClient.exec({ + method: "GET", + uri: "/tokens/list", + }) + ).data; + } +} diff --git a/virtweb_frontend/src/routes/TokensListRoute.tsx b/virtweb_frontend/src/routes/TokensListRoute.tsx new file mode 100644 index 0000000..14a8d2a --- /dev/null +++ b/virtweb_frontend/src/routes/TokensListRoute.tsx @@ -0,0 +1,118 @@ +import React from "react"; +import { APIToken, APITokenURL, TokensApi } from "../api/TokensApi"; +import { AsyncWidget } from "../widgets/AsyncWidget"; +import { + Button, + IconButton, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from "@mui/material"; +import { RouterLink } from "../widgets/RouterLink"; +import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer"; +import { useNavigate } from "react-router-dom"; +import VisibilityIcon from "@mui/icons-material/Visibility"; +import { TimeWidget, timeDiff } from "../widgets/TimeWidget"; + +export function TokensListRoute(): React.ReactElement { + const [list, setList] = React.useState(); + + const [count] = React.useState(1); + + const load = async () => { + setList(await TokensApi.GetList()); + }; + + return ( + } + /> + ); +} + +export function TokensListRouteInner(p: { + list: APIToken[]; +}): React.ReactElement { + const navigate = useNavigate(); + + return ( + + + + } + > + + + + + Name + Description + Created + Updated + Last used + IP restriction + Max inactivity + Rights + Actions + + + + {p.list.map((t) => { + return ( + navigate(APITokenURL(t))} + > + {t.name} + {t.description} + + + + + + + + + + {t.ip_restriction} + + {t.max_inactivity && timeDiff(0, t.max_inactivity)} + + + {t.rights.map((r) => { + return ( +
+ {r.verb} {r.path} +
+ ); + })} +
+ + + + + + + + +
+ ); + })} +
+
+
+
+ ); +} diff --git a/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx b/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx index 4af33e4..7969bbd 100644 --- a/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx +++ b/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx @@ -1,4 +1,5 @@ import { + mdiApi, mdiBoxShadow, mdiDisc, mdiHome, @@ -72,6 +73,11 @@ export function BaseAuthenticatedPage(): React.ReactElement { uri="/iso" icon={} /> + } + /> ; + return ( + + {timeDiffFromNow(p.time)} + + ); +}