fix: masquer les erreurs SQL des connecteurs web
This commit is contained in:
@@ -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
|
||||
|
||||
17
server/webImportSourcesError.test.ts
Normal file
17
server/webImportSourcesError.test.ts
Normal 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");
|
||||
});
|
||||
});
|
||||
25
server/webImportSourcesError.ts
Normal file
25
server/webImportSourcesError.ts
Normal 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 });
|
||||
}
|
||||
Reference in New Issue
Block a user