Add new template format with hashing algorithm
All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 4s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 1m18s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 6s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 0s

This commit is contained in:
oom 2026-10-22 22:33:14 +07:00
parent 280cc2da40
commit ac6c0dc71e
17 changed files with 2157 additions and 609 deletions

View file

@ -1,8 +1,6 @@
import { NextResponse } from "next/server";
import {
templateContentControls,
type TemplateData,
} from "../lib-tmpl";
import { DocumentTemplate, templateContentControls, setCustomDocProps, getDocProps, templateDynamicContents } from "@/lib/lib-tmpl";
import { generateHmacSha256, verifyHmacSha256, signDataEd25519, verifyDataEd25519, sortObjectKeys } from '@/lib/lib-utils';
export const runtime = "nodejs";
@ -20,7 +18,13 @@ export async function POST(request: Request) {
const template = formData.get("template");
const dataFile = formData.get("data");
const dataJson = formData.get("dataJson");
const TEST_SECRET = (typeof formData.get("secret") === "string") ?
String(formData.get("secret")) : "super_secret";
const TEST_PRIVATE_KEY_HEX = (typeof formData.get("private_key") === "string") ?
String(formData.get("private_key")) : "8f2077b57b39399b6a7828f35da03a63ade8e3a36a6bf437b091a8bdb3d18ee1";
console.log(`secret:${TEST_SECRET}`)
console.log(`private:${TEST_PRIVATE_KEY_HEX}`)
// -----------------------------
// ตรวจสอบ Template
// -----------------------------
@ -62,14 +66,14 @@ export async function POST(request: Request) {
// อ่าน JSON
// -----------------------------
let data: TemplateData;
let templateData: DocumentTemplate;
// JSON ผิด syntax เป็นความผิดของฝั่งผู้เรียก — คืน 400 ไม่ใช่ 500
// (catch กลางท้ายฟังก์ชันสงวนไว้ให้ error ของระบบเท่านั้น)
try {
if (typeof dataJson === "string" && dataJson.length > 0) {
// กรณีส่ง JSON ผ่าน form field
data = JSON.parse(dataJson) as TemplateData;
templateData = JSON.parse(dataJson) as DocumentTemplate;
} else if (dataFile instanceof File) {
if (dataFile.size > MAX_UPLOAD_BYTES) {
return NextResponse.json(
@ -84,7 +88,7 @@ export async function POST(request: Request) {
// กรณี upload data.json
const text = await dataFile.text();
data = JSON.parse(text) as TemplateData;
templateData = JSON.parse(text) as DocumentTemplate;
} else {
return NextResponse.json(
{
@ -99,9 +103,8 @@ export async function POST(request: Request) {
return NextResponse.json(
{
success: false,
error: `Invalid JSON data (${
error instanceof Error ? error.message : "parse error"
}).`,
error: `Invalid JSON data (${error instanceof Error ? error.message : "parse error"
}).`,
},
{ status: 400 },
);
@ -109,9 +112,9 @@ export async function POST(request: Request) {
// JSON ต้องเป็น object
if (
data === null ||
typeof data !== "object" ||
Array.isArray(data)
templateData === null ||
typeof templateData !== "object" ||
Array.isArray(templateData)
) {
return NextResponse.json(
{
@ -126,18 +129,52 @@ export async function POST(request: Request) {
// Template File → Buffer
// -----------------------------
const templateBuffer = Buffer.from(
let templateBuffer: Buffer = Buffer.from(
await template.arrayBuffer(),
);
// -----------------------------
// ใช้ lib-tmpl.ts เดิม
// -----------------------------
//Calculate hash
const originalTicket_data = templateData?.info?.ticket_data //expect valid json string
// console.log("templateData",templateData?.info?.ticket_data)
if (originalTicket_data && typeof originalTicket_data === 'string') {
try {
const output = templateContentControls(
templateBuffer,
data,
);
const ttlSeconds: number = 300
const originalTicketObj = JSON.parse(originalTicket_data)//sort and add expire to ticket data
if (originalTicketObj && typeof originalTicketObj === 'object') {
console.log("Found valid ticket data: hash it")
// คำนวณค่า expire (ปัจจุบัน + จำนวนวินาทีที่ต้องการให้หมดอายุ)
// หาร 1000 เพราะต้องการหน่วยวินาที (sec) ไม่ใช่มิลลิวินาที (ms)
const expireTimestamp = Math.floor(Date.now() / 1000) + ttlSeconds;
const fullObj = { ...originalTicketObj, exp: expireTimestamp };
const sortedObj = sortObjectKeys(fullObj);
// แปลงกลับเป็น JSON string เพื่อนำไปใช้ส่งและทำ Hash
const ticket_data = JSON.stringify(sortedObj);
// console.log("check secret:",TEST_SECRET,TEST_PRIVATE_KEY_HEX,ticket_data)
const HmacSha256 = generateHmacSha256(ticket_data, TEST_SECRET)
const Ed25519 = signDataEd25519(ticket_data, TEST_PRIVATE_KEY_HEX)
templateBuffer = setCustomDocProps(templateBuffer, { ticket_data, HmacSha256, Ed25519 })
}
} catch (error) {
console.error("Set custom property fail",error);
}
}
// Apply Dynamic Content
if (templateData?.dc && typeof templateData?.dc === "object") {
console.log("Apply Dynamic Content")
templateBuffer = Buffer.from(await templateDynamicContents(templateBuffer, templateData.dc))
}
// Apply Content Control
if (templateData?.cc && typeof templateData?.cc === "object") {
console.log("Apply Content Control")
templateBuffer = templateContentControls(templateBuffer, templateData.cc);
}
const output = templateBuffer;
// -----------------------------
// ส่ง DOCX กลับ