2.6 KiB
2.6 KiB
CLI Module Design
Problem
pyproject.toml declares porchlight = "porchlight.cli:main" with typer>=0.15 as a
dependency, but no cli.py exists. The app has no CLI entry point for administrative
tasks -- operators must use the Python shell or raw SQL to create invite links or
bootstrap initial users.
Decision
Create src/porchlight/cli.py with two commands: create-invite and initial-admin.
Skip a serve command since Docker/uvicorn handles that already.
Commands
porchlight create-invite <username>
Generate a magic link registration URL for a new user.
Options:
--ttl SECONDS-- link expiration (default: from settings, 86400s)--note TEXT-- optional note stored with the link
Behavior:
- Opens SQLite DB via existing
open_db()context manager - Creates
MagicLinkServicewithSQLiteMagicLinkRepository - Calls
service.create(username=username, note=note, created_by="cli") - Prints full URL:
{issuer}/register/{token} - Reads
OIDC_OP_ISSUERenv var for base URL (required) - Reads
OIDC_OP_SQLITE_PATHfor DB path (default:data/oidc_op.db)
porchlight initial-admin <username>
Bootstrap the first admin user with a registration link.
Options:
--group TEXT-- groups to assign (default:["admin", "users"]), repeatable
Behavior:
- Opens SQLite DB
- Checks if username already exists -- error if so
- Generates unique userid via
generate_unique_userid() - Creates user with specified groups
- Creates a magic link so the admin can visit the URL to set up credentials
- Prints full URL:
{issuer}/register/{token}
Route change: /register/{token}
Modify register_magic_link to handle existing users:
- Before creating the user, call
user_repo.get_by_username(link.username) - If user exists: skip creation, log them in, redirect to
/manage/credentials?setup=1 - If user doesn't exist: create as before with
groups=["users"]
This makes the registration route work for both fresh invites and admin-created users who need to set up credentials.
Implementation notes
- Both commands use
asyncio.run()to call async helpers - Config loaded via
Settings()(pydantic-settings reads env vars) - No new dependencies required -- Typer is already declared
- No schema changes needed
Files changed
| File | Change |
|---|---|
src/porchlight/cli.py |
New -- Typer app with two commands |
src/porchlight/authn/routes.py |
Modify register_magic_link for existing users |
tests/test_cli.py |
New -- tests for both CLI commands |
tests/test_auth_routes/test_register_magic_link.py |
Add test for existing user registration |