Add self-service "change my password" option in Account Settings
New section in Settings: current password + new password + confirm, verified against the existing hash before accepting. On success it signs out every other session for that account (in case one was compromised) but keeps the current session logged in, so changing your password doesn't immediately kick you back to the login screen. Renamed the underlying db.js function (adminSetPassword -> setUserPassword) since it's now shared by both this and the existing admin-assisted reset. Verified live: old password rejected after change, new password works, current session stayed logged in throughout. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+6
-3
@@ -298,8 +298,8 @@ export function adminDeleteProject(id) {
|
||||
db.prepare('DELETE FROM projects WHERE id = ?').run(id);
|
||||
}
|
||||
|
||||
/** Overwrites a user's password hash directly — used for admin-assisted password resets. */
|
||||
export function adminSetPassword(userId, passwordHash) {
|
||||
/** Overwrites a user's password hash directly — used for both self-service and admin-assisted resets. */
|
||||
export function setUserPassword(userId, passwordHash) {
|
||||
db.prepare('UPDATE users SET password_hash = ? WHERE id = ?').run(passwordHash, userId);
|
||||
}
|
||||
|
||||
@@ -337,10 +337,13 @@ export function pruneExpiredSessions() {
|
||||
* Logs a user out everywhere by deleting every session that belongs to them.
|
||||
* Sessions don't have an indexed user_id column (they're just an opaque JSON
|
||||
* blob to express-session), so this scans and parses — fine at this app's scale.
|
||||
* Pass exceptSid to keep one session alive (e.g. the one completing a self-service
|
||||
* password change, so the user isn't immediately logged out of their own action).
|
||||
*/
|
||||
export function destroyAllSessionsForUser(userId) {
|
||||
export function destroyAllSessionsForUser(userId, exceptSid = null) {
|
||||
const rows = db.prepare('SELECT sid, sess FROM sessions').all();
|
||||
const staleSids = rows
|
||||
.filter((row) => row.sid !== exceptSid)
|
||||
.filter((row) => {
|
||||
try {
|
||||
return JSON.parse(row.sess)?.userId === userId;
|
||||
|
||||
Reference in New Issue
Block a user