enlace_auth.admin.routes#
Admin HTTP routes: user CRUD, password reset, app policy + grants.
Endpoints (all under /_admin/api/):
GET /users— list registered usersPOST /users— create a user (admin-created)DELETE /users/{email}— delete a user (refuses last admin)POST /users/{email}/password— admin reset another user’s passwordPOST /users/{email}/reset-link— mint a one-time link the user follows to choose their own password. Preferred over the endpoint above: the admin never learns, transmits, or has to invent a credential. It is also the only recovery path that works when no SMTP sender is configured, since the admin delivers the link by hand.GET /apps— list apps with their access policy + (forprotected:userapps) their runtime grantsPOST /grants— grant a user runtime access to an appDELETE /grants/{app_id}/{email}— revoke a runtime grant
A minimal HTML dashboard is also mounted at GET /_admin/ (and
/_admin/index.html); it consumes the JSON endpoints above. The HTML
lives next to this file at static/index.html and is served via
importlib.resources so it ships in the wheel without any build step.
Self-service POST /auth/me/password (change own password) lives in
enlace_auth.auth.routes so it’s reachable to any authenticated user — it
is NOT under /_admin because the admin access rule would block non-admins.
Access control:
/_admin/*is gated byPlatformAuthMiddlewarevia the access rule the plugin installs (allowed_users=admin_emails). By the time a request reaches this router, the caller is an admin.
Runtime grants are ADDITIVE on top of each app’s static app.toml
allowed_users and carry an optional UTC expiry — see
enlace_auth.auth.grants.
Functions
|
Build a FastAPI router exposing |
Build a FastAPI router that serves the bundled HTML dashboard. |
- enlace_auth.admin.routes.make_admin_router(*, user_store, session_store, admin_emails=(), apps=(), grant_store=None, protected_user_apps=(), share_store=None, store_apps=(), signing_key=None, reset_link_ttl=259200, resource_allowlist=None, oauth_server_enabled=False, public_base_url=None, on_credentials_changed=None)[source]#
Build a FastAPI router exposing
/_admin/api/*endpoints.admin_emailsis captured by closure so the router can enforce last-admin protection on delete. The middleware handles the broader “must be an admin to see /_admin” check.grant_store(aGrantStore) andprotected_user_appsenable the runtime grant endpoints. Whengrant_storeis None those endpoints return 503.signing_keyenables the reset-link endpoint (same key the auth router signs with, so the link it mints verifies there). Omit it and that endpoint returns 503, mirroring howgrant_storegates the grant endpoints.public_base_urlis the platform’s public origin for minted reset links (falls back to the request origin).reset_link_ttlis how long a minted link stays usable — longer than an emailed one, because delivery is a human round trip.resource_allowlistis the OAuth server’s per-connector allow-list (seeenlace_auth.auth.oauth_server). It exists here purely so/appscan tell the truth about connectors: an OAuth resource server is declaredaccess = "public"because enlace must NOT gate it at the session layer — it authenticates its own bearer tokens instead. Reporting that as a bare “public” badge invites the reader to conclude private data is world-open (it isn’t) or, worse, to make some other app public by analogy (which would be). Passing the allow-list lets the dashboard show who can actually reach each one.oauth_server_enabledlets it also say what happens to a resource that is NOT listed: refused to everyone while an allowlist is set, open to every account when the server runs without one.on_credentials_changed(hook(email, *, keep=None)) runs after a user is deleted or has their password set. The default revokes the account’s browser sessions; the plugin injects one that also revokes its OAuth connector refresh families (enlace_auth.auth.revocation).- Return type:
APIRouter
- enlace_auth.admin.routes.make_admin_ui_router()[source]#
Build a FastAPI router that serves the bundled HTML dashboard.
Mounted at
/_admin/; gated by the same admin access rule as the API, so unauthenticated browsers get redirected to login by the auth middleware before they ever reach this handler.- Return type:
APIRouter