Implement backend and frontend endpoints to create, read, update, and delete admin users. Includes validation to ensure at least one admin always exists to prevent lockouts. All endpoints are secured so only existing admins can modify the admin list.
Changes (17 files, +1402 / -32)
Backend
New: backend/app/api/users.py — Admin user management CRUD endpoints:
GET /api/admin/users — List all admin users
POST /api/admin/users — Create new admin with hashed password + admin role
PUT /api/admin/users/{id} — Update admin display name
Modified: backend/app/user_models.py — Role model + user_roles association table for multi-admin support. New is_admin_effective property checks both legacy is_admin flag and role-based admin.
Modified: backend/app/main.py — Register new /api/admin/users router + bootstrap admin user on startup
New: backend/migrate_roles.py — Migration script for roles + user_roles tables
Frontend
New: src/app/interfaces/admin-user.ts — AdminUser TypeScript interface New: src/app/services/admin-user.service.ts — HTTP client for admin user CRUD New: src/app/admin/admin-users-tab.component.* — Admin Users tab with list + add/delete UI Modified: src/app/admin/admin.component.* — Wire Admin Users tab into admin dashboard
Tests
10 new tests in test_admin_users.py (CRUD endpoints + auth guard) 23 new tests in test_admin_login.py (conditional bootstrap login scenarios) 15 new tests in test_user_models.py (role model + is_admin_effective)
Total: 140 tests pass (all existing + new)
Security
All admin endpoints protected by get_current_admin_user dependency (JWT + DB verification)
Password hashing with bcrypt
Self-deletion blocked
Last-admin-deletion blocked (prevents lockouts)
Bootstrap credentials disabled once admins exist in the DB
## Summary
Implement backend and frontend endpoints to create, read, update, and delete admin users. Includes validation to ensure at least one admin always exists to prevent lockouts. All endpoints are secured so only existing admins can modify the admin list.
## Changes (17 files, +1402 / -32)
### Backend
**New: `backend/app/api/users.py`** — Admin user management CRUD endpoints:
- `GET /api/admin/users` — List all admin users
- `POST /api/admin/users` — Create new admin with hashed password + admin role
- `PUT /api/admin/users/{id}` — Update admin display name
- `DELETE /api/admin/users/{id}` — Delete admin (self-deletion blocked, last-admin blocked)
**Modified: `backend/app/user_models.py`** — Role model + user_roles association table for multi-admin support. New `is_admin_effective` property checks both legacy `is_admin` flag and role-based admin.
**Modified: `backend/app/api/auth.py`** — Conditional bootstrap login:
- No admins exist → bootstrap creds accepted, first admin auto-provisioned
- Admins exist → bootstrap creds rejected (403), normal password login required
**Modified: `backend/app/auth.py`** — `get_current_admin_user` checks `is_admin_effective` (legacy + role-based)
**Modified: `backend/app/main.py`** — Register new `/api/admin/users` router + bootstrap admin user on startup
**New: `backend/migrate_roles.py`** — Migration script for roles + user_roles tables
### Frontend
**New: `src/app/interfaces/admin-user.ts`** — AdminUser TypeScript interface
**New: `src/app/services/admin-user.service.ts`** — HTTP client for admin user CRUD
**New: `src/app/admin/admin-users-tab.component.*`** — Admin Users tab with list + add/delete UI
**Modified: `src/app/admin/admin.component.*`** — Wire Admin Users tab into admin dashboard
### Tests
**10 new tests** in `test_admin_users.py` (CRUD endpoints + auth guard)
**23 new tests** in `test_admin_login.py` (conditional bootstrap login scenarios)
**15 new tests** in `test_user_models.py` (role model + is_admin_effective)
**Total: 140 tests pass** (all existing + new)
## Security
- All admin endpoints protected by `get_current_admin_user` dependency (JWT + DB verification)
- Password hashing with bcrypt
- Self-deletion blocked
- Last-admin-deletion blocked (prevents lockouts)
- Bootstrap credentials disabled once admins exist in the DB
- Add Role model and user_roles association table (many-to-many)
- Add password_hash column to User model (nullable, for future bcrypt)
- Keep is_admin boolean for backward compatibility
- Add is_admin_effective property: true if legacy is_admin OR 'admin' role
- Update auth dependency (get_current_admin_user) to use is_admin_effective
- Update bootstrap login to auto-create 'admin' role and assign on login
- Update Google OAuth login to use is_admin_effective for token creation
- Add migrate_roles.py: idempotent migration script to backfill roles
- Add unit tests for Role, User, association table, and is_admin_effective
Backend:
- /api/admin/users: GET list, POST create, PUT update, DELETE
- Admin users can be added with email, display name, and password
- Self-deletion and last-admin deletion are blocked
- Admin role auto-assigned on creation
Frontend:
- AdminUsersTabComponent: list + add/delete admin users
- AdminUserService: HTTP client for admin user CRUD
- AdminUser interface
- 'Admins' tab added to admin dashboard
Tests:
- 10 new tests for admin user management endpoints
- 140 total tests pass (130 original + 10 new)
The previous check counted ALL users (func.count(User.id)), which
incorrectly blocked bootstrap login if any non-admin user (e.g.,
Google OAuth sign-in) already existed. The fix queries specifically
for admin users using the legacy is_admin flag OR the admin role
assignment in user_roles.
Also add tests for the non-admin-user-only scenario and fix the
stale test_non_admin_user_cannot_login_as_admin assertion (401
not 403 — bootstrap path is still active when no admin exists).
Building for docker deployment calls npx ng build --configuration production which is currently failing with an error.
fix the CI-CD pipe to catch this error. but don't worry about actually fixing the error - fix the ci/cd pipe to capture this scenario.
Building for docker deployment calls `npx ng build --configuration production` which is currently failing with an error.
1. fix the CI-CD pipe to catch this error. but don't worry about actually fixing the error - fix the ci/cd pipe to capture this scenario.
- Add 'frontend-build' job that runs 'npx ng build --configuration production'
- Wire frontend-build into quality-gate dependencies
- Include feature/multi-admin-roles in CI push branches
- Build failures now fail the pipeline instead of being silently missed
Fixed the CI/CD pipeline to catch Angular production build failures.
Changes:
Added a new frontend-build CI job that runs npx ng build --configuration production after npm ci
Wired frontend-build into the quality-gate job dependencies so the pipeline fails if the build does not compile
Added feature/multi-admin-roles to the CI push branches so this branch triggers the pipeline
The build step does NOT have || true — failures will now fail the pipeline and surface the exact Angular compiler error. The actual build error itself was not fixed, as requested.
Fixed the CI/CD pipeline to catch Angular production build failures.
**Changes:**
- Added a new `frontend-build` CI job that runs `npx ng build --configuration production` after `npm ci`
- Wired `frontend-build` into the `quality-gate` job dependencies so the pipeline fails if the build does not compile
- Added `feature/multi-admin-roles` to the CI push branches so this branch triggers the pipeline
The build step does NOT have `|| true` — failures will now fail the pipeline and surface the exact Angular compiler error. The actual build error itself was not fixed, as requested.
Some required checks failed
CI Pipeline / backend-test (push) Successful in 7m58s
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Implement backend and frontend endpoints to create, read, update, and delete admin users. Includes validation to ensure at least one admin always exists to prevent lockouts. All endpoints are secured so only existing admins can modify the admin list.
Changes (17 files, +1402 / -32)
Backend
New:
backend/app/api/users.py— Admin user management CRUD endpoints:GET /api/admin/users— List all admin usersPOST /api/admin/users— Create new admin with hashed password + admin rolePUT /api/admin/users/{id}— Update admin display nameDELETE /api/admin/users/{id}— Delete admin (self-deletion blocked, last-admin blocked)Modified:
backend/app/user_models.py— Role model + user_roles association table for multi-admin support. Newis_admin_effectiveproperty checks both legacyis_adminflag and role-based admin.Modified:
backend/app/api/auth.py— Conditional bootstrap login:Modified:
backend/app/auth.py—get_current_admin_userchecksis_admin_effective(legacy + role-based)Modified:
backend/app/main.py— Register new/api/admin/usersrouter + bootstrap admin user on startupNew:
backend/migrate_roles.py— Migration script for roles + user_roles tablesFrontend
New:
src/app/interfaces/admin-user.ts— AdminUser TypeScript interfaceNew:
src/app/services/admin-user.service.ts— HTTP client for admin user CRUDNew:
src/app/admin/admin-users-tab.component.*— Admin Users tab with list + add/delete UIModified:
src/app/admin/admin.component.*— Wire Admin Users tab into admin dashboardTests
10 new tests in
test_admin_users.py(CRUD endpoints + auth guard)23 new tests in
test_admin_login.py(conditional bootstrap login scenarios)15 new tests in
test_user_models.py(role model + is_admin_effective)Total: 140 tests pass (all existing + new)
Security
get_current_admin_userdependency (JWT + DB verification)Building for docker deployment calls
npx ng build --configuration productionwhich is currently failing with an error.Fixed the CI/CD pipeline to catch Angular production build failures.
Changes:
frontend-buildCI job that runsnpx ng build --configuration productionafternpm cifrontend-buildinto thequality-gatejob dependencies so the pipeline fails if the build does not compilefeature/multi-admin-rolesto the CI push branches so this branch triggers the pipelineThe build step does NOT have
|| true— failures will now fail the pipeline and surface the exact Angular compiler error. The actual build error itself was not fixed, as requested.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.