diff --git a/src/seedpass/api.py b/src/seedpass/api.py index df00ff62..31de348a 100644 --- a/src/seedpass/api.py +++ b/src/seedpass/api.py @@ -43,21 +43,24 @@ def _reload_relays(relays: list[str]) -> None: pass -def start_server(fingerprint: str | None = None) -> str: +def start_server(fingerprint: str | None = None, token: str | None = None) -> str: """Initialize global state and return the API token. Parameters ---------- fingerprint: Optional seed profile fingerprint to select before starting the server. + token: + Optional API token to use. If omitted, it checks the + ``SEEDPASS_API_TOKEN`` environment variable, or generates a new one. """ global _pm, _token if fingerprint is None: _pm = PasswordManager() else: _pm = PasswordManager(fingerprint=fingerprint) - _token = secrets.token_urlsafe(16) - print(f"API token: {_token}") + + _token = token or os.getenv("SEEDPASS_API_TOKEN") or secrets.token_urlsafe(16) origins = [ o.strip() for o in os.getenv("SEEDPASS_CORS_ORIGINS", "").split(",") diff --git a/src/seedpass/cli.py b/src/seedpass/cli.py index 9de63a45..a3f03d97 100644 --- a/src/seedpass/cli.py +++ b/src/seedpass/cli.py @@ -1,6 +1,7 @@ from pathlib import Path from typing import Optional, List import json +import os import typer import sys @@ -811,10 +812,16 @@ def update_checksum(ctx: typer.Context) -> None: @api_app.command("start") -def api_start(ctx: typer.Context, host: str = "127.0.0.1", port: int = 8000) -> None: +def api_start( + ctx: typer.Context, + host: str = "127.0.0.1", + port: int = 8000, + token: Optional[str] = typer.Option(None, "--token", help="API token"), +) -> None: """Start the SeedPass API server.""" - token = api_module.start_server(ctx.obj.get("fingerprint")) - typer.echo(f"API token: {token}") + actual_token = api_module.start_server(ctx.obj.get("fingerprint"), token=token) + if not os.getenv("SEEDPASS_API_TOKEN") and token is None: + typer.echo(f"API token: {actual_token}", err=True) uvicorn.run(api_module.app, host=host, port=port) @@ -823,10 +830,11 @@ def api_stop(ctx: typer.Context, host: str = "127.0.0.1", port: int = 8000) -> N """Stop the SeedPass API server.""" import requests + token = os.getenv("SEEDPASS_API_TOKEN", api_module._token) try: requests.post( f"http://{host}:{port}/api/v1/shutdown", - headers={"Authorization": f"Bearer {api_module._token}"}, + headers={"Authorization": f"Bearer {token}"}, timeout=2, ) except Exception as exc: # pragma: no cover - best effort