Update CLAUDE.md with features added since initial version
Covers: connected clients popup, get_ap_clients/get_all_clients, new API endpoints, session recovery behaviour, reboot button locking, IP range filter, and sortable columns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
27
CLAUDE.md
27
CLAUDE.md
@@ -50,8 +50,22 @@ A module-level singleton (`omada_client`). Key behaviour:
|
|||||||
- **Sites are fetched from** `GET /api/v2/users/current` → `result.privilege.sites[]`, not `/api/v2/sites` (which requires root admin and returns empty for regular admins).
|
- **Sites are fetched from** `GET /api/v2/users/current` → `result.privilege.sites[]`, not `/api/v2/sites` (which requires root admin and returns empty for regular admins).
|
||||||
- **Devices list**: `GET /{omadacId}/api/v2/sites/{siteKey}/devices` filtered by `type == "ap"`. There is no `/aps` endpoint in v6.x.
|
- **Devices list**: `GET /{omadacId}/api/v2/sites/{siteKey}/devices` filtered by `type == "ap"`. There is no `/aps` endpoint in v6.x.
|
||||||
- **Reboot**: `POST /{omadacId}/api/v2/sites/{siteKey}/cmd/devices/{mac}/reboot` via the web session client. Response `errorCode: -39009` with `"Rebooting... Please wait."` is the success response — treat it as non-error alongside `0`. OpenAPI client credentials (`OMADA_CLIENT_ID`/`OMADA_CLIENT_SECRET`) are no longer used for reboot.
|
- **Reboot**: `POST /{omadacId}/api/v2/sites/{siteKey}/cmd/devices/{mac}/reboot` via the web session client. Response `errorCode: -39009` with `"Rebooting... Please wait."` is the success response — treat it as non-error alongside `0`. OpenAPI client credentials (`OMADA_CLIENT_ID`/`OMADA_CLIENT_SECRET`) are no longer used for reboot.
|
||||||
- **Session expiry** is handled in `_request_with_retry`: error codes `-1006`, `-1003`, `-30109` trigger automatic re-login.
|
- **Session expiry** is handled in `_request_with_retry`: error codes `-1006`, `-1003`, `-30109` trigger automatic re-login + re-fetch of sites. If all sites fail in `get_aps()`, the token and sites cache are cleared so the next request triggers a fresh login rather than staying broken indefinitely.
|
||||||
- **Uptime safety check**: `reboot_ap()` re-fetches live uptime before issuing the command; it raises if `uptimeLong < 300` seconds (5 minutes). The UI also disables the reboot button client-side for the same condition.
|
- **Uptime safety check**: `reboot_ap()` re-fetches live uptime before issuing the command; it raises if `uptimeLong < 300` seconds (5 minutes). The UI also disables the reboot button client-side for the same condition.
|
||||||
|
- **Connected clients**: `get_ap_clients(ap_mac, site_key)` fetches clients for a specific AP via `GET /sites/{key}/clients?filters.apMac={mac}`, with automatic fallback to fetching all site clients and filtering client-side if the controller doesn't support that query param. `get_all_clients()` fetches all clients across all sites grouped by AP MAC.
|
||||||
|
|
||||||
|
### API endpoints (`app/main.py`)
|
||||||
|
|
||||||
|
Beyond the page routes, the JSON API endpoints are:
|
||||||
|
|
||||||
|
| Method | Path | Purpose |
|
||||||
|
|--------|------|---------|
|
||||||
|
| `POST` | `/api/reboot` | Reboot a single AP; CSRF-validated |
|
||||||
|
| `POST` | `/api/reboot-bulk` | Reboot multiple APs; CSRF-validated |
|
||||||
|
| `GET` | `/api/ap-clients` | `?mac=&site_key=` — clients connected to one AP |
|
||||||
|
| `GET` | `/api/all-clients` | All clients across all sites, keyed by AP MAC |
|
||||||
|
| `GET` | `/health` | Docker healthcheck |
|
||||||
|
| `GET` | `/debug/sites` | Lists accessible Omada sites (diagnostic) |
|
||||||
|
|
||||||
### Authentication (`app/auth.py`)
|
### Authentication (`app/auth.py`)
|
||||||
|
|
||||||
@@ -59,12 +73,21 @@ Authentik OIDC Authorization Code Flow. The JWT `id_token` is decoded **without
|
|||||||
|
|
||||||
`AUTH_DISABLED=true` injects a hardcoded `DEV_USER` on `/auth/login` — no Authentik required.
|
`AUTH_DISABLED=true` injects a hardcoded `DEV_USER` on `/auth/login` — no Authentik required.
|
||||||
|
|
||||||
All POST API endpoints (`/api/reboot`, `/api/reboot-bulk`) validate a CSRF token stored in the session and echoed in the JSON request body.
|
All POST API endpoints validate a CSRF token stored in the session and echoed in the JSON request body.
|
||||||
|
|
||||||
### Database (`app/database.py`)
|
### Database (`app/database.py`)
|
||||||
|
|
||||||
Single table `reboot_log` written on every reboot attempt (success and error). `DB_PATH` defaults to `/data/audit.db` (Docker volume mount). Override to `./audit.db` for local dev.
|
Single table `reboot_log` written on every reboot attempt (success and error). `DB_PATH` defaults to `/data/audit.db` (Docker volume mount). Override to `./audit.db` for local dev.
|
||||||
|
|
||||||
|
### Frontend (`app/templates/index.html`)
|
||||||
|
|
||||||
|
Key client-side behaviours to be aware of when editing:
|
||||||
|
|
||||||
|
- **Reboot locking**: `lockApRow(mac)` disables the row button and checkbox immediately on confirm — button text transitions `Rebooting… → Rebooted / Failed` and stays disabled for the session.
|
||||||
|
- **Clients popup**: clicking an AP name cell fires `openClientsModal()`, which calls `/api/ap-clients` and renders a modal table sorted by IP. Uses the same `ipToNum()` helper as the column sort.
|
||||||
|
- **IP range filter** ("Filter .150–.155"): fetches `/api/ap-clients` for every AP in parallel via `Promise.all`, retains only APs where a connected client IP has last octet 150–155. Result is cached in `ipMatchedMacs` (a `Set`) for the session.
|
||||||
|
- **Column sort**: Name, Site, IP Address headers are clickable. `ipToNum()` is used for numeric IP comparison. Default sort on load is by Name (triggered by programmatic `.click()` on the Name header). Both the text filter and the IP range filter compose with the sort via a shared `applyFilters()` function.
|
||||||
|
|
||||||
### Deployment
|
### Deployment
|
||||||
|
|
||||||
- Docker exposes port `8080`; `docker-compose.yml` maps it to host port `8098`.
|
- Docker exposes port `8080`; `docker-compose.yml` maps it to host port `8098`.
|
||||||
|
|||||||
Reference in New Issue
Block a user