feat: platform admin dashboard - #79
Merged
Merged
Conversation
…keeping the invite flow dormant
…he computed style
…rack still references
…lear the option highlight when hovering the footer
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
🚅 Deployed to the nexus-pr-79 environment in nexus
|
ethnjs
marked this pull request as ready for review
September 17, 2026 05:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A platform-admin dashboard: accounts, tournaments, and the university/event catalog, each as a real table instead of psql. Admins get inline editing, bulk-safe row actions, and a toast on every change instead of a silent success or a stack trace.
Along the way: an admin can no longer demote, deactivate, or delete their own account through the admin routes, and a handful of pre-existing bugs surfaced by building this got fixed in place.
Closes #78
What changed
Backend
Schemas and routes
AdminTournamentRead(schemas/tournament/__init__.py) — the platform-admin audience gets the owner's name and event/volunteer counts; member-facingTournamentReadis untouched.POST /admin/users/{user_id}/password-reset/— sends the same email the public forgot-password flow sends, but reports real errors (400/429/500) instead of the enumeration-safe generic 200, since the caller already knows who the user is.AdminRegisterRequest,POST /admin/auth/register/, andPOST /admin/auth/account-setup/resend/— dead code for an invite flow that's been dormant since nothing mints anaccount_setuptoken; deleting from the API surface it was actually reachable through.DELETE /universities/{id}/now also 409s when a tournament track still references it. (fix — previously only chapters and users were checked, so deleting a university that only a track pointed at nulled the track'suniversity_idand left it satisfying neither the university-or-location invariant, which failed as a 500 later.)Logic
PATCH /admin/users/{id}/revokes sessions on any move offstatus="active", not just"locked". (fix — deactivating a user used to leave their existing sessions live.)"active"through this route — both are irreversible from the caller's side. Self-deactivation still exists atPOST /users/me/deactivate/, password-confirmed.DELETE /admin/users/{id}/;DELETE /users/me/is the intended path, also password-confirmed.DELETE /tournaments/{id}/now lets an admin delete an archived tournament; the owner-facing 403 against deleting archived tournaments is unchanged. (fix — admin cleanup couldn't reach anything once it was archived.)Frontend
Admin dashboard
/dashboard/adminsection: flat admin rail (AdminSidebar), sharing the generic sidebar extracted out for it.admin/users) — role/status inline edit,AdminUserPanelprofile side panel opens from anywhere in the row, step arrows between rows, admin-triggered password reset.admin/tournaments) — owner, event/volunteer counts, one season picker replacing separate event tabs, with staged season adds.admin/universities) — inline editing,NewUniversityModal.admin/events) — events/categories,CategoriesModal,NewEventModal, season grid.AccountBadgesand a header badges slot (ProfileHeader) surface admin account state (role, status) on the profile page itself, so an admin viewing any member's profile sees it without cross-referencing the accounts table.useActionToast— every admin action reports its outcome (success or the server's error message) instead of failing silently.ConfirmModalfor destructive row actions.Shared UI fixes
Inputmerges a caller'sstyleprop into the computed style instead of letting it replace the whole object. (fix — passingstyleused to wipe border, height, padding, background, and font along with whatever the caller actually meant to override.)Dropdownfooter padding now matches the option rows, and hovering the footer clears the option highlight instead of leaving a stale one lit.formatDatesputs the year on each run instead of hoisting one to the end, when a tournament's days cross a year boundary. (fix — a state tournament with quals in Sept and finals the next April was silently mislabeling every day outside the hoisted year.)Out of scope
User.status="invited") — only its unreachable admin routes were removed here; re-enabling it is a separate piece of work.Test plan
pytestpasses locallyAutomated
test_users.py— self-demote/deactivate/delete guards, session revocation on any non-active status, admin password-reset (success, no-password 400, propagated errors).test_universities.py— delete blocked by a referencing track.tournament/test_admin.py—AdminTournamentReadshape, owner/count fields.tournament/test_core.py— admin can delete an archived tournament.test_auth.py— removed coverage for the deleted admin-register/resend routes.Manual
styleoverride into a fewInputusages — border/height/padding intact.