Files
Anonyme/app/components/AnonymizationLogic.tsx
2025-07-26 21:39:49 +02:00

178 lines
5.1 KiB
TypeScript

import { useState } from "react";
interface EntityMapping {
originalValue: string;
anonymizedValue: string;
entityType: string;
startIndex: number;
endIndex: number;
}
interface AnonymizationLogicProps {
sourceText: string;
fileContent: string;
uploadedFile: File | null;
setOutputText: (text: string) => void;
setError: (error: string | null) => void;
setEntityMappings: (mappings: EntityMapping[]) => void;
}
export const useAnonymization = ({
sourceText,
fileContent,
uploadedFile,
setOutputText,
setError,
setEntityMappings,
}: AnonymizationLogicProps) => {
const [isProcessing, setIsProcessing] = useState(false);
const anonymizeData = async () => {
const textToProcess = sourceText || fileContent || "";
if (!textToProcess.trim()) {
setError(
"Veuillez saisir du texte à anonymiser ou télécharger un fichier"
);
return;
}
setIsProcessing(true);
setError(null);
setOutputText("");
setEntityMappings([]);
try {
if (
uploadedFile &&
uploadedFile.type === "application/pdf" &&
!fileContent
) {
const formData = new FormData();
formData.append("file", uploadedFile);
const response = await fetch("/api/process-document", {
method: "POST",
body: formData,
});
if (!response.ok) {
throw new Error("Erreur lors du traitement du PDF");
}
const data = await response.json();
if (data.error) {
throw new Error(data.error);
}
if (data.anonymizedText) {
setOutputText(data.anonymizedText);
// TODO: Extraire les mappings depuis les résultats Presidio
setIsProcessing(false);
return;
}
}
await new Promise((resolve) => setTimeout(resolve, 1500));
// Simulation des mappings pour le fallback
const mappings: EntityMapping[] = [];
let anonymized = textToProcess;
// Noms
const nameMatches = textToProcess.matchAll(/\b[A-Z][a-z]+ [A-Z][a-z]+\b/g);
let nameCounter = 1;
for (const match of nameMatches) {
const replacement = `[Nom${nameCounter}]`;
mappings.push({
originalValue: match[0],
anonymizedValue: replacement,
entityType: "PERSON",
startIndex: match.index!,
endIndex: match.index! + match[0].length
});
anonymized = anonymized.replace(match[0], replacement);
nameCounter++;
}
// Téléphones
const phoneMatches = textToProcess.matchAll(/\b0[1-9](?:[\s.-]?\d{2}){4}\b/g);
let phoneCounter = 1;
for (const match of phoneMatches) {
const replacement = `[Téléphone${phoneCounter}]`;
mappings.push({
originalValue: match[0],
anonymizedValue: replacement,
entityType: "PHONE_NUMBER",
startIndex: match.index!,
endIndex: match.index! + match[0].length
});
anonymized = anonymized.replace(match[0], replacement);
phoneCounter++;
}
// Emails
const emailMatches = textToProcess.matchAll(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g);
let emailCounter = 1;
for (const match of emailMatches) {
const replacement = `[Email${emailCounter}]`;
mappings.push({
originalValue: match[0],
anonymizedValue: replacement,
entityType: "EMAIL_ADDRESS",
startIndex: match.index!,
endIndex: match.index! + match[0].length
});
anonymized = anonymized.replace(match[0], replacement);
emailCounter++;
}
// Adresses
const addressMatches = textToProcess.matchAll(/\b\d{1,3}\s+[a-zA-Z\s]+,\s*\d{5}\s+[a-zA-Z\s]+\b/g);
let addressCounter = 1;
for (const match of addressMatches) {
const replacement = `[Adresse${addressCounter}]`;
mappings.push({
originalValue: match[0],
anonymizedValue: replacement,
entityType: "LOCATION",
startIndex: match.index!,
endIndex: match.index! + match[0].length
});
anonymized = anonymized.replace(match[0], replacement);
addressCounter++;
}
// Numéros de sécurité sociale
const ssnMatches = textToProcess.matchAll(/\b\d\s\d{2}\s\d{2}\s\d{2}\s\d{3}\s\d{3}\s\d{2}\b/g);
let ssnCounter = 1;
for (const match of ssnMatches) {
const replacement = `[NuméroSS${ssnCounter}]`;
mappings.push({
originalValue: match[0],
anonymizedValue: replacement,
entityType: "FR_NIR",
startIndex: match.index!,
endIndex: match.index! + match[0].length
});
anonymized = anonymized.replace(match[0], replacement);
ssnCounter++;
}
setOutputText(anonymized);
setEntityMappings(mappings);
} catch (error) {
console.error("Erreur anonymisation:", error);
setError(
error instanceof Error
? error.message
: "Erreur lors de l'anonymisation"
);
} finally {
setIsProcessing(false);
}
};
return { anonymizeData, isProcessing };
};