feat(auth): finish PMS-4 story (mailer, MFA TOTP, API keys) #20
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/auth-story-pms-4"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the bulk of YouTrack story PMS-4 (auth + user management). One commit per sub-task.
Sub-tasks
list_usersreal query: already shipped in the audit-batch series; closed administratively.src/modules/auth/rate_limit.rs; closed administratively.utils::email::Mailer(LogMailer dev, SmtpMailer prod via lettre). Selected bySMTP_HOSTpresence. Wired intoAuthService::request_password_reset. Frontend link is built fromCLIENT_ORIGIN./reset-password/<token>link, reusing the existing reset machinery rather than introducing a parallel setup-token table.users.mfa_secret(base32) viamokosh_auth_crypto::totp::verify(+-1 step skew). Three new endpoints:POST /me/mfa/setup(stage secret + provisioning URI),POST /me/mfa/enable(confirm one code, flip flag),POST /me/mfa/disable(clear after password re-auth).POST /me/api-keys,GET /me/api-keys,DELETE /me/api-keys/:id. Raw key returned once on create; DB stores onlykey_prefix(10-char index) + argon2 hash.Behaviour-visible changes
AuthService::newis preserved; newAuthService::with_maileris the production constructor (called bycreate_api_router).create_api_routergains a finalmailer: Arc<dyn Mailer>parameter;main.rsbuilds it fromMailerConfig::from_env. The boot path hard-fails on misconfiguration (e.g. SMTP_USERNAME without SMTP_PASSWORD) rather than silently downgrading to LogMailer.users.mfa_secretis now read/written on enrollment and consulted on login whenmfa_enabled = true. No schema change required.api_keysrows are created onPOST /me/api-keys; no bearer-auth middleware change yet (kept out of scope; tracked separately).Test plan
cargo check --bin mokosh-serverclean (verified locally).POST /api/v1/auth/forgot-passwordfor a known user logs the reset link (LogMailer dev) or sends via SMTP (compose.dev.yml mailpit at http://localhost:8025).POST /api/v1/auth/me/mfa/setupreturns secret + URI; an authenticator app loaded with the URI produces codes thatPOST /me/mfa/enableaccepts; subsequent login requires the code.POST /api/v1/auth/me/api-keysreturns apsa_...key;GETlists with prefix only;DELETEremoves it.Closes #PMS-4
Add `utils:📧:Mailer` with `LogMailer` (dev) and `SmtpMailer` (lettre). `MailerConfig::from_env` selects the implementation based on `SMTP_HOST`. `AuthService::request_password_reset` now dispatches the reset link through the configured mailer; the link is built from the new `frontend_base_url` field (sourced from `CLIENT_ORIGIN`). The mailer is constructed once at startup and threaded through `create_api_router` -> `AuthService::with_mailer`. Send failures are logged but do not change the public response shape, preserving the existing enumeration-resistant behaviour of `/auth/forgot-password`. #PMS-7 State DonePull request closed