mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 12:06:57 +02:00
feat(auth): enable password login on OAuth-only accounts, with disable control
Admins can now reset the password of an OAuth-only user, which creates their credentials and enables password login; the new 'Disable password login' row action removes those credentials again. Resetting a password revokes all existing sessions. - add users.password_login_enabled column (migration 0005) - admin reset: set password, enable login, revoke sessions - disable action: clear password, disable login (only on OAuth-linked rows) - account endpoint: refuse password updates on OAuth-linked users - e2e: wipe the test DB before the webServer starts (Playwright starts the server before globalSetup, so wiping there orphaned the DB file) - row-actions strip test: five square actions, wrap on phone widths
This commit is contained in:
committed by
Fred Cabassut
parent
e315b8c7ec
commit
e4606cfc70
@@ -91,7 +91,7 @@ For a single-user app with multiple devices:
|
||||
See `src/lib/server/db/schema.ts` for the complete Drizzle schema.
|
||||
|
||||
Key tables:
|
||||
- `users` - User accounts (password hash, OAuth provider link, role)
|
||||
- `users` - User accounts (password hash, `password_login_enabled`, OAuth provider link, role)
|
||||
- `sessions` - Auth sessions (30-day TTL)
|
||||
- `notes` - Core note data with version tracking
|
||||
- `tags` - Unique tag names
|
||||
|
||||
+7
-7
@@ -14,20 +14,20 @@ On first launch, Crumbs presents a setup screen to create the initial admin acco
|
||||
|
||||
### Admin password resets
|
||||
|
||||
An admin can reset the password of any user other than themselves, provided that account signs in with a password. Crumbs generates the new password and shows it once in that user's row — copy it and pass it to the user out of band, because it is not stored anywhere and cannot be shown again once dismissed. If SMTP is configured Crumbs also tries to notify the user that their password was reset, but the attempt is best-effort: a delivery failure is logged on the server and never surfaced in the UI, so a successful reset is not evidence the user was told. The notification never contains the password.
|
||||
An admin can reset the password of any user other than themselves. Crumbs generates the new password and shows it once in that user's row — copy it and pass it to the user out of band, because it is not stored anywhere and cannot be shown again once dismissed. If SMTP is configured Crumbs also tries to notify the user that their password was reset, but the attempt is best-effort: a delivery failure is logged on the server and never surfaced in the UI, so a successful reset is not evidence the user was told. The notification never contains the password.
|
||||
|
||||
The control appears on every row, but is unavailable in two cases, each stating its reason on the row:
|
||||
The control appears on every row, but is unavailable in two cases:
|
||||
|
||||
- **Your own row** — change your own password in **Settings > Profile**, which verifies your current password first.
|
||||
- **An account that signs in via OAuth/SSO** — it has no password the login form would accept, so setting one would hand the user a credential that cannot work.
|
||||
- **While a generated password is still on screen** — dismiss it first if you need to generate another.
|
||||
|
||||
It is also unavailable while a generated password is still on screen, and that case gives no reason — dismiss the password first if you need to generate another.
|
||||
A reset enables password login for that account if it was not already enabled — including OAuth-only accounts — without removing their SSO link. Both sign-in methods can coexist.
|
||||
|
||||
A reset does not sign the user out. **Revoke all sessions** is a separate action on the same row and, like the reset, is not offered for your own account.
|
||||
A reset **revokes all of the user's sessions** — they must sign in again with the new password (or via OAuth if linked). **Disable password login** is a separate action on rows where password login is enabled; it clears the stored hash, turns off password login, and revokes all sessions. It is not offered on your own row.
|
||||
|
||||
A displayed password is only good until that account's password changes again: any later reset — by another admin, or by the user themselves from **Settings > Profile** — silently invalidates one still on screen, and nothing marks it as stale. Separately, if Crumbs cannot confirm a reset it says so and shows the password anyway; keep that one, since it may or may not have been applied, and reset again if the user cannot sign in.
|
||||
|
||||
> **No password recovery.** Crumbs has no forgot-password flow. An admin who forgets their own password cannot reset it themselves: the admin control excludes their own row, and the profile flow requires the current password. Another admin can reset you, so keep a second admin account as cheap insurance. Failing that, if an OAuth/SSO provider is configured and your account's email matches your identity there, signing in with that provider gets you back in without a password — at the cost of handing the account over to the provider permanently, after which your password no longer works. With no other admin and no provider configured, there is no way back in through the app.
|
||||
> **No password recovery.** Crumbs has no forgot-password flow. An admin who forgets their own password cannot reset it themselves: the admin control excludes their own row, and the profile flow requires the current password. Another admin can reset you, so keep a second admin account as cheap insurance. Failing that, if an OAuth/SSO provider is configured and your account's email matches your identity there, signing in with that provider gets you back in without a password. An admin can also enable password login on an OAuth-linked account via **Settings > Users**. With no other admin and no provider configured, there is no way back in through the app.
|
||||
|
||||
## OAuth / SSO
|
||||
|
||||
@@ -52,7 +52,7 @@ OAuth does **not** auto-create accounts. Users must be pre-created by an admin:
|
||||
|
||||
After initial linking, the user is identified by their provider-specific ID (`sub` claim), so email changes on the provider side won't break login.
|
||||
|
||||
Tick **OAuth-only (no password)** when creating these accounts — the provider is how they will sign in anyway. If you set a password instead, treat it as temporary: the first OAuth sign-in hands the account over to the provider, after which the password no longer works at the login form and the admin password reset is unavailable for that account.
|
||||
Tick **OAuth-only (no password)** when creating these accounts — the provider is how they will sign in. An admin can later enable password login via **Settings > Users** if the IdP becomes unavailable. If you set a password at invite time, it keeps working after the user's first OAuth sign-in — both methods coexist independently.
|
||||
|
||||
### Environment variables
|
||||
|
||||
|
||||
+3
-2
@@ -143,9 +143,10 @@
|
||||
- Admin dashboard to create, list, and delete users
|
||||
- Assign roles (admin / user)
|
||||
- Reset another user's password — Crumbs generates a 20-character password and shows it once in that user's row, with a copy button; it cannot be shown again
|
||||
- Only for accounts that sign in with a password — OAuth/SSO accounts show why the reset is unavailable
|
||||
- Works for any account other than your own, including OAuth-only — the reset deliberately enables password login and revokes all sessions
|
||||
- **Disable password login** turns off password auth, clears the hash, and revokes sessions (not offered on your own row)
|
||||
- Your own password is changed from Settings > Profile, not here
|
||||
- A reset does not sign the user out — revoke their sessions separately to force a logout
|
||||
- Use **Revoke all sessions** separately if you need to force a logout without changing credentials
|
||||
- Revoke all sessions (force logout) for any user other than yourself
|
||||
|
||||
### PWA / Offline-First
|
||||
|
||||
Reference in New Issue
Block a user