Add Groups management and split Admin navigation

- New backend: Group + GroupMembership models, schemas, CRUD router at
  /api/admin/groups (list, create, get detail, update, delete, add/remove members)
- New Alembic migration: groups and group_memberships tables
- Frontend: Admin sidebar item is now an expandable accordion with
  Users and Groups sub-items; AdminPage redirects to /admin/users;
  new AdminUsersPage and AdminGroupsPage with inline member management panel
- API client: 7 new group functions + TypeScript types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-17 20:49:54 +02:00
parent 2bb1e03adf
commit 4e9ed97b05
15 changed files with 1035 additions and 191 deletions
+26 -6
View File
@@ -18,7 +18,9 @@ All API calls go through `src/api/client.ts` (single Axios instance, JWT injecte
| `/apps/documents` | `DocumentsPage` | Required |
| `/apps/documents/settings/admin` | `DocumentAdminSettingsPage` | Admin only |
| `/apps/ai/settings/admin` | `AIAdminSettingsPage` | Admin only |
| `/admin` | `AdminPage` | Admin only |
| `/admin` | `AdminPage` (redirects to `/admin/users`) | Admin only |
| `/admin/users` | `AdminUsersPage` | Admin only |
| `/admin/groups` | `AdminGroupsPage` | Admin only |
| `/profile` | `ProfilePage` | Required |
`PrivateRoute` redirects to `/login` when no token. `AdminRoute` redirects to `/` when not admin.
@@ -90,10 +92,20 @@ Cards are rendered dynamically from `GET /api/services` (polled every 30 s via T
- Upload Limits section only (max PDF size in MB)
- Save button
### Admin page (`/admin`)
### Admin — Users page (`/admin/users`)
- User list with role and active status
- Inline role/status editing
- Inline active status toggle
- Create user form (email, name, password, admin flag)
- Delete user
### Admin — Groups page (`/admin/groups`)
- Group list with name, description, member count
- Create group (name, optional description)
- Edit group name / description inline panel
- Delete group (with confirmation)
- Expand group row to manage members: view members, remove members, add non-members from dropdown
### Profile page (`/profile`)
@@ -123,6 +135,13 @@ Key functions:
| `updateAISettings(data)` | `PATCH /settings/ai` |
| `testAIConnection()` | `POST /settings/ai/test` |
| `getDocumentLimits()` | `GET /settings/documents/limits` |
| `adminListGroups()` | `GET /admin/groups` |
| `adminCreateGroup(data)` | `POST /admin/groups` |
| `adminGetGroup(id)` | `GET /admin/groups/{id}` with members |
| `adminUpdateGroup(id, data)` | `PATCH /admin/groups/{id}` |
| `adminDeleteGroup(id)` | `DELETE /admin/groups/{id}` |
| `adminAddGroupMember(gId, uId)` | `POST /admin/groups/{gId}/members/{uId}` |
| `adminRemoveGroupMember(gId, uId)` | `DELETE /admin/groups/{gId}/members/{uId}` |
| `updateDocumentLimits(data)` | `PATCH /settings/documents/limits` |
---
@@ -150,7 +169,7 @@ Key functions:
- **JWT in `localStorage`** — XSS risk; migrate to `httpOnly` cookie when backend supports it
- **No toast / notification system** — errors shown inline; success is silent
- **No loading skeletons** — "Loading…" text only
- **No group/sharing UI** — blocked on backend groups system
- **No app permission UI** per group — groups exist but permission grants are not yet implemented
- **No app permission UI** — all apps visible to all authenticated users
---
@@ -165,7 +184,8 @@ Key functions:
- [ ] `POST /queue/jobs` integration — show AI processing queue status / progress per document
- [ ] Re-process document button (`POST /documents/{id}/reprocess` — needs backend endpoint first)
- [ ] Advanced filter: extracted data fields (vendor, due date, amount) — needs backend support
- [ ] Groups + document sharing UI — blocked on backend
- [ ] App permissions UI in Admin page
- [x] Groups admin UI — list, create, edit, delete, add/remove members
- [ ] App permissions UI per group (blocked on backend group_app_permissions)
- [ ] Document sharing UI (blocked on backend)
- [ ] `httpOnly` cookie auth (requires backend change)
- [ ] Bulk document operations (select multiple, bulk delete / bulk categorise)