feat: add GET /api/documents/latest returning latest version file with stamped ticket
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 1m23s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 5s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 0s
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 1m23s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 5s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 0s
Server-to-server endpoint for the e-Court backend (x-api-key against DOCVER_API_KEY or EXTERNAL_API_KEY): - type=pdf returns the latest version's PDF bytes (404 when absent) - type=docx stamps fresh ticket custom properties (exp + HmacSha256 via addinTicketSecret(), Ed25519 when PRIVATE_KEY_HEX is set) into an in-memory copy before returning — MinIO object is never modified - docId comes from fid inside the ticket_data query param, which must include fid/uid/uname so the stamped file stays redeemable by the add-in at /api/documents/token (buildStampedTicketData drops null values because parseDocverTicket rejects tid:null) - adds parseTicketDataParam, parseLatestTypeParam, requireDocumentApiKey, findLatestVersionForDoc, getVersionObjectBytes + unit tests (320 pass) - syncs PLAN-DOCVER.md, OpenAPI spec and .env.example Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
5bc8d9a817
commit
0b6ee8cc84
12 changed files with 806 additions and 9 deletions
|
|
@ -18,6 +18,7 @@ import {
|
|||
} from "@/db/schema";
|
||||
import {
|
||||
contentDispositionValue,
|
||||
DOCVER_MAX_UPLOAD_BYTES,
|
||||
DOCX_CONTENT_TYPE,
|
||||
PDF_CONTENT_TYPE,
|
||||
} from "@/lib/document-versioning";
|
||||
|
|
@ -177,6 +178,35 @@ export async function presignVersionUrl(
|
|||
};
|
||||
}
|
||||
|
||||
/** อ่านไบต์ของ object หนึ่งกลับมาเป็น Buffer — ใช้กับ GET /api/documents/latest
|
||||
* ที่ต้องคืนไฟล์ผ่าน response เอง (ไม่ใช่ presigned URL) · อ่านอย่างเดียว ไม่เขียน
|
||||
* กลับ: การ stamp ticket ของ route ทำบนสำเนอในหน่วยความจำ · กันขนาดเกิน cap ของ
|
||||
* กลุ่ม (object เขียนผ่านกลุ่มนี้เองจึงไม่ควรเกิน — เกิน = ข้อมูลแปลกปลอม อ่านต่อไม่ได้)
|
||||
* · ล้มทุกกรณี = throw ให้ route catch เป็น 500 */
|
||||
export async function getVersionObjectBytes(
|
||||
versionId: string,
|
||||
format: "docx" | "pdf",
|
||||
): Promise<Buffer> {
|
||||
const { client, config } = getClient();
|
||||
const key = versionObjectKeys(versionId)[format];
|
||||
const stream = await client.getObject(config.bucket, key);
|
||||
return await new Promise<Buffer>((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
let total = 0;
|
||||
stream.on("data", (chunk: Buffer) => {
|
||||
total += chunk.length;
|
||||
if (total > DOCVER_MAX_UPLOAD_BYTES) {
|
||||
stream.destroy();
|
||||
reject(new Error(`docver: object ${key} ใหญ่เกิน ${DOCVER_MAX_UPLOAD_BYTES} bytes`));
|
||||
return;
|
||||
}
|
||||
chunks.push(chunk);
|
||||
});
|
||||
stream.on("end", () => resolve(Buffer.concat(chunks)));
|
||||
stream.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── DB ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
export async function findDocumentByDocId(docId: string): Promise<DocumentRow | null> {
|
||||
|
|
@ -207,6 +237,21 @@ export async function findVersionForDoc(
|
|||
return row?.version ?? null;
|
||||
}
|
||||
|
||||
/** version ล่าสุดของเอกสาร (docId) — join แบบ findVersionForDoc + เรียงเลข version
|
||||
* จากมากไปน้อยแล้วเอาตัวแรก · ใช้กับ GET /api/documents/latest */
|
||||
export async function findLatestVersionForDoc(
|
||||
docId: string,
|
||||
): Promise<DocumentVersionRow | null> {
|
||||
const [row] = await db
|
||||
.select({ version: documentVersions })
|
||||
.from(documentVersions)
|
||||
.innerJoin(documents, eq(documentVersions.documentId, documents.id))
|
||||
.where(eq(documents.docId, docId))
|
||||
.orderBy(desc(documentVersions.versionNumber))
|
||||
.limit(1);
|
||||
return row?.version ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* เอกสาร (docId) นี้เคยมี version ที่สร้างโดย userId นี้หรือยัง — ใช้เป็นหลักฐาน
|
||||
* "เคยทำงานกับเอกสารนี้" ตอนยอมรับ ticket ที่หมดอายุ (requirement ขั้น 7:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue