Added a link to the admin user's menu for the admin dashboard #542
No reviewers
Labels
No labels
Kestra
bug
enhancement
someday
subtask
☁️ api
🎛️ infrastructure
🐞 sentry
📆 2025 Season
📝 pages
allpicks
📝 pages
picks
📝 pages
standings
🚀 performance
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
johnsturgeon/tgfp-web!542
Loading…
Reference in a new issue
No description provided.
Delete branch "add-an-admin-only-link-to-the-nav-535"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Just stubbed out the dashboard page for now, added the route, and the 'auth'
Also moved awards_for_week to be next the the other 'for_week' methods
Created a common property for is_admin
Summary
This is a small, well-scoped change: it introduces a
Player.is_adminproperty, routes the admin check (template +require_admin) through it, cachesConfig.get_config(), stubs a/v3/adminroute with a nav link, and relocatesawards_for_week. The refactor is clean and behavior-preserving; the main gaps are test coverage for the new admin path and a couple of minor consistency/layering notes.Worth fixing
/v3/adminroute orrequire_adminon the v3 side (app/routers/v3.py:222,app/models/player.py:156). The codebase otherwise tests admin gating carefully (tests/test_admin_player_routes.py,tests/test_admin_email_routes.pystand up a signed-in admin against the v2 routes), so the new route is a coverage gap by local convention. A minimal test that a non-admin gets403and the admin gets200on/v3/admin, plus a directis_admintrue/false case intests/test_player_model.py, would match the existing bar.is_adminis only exercised indirectly through the unchanged v2 admin routes today.Nits
Config.get_config()is now permanently memoized (app/config/config.py:77-79). This is the stated intent ("never read.envafter startup"), and it also makes every module'sconfigthe same instance instead of independent copies — a net consistency win. Worth being aware that any future test wanting to re-read the environment mid-process can no longer do so viaget_config()(existing tests correctly mutate the shared instance throughmonkeypatch.setattr, e.g.tests/test_mailer.py:47-49, which still works). The@classmethodover@cacheordering is correct.is_adminis a case-sensitive email comparison (app/models/player.py:158) whilePlayer.by_emaildeliberately compares case-insensitively and notes emails can differ only by case (app/models/player.py:186-199). This is not a regression — the old template andrequire_adminboth used exact==— but if an admin ever signs up with differently-cased mail thanTGFP_ADMIN_EMAIL, the gate silently fails closed. Considerself.email.lower() == Config.get_config().TGFP_ADMIN_EMAIL.lower()for consistency.app/models/player.pynow importsapp.configat module top level, makingplayer.pythe only model with a direct config dependency. Becauseget_config()is cached (and already warmed at import in a dozen places), theis_adminattribute access won't do blocking work per request, so it doesn't trip the spirit of theapp/modelslayering guard intests/test_integrity.py(which only forbids the Tank01 provider). Fine as-is; just flagging the new coupling.app/templates/v3/admin.htmlhas no trailing newline and a stray double space in theclassattribute (text-stone-600 pb-4). Cosmetic.