Add Temporary Passwords and Forced Password Change
What does this MR do and why?
Adds a temporary password / forced password change feature to Crafty, allowing admins to reset user passwords and optionally require the user to set a new password on their next login.
Key changes
-
Database migration (
20260216_temp_password.py): Addsrequire_password_change(boolean) andpassword_expires(nullable datetime) columns to theuserstable. -
New API endpoint
POST /api/v2/users/:id/reset-password: Allows admins (superuser orUSER_CONFIGpermission) to reset a user's password. Requires the client to provide the password (generation is handled client-side with configurable length, default 16). Supports optional expiry window (expires_hours, -1 for no expiry) and arequire_password_changeflag. Includes superuser protection (non-superusers cannot reset superuser passwords) and a manager guard (non-superusers can only reset passwords for users they directly manage). -
API gate (
base_handler.py): Whenrequire_password_changeis set, all API requests are blocked with a403 PASSWORD_CHANGE_REQUIREDerror exceptPATCH /api/v2/users/@me(password change) andPOST /api/v2/auth/invalidate_tokens(logout). API key access is exempt. -
Login flow (
login.py): Checks for expired temp passwords at login time (returns401 TEMP_PASSWORD_EXPIRED). When the user hasrequire_password_changeset, the login response includesrequire_password_change: true. -
Forced password change UI (embedded in
login.html): A hidden<form id="change-password-form">is revealed in-place on the login page after a successful login withrequire_password_change: true. CallsPATCH /api/v2/users/@meto bypass the API gate. Includes client-side validation (match check, min length 8). -
Password flag auto-clear: When a user successfully changes their password (via the shared
UsersController.update_user()method, called by bothPATCH /api/v2/users/@meandPATCH /api/v2/users/:id),require_password_changeandpassword_expiresare automatically cleared, and all existing tokens are invalidated. -
Admin UI updates (
panel_config.html,panel_edit_user.html): Adds a reset password dialog (with generate button, length selector, expiry hours, and require-change checkbox). Onpanel_config.html, the dialog appears for all other users. Onpanel_edit_user.html, the reset button is restricted to superusers editing other users. Self-edit shows the standard password change dialog instead. -
Translation keys: Full English translations added under the
tempPasswordnamespace for the reset dialog UI, pluspasswordChangeRequiredandtempPasswordExpiredkeys in theloginnamespace for login-time messages.
Closes Issues
I also see the opportunity to add MFA setup to the change password workflow. This can be done in a future branch.
Screenshots or screen recordings
Config.json
How to set up and validate locally
- Start the Crafty 4 dev server - the
20260216_temp_passwordmigration will run automatically, adding the new columns. -
Reset a user's password as admin:
- Go to Crafty Config > Users and click the lock icon next to a user (not yourself).
- In the dialog, optionally set a password length, expiry, and toggle "Require password change." Click "Reset Password."
- Confirm the generated password is displayed.
-
Log in as the reset user:
- Use the temporary password to log in.
- Verify you are redirected to
/panel/change_password. - Verify you cannot navigate to other pages or make API calls (403 gate).
- Set a new password and confirm redirect to the dashboard.
-
Test expiry:
- Reset a user's password with a short expiry (e.g., 1 hour).
- Attempt to log in - verify
TEMP_PASSWORD_EXPIREDerror.
-
Test superuser protection:
- As a non-superuser with
USER_CONFIGpermission, try to reset a superuser's password - verify 403ACCESS_DENIED.
- As a non-superuser with
-
Test self-edit:
- On the panel config user list, verify your own row shows the standard password change dialog (not the reset dialog).
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
- Have you checked this doesn't interfere/conflict/duplicate someone elses work?
- Have you fully tested your changes?
- Have you resolved any lint issues?
- Have you assigned a reviewer?
- Have you applied correct labels?
Edited by Corey Koval





