import { getTableColumns } from "drizzle-orm" import { describe, expect, it } from "vitest" import { emailVerificationTokens, passwordResetTokens, refreshTokens, users } from "../src/db/schema/index.js" import { hashPassword, verifyPassword } from "../src/services/password.js" import { generateToken, hashToken } from "../src/services/tokens.js" describe("token opachi", () => { it("256 bit casuali, hash SHA-256 diverso dal token", () => { const { token, hash } = generateToken() expect(Buffer.from(token, "base64url")).toHaveLength(32) expect(hash).toMatch(/^[0-9a-f]{64}$/) expect(hash).not.toContain(token) expect(hashToken(token)).toBe(hash) expect(generateToken().token).not.toBe(token) }) }) describe("password", () => { it("argon2id, verifica ok/ko, hash malformato -> false", async () => { const h = await hashPassword("una password lunga") expect(h.startsWith("$argon2id$")).toBe(true) expect(await verifyPassword(h, "una password lunga")).toBe(true) expect(await verifyPassword(h, "sbagliata")).toBe(false) expect(await verifyPassword("non-un-hash", "x")).toBe(false) }) }) describe("schema: niente segreti in chiaro", () => { it.each([ ["refresh_tokens", refreshTokens], ["password_reset_tokens", passwordResetTokens], ["email_verification_tokens", emailVerificationTokens], ])("%s ha solo token_hash", (_name, table) => { const columns = Object.values(getTableColumns(table)).map((c) => c.name) expect(columns).toContain("token_hash") expect(columns.filter((c) => /token|secret/.test(c) && c !== "token_hash")).toEqual([]) }) it("users ha password_hash e nessuna colonna password in chiaro", () => { const columns = Object.values(getTableColumns(users)).map((c) => c.name) expect(columns).toContain("password_hash") expect(columns).not.toContain("password") }) })