feat: Zod validation on all API inputs (PRD §5.2)
26 files with Zod schemas, 27 safeParse calls. All POST/PATCH handlers now validate input: - Missing required fields → 400 with structured error - Invalid types (string vs number) → 400 - Out-of-range values (probability >100, negative amounts) → 400 - Valid data still works (behavior preserved) Pattern: schema.safeParse(await req.json()) → 400 on failure
This commit is contained in:
1 parent
3d56770669
commit
2614ce4e3d
25 files changed
+316
-116
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import * as net from 'net'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -13,6 +14,14 @@ interface MailTestResult {
|
||||
error?: string
|
||||
}
|
||||
|
||||
const testMailSchema = z.object({
|
||||
smtpHost: z.string().optional(),
|
||||
smtpPort: z.number().int().min(0).max(65535).optional(),
|
||||
imapHost: z.string().optional(),
|
||||
imapPort: z.number().int().min(0).max(65535).optional(),
|
||||
user: z.string().optional(),
|
||||
})
|
||||
|
||||
// Real TCP connection test to an SMTP/IMAP server.
|
||||
// Attempts to open a socket, read the greeting banner, then close.
|
||||
// No fake success — returns the actual connection result or error.
|
||||
@@ -76,13 +85,11 @@ function testConnection(host: string, port: number, timeoutMs = 8000): Promise<M
|
||||
// POST /api/aos/setup/test-mail
|
||||
// Real SMTP + IMAP connection test. No simulation.
|
||||
export async function POST(req: Request) {
|
||||
const body = (await req.json().catch(() => ({}))) as {
|
||||
smtpHost?: string
|
||||
smtpPort?: number
|
||||
imapHost?: string
|
||||
imapPort?: number
|
||||
user?: string
|
||||
const parsed = testMailSchema.safeParse(await req.json().catch(() => ({})))
|
||||
if (!parsed.success) {
|
||||
return NextResponse.json({ error: 'validation failed', details: parsed.error.flatten() }, { status: 400 })
|
||||
}
|
||||
const body = parsed.data
|
||||
|
||||
const [smtp, imap] = await Promise.all([
|
||||
testConnection(body.smtpHost ?? '', Number(body.smtpPort) || 0),
|
||||
|
||||
Reference in new issue
Block a user