"""hf-cli config … — runtime configuration stored in DB. Currently only the OIDC provider config has a CLI surface (it used to live in the AbstractWizard config). Mirrors dialectic-cli's `config oidc` shape: only the flags you pass are mutated, the rest stays unchanged. Prints the post-update row with client_secret masked unless --show-secret is given. """ import argparse import json import sys from app.core.config import SessionLocal from app.models.oidc_settings import OidcSettings def _emit(payload: dict) -> None: sys.stdout.write(json.dumps(payload, indent=2) + "\n") def _bool(v: str) -> bool: return v.lower() in ("1", "true", "yes", "on") def _cmd_oidc(argv: list[str]) -> int: p = argparse.ArgumentParser(prog="hf-cli config oidc") p.add_argument("--issuer", default=None) p.add_argument("--client-id", default=None) p.add_argument("--client-secret", default=None) p.add_argument("--redirect-uri", default=None) p.add_argument("--post-login-redirect", default=None) p.add_argument("--scopes", default=None, help='Default: "openid email profile"') p.add_argument("--admin-role", default=None, help="OIDC role name that bootstraps an unbound hf admin " "on first OIDC-only login. Default: admin.") p.add_argument("--enabled", default=None, help="true|false. Without this flag the row's existing " "value is preserved.") p.add_argument("--show-secret", action="store_true", help="Reveal client_secret in the output (local audit " "only — never paste into chat).") args = p.parse_args(argv) db = SessionLocal() try: row = db.query(OidcSettings).filter(OidcSettings.id == 1).first() if row is None: row = OidcSettings(id=1, enabled=False) db.add(row) if args.issuer is not None: row.issuer = args.issuer.strip() or None if args.client_id is not None: row.client_id = args.client_id.strip() or None if args.client_secret is not None: row.client_secret = args.client_secret or None if args.redirect_uri is not None: row.redirect_uri = args.redirect_uri.strip() or None if args.post_login_redirect is not None: row.post_login_redirect = args.post_login_redirect.strip() or None if args.scopes is not None: row.scopes = args.scopes.strip() or None if args.admin_role is not None: row.admin_role = args.admin_role.strip() or None if args.enabled is not None: row.enabled = _bool(args.enabled) db.commit() db.refresh(row) out: dict = { "enabled": bool(row.enabled), "issuer": row.issuer, "client_id": row.client_id, "redirect_uri": row.redirect_uri, "post_login_redirect": row.post_login_redirect, "scopes": row.scopes, "admin_role": row.admin_role, } if args.show_secret: out["client_secret"] = row.client_secret elif row.client_secret: out["client_secret"] = "***set***" else: out["client_secret"] = None _emit({"ok": True, "config": out}) return 0 finally: db.close() ACTIONS = { "oidc": _cmd_oidc, } def dispatch(argv: list[str]) -> int: if not argv: sys.stderr.write("config: missing action; one of: " + ", ".join(ACTIONS) + "\n") return 1 action, rest = argv[0], argv[1:] fn = ACTIONS.get(action) if not fn: sys.stderr.write(f"config: unknown action '{action}'; valid: {', '.join(ACTIONS)}\n") return 1 return fn(rest)