espace-paie-odentas/app/api/documents/generaux/route.ts

158 lines
4.7 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { GetObjectCommand } from "@aws-sdk/client-s3";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
const s3Client = new S3Client({
region: process.env.AWS_REGION || "eu-west-3",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID || "",
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || "",
},
});
const BUCKET_NAME = (process.env.AWS_S3_BUCKET || "odentas-docs").trim();
// Fonction pour slugifier les noms (enlever accents, espaces, etc.)
function slugify(text: string): string {
return text
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '') // Enlever les accents
.toLowerCase()
.trim()
.replace(/[^a-z0-9]+/g, '-') // Remplacer les caractères spéciaux par des tirets
.replace(/^-+|-+$/g, ''); // Enlever les tirets en début/fin
}
// Types de documents généraux
const DOC_TYPES = {
"contrat-odentas": "Contrat Odentas",
"licence-spectacles": "Licence de spectacles",
"rib": "RIB",
"kbis-jo": "KBIS / Journal Officiel",
"delegation-signature": "Délégation de signature"
};
interface GeneralDocument {
type: string;
label: string;
available: boolean;
key?: string;
name?: string;
size?: number;
lastModified?: string;
downloadUrl?: string;
}
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const orgId = searchParams.get('org_id');
if (!orgId) {
return NextResponse.json({
error: "Organization ID requis"
}, { status: 400 });
}
// Vérifier l'authentification
const sb = createRouteHandlerClient({ cookies });
const { data: { user } } = await sb.auth.getUser();
if (!user) {
return NextResponse.json({
error: "Non authentifié"
}, { status: 401 });
}
// Récupérer la clé de l'organisation (structure_api)
const { data: org, error: orgError } = await sb
.from('organizations')
.select('structure_api')
.eq('id', orgId)
.single();
if (orgError || !org?.structure_api) {
return NextResponse.json({
error: "Organisation non trouvée"
}, { status: 404 });
}
const orgKey = slugify(org.structure_api);
const prefix = `documents/${orgKey}/docs-generaux/`;
// Lister les fichiers dans S3
const listCommand = new ListObjectsV2Command({
Bucket: BUCKET_NAME,
Prefix: prefix,
});
const listResponse = await s3Client.send(listCommand);
// Initialiser tous les types de documents
const documents: GeneralDocument[] = Object.entries(DOC_TYPES).map(([type, label]) => ({
type,
label,
available: false
}));
// Si des fichiers existent, les associer aux types correspondants
if (listResponse.Contents && listResponse.Contents.length > 0) {
for (const item of listResponse.Contents) {
if (!item.Key) continue;
const fileName = item.Key.split('/').pop() || '';
// Ignorer les fichiers système comme .DS_Store
if (fileName.startsWith('.') || fileName === '.DS_Store') {
continue;
}
// Déterminer le type de document basé sur le préfixe du nom de fichier
for (const [type, label] of Object.entries(DOC_TYPES)) {
if (fileName.toLowerCase().startsWith(type)) {
// Générer une URL pré-signée valide 1 heure
const getCommand = new GetObjectCommand({
Bucket: BUCKET_NAME,
Key: item.Key,
});
const signedUrl = await getSignedUrl(s3Client, getCommand, {
expiresIn: 3600 // 1 heure
});
// Trouver le document correspondant et le mettre à jour
const docIndex = documents.findIndex(d => d.type === type);
if (docIndex !== -1) {
documents[docIndex] = {
type,
label,
available: true,
key: item.Key,
name: fileName,
size: item.Size || 0,
lastModified: item.LastModified?.toISOString() || new Date().toISOString(),
downloadUrl: signedUrl
};
}
break;
}
}
}
}
return NextResponse.json({
documents,
orgKey
});
} catch (error) {
console.error("Erreur récupération documents généraux S3:", error);
return NextResponse.json(
{ error: "Erreur lors de la récupération des documents" },
{ status: 500 }
);
}
}