mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-08-26 17:31:37 +00:00
decouple: add /api/auth/whoami to navi-admin (preparing recon migration)
PR-A of the 2-PR whoami migration. Net-new, additive endpoint in navi-admin
matching recon's existing handler shape exactly. Recon's handler stays live in
this PR; once nginx routes /api/auth/whoami to :8427 (out-of-band) and recon's
handler is removed (PR-B), navi-admin is the sole owner.
- New services/navi_admin/auth_route.py with its own blueprint (navi_admin_auth):
GET /api/auth/whoami reads X-Authentik-Username, returns {authenticated,
username}. NOT @require_auth — it's the "am I logged in?" check, must answer
the unauthenticated case (mirrors recon).
- app.py: register the new blueprint (2 lines).
- test_auth.py: header-present + header-absent cases.
Kept in its own blueprint/file so admin_route.py's "all routes @require_auth"
invariant stays true. recon and nginx untouched (additive only).
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
767818b88e
commit
05b614a22f
3 changed files with 46 additions and 0 deletions
|
|
@ -10,6 +10,7 @@ from flask import Flask
|
|||
from shared.git_sha import git_short_sha
|
||||
|
||||
from . import admin_route
|
||||
from . import auth_route
|
||||
|
||||
|
||||
def create_app():
|
||||
|
|
@ -35,4 +36,5 @@ def create_app():
|
|||
return response
|
||||
|
||||
app.register_blueprint(admin_route.bp)
|
||||
app.register_blueprint(auth_route.bp)
|
||||
return app
|
||||
|
|
|
|||
22
backend/services/navi_admin/auth_route.py
Normal file
22
backend/services/navi_admin/auth_route.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"""navi-admin auth-state route.
|
||||
|
||||
GET /api/auth/whoami the caller's Authentik auth state, for the frontend
|
||||
|
||||
Ungated by design: this is the "am I logged in?" check, so it must answer even
|
||||
when unauthenticated (no ``@require_auth``). Behind Caddy's forward_auth the
|
||||
``X-Authentik-Username`` header is present iff the caller is authenticated;
|
||||
this mirrors the handler recon served before the navi-recon decoupling.
|
||||
"""
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
bp = Blueprint('navi_admin_auth', __name__)
|
||||
|
||||
|
||||
@bp.route('/api/auth/whoami')
|
||||
def auth_whoami():
|
||||
"""Return the caller's auth state. Behind forward_auth, so the header is
|
||||
present when authenticated; absent → the unauthenticated response (not 401)."""
|
||||
username = request.headers.get('X-Authentik-Username')
|
||||
if username:
|
||||
return jsonify({'authenticated': True, 'username': username})
|
||||
return jsonify({'authenticated': False, 'username': None})
|
||||
22
backend/services/navi_admin/tests/test_auth.py
Normal file
22
backend/services/navi_admin/tests/test_auth.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
"""Hermetic tests for navi-admin's /api/auth/whoami auth-state endpoint.
|
||||
|
||||
Mirrors the handler recon served pre-decoupling: reads X-Authentik-Username,
|
||||
returns {authenticated, username}, never 401 (ungated by design).
|
||||
"""
|
||||
from services.navi_admin.app import create_app
|
||||
|
||||
|
||||
def _client():
|
||||
return create_app().test_client()
|
||||
|
||||
|
||||
def test_whoami_header_present():
|
||||
resp = _client().get('/api/auth/whoami', headers={'X-Authentik-Username': 'matt'})
|
||||
assert resp.status_code == 200
|
||||
assert resp.get_json() == {'authenticated': True, 'username': 'matt'}
|
||||
|
||||
|
||||
def test_whoami_header_absent():
|
||||
resp = _client().get('/api/auth/whoami')
|
||||
assert resp.status_code == 200
|
||||
assert resp.get_json() == {'authenticated': False, 'username': None}
|
||||
Loading…
Add table
Add a link
Reference in a new issue