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 { resolveBapExportDestination } from "./exportDestinationResolver";
|
||||||
import { startEmailImportService, stopEmailImportService, isEmailImportServiceRunning, triggerEmailCheck, triggerManualEmailCheck, testImapConnection } from "./emailImportService";
|
import { startEmailImportService, stopEmailImportService, isEmailImportServiceRunning, triggerEmailCheck, triggerManualEmailCheck, testImapConnection } from "./emailImportService";
|
||||||
import { startFolderImportService, stopFolderImportService, isFolderImportServiceRunning } from "./folderImportService";
|
import { startFolderImportService, stopFolderImportService, isFolderImportServiceRunning } from "./folderImportService";
|
||||||
|
import { getSafeWebImportSourceError, logWebImportSourceSaveFailure } from "./webImportSourcesError";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { processFreeproExcel } from "./freeproService";
|
import { processFreeproExcel } from "./freeproService";
|
||||||
import { runFreeproAutoImport, testFreeproConnection, startFreeproAutoJob, stopFreeproAutoJob, frequencyToMs } from "./freeproAutoImport";
|
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),
|
autoEnabled: z.number().min(0).max(1).default(0),
|
||||||
}))
|
}))
|
||||||
.mutation(async ({ input, ctx }) => {
|
.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
|
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