feat(auth): align login and bootstrap with new user schema

This commit is contained in:
2026-06-19 01:05:33 +02:00
parent 2ed9445f7f
commit 01d89cd21b
10 changed files with 503 additions and 60 deletions
@@ -1,5 +1,6 @@
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest"
import type { PrismaClient } from "@/generated/prisma/client"
import { normalizeEmail } from "@/lib/email"
import { createTestUser } from "../helpers/factories"
import {
resetIntegrationTestDatabase,
@@ -51,18 +52,21 @@ describe("user use-cases", () => {
expect(result).toEqual({ success: true })
const user = await prisma.user.findUniqueOrThrow({
where: { email: "new-user@example.test" },
where: { emailNormalized: normalizeEmail("new-user@example.test") },
})
expect(user).toMatchObject({
name: "New User",
email: "new-user@example.test",
role: "STAFF",
isActive: true,
status: "ACTIVE",
})
expect(user.password).not.toBe("secure-password")
expect(user.activatedAt).toBeInstanceOf(Date)
expect(user.passwordChangedAt).toBeInstanceOf(Date)
expect(user.passwordHash).not.toBe("secure-password")
if (!user.passwordHash) throw new Error("Expected password hash")
await expect(
verifyPassword("secure-password", user.password),
verifyPassword("secure-password", user.passwordHash),
).resolves.toBe(true)
})
@@ -87,7 +91,7 @@ describe("user use-cases", () => {
await expect(prisma.user.count()).resolves.toBe(1)
await expect(
prisma.user.findUniqueOrThrow({
where: { email: "existing@example.test" },
where: { emailNormalized: normalizeEmail("existing@example.test") },
}),
).resolves.toMatchObject({ email: "existing@example.test" })
})
@@ -120,7 +124,7 @@ describe("user use-cases", () => {
name: "Edited User",
email: "edited@example.test",
role: "MANAGER",
isActive: true,
status: "ACTIVE",
})
await expect(
@@ -163,7 +167,7 @@ describe("user use-cases", () => {
await expect(
prisma.user.findUniqueOrThrow({ where: { id: admin.id } }),
).resolves.toMatchObject({ role: "ADMIN", isActive: true })
).resolves.toMatchObject({ role: "ADMIN", status: "ACTIVE" })
})
it("protects the last active administrator but allows deactivation when another active admin exists", async () => {
@@ -204,7 +208,7 @@ describe("user use-cases", () => {
await expect(
prisma.user.findUniqueOrThrow({ where: { id: firstAdmin.id } }),
).resolves.toMatchObject({ isActive: false })
).resolves.toMatchObject({ status: "DISABLED" })
})
it("prevents self-deactivation", async () => {
@@ -224,7 +228,7 @@ describe("user use-cases", () => {
await expect(
prisma.user.findUniqueOrThrow({ where: { id: admin.id } }),
).resolves.toMatchObject({ isActive: true })
).resolves.toMatchObject({ status: "ACTIVE" })
})
it("resets a user password and rejects missing users", async () => {
@@ -244,9 +248,10 @@ describe("user use-cases", () => {
where: { id: user.id },
})
expect(updatedUser.password).not.toBe(user.password)
expect(updatedUser.passwordHash).not.toBe(user.passwordHash)
if (!updatedUser.passwordHash) throw new Error("Expected password hash")
await expect(
verifyPassword("new-secure-password", updatedUser.password),
verifyPassword("new-secure-password", updatedUser.passwordHash),
).resolves.toBe(true)
await expect(