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
|
|
@ -858,6 +858,100 @@ export const openApiSpec = {
|
|||
},
|
||||
},
|
||||
},
|
||||
"/api/documents/latest": {
|
||||
get: {
|
||||
tags: ["documents"],
|
||||
summary:
|
||||
"ดาวน์โหลดไฟล์ของ version ล่าสุด (docx พร้อม stamp ticket ใหม่ / pdf ตรง ๆ)",
|
||||
description:
|
||||
"ให้ backend e-Court ดึงไฟล์ **version ล่าสุด** ของเอกสารกลับไปเปิดให้ผู้ใช้ " +
|
||||
"(server-to-server — ไม่ใช้ Bearer token)\n\n" +
|
||||
"- **auth**: header `x-api-key` เทียบ env `DOCVER_API_KEY` **หรือ** " +
|
||||
"`EXTERNAL_API_KEY` ตัวใดตัวหนึ่ง (ต่างจาก /token ที่รับ DOCVER_API_KEY " +
|
||||
"อย่างเดียว) · ทั้งคู่ไม่ตั้ง = 401 fail closed\n" +
|
||||
"- เอกสารถูกระบุด้วย `fid` **ใน ticket_data** (ไม่ใช่ token)\n" +
|
||||
"- `type=pdf` → คืนไบต์ pdf ตรง ๆ (version ล่าสุดไม่มีสำเนา PDF = 404)\n" +
|
||||
"- `type=docx` → server เติม `exp` ใหม่ (now + `TICKET_SEC` default 300 วิ) + " +
|
||||
"คำนวณ `HmacSha256` (secret ตาม chain `ADDIN_TICKET_SECRET` → `SECRET` → " +
|
||||
"`\"super_secret\"` ให้ตรงฝั่ง verify ของ add-in) และ `Ed25519` (เฉพาะเมื่อ " +
|
||||
"`PRIVATE_KEY_HEX` ตั้ง) แล้วเขียน custom properties ลง**สำเนาในหน่วยความจำ** " +
|
||||
"ก่อนคืนไฟล์ — object ใน MinIO ไม่ถูกแต่ (non-destructive) และเขียนทับ stamp " +
|
||||
"เดิมของ template ได้\n" +
|
||||
"- **ticket_data บังคับ `fid` + `uid` + `uname`** (`tid` optional · `exp` ถ้าส่ง " +
|
||||
"ต้องเป็นจำนวนเต็ม แต่จะถูกเติมใหม่เสมอ) เพราะ parser ฝั่ง add-in บังคับทั้งสาม — " +
|
||||
"⚠️ `uid` ต้องเป็น*รหัส*ผู้ใช้ (ไม่ใช่ชื่อ) และต้องส่ง `uname` (ชื่อแสดงผล)\n" +
|
||||
"- ticket_data หลังเติม exp ยาวเกิน 255 ตัวอักษร = 400 (ข้อจำกัด custom property " +
|
||||
"ของ Word)",
|
||||
security: [{ ApiKeyAuth: [] }],
|
||||
parameters: [
|
||||
{
|
||||
name: "type",
|
||||
in: "query",
|
||||
required: true,
|
||||
schema: { type: "string", enum: ["docx", "pdf"] },
|
||||
description: "ชนิดไฟล์ที่จะดาวน์โหลด (บังคับระบุ — ไม่มีค่า default)",
|
||||
},
|
||||
{
|
||||
name: "ticket_data",
|
||||
in: "query",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
description:
|
||||
"JSON string ของ ticket เช่น " +
|
||||
"`{\"fid\":\"DOC-2569-0001\",\"uid\":\"123\",\"uname\":\"สมชาย ใจดี\"}` " +
|
||||
"(ต้อง URL-encode — ใช้ URLSearchParams ของฝั่งเรียกก็ได้)",
|
||||
example:
|
||||
"{\"fid\":\"DOC-2569-0001\",\"uid\":\"123\",\"uname\":\"สมชาย ใจดี\"}",
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
description:
|
||||
"ไบต์ของไฟล์ (docx = ผ่านการ stamp ticket ใหม่ · pdf = ตรงจาก version ล่าสุด)",
|
||||
headers: {
|
||||
"Content-Disposition": {
|
||||
description: "attachment พร้อมชื่อไฟล์ของ version (ชื่อไทยผ่าน filename*)",
|
||||
schema: { type: "string" },
|
||||
},
|
||||
"Cache-Control": {
|
||||
description: "no-store — ไฟล์ผูกกับ ticket/exp ของ request นั้น",
|
||||
schema: { type: "string" },
|
||||
},
|
||||
},
|
||||
content: {
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
|
||||
schema: { type: "string", format: "binary" },
|
||||
},
|
||||
"application/pdf": {
|
||||
schema: { type: "string", format: "binary" },
|
||||
},
|
||||
},
|
||||
},
|
||||
400: { $ref: "#/components/responses/BadRequest" },
|
||||
401: {
|
||||
description:
|
||||
"x-api-key ไม่ตรงทั้ง DOCVER_API_KEY และ EXTERNAL_API_KEY หรือทั้งคู่ไม่ตั้งค่า " +
|
||||
"(ไม่ใส่ header กับ key ผิดได้ข้อความเดียวกัน)",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description:
|
||||
"ไม่พบเอกสารนี้ในระบบ (ยังไม่เคยอัปโหลด version) หรือ type=pdf แต่ version " +
|
||||
"ล่าสุดไม่มีสำเนา PDF",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
500: { $ref: "#/components/responses/ServerError" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
securitySchemes: {
|
||||
|
|
@ -868,7 +962,8 @@ export const openApiSpec = {
|
|||
description:
|
||||
"x-api-key ของ N10 = env EXTERNAL_API_KEY · ของการขอ token กลุ่ม documents = env " +
|
||||
"DOCVER_API_KEY (คนละค่ากับของ N10 — กดปุ่ม Authorize ใส่ครั้งเดียวแล้วใช้ได้ทุก " +
|
||||
"request ของกลุ่มที่ key ตรง)",
|
||||
"request ของกลุ่มที่ key ตรง) · GET /api/documents/latest พิเศษ: รับได้ทั้งสองค่า " +
|
||||
"(DOCVER_API_KEY **หรือ** EXTERNAL_API_KEY ตัวใดตัวหนึ่งตรง = ผ่าน)",
|
||||
},
|
||||
DocverBearer: {
|
||||
type: "http",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue