Sfoglia il codice sorgente

RHL-044 fix(auth): refresh session after password change

codeUWE 1 mese fa
parent
commit
7bd30e088a

+ 11 - 1
app/api/auth/change-password/route.js

@@ -2,7 +2,7 @@ import bcrypt from "bcryptjs";
 
 import User from "@/models/user";
 import { getDb } from "@/lib/db";
-import { getSession } from "@/lib/auth/session";
+import { getSession, createSession } from "@/lib/auth/session";
 import { validateNewPassword } from "@/lib/auth/passwordPolicy";
 import {
 	withErrorHandling,
@@ -98,6 +98,16 @@ export const POST = withErrorHandling(
 
 		await user.save();
 
+		// Refresh the session cookie so frontend revalidation sees the cleared flag
+		// immediately (no logout/login roundtrip required).
+		await createSession({
+			userId: user._id.toString(),
+			role: user.role ?? session.role,
+			branchId: user.branchId ?? session.branchId ?? null,
+			email: user.email ?? session.email ?? null,
+			mustChangePassword: false,
+		});
+
 		return json({ ok: true }, 200);
 	},
 	{ logPrefix: "[api/auth/change-password]" },

+ 15 - 1
app/api/auth/change-password/route.test.js

@@ -4,6 +4,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
 
 vi.mock("@/lib/auth/session", () => ({
 	getSession: vi.fn(),
+	createSession: vi.fn(),
 }));
 
 vi.mock("@/lib/db", () => ({
@@ -26,7 +27,7 @@ vi.mock("bcryptjs", () => {
 	};
 });
 
-import { getSession } from "@/lib/auth/session";
+import { getSession, createSession } from "@/lib/auth/session";
 import { getDb } from "@/lib/db";
 import User from "@/models/user";
 import { compare as bcryptCompare, hash as bcryptHash } from "bcryptjs";
@@ -186,6 +187,7 @@ describe("POST /api/auth/change-password", () => {
 
 		expect(bcryptHash).not.toHaveBeenCalled();
 		expect(user.save).not.toHaveBeenCalled();
+		expect(createSession).not.toHaveBeenCalled();
 	});
 
 	it("returns 400 when new password is weak", async () => {
@@ -230,6 +232,7 @@ describe("POST /api/auth/change-password", () => {
 
 		expect(bcryptHash).not.toHaveBeenCalled();
 		expect(user.save).not.toHaveBeenCalled();
+		expect(createSession).not.toHaveBeenCalled();
 	});
 
 	it("returns 200 and updates passwordHash + clears flags on success", async () => {
@@ -237,11 +240,15 @@ describe("POST /api/auth/change-password", () => {
 			userId: "u1",
 			role: "branch",
 			branchId: "NL01",
+			email: "branch@example.com",
 		});
 
 		const user = {
 			_id: "507f1f77bcf86cd799439011",
 			passwordHash: "old-hash",
+			role: "branch",
+			branchId: "NL01",
+			email: "branch@example.com",
 			mustChangePassword: true,
 			passwordResetToken: "tok",
 			passwordResetExpiresAt: new Date("2030-01-01"),
@@ -273,5 +280,12 @@ describe("POST /api/auth/change-password", () => {
 		expect(user.passwordResetExpiresAt).toBe(null);
 
 		expect(user.save).toHaveBeenCalledTimes(1);
+		expect(createSession).toHaveBeenCalledWith({
+			userId: "507f1f77bcf86cd799439011",
+			role: "branch",
+			branchId: "NL01",
+			email: "branch@example.com",
+			mustChangePassword: false,
+		});
 	});
 });