Commit Graph
1 Commits
Author SHA1 Message Date
Donkie c0a960cbe3 auth: command line administration
Adds `python -m spoolman.cli`, the way back in when nobody can sign in: a
forgotten owner password, a disabled account, an owner who has left. This is
why the design has no per-user recovery codes.

    docker exec -it spoolman python -m spoolman.cli auth status

Commands: auth status; user list/create/reset-password/set-level/enable/
disable; session revoke-all. Generated passwords are printed once.

Module form rather than a console script, because the Docker image runs
Spoolman from source and there is no installed distribution to hang an entry
point on. argparse rather than a dependency: eight subcommands do not
justify adding click or typer to the runtime image.

It never runs migrations. If the auth tables are missing it says so and
exits 2, because the fix is to start the server once and let it migrate --
having two things that can migrate the schema is how databases get hurt.

It deliberately works while SPOOLMAN_AUTH_ENABLED is unset, since the
intended first run is to create an owner and only then turn auth on.

Fixes a bug found by running it: "user create <name> --owner" produced an
owner at level read, because the --level default won over the flag. An owner
who cannot change anything is useless and would have sent someone straight
back to the CLI. --admin and --owner now imply manage, and an explicit lower
--level is reported rather than silently ignored.

Adds database.get_engine(), since the schema check needs the engine and the
Database instance is module-private.

Verified against a real database: refuses to run before migrations (exit 2);
reports an unclaimed instance; creates owner, edit and admin accounts with
the right levels; refuses a second owner and a duplicate username; refuses
to disable the owner; reset-password ends existing sessions and sets
must_change_password. Most importantly, end to end: a password generated by
the CLI signs in through the API, arrives with must_change_password set, and
carries the owner's manage level for both reads and writes.
2026-07-28 09:58:27 +02:00