Commit Graph
21 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
Donkie e509378392 chore: require Python 3.14
The declared floor was ">=3.10", but nothing enforced it: the Docker image
has pinned python:3.14-slim-bookworm for amd64/arm64/armv7 for some time,
and scripts/install.sh runs "uv sync" without UV_PYTHON_DOWNLOADS=0, so uv
fetches a managed interpreter when the system one is too old. Every
dependency declares a floor of <=3.10 with no upper cap.

Raising it unlocks enum.StrEnum, datetime.UTC and typing.Self for the
authentication work that follows.

Consequences handled here:

- uv.lock regenerated. Four pure-backport packages drop out
  (async-timeout, backports-asyncio-runner, exceptiongroup, tomli).

- ruff target-version follows to py314, which switches on PEP 649 deferred
  annotations and with them a batch of previously-dormant rules. The safe
  automatic fixes are applied: datetime.timezone.utc -> datetime.UTC
  (UP017) and redundant quotes dropped from annotations (UP037).

- TC001/TC002/TC003 are ignored rather than applied. They want type-only
  imports moved into "if TYPE_CHECKING:" blocks, which is wrong here:
  FastAPI resolves Annotated[AsyncSession, Depends(...)] and websocket
  parameters at runtime, Pydantic resolves field types at runtime, and
  SQLAlchemy resolves Mapped[...] at mapper-configuration time. A
  TYPE_CHECKING-only import is absent from the runtime namespace, so
  applying them breaks dependency injection. Ruff classifies all 50 as
  unsafe fixes for that reason.

Verified: ruff check/format clean, uv lock --check clean, alembic head
resolves, SQLAlchemy mappers configure with all relationships intact and
lazy="selectin" preserved on the extra-field collections.
2026-07-27 20:09:43 +02:00
Donkie b942d1f8a1 Replaced pdm with uv, updated backend deps, python 3.10 minimum, simplified install script 2026-01-07 22:01:02 +01:00
Paul Sinclair ea36a94327 🔨 Add pool_recycle for MySQL 2025-04-05 09:58:34 -04:00
Donkie 70ea7ad414 Update python dependencies and ruff/black versions 2025-03-16 21:34:02 +01:00
Donkie 535fa40ad2 Updated most python dependencies
Primarily FastAPI and Pydantic to v2. Also ruff to latest.

Updated some code to support Pydantic v2
2024-05-23 19:42:27 +02:00
Donkie 21d541a680 Added script to download files from external db 2024-05-12 10:48:33 +02:00
Dmitry Belousov 91d922d0b8 fixed version prometheus-client
added env variable SPOOLMAN_METRICS_ENABLED for enabled database collector

set metrics path as /metrics

checked Null values at vendors, init weight and price
removed some logs
2024-04-15 00:17:36 +03:00
Dmitry Belousov 2aa0a4f1b0 WA for FastApi session manager 2024-04-12 01:20:35 +03:00
Dmitry Belousov 28b2bfec50 Added prometheus client
Added scheduler for compute current spool metrics and info
2024-04-09 15:25:09 +03:00
Donkie 796523a860 Fixed db backups not using the fancy get_backups_dir function 2023-11-25 21:58:20 +01:00
Donkie d3a4dcfcf8 Added logging for when scheduled backup runs 2023-07-07 17:37:17 +02:00
Donkie f24b9610e8 Added automatic nightly SQLite backups
Resolves #22
2023-07-04 14:59:05 +02:00
Donkie d201f17e5e Improved manually specifying sqlite db 2023-07-04 12:10:14 +02:00
Donkie 94d8cbf227 SQLite dbs now handle concurrent reqs better
Closes #7
2023-06-30 22:28:01 +02:00
Donkie de1bf05922 Added Alembic for migrations 2023-05-27 23:14:06 +02:00
Donkie ba6fb62c7b Enabled pool_pre_ping to mitigate postgres drop 2023-05-21 23:38:21 +02:00
Donkie 1c59e0efd5 Added logging level env var 2023-05-09 21:44:25 +02:00
Donkie ed3e30ea75 Improved compatibility with postgres 2023-05-09 20:03:19 +02:00
Donkie 1a148c0991 Added proper support for all databases 2023-04-06 16:19:33 +02:00
Donkie 6fd9662c42 Renamed to Spoolman
Spoolson just didn't sound that good after all
2023-04-02 19:19:15 +02:00