- Remplacement de DocuSeal par solution souveraine Odentas Sign - Système d'authentification OTP pour signataires (bcryptjs + JWT) - 8 routes API: send-otp, verify-otp, sign, pdf-url, positions, status, webhook, signers - Interface moderne avec canvas de signature et animations (framer-motion, confetti) - Système de templates pour auto-détection des positions de signature (CDDU, RG, avenants) - PDF viewer avec @react-pdf-viewer (compatible Next.js) - Stockage S3: source/, signatures/, evidence/, signed/, certs/ - Tables Supabase: sign_requests, signers, sign_positions, sign_events, sign_assets - Evidence bundle automatique (JSON metadata + timestamps) - Templates emails: OTP et completion - Scripts Lambda prêts: pades-sign (KMS seal) et tsaStamp (RFC3161) - Mode test détecté automatiquement (emails whitelist) - Tests complets avec PDF CDDU réel (2 signataires)
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { verifySignatureSession } from '@/lib/odentas-sign/jwt';
|
|
import { supabaseAdmin } from '@/lib/odentas-sign/supabase';
|
|
import { getPresignedDownloadUrl } from '@/lib/odentas-sign/s3';
|
|
|
|
/**
|
|
* GET /api/odentas-sign/requests/:id/pdf-url
|
|
* Récupère l'URL présignée du PDF source
|
|
*/
|
|
export async function GET(
|
|
request: NextRequest,
|
|
{ params }: { params: { id: string } }
|
|
) {
|
|
try {
|
|
const requestId = params.id;
|
|
|
|
// Vérifier le token JWT
|
|
const authHeader = request.headers.get('Authorization');
|
|
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
return NextResponse.json(
|
|
{ error: 'Token manquant ou invalide' },
|
|
{ status: 401 }
|
|
);
|
|
}
|
|
|
|
const token = authHeader.split(' ')[1];
|
|
const payload = verifySignatureSession(token);
|
|
|
|
if (!payload || payload.requestId !== requestId) {
|
|
return NextResponse.json(
|
|
{ error: 'Token invalide ou expiré' },
|
|
{ status: 401 }
|
|
);
|
|
}
|
|
|
|
// Récupérer le document depuis la DB
|
|
const { data: signRequest, error } = await supabaseAdmin
|
|
.from('sign_requests')
|
|
.select('source_s3_key, status')
|
|
.eq('id', requestId)
|
|
.single();
|
|
|
|
if (error || !signRequest) {
|
|
console.error('Erreur DB lors de la récupération du document:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Demande de signature introuvable' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
// Générer l'URL présignée (valide 1h)
|
|
const presignedUrl = await getPresignedDownloadUrl(signRequest.source_s3_key, 3600);
|
|
|
|
return NextResponse.json({
|
|
url: presignedUrl,
|
|
s3Key: signRequest.source_s3_key,
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('Erreur lors de la génération de l\'URL PDF:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Erreur serveur lors de la génération de l\'URL' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|