From ef2476bade591336293cb018743b07bbb6a90a69 Mon Sep 17 00:00:00 2001 From: Adisak Date: Tue, 28 Oct 2025 16:58:59 +0700 Subject: [PATCH 1/2] revert --- .../KpiUserEvaluationController.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/controllers/KpiUserEvaluationController.ts b/src/controllers/KpiUserEvaluationController.ts index 0e69f88..9816fb0 100644 --- a/src/controllers/KpiUserEvaluationController.ts +++ b/src/controllers/KpiUserEvaluationController.ts @@ -1328,23 +1328,23 @@ export class KpiUserEvaluationController extends Controller { "ไม่พบข้อมูลรายการประเมินผลการปฏิบัติราชการระดับบุคคลนี้", ); } - // await new CallAPI() - // .PostData(request, "/placement/noti/profiles", { - // subject: `${kpiUserEvaluation.prefix}${kpiUserEvaluation.firstName} ${kpiUserEvaluation.lastName} มีความเห็นต่างเนื่องจาก: ${requestBody.reason}`, - // body: `${kpiUserEvaluation.prefix}${kpiUserEvaluation.firstName} ${kpiUserEvaluation.lastName} มีความเห็นต่างเนื่องจาก: ${requestBody.reason}`, - // receiverUserIds: [ - // { - // receiverUserId: kpiUserEvaluation.evaluatorId, - // notiLink: `${process.env.VITE_URL_USER}/KPI-evaluator/${kpiUserEvaluation.id}`, - // }, - // ], - // payload: "", - // isSendMail: true, - // isSendInbox: true, - // isSendNotification: true, - // }) - // .then(() => {}) - // .catch(() => {}); + await new CallAPI() + .PostData(request, "/placement/noti/profiles", { + subject: `${kpiUserEvaluation.prefix}${kpiUserEvaluation.firstName} ${kpiUserEvaluation.lastName} มีความเห็นต่างเนื่องจาก: ${requestBody.reason}`, + body: `${kpiUserEvaluation.prefix}${kpiUserEvaluation.firstName} ${kpiUserEvaluation.lastName} มีความเห็นต่างเนื่องจาก: ${requestBody.reason}`, + receiverUserIds: [ + { + receiverUserId: kpiUserEvaluation.evaluatorId, + notiLink: `${process.env.VITE_URL_USER}/KPI-evaluator/${kpiUserEvaluation.id}`, + }, + ], + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then(() => {}) + .catch(() => {}); const before = structuredClone(kpiUserEvaluation); let _null: any = null; kpiUserEvaluation.evaluationStatus = "EVALUATING_EVALUATOR"; From f3e90ef95555b6f677c281c300b27b44cf828bc8 Mon Sep 17 00:00:00 2001 From: Adisak Date: Wed, 29 Oct 2025 09:54:37 +0700 Subject: [PATCH 2/2] test safeStringify --- src/interfaces/call-api.ts | 14 +++++++------- src/interfaces/utils.ts | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/interfaces/call-api.ts b/src/interfaces/call-api.ts index 73f6c90..3ae4a7c 100644 --- a/src/interfaces/call-api.ts +++ b/src/interfaces/call-api.ts @@ -12,7 +12,7 @@ import { Path, } from "tsoa"; import axios from "axios"; -import { addLogSequence } from "./utils"; +import { addLogSequence, safeStringify } from "./utils"; class CallAPI { //Get @@ -34,7 +34,7 @@ class CallAPI { request: { method: "GET", url: url, - response: JSON.stringify(response.data.result), + response: safeStringify(response.data.result), }, }); return response.data.result; @@ -46,7 +46,7 @@ class CallAPI { request: { method: "GET", url: url, - response: JSON.stringify(error), + response: safeStringify(error), }, }); throw error; @@ -71,8 +71,8 @@ class CallAPI { request: { method: "POST", url: url, - payload: JSON.stringify(sendData), - response: JSON.stringify(response.data.result), + payload: safeStringify(sendData), + response: safeStringify(response.data.result), }, }); return response.data.result; @@ -84,8 +84,8 @@ class CallAPI { request: { method: "POST", url: url, - payload: JSON.stringify(sendData), - response: JSON.stringify(error), + payload: safeStringify(sendData), + response: safeStringify(error), }, }); throw error; diff --git a/src/interfaces/utils.ts b/src/interfaces/utils.ts index c667f54..259b113 100644 --- a/src/interfaces/utils.ts +++ b/src/interfaces/utils.ts @@ -27,8 +27,8 @@ export function setLogDataDiff(req: RequestWithUser, data: DataDiff) { typeof data.after === "object" ) { req.app.locals.logData.dataDiff = { - before: JSON.stringify(data.before), - after: JSON.stringify(data.after), + before: safeStringify(data.before), + after: safeStringify(data.after), }; } else { console.error("Invalid data provided: both before and after must be valid objects."); @@ -45,3 +45,33 @@ export function addLogSequence(req: RequestWithUser, data: LogSequence) { export function editLogSequence(req: RequestWithUser, index: number, data: LogSequence) { req.app.locals.logData.sequence[index] = data; } + +/** + * ปลอดภัยกว่า JSON.stringify() + * - กัน circular reference + * - จำกัดความลึก + * - return string แน่นอนเสมอ + */ +export function safeStringify(obj: any, space?: number): string { + const cache = new WeakSet(); + + try { + return JSON.stringify( + obj, + (key, value) => { + // ป้องกัน circular reference + if (typeof value === "object" && value !== null) { + if (cache.has(value)) { + return "[Circular]"; + } + cache.add(value); + } + return value; + }, + space, + ); + } catch (err) { + console.error("⚠️ safeStringify error:", err); + return "[Unserializable object]"; + } +}