Files
Mangalord/backend/Cargo.toml
MechaCat02 c7cb689984 feat: settings page exercises the password-change endpoint
The 0.10.0 backend endpoint had no UI caller — the audit flagged it
as either-ship-a-form-or-remove-the-endpoint dead code. Shipping the
form, plus the bearer-token-keeps-working regression test the audit
asked for to pin the docstring contract.

Backend:
- New test change_password_via_bearer_leaves_bearer_working asserts
  that PATCH /me/password called with Authorization: Bearer wipes
  cookie sessions but leaves the bearer (api_token) intact and usable
  — matches the docstring claim that bot tokens are opt-in to revoke.

Frontend:
- lib/api/auth.ts: new changePassword(input) wrapping PATCH
  /v1/auth/me/password. Vitest covers happy 204, 401 unauthenticated
  (wrong current), 400 invalid_input (weak new) — same envelope
  parsing shape used elsewhere.
- routes/settings/+page.svelte: minimal form with current /
  new / confirm fields, derived passwordsMatch + canSubmit guards
  (submit stays disabled until current is filled, new is ≥8 chars,
  new == confirm). Shows the API's message inline on failure.
  Documents the "other devices signed out, bot tokens stay" UX in a
  short hint.
- routes/+layout.svelte: new "Settings" link in the session-aware
  nav (between username and Logout) for authed users only.
- e2e/settings.spec.ts (5 cases): nav link reaches the form,
  successful change shows confirmation + clears the form, 401
  surfaces inline, password mismatch keeps submit disabled, anonymous
  user gets a sign-in prompt instead of the form.

Lockstep version bump to 0.11.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 00:16:22 +02:00

47 lines
1.2 KiB
TOML

[package]
name = "mangalord"
version = "0.11.0"
edition = "2021"
[lib]
path = "src/lib.rs"
[[bin]]
name = "mangalord"
path = "src/main.rs"
[dependencies]
axum = { version = "0.7", features = ["macros", "multipart"] }
tokio = { version = "1", features = ["full"] }
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "uuid", "chrono", "macros", "migrate"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
uuid = { version = "1", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tower = { version = "0.5", features = ["util"] }
tower-http = { version = "0.6", features = ["trace", "cors"] }
thiserror = "1"
anyhow = "1"
async-trait = "0.1"
dotenvy = "0.15"
argon2 = "0.5"
rand = "0.8"
sha2 = "0.10"
subtle = "2"
base64 = "0.22"
axum-extra = { version = "0.9", features = ["cookie", "typed-header"] }
time = "0.3"
infer = "0.16"
tokio-util = { version = "0.7", features = ["io"] }
futures-core = "0.3"
bytes = "1"
[dev-dependencies]
tempfile = "3"
tower = { version = "0.5", features = ["util"] }
http-body-util = "0.1"
mime = "0.3"
futures-util = "0.3"