forked from retoor/devplacepy
feat: add admin/internal database API with CRUD, read-only query, and natural-language SQL endpoints
Add a new `/dbapi` router package providing a generic database API over `dataset`, restricted to admin sessions, admin API keys, and the internal gateway key. Includes: - `tables.py`: list all tables and inspect table schemas - `crud.py`: full CRUD operations (GET, POST, PATCH, DELETE) with soft-delete awareness, born-live inserts, `?include_deleted`, `.../restore`, and `?hard=true` purge - `query.py`: validated read-only SELECT execution via sqlglot parsing, classification, and EXPLAIN dry-run; async query jobs with WebSocket streaming via `DbApiJobService` - `nl.py`: natural-language-to-SQL conversion using the platform AI gateway with re-prompting until validation passes Also register `DbApiJobService` and `PubSubService` in the service manager, add `DBAPI_DIR` to config data paths, and force cleartext `http://` connections to HTTP/1.1 in `curl_transport` to fix large request failures against uvicorn's HTTP/1.1-only internal gateway.
This commit is contained in:
@@ -697,6 +697,20 @@ Removing a record is a **soft delete**, not a physical one: it stamps `deleted_a
|
||||
|
||||
A member may delete only their own content, but an **administrator may delete any member's** post, comment, gist, project, project file, or attachment - the owner-or-admin check lives on each delete endpoint, so it applies equally to the web UI and to the Devii assistant (which acts purely through the platform API as the signed-in user). When an admin's Devii is asked to delete something it requires explicit confirmation before each deletion, and the result is the same soft delete, restorable from Trash.
|
||||
|
||||
### Database API (`/dbapi`, admin or internal only)
|
||||
|
||||
An administrator (session or admin API key) or an internal service (the gateway internal key) can read and update any table through a single, safe API; members and guests get `403`.
|
||||
|
||||
- **CRUD per table:** `GET /dbapi/{table}` (filtered, searchable, keyset pagination), `GET /dbapi/{table}/{key}/{value}`, `POST /dbapi/{table}`, `PATCH /dbapi/{table}/{key}/{value}`, `DELETE /dbapi/{table}/{key}/{value}` (soft delete, `?hard=true` to purge), and `.../restore`. Inserts are born-live; unknown columns are rejected; deny-listed tables (sessions, password resets) are never exposed.
|
||||
- **`query()` is read-only:** `POST /dbapi/query` runs a single validated SELECT and returns rows. Every query is parsed (sqlglot), classified, and dry-run with `EXPLAIN` on a read-only connection before execution; non-SELECT statements are refused and a SELECT with no WHERE/JOIN/LIMIT is flagged as suspicious. All writes go through the structured CRUD, never raw SQL.
|
||||
- **Ask in plain language:** `POST /dbapi/nl` turns a question such as *"all users registered longer than three days"* into a validated SELECT (auto-adding `deleted_at IS NULL` for soft-delete tables), using the platform AI gateway and re-prompting until the SQL validates; pass `execute=true` to also run it.
|
||||
- **Async:** `POST /dbapi/query/async` runs a heavy query off the request path and streams progress over `WS /dbapi/query/{uid}/ws`.
|
||||
- The Devii assistant exposes the same capability to administrators, with every insert/update/delete requiring explicit confirmation.
|
||||
|
||||
### Pub/Sub bus (`/pubsub`)
|
||||
|
||||
A database-free publish/subscribe bus for live updates without polling. Clients connect to `WS /pubsub/ws` to subscribe to topics (with `foo.*` wildcards) and publish messages; backends and administrators can also publish over `POST /pubsub/publish`. Users may use their own `user.{uid}.*` namespace and subscribe to shared `public.*` topics; administrators and internal services may use any topic. The browser client is available as `app.pubsub.subscribe(topic, cb)` / `app.pubsub.publish(topic, data)`. The bus is in-memory and best-effort by design.
|
||||
|
||||
## Testing
|
||||
|
||||
- **932 tests** split into three tiers under `tests/`: `unit/` (pure in-process), `api/` (HTTP integration against the live server), and `e2e/` (Playwright browser)
|
||||
|
||||
Reference in New Issue
Block a user