Merge branch 'forgejo-dev' into working
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 1m12s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 4s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s
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 1m12s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 4s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s
Resolve CLAUDE.md: คำอธิบาย lib/document-versioning.ts เอาของ forgejo-dev (field `fields` ถอดออก 2026-10-30) ส่วน lib/docver-token.ts เอาของ working (purpose login / verifyDocverLoginToken — โค้ดฝั่ง forgejo-dev มีครบแล้ว แค่คำอธิบายล้าหลัง) Verify: npx tsc --noEmit ผ่าน · vitest 23 files / 338 tests ผ่าน Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
commit
a288e5643c
31 changed files with 1445 additions and 278 deletions
|
|
@ -118,6 +118,96 @@ export function parseDocverTicket(raw: string): DocverTicketParseResult {
|
|||
return { ok: true, ticket: { exp, fid, tid, uid, uname } };
|
||||
}
|
||||
|
||||
/** ticket ก่อนเติม exp ของ parseTicketDataParam — exp เติมตอน stamp เสมอ */
|
||||
export type TicketDataParam = {
|
||||
fid: string;
|
||||
uid: string;
|
||||
uname: string;
|
||||
tid: string | null;
|
||||
};
|
||||
|
||||
export type TicketDataParamResult =
|
||||
| { ok: true; ticket: TicketDataParam }
|
||||
| { ok: false; error: string };
|
||||
|
||||
/** cap ความยาวรวมของ query param ticket_data — เทียบ parseTicketTokenBody
|
||||
* ของ lib/addin-ticket.ts (body ทาง ticket ของ POST /api/documents/token) */
|
||||
const TICKET_DATA_PARAM_MAX = 2048;
|
||||
|
||||
/**
|
||||
* แกะ + ตรวจ query param `ticket_data` ของ GET /api/documents/latest —
|
||||
* JSON string ของ ticket ที่ยังไม่มี exp (server เติม exp ใหม่ตอน stamp เสมอ
|
||||
* จึงไม่บังคับ แต่ถ้าส่งมาต้องเป็นจำนวนเต็ม)
|
||||
*
|
||||
* บังคับ fid/uid/uname ครบตั้งแต่รับเข้า: parseDocverTicket ด้านบนบังคับทั้งสาม
|
||||
* ตอน add-in เอาไฟล์ไป redeem ที่ /api/documents/token — ปล่อย ticket ที่ขาด
|
||||
* field ผ่านไปเงียบ ๆ = คืนไฟล์ที่ add-in เปิดใช้ไม่ได้ภายหลัง
|
||||
*/
|
||||
export function parseTicketDataParam(raw: string | null): TicketDataParamResult {
|
||||
if (raw === null || raw.trim() === "") {
|
||||
return { ok: false, error: "ต้องระบุ ticket_data (JSON string ของ ticket)" };
|
||||
}
|
||||
if (raw.length > TICKET_DATA_PARAM_MAX) {
|
||||
return { ok: false, error: `ticket_data ยาวเกิน ${TICKET_DATA_PARAM_MAX} ตัวอักษร` };
|
||||
}
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(raw);
|
||||
} catch {
|
||||
return { ok: false, error: "ticket_data ไม่ใช่ JSON ที่ถูกต้อง" };
|
||||
}
|
||||
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
return { ok: false, error: "ticket_data ต้องเป็น JSON object" };
|
||||
}
|
||||
const record = parsed as Record<string, unknown>;
|
||||
for (const key of Object.keys(record)) {
|
||||
if (!(TICKET_FIELDS as readonly string[]).includes(key)) {
|
||||
return {
|
||||
ok: false,
|
||||
error: `ticket_data มี field ที่ไม่รู้จัก '${key}' (รับเฉพาะ ${TICKET_FIELDS.join(", ")})`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// exp ไม่บังคับ (server เติมใหม่ตอน stamp) — แต่ถ้าส่งมาต้องผิดรูปไม่ได้ กันเงียบ ๆ
|
||||
if (record.exp !== undefined &&
|
||||
(typeof record.exp !== "number" || !Number.isSafeInteger(record.exp))) {
|
||||
return { ok: false, error: "ticket_data ของ exp ต้องเป็นจำนวนเต็ม (unix วินาที)" };
|
||||
}
|
||||
|
||||
const field = (name: "uid" | "uname" | "fid"): string | null => {
|
||||
const value = record[name];
|
||||
if (typeof value !== "string" || value.trim() === "") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length <= TICKET_LIMITS[name] ? trimmed : null;
|
||||
};
|
||||
|
||||
const uid = field("uid");
|
||||
if (uid === null) return { ok: false, error: "ticket_data ต้องมี uid (string 1–100)" };
|
||||
const uname = field("uname");
|
||||
if (uname === null) return { ok: false, error: "ticket_data ต้องมี uname (string 1–200)" };
|
||||
const fid = field("fid");
|
||||
if (fid === null) return { ok: false, error: "ticket_data ต้องมี fid (string 1–200)" };
|
||||
|
||||
let tid: string | null = null;
|
||||
if (record.tid !== undefined) {
|
||||
if (typeof record.tid !== "string") {
|
||||
return { ok: false, error: "ticket_data ของ tid ต้องเป็น string" };
|
||||
}
|
||||
const trimmed = record.tid.trim();
|
||||
if (trimmed !== "") {
|
||||
if (trimmed.length > TICKET_LIMITS.tid) {
|
||||
return { ok: false, error: "ticket_data ของ tid ยาวเกิน 100 ตัวอักษร" };
|
||||
}
|
||||
tid = trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
return { ok: true, ticket: { fid, uid, uname, tid } };
|
||||
}
|
||||
|
||||
/** exp หมดอายุไหม — exp เท่ากับ now พอดีก็ถือว่าหมดแล้ว */
|
||||
export function isTicketExpired(exp: number, nowSec: number = Math.floor(Date.now() / 1000)): boolean {
|
||||
return exp <= nowSec;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue