diff --git a/pitch-deck/app/api/admin/fp-patch/route.ts b/pitch-deck/app/api/admin/fp-patch/route.ts index b972448..758828e 100644 --- a/pitch-deck/app/api/admin/fp-patch/route.ts +++ b/pitch-deck/app/api/admin/fp-patch/route.ts @@ -1,11 +1,14 @@ import { NextRequest, NextResponse } from 'next/server' +import { requireAdmin } from '@/lib/admin-auth' import pool from '@/lib/db' /** - * TEMPORARY: Auth disabled for one-time patch. Will be re-secured immediately after. + * Admin-only patch endpoint for Finanzplan data corrections. * POST /api/admin/fp-patch */ export async function POST(request: NextRequest) { + const guard = await requireAdmin(request) + if (guard.kind === 'response') return guard.response const results: string[] = [] diff --git a/pitch-deck/app/api/fp-patch/route.ts b/pitch-deck/app/api/fp-patch/route.ts deleted file mode 100644 index b972448..0000000 --- a/pitch-deck/app/api/fp-patch/route.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { NextRequest, NextResponse } from 'next/server' -import pool from '@/lib/db' - -/** - * TEMPORARY: Auth disabled for one-time patch. Will be re-secured immediately after. - * POST /api/admin/fp-patch - */ -export async function POST(request: NextRequest) { - - const results: string[] = [] - - // 1. Halve insurance costs for 2027 (months m13-m24) - const insuranceLabels = [ - 'D&O-Versicherung', - 'E&O-Versicherung', - 'Produkthaftpflicht', - 'Cyber-Versicherung', - 'Rechtsschutzversicherung', - ] - - for (const label of insuranceLabels) { - try { - // Get the row - const { rows } = await pool.query( - `SELECT id, row_label, values FROM fp_betriebliche_aufwendungen - WHERE row_label = $1 - AND scenario_id = (SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1)`, - [label] - ) - if (rows.length === 0) { - // Try partial match - const { rows: partial } = await pool.query( - `SELECT id, row_label, values FROM fp_betriebliche_aufwendungen - WHERE row_label ILIKE $1 - AND scenario_id = (SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1)`, - [`%${label}%`] - ) - if (partial.length === 0) { - results.push(`NOT FOUND: ${label}`) - continue - } - rows.push(...partial) - } - - for (const row of rows) { - const values = row.values || {} - const updates: Record = {} - - // 2027 = months m13 to m24 - for (let m = 13; m <= 24; m++) { - const key = `m${m}` - const current = values[key] || 0 - if (current > 0) { - updates[key] = Math.round(current / 2) - } - } - - if (Object.keys(updates).length > 0) { - const newValues = { ...values, ...updates } - await pool.query( - 'UPDATE fp_betriebliche_aufwendungen SET values = $1, updated_at = NOW() WHERE id = $2', - [JSON.stringify(newValues), row.id] - ) - results.push(`HALVED 2027: ${row.row_label} (id=${row.id})`) - } else { - results.push(`NO VALUES 2027: ${row.row_label}`) - } - } - } catch (err) { - results.push(`ERROR ${label}: ${err instanceof Error ? err.message : String(err)}`) - } - } - - // 2. Delete "Editorial Content" row - try { - const { rowCount } = await pool.query( - `DELETE FROM fp_betriebliche_aufwendungen - WHERE row_label ILIKE '%Editorial Content%' - AND scenario_id = (SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1)` - ) - results.push(`DELETED Editorial Content: ${rowCount} row(s)`) - } catch (err) { - results.push(`ERROR deleting Editorial Content: ${err instanceof Error ? err.message : String(err)}`) - } - - return NextResponse.json({ success: true, results }) -} diff --git a/pitch-deck/middleware.ts b/pitch-deck/middleware.ts index 5352691..2cfd3ba 100644 --- a/pitch-deck/middleware.ts +++ b/pitch-deck/middleware.ts @@ -6,7 +6,6 @@ const PUBLIC_PATHS = [ '/auth', // investor login pages '/api/auth', // investor auth API '/api/health', - '/api/fp-patch', // TEMP: one-time DB patch, will be removed '/api/admin-auth', // admin login API '/pitch-admin/login', // admin login page '/_next',