fix: masquer les erreurs SQL des connecteurs web

This commit is contained in:
Manus
2026-09-30 13:55:36 +00:00
committed by manus-admin
parent 343ad71a59
commit a9c81b4238
3 changed files with 51 additions and 1 deletions

View File

@@ -107,6 +107,7 @@ import { drawBapCartouche } from "./bapCartouche";
import { resolveBapExportDestination } from "./exportDestinationResolver";
import { startEmailImportService, stopEmailImportService, isEmailImportServiceRunning, triggerEmailCheck, triggerManualEmailCheck, testImapConnection } from "./emailImportService";
import { startFolderImportService, stopFolderImportService, isFolderImportServiceRunning } from "./folderImportService";
import { getSafeWebImportSourceError, logWebImportSourceSaveFailure } from "./webImportSourcesError";
import { TRPCError } from "@trpc/server";
import { processFreeproExcel } from "./freeproService";
import { runFreeproAutoImport, testFreeproConnection, startFreeproAutoJob, stopFreeproAutoJob, frequencyToMs } from "./freeproAutoImport";
@@ -2731,7 +2732,14 @@ export const appRouter = router({
autoEnabled: z.number().min(0).max(1).default(0),
}))
.mutation(async ({ input, ctx }) => {
return createWebImportSource({ ...input, userId: ctx.user.id });
try {
return await createWebImportSource({ ...input, userId: ctx.user.id });
} catch (error) {
// Les erreurs MySQL/Drizzle peuvent contenir la requête et les paramètres saisis.
// Elles restent masquées côté navigateur.
logWebImportSourceSaveFailure(error);
throw getSafeWebImportSourceError(error);
}
}),
update: protectedProcedure

View File

@@ -0,0 +1,17 @@
import { describe, expect, it } from "vitest";
import { WEB_IMPORT_SOURCE_SAVE_ERROR, getSafeWebImportSourceError } from "./webImportSourcesError";
describe("getSafeWebImportSourceError", () => {
it("never returns the SQL statement or connector parameters to the client", () => {
const databaseError = new Error(
"Failed query: insert into `webImportSources` (...) values (...) params: amazon@example.fr, secret-value",
);
const safeError = getSafeWebImportSourceError(databaseError);
expect(safeError.code).toBe("INTERNAL_SERVER_ERROR");
expect(safeError.message).toBe(WEB_IMPORT_SOURCE_SAVE_ERROR);
expect(safeError.message).not.toContain("insert into");
expect(safeError.message).not.toContain("secret-value");
});
});

View File

@@ -0,0 +1,25 @@
import { TRPCError } from "@trpc/server";
export const WEB_IMPORT_SOURCE_SAVE_ERROR =
"Impossible d’enregistrer le connecteur. Vérifiez les informations saisies puis réessayez.";
/**
* Masque toute erreur Drizzle/MySQL avant son retour au navigateur : les erreurs
* de pilote peuvent contenir la requête SQL et les paramètres de connexion.
*/
export function getSafeWebImportSourceError(_error: unknown): TRPCError {
return new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: WEB_IMPORT_SOURCE_SAVE_ERROR,
});
}
/** Journalise uniquement les métadonnées techniques non sensibles. */
export function logWebImportSourceSaveFailure(error: unknown): void {
const technicalCode =
error && typeof error === "object" && "code" in error && typeof error.code === "string"
? error.code
: "unknown";
console.error("[WebImportSources] Échec d’enregistrement", { technicalCode });
}