feat: auth-aware UI and role-based access control #67

Merged
TheFurya merged 10 commits from feature/auth-aware-ui-and-role-based-access-control into develop 2026-03-21 11:44:07 +01:00
Owner

Summary

  • Add is_admin column to users table with Alembic migration and a require_admin FastAPI dependency that protects all admin-facing write endpoints (games, pokemon, evolutions, bosses, routes CRUD)
  • Expose admin status to frontend via user API and update AuthContext to fetch/store isAdmin after login
  • Make navigation menu auth-aware (different links for logged-out, logged-in, and admin users) and protect frontend routes with ProtectedRoute and AdminRoute components, preserving deep-linking through redirects
  • Fix test reliability: drop_all before create_all to clear stale PostgreSQL enums from interrupted test runs
  • Fix test auth: add admin_client fixture and use valid UUID for mock user so tests pass with new admin-protected endpoints

Test plan

  • All 252 backend tests pass
  • Verify non-admin users cannot access admin write endpoints (games, pokemon, evolutions, bosses CRUD)
  • Verify admin users can access admin endpoints normally
  • Verify navigation shows correct links for logged-out, logged-in, and admin states
  • Verify /admin/* routes redirect non-admin users with a toast
  • Verify /runs/new and /genlockes/new redirect unauthenticated users to login, then back after auth

🤖 Generated with Claude Code

## Summary - Add `is_admin` column to users table with Alembic migration and a `require_admin` FastAPI dependency that protects all admin-facing write endpoints (games, pokemon, evolutions, bosses, routes CRUD) - Expose admin status to frontend via user API and update AuthContext to fetch/store `isAdmin` after login - Make navigation menu auth-aware (different links for logged-out, logged-in, and admin users) and protect frontend routes with `ProtectedRoute` and `AdminRoute` components, preserving deep-linking through redirects - Fix test reliability: `drop_all` before `create_all` to clear stale PostgreSQL enums from interrupted test runs - Fix test auth: add `admin_client` fixture and use valid UUID for mock user so tests pass with new admin-protected endpoints ## Test plan - [x] All 252 backend tests pass - [x] Verify non-admin users cannot access admin write endpoints (games, pokemon, evolutions, bosses CRUD) - [x] Verify admin users can access admin endpoints normally - [x] Verify navigation shows correct links for logged-out, logged-in, and admin states - [x] Verify `/admin/*` routes redirect non-admin users with a toast - [x] Verify `/runs/new` and `/genlockes/new` redirect unauthenticated users to login, then back after auth 🤖 Generated with [Claude Code](https://claude.com/claude-code)
TheFurya added 8 commits 2026-03-21 11:31:36 +01:00
Add `is_admin` boolean column (default false) via Alembic migration
for role-based access control.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add require_admin FastAPI dependency that checks is_admin column on users
table. Apply it to all admin-facing write endpoints (games, pokemon,
evolutions, bosses, routes CRUD). Run-scoped endpoints remain protected
by require_auth only since they manage user's own data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add is_admin field to UserResponse schema and update AuthContext to
fetch user profile after login, storing and exposing isAdmin boolean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap /runs/new and /genlockes/new with ProtectedRoute (requires login)
- Create AdminRoute component that checks isAdmin, redirects non-admins
  with a toast notification
- Wrap all /admin/* routes with AdminRoute
- Deep-linking preserved: unauthenticated users redirect to login, then
  back to the original protected route after auth

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Navigation links now change based on authentication state:
- Logged out: Home, Runs, Genlockes, Stats
- Logged in: New Run, My Runs, Genlockes, Stats
- Admin: adds Admin link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The frontend needs to know if the current user is an admin so it can show/hide the Admin nav link and protect admin routes client-side.

Bean: nuzlocke-tracker-5svj

chore: Update beans
If a previous test run was interrupted before teardown, PostgreSQL enum
types persist with stale values, causing create_all to fail. Adding
drop_all first ensures a clean slate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chore: update bean
Some checks failed
CI / backend-tests (pull_request) Failing after 32s
CI / frontend-tests (pull_request) Failing after 29s
afd1c2543a
TheFurya added 1 commit 2026-03-21 11:39:48 +01:00
fix(tests): use admin_client for admin-protected endpoints
Some checks failed
CI / backend-tests (pull_request) Successful in 26s
CI / frontend-tests (pull_request) Failing after 29s
c17e776408
After adding require_admin to admin endpoints, tests using
unauthenticated client or auth_client got 401/403. Also fix mock user
ID to be a valid UUID (was "test-user-123", now a proper UUID4).

- Add admin_override and admin_client fixtures to conftest
- Update test_pokemon.py, test_games.py, test_genlocke_boss.py to use
  admin_client for write operations on admin endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TheFurya added 1 commit 2026-03-21 11:42:27 +01:00
fix(tests): mock useAuth in Layout tests for auth-aware navigation
All checks were successful
CI / backend-tests (pull_request) Successful in 28s
CI / frontend-tests (pull_request) Successful in 32s
533f0cad4a
Layout now renders different nav links based on auth state. Tests were
using a real AuthProvider which resolved to no user, causing them to
look for "My Runs" and "Admin" links that only appear when logged in.

Mock useAuth to test both logged-out and logged-in-as-admin states.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TheFurya merged commit e8ded9184b into develop 2026-03-21 11:44:07 +01:00
TheFurya deleted branch feature/auth-aware-ui-and-role-based-access-control 2026-03-21 11:44:08 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: pokemon/nuzlocke-tracker#67