feat(auth): add admin user management dashboard

- Add UserProfile model (app/models.py) with per-user settings: display_name, daily_upload_limit, notes, is_blocked
- Add Alembic migration 013_add_user_profiles for the new table
- Add REST API at /api/admin/users/ with list, get, upsert (PUT), delete endpoints (admin-only)
- Add HTML template admin_users.html with Alpine.js: filterable user list, paginated table, edit/create modal, delete confirmation modal
- Add view handler at /admin/users (admin-only redirect guard)
- Register routers in app/api/__init__.py and app/views/__init__.py
- Add 'Users' link to admin nav dropdown in base.html (desktop + mobile)
- Add 27 tests covering auth, list, get, upsert, delete, and model constraints
- Register UserProfile in conftest.py model imports
- Document new endpoints in docs/API.md

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-06 13:45:35 +00:00
parent 4cf93dc16e
commit 56f7f2351f
11 changed files with 1508 additions and 1 deletions
+84
View File
@@ -728,6 +728,90 @@ curl "http://<your-instance>/api/users/search?q=risti&limit=5"
---
### Admin User Management
**Admin only.** These endpoints let administrators list all known users, view per-user statistics,
and manage per-user settings such as custom upload limits, display names, and blocked status.
---
**GET** `/api/admin/users/`
List all known users — anyone who has uploaded a document or has an explicit profile.
Returns aggregate document statistics merged with profile data.
**Query Parameters**:
- `q` (optional): Substring filter on user ID (case-insensitive)
- `page` (optional): Page number (default: 1)
- `per_page` (optional): Items per page (default: 25, max: 100)
```bash
curl "http://<your-instance>/api/admin/users/" \
-H "Cookie: session=<admin-session>"
```
**Response**:
```json
{
"users": [
{
"user_id": "alice@example.com",
"display_name": "Alice Smith",
"daily_upload_limit": 50,
"notes": null,
"is_blocked": false,
"profile_id": 1,
"document_count": 42,
"last_upload": "2026-02-15T10:23:00"
}
],
"total": 1,
"page": 1,
"per_page": 25,
"pages": 1
}
```
---
**GET** `/api/admin/users/{user_id}`
Return profile and document statistics for a specific user.
```bash
curl "http://<your-instance>/api/admin/users/alice%40example.com"
```
---
**PUT** `/api/admin/users/{user_id}`
Create or update the admin-managed profile for a user. If no profile exists one is created.
**Request body**:
```json
{
"display_name": "Alice Smith",
"daily_upload_limit": 50,
"notes": "VIP customer",
"is_blocked": false
}
```
- `display_name` (optional): Human-readable name shown in the admin UI
- `daily_upload_limit` (optional): Per-user daily cap; `null` = use global default; `0` = unlimited
- `notes` (optional): Admin-only text notes
- `is_blocked`: When `true`, blocks new uploads from this user
---
**DELETE** `/api/admin/users/{user_id}`
Delete the admin-managed profile for a user. Documents owned by the user are **not** removed.
Returns `204 No Content` on success, `404` if no profile exists.
---
### Settings Suggestions (Autocomplete)
**GET** `/api/settings/{key}/suggestions`