fix(dataroom): use getSessionFromCookie() instead of middleware headers; fix auth page overflow
Build pitch-deck / build-push-deploy (push) Successful in 1m33s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 37s
CI / test-python-voice (push) Successful in 31s
CI / test-bqas (push) Successful in 27s

Dataroom routes were reading x-investor-id from request headers which
the middleware sets as response headers — these don't reach route handlers
when the admin fallback path runs (NextResponse.next() without header).
Switch to getSessionFromCookie() consistent with all other investor routes.

Auth page DSGVO footer switched from absolute bottom-0 to normal flow
so the expanded Art. 13 notice doesn't overlap the login card.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-05-01 16:03:21 +02:00
parent 07039cc408
commit 370143b643
4 changed files with 24 additions and 17 deletions
@@ -1,15 +1,16 @@
import { NextRequest, NextResponse } from 'next/server' import { NextRequest, NextResponse } from 'next/server'
import pool from '@/lib/db' import pool from '@/lib/db'
import { streamFile } from '@/lib/dataroom-storage' import { streamFile } from '@/lib/dataroom-storage'
import { logAudit } from '@/lib/auth' import { logAudit, getSessionFromCookie } from '@/lib/auth'
import path from 'path' import path from 'path'
interface Ctx { params: Promise<{ id: string }> } interface Ctx { params: Promise<{ id: string }> }
export async function GET(request: NextRequest, ctx: Ctx) { export async function GET(request: NextRequest, ctx: Ctx) {
const investorId = request.headers.get('x-investor-id') const session = await getSessionFromCookie()
const sessionId = request.headers.get('x-session-id') if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
if (!investorId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const investorId = session.sub
const sessionId = session.sessionId
const { id } = await ctx.params const { id } = await ctx.params
@@ -1,11 +1,13 @@
import { NextRequest, NextResponse } from 'next/server' import { NextRequest, NextResponse } from 'next/server'
import pool from '@/lib/db' import pool from '@/lib/db'
import { getSessionFromCookie } from '@/lib/auth'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest) { export async function GET(request: NextRequest) {
const investorId = request.headers.get('x-investor-id') const session = await getSessionFromCookie()
if (!investorId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
const investorId = session.sub
const { rows } = await pool.query( const { rows } = await pool.query(
`SELECT d.id, d.filename, d.display_name, d.mime_type, d.file_size, r.released_at `SELECT d.id, d.filename, d.display_name, d.mime_type, d.file_size, r.released_at
+9 -7
View File
@@ -1,16 +1,17 @@
import { NextRequest, NextResponse } from 'next/server' import { NextRequest, NextResponse } from 'next/server'
import pool from '@/lib/db' import pool from '@/lib/db'
import { investorUploadDir, saveFile, safeName } from '@/lib/dataroom-storage' import { investorUploadDir, saveFile, safeName } from '@/lib/dataroom-storage'
import { logAudit } from '@/lib/auth' import { logAudit, getSessionFromCookie } from '@/lib/auth'
import { randomUUID } from 'crypto' import { randomUUID } from 'crypto'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
const MAX_BYTES = parseInt(process.env.DATAROOM_MAX_UPLOAD_MB || '50') * 1024 * 1024 const MAX_BYTES = parseInt(process.env.DATAROOM_MAX_UPLOAD_MB || '50') * 1024 * 1024
export async function GET(request: NextRequest) { export async function GET(_request: NextRequest) {
const investorId = request.headers.get('x-investor-id') const session = await getSessionFromCookie()
if (!investorId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
const investorId = session.sub
const { rows } = await pool.query( const { rows } = await pool.query(
`SELECT id, filename, display_name, mime_type, file_size, created_at `SELECT id, filename, display_name, mime_type, file_size, created_at
@@ -23,9 +24,10 @@ export async function GET(request: NextRequest) {
} }
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
const investorId = request.headers.get('x-investor-id') const session = await getSessionFromCookie()
const sessionId = request.headers.get('x-session-id') if (!session) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
if (!investorId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) const investorId = session.sub
const sessionId = session.sessionId
const formData = await request.formData() const formData = await request.formData()
const file = formData.get('file') as File | null const file = formData.get('file') as File | null
+6 -4
View File
@@ -39,15 +39,16 @@ export default function AuthPage() {
} }
return ( return (
<div className="h-screen flex items-center justify-center bg-[#0a0a1a] relative overflow-hidden"> <div className="min-h-screen flex flex-col bg-[#0a0a1a] relative overflow-x-hidden">
{/* Background gradient */} {/* Background gradient */}
<div className="absolute inset-0 bg-gradient-to-br from-indigo-950/30 via-transparent to-purple-950/20" /> <div className="absolute inset-0 bg-gradient-to-br from-indigo-950/30 via-transparent to-purple-950/20 pointer-events-none" />
<div className="flex-1 flex items-center justify-center py-12 px-6">
<motion.div <motion.div
initial={{ opacity: 0, y: 20 }} initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }} animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }} transition={{ duration: 0.6 }}
className="relative z-10 text-center max-w-md mx-auto px-6" className="relative z-10 text-center max-w-md w-full mx-auto"
> >
<div className="mb-8"> <div className="mb-8">
<h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent mb-2"> <h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent mb-2">
@@ -122,9 +123,10 @@ export default function AuthPage() {
We are an AI-first company. No PDFs. No slide decks. Just code. We are an AI-first company. No PDFs. No slide decks. Just code.
</p> </p>
</motion.div> </motion.div>
</div>
{/* Privacy Notice Footer */} {/* Privacy Notice Footer */}
<div className="absolute bottom-0 left-0 right-0 px-8 py-4 border-t border-white/5"> <div className="relative z-10 px-8 py-5 border-t border-white/5">
<div className="max-w-2xl mx-auto"> <div className="max-w-2xl mx-auto">
<p className="text-[10px] text-white/20 leading-relaxed text-center"> <p className="text-[10px] text-white/20 leading-relaxed text-center">
<strong className="text-white/25">Datenschutzhinweis (Art. 13 DSGVO):</strong> Beim Zugriff werden technische Zugriffsdaten (IP-Adresse, Zeitpunkt, Browser) sowie  soweit eingeladen  personenbezogene Kontaktdaten (E-Mail, Name, Unternehmen) verarbeitet. Zweck: Zugangsverwaltung und Missbrauchsprävention. Rechtsgrundlage: Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse). Speicherdauer: max. 30 Tage nach letztem Zugriff; nicht aktivierte Zugänge nach 90 Tagen. Danach automatische Anonymisierung. Ihre Rechte gem. Art. 1521 DSGVO (Auskunft, Berichtigung, Löschung, Einschränkung, Datenübertragbarkeit, Widerspruch): Anfragen an pitch@breakpilot.ai. Beschwerderecht bei der Aufsichtsbehörde: LfDI Baden-Württemberg (www.baden-wuerttemberg.datenschutz.de).</p> <strong className="text-white/25">Datenschutzhinweis (Art. 13 DSGVO):</strong> Beim Zugriff werden technische Zugriffsdaten (IP-Adresse, Zeitpunkt, Browser) sowie  soweit eingeladen  personenbezogene Kontaktdaten (E-Mail, Name, Unternehmen) verarbeitet. Zweck: Zugangsverwaltung und Missbrauchsprävention. Rechtsgrundlage: Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse). Speicherdauer: max. 30 Tage nach letztem Zugriff; nicht aktivierte Zugänge nach 90 Tagen. Danach automatische Anonymisierung. Ihre Rechte gem. Art. 1521 DSGVO (Auskunft, Berichtigung, Löschung, Einschränkung, Datenübertragbarkeit, Widerspruch): Anfragen an pitch@breakpilot.ai. Beschwerderecht bei der Aufsichtsbehörde: LfDI Baden-Württemberg (www.baden-wuerttemberg.datenschutz.de).</p>