mirror of
https://git.coastit.co.za/caitlin/CRM_ENVR.git
synced 2026-07-10 11:15:43 +02:00
bc83af8e00
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.
43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
import { describe, it, expect } from "vitest"
|
|
import { sanitizeSvg } from "@/lib/sanitize"
|
|
|
|
describe("sanitizeSvg", () => {
|
|
it("strips script tags", () => {
|
|
const input = `<svg><script>alert('xss')</script><rect width="100" height="100"/></svg>`
|
|
const result = sanitizeSvg(input)
|
|
expect(result).not.toContain("script")
|
|
expect(result).toContain("<svg")
|
|
expect(result).toContain("<rect")
|
|
})
|
|
|
|
it("strips event handler attributes", () => {
|
|
const input = `<svg onload="alert(1)"><rect width="100" height="100"/></svg>`
|
|
const result = sanitizeSvg(input)
|
|
expect(result).not.toContain("onload")
|
|
expect(result).toContain("<svg")
|
|
expect(result).toContain("<rect")
|
|
})
|
|
|
|
it("strips onclick attributes", () => {
|
|
const input = `<svg><rect onclick="evil()" width="100" height="100"/></svg>`
|
|
const result = sanitizeSvg(input)
|
|
expect(result).not.toContain("onclick")
|
|
expect(result).toContain("<rect")
|
|
expect(result).toContain('width="100"')
|
|
})
|
|
|
|
it("removes javascript: URLs", () => {
|
|
const input = `<svg><a href="javascript:alert(1)">click</a></svg>`
|
|
const result = sanitizeSvg(input)
|
|
expect(result).not.toContain("javascript:")
|
|
})
|
|
|
|
it("passes through clean SVGs unchanged (except whitespace)", () => {
|
|
const input = `<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/></svg>`
|
|
const result = sanitizeSvg(input)
|
|
expect(result).toContain("viewBox")
|
|
expect(result).toContain("<circle")
|
|
expect(result).toContain('cx="12"')
|
|
})
|
|
})
|