3.5 KiB
radui — RADIUS Admin Portal
Web UI for the radapi FreeRADIUS REST API. Manage clients
(customer MACs), devices (NAS/AP boxes seen in accounting), and VLANs
without touching SQL. Admins also manage users, API keys, and view an
activity log. Auth is a username/password login; the backend returns a session
token stored in the browser (localStorage) and sent as Authorization: Bearer
on every request.
Stack
- React 19 + Vite + TypeScript
- Tailwind v4 + shadcn/ui-style components (Radix primitives)
- react-router-dom, sonner (toasts)
- Node provided via
shell.nix(NixOS) — no global install needed
Develop
nix-shell # drops you into a shell with node 22 + npm
npm install # first time only
npm run dev # http://localhost:5173
Or as a one-liner without entering the shell:
nix-shell --run "npm run dev -- --host 0.0.0.0"
Talking to the API
In dev, Vite proxies /api/* to the backend so the browser makes same-origin
requests (no CORS) and the token is only ever sent as a header. The target defaults
to http://10.0.1.235:8000; override it:
VITE_API_TARGET=http://192.168.1.21:8000 npm run dev
Log in with admin / admin on first run (you'll be prompted to change the
password), then create real users from the Users page. A 401 from any request
clears the stored token and returns you to the login screen.
Build
npm run build # tsc -b && vite build → dist/
npm run preview # serve the production build locally
For production the built dist/ is static — serve it behind the same origin as the
API (or set VITE_API_BASE to the API's absolute URL at build time).
Layout
src/
main.tsx providers (router, auth, toaster)
App.tsx auth gate + forced-password-change + nav (role-gated) + routes
auth/auth.tsx session auth context (login/logout, current user, 401 handling)
lib/api.ts typed API client (auth + users + apikeys + logs + client/device/vlan)
lib/utils.ts cn() helper
pages/
Login.tsx username/password login screen
ChangePassword.tsx change own password (also the forced first-login screen)
Users.tsx admin: list/create/delete users + reset password
ApiKeys.tsx admin: create (shown once) / list / revoke API keys
Logs.tsx admin: paginated activity log
Clients.tsx client list + add/edit/delete + CSV import/export dialogs
Devices.tsx NAS device list + editable alias
Vlans.tsx VLAN list + add/rename/delete dialogs
components/
ClientImportExport.tsx CSV import (preview/confirm) + export dialog
ui/ button, input, label, dialog, select, table, card, badge, sonner
Notes
- Clients — add requires MAC, group (VLAN), name, phone; alias optional. The
group dropdown is populated from
GET /vlan/. Edit changes any subset of group, status, name, phone, alias. - CSV import parses the file client-side, does a dry-run against
POST /client/importto preview valid/error rows, and only writes on confirm. Export downloads all clients as CSV. - Devices — lists NAS/AP boxes from accounting, one row per AP MAC (with its
NAS IP and all SSIDs — extra SSIDs collapse to
SSID1 (and N more…)on hover). The only editable field is the humanalias(PUT /device/{ap_mac}). - Validation/
4xxerrors from the API surface as toasts with the server's message (422 field errors are flattened tofield: message).