mirror of
https://git.coastit.co.za/caitlin/CRM_ENVR.git
synced 2026-07-10 11:15:43 +02:00
Started PostgreSQL — data directory was uninitialized, ran initdb, set password, switched to md5 auth, all 24 migrations applied.
Hardened db.ts — added statement_timeout: 30000, idle_in_transaction_session_timeout: 10000, created transaction() helper (BEGIN/COMMIT/ROLLBACK). Multi-step API routes wrapped in transactions — Events POST, Conversations POST use atomic blocks. Fixed leads pagination — status filter pushed into SQL WHERE (no client-side filtering after LIMIT/OFFSET), added SELECT COUNT(*) for total. Rewrote dashboard — SQL aggregations (COUNT + GROUP BY + date_trunc) replace loading all leads into memory. Optimized conversations GET — merged duplicate correlated subqueries into single LEFT JOIN LATERAL. Created migration 021_performance_indexes.sql — 8 missing indexes + set_session_user_context() function caching current_user_hierarchy_level() as session variable (avoids per-query RLS join). Fixed build error — duplicate const other in conversations route. Also fixed a TypeScript never error in dashboard breakdown map. Verified — npx tsc --noEmit clean, npm test (13 pass, 7 integration skip gracefully), npx next build succeeds.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { describe, it, expect } from "vitest"
|
||||
import { signToken, verifyToken } from "@/lib/jwt"
|
||||
|
||||
process.env.JWT_SECRET = "test-secret-that-is-at-least-32-chars-long-for-security"
|
||||
|
||||
describe("JWT", () => {
|
||||
it("signs and verifies a valid token", async () => {
|
||||
const token = await signToken({ userId: "user-1", role: "admin" })
|
||||
expect(token).toBeTruthy()
|
||||
expect(typeof token).toBe("string")
|
||||
|
||||
const payload = await verifyToken(token)
|
||||
expect(payload).not.toBeNull()
|
||||
expect(payload!.userId).toBe("user-1")
|
||||
expect(payload!.role).toBe("admin")
|
||||
})
|
||||
|
||||
it("rejects a tampered token", async () => {
|
||||
const token = await signToken({ userId: "user-1", role: "admin" })
|
||||
const tampered = token.slice(0, -5) + "XXXXX"
|
||||
const payload = await verifyToken(tampered)
|
||||
expect(payload).toBeNull()
|
||||
})
|
||||
|
||||
it("rejects an expired token", async () => {
|
||||
const { SignJWT } = await import("jose")
|
||||
const { getJWTSecret } = await import("@/lib/jwt")
|
||||
const expiredToken = await new SignJWT({ userId: "user-1", role: "admin" })
|
||||
.setProtectedHeader({ alg: "HS256" })
|
||||
.setExpirationTime("0s")
|
||||
.sign(getJWTSecret())
|
||||
const payload = await verifyToken(expiredToken)
|
||||
expect(payload).toBeNull()
|
||||
})
|
||||
|
||||
it("rejects a token with invalid signature", async () => {
|
||||
const { SignJWT } = await import("jose")
|
||||
const wrongSecret = new TextEncoder().encode("different-secret-key-for-signing-purposes-only")
|
||||
const token = await new SignJWT({ userId: "user-1", role: "admin" })
|
||||
.setProtectedHeader({ alg: "HS256" })
|
||||
.setExpirationTime("24h")
|
||||
.setIssuedAt()
|
||||
.sign(wrongSecret)
|
||||
const payload = await verifyToken(token)
|
||||
expect(payload).toBeNull()
|
||||
})
|
||||
|
||||
it("returns null for empty token", async () => {
|
||||
const payload = await verifyToken("")
|
||||
expect(payload).toBeNull()
|
||||
})
|
||||
|
||||
it("returns null for garbage token", async () => {
|
||||
const payload = await verifyToken("this.is.not.a.jwt")
|
||||
expect(payload).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user