Refactor ticket verification and installation scripts
All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 3s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 1m17s
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

- Split `verifyAddinTicket` into two functions: `verifyAddinTicketHmac` (ignores expiration) and `verifyAddinTicket` (checks expiration).
- Add `hasVersionByUser` function to check if a document has been previously worked on by a user, allowing expired tickets to be accepted if the user has a history with the document.
- Update OpenAPI specification to reflect changes in ticket expiration handling.
- Introduce new scripts for installing and uninstalling the Word add-in on Windows and macOS, providing a streamlined process for sideloading the add-in.
- Enhance tests for ticket verification to cover new functionality regarding expired tickets and user history.
This commit is contained in:
Suphonchai Phoonsawat 2026-10-28 14:42:03 +07:00
parent 3726cb742f
commit b1449ab668
14 changed files with 727 additions and 75 deletions

View file

@ -33,15 +33,15 @@ export function addinTicketSecret(): string {
}
/**
* ตรวจ ticket เต็มชุด (HMAC → parse → exp) — ไม่แยกสาเหตุออกมา
* (route ตอบ 401 ข้อความเดียวกันทุกกรณี กันใช้ endpoint เป็น oracle —
* add-in รู้สาเหตุจริงจากการตรวจเองฝั่ง client อยู่แล้ว)
* ตรวจ ticket แบบไม่สน exp (HMAC → parse) — ใช้เมื่อ route จะตัดสิน "ticket หมดอายุ
* แต่เอกสารนี้เคยทำงานโดย uid เดียวกัน" เองผ่าน DB (requirement ขั้น 7: กลับมาทำ
* เอกสารเดิมผ่านได้แม้ ticket หมดอายุ) — ตัวตนของผู้ถือยังยึด HMAC ของ e-Court
* เหมือนเดิม แค่ไม่ใช้อายุ ticket เป็นเกณฑ์ตัดสิทธิ์ ณ จุดนี้
*/
export function verifyAddinTicket(
export function verifyAddinTicketHmac(
ticketData: string,
hmacHex: string,
secret: string,
nowSec: number = Math.floor(Date.now() / 1000),
): { ok: true; ticket: DocverTicket } | { ok: false } {
const digest = normalizeHexDigest(hmacHex);
if (digest === null) return { ok: false };
@ -55,10 +55,26 @@ export function verifyAddinTicket(
const parsed = parseDocverTicket(ticketData);
if (!parsed.ok) return { ok: false };
if (isTicketExpired(parsed.ticket.exp, nowSec)) return { ok: false };
return { ok: true, ticket: parsed.ticket };
}
/**
* ตรวจ ticket เต็มชุด (HMAC → parse → exp) — ไม่แยกสาเหตุออกมา
* (route ตอบ 401 ข้อความเดียวกันทุกกรณี กันใช้ endpoint เป็น oracle —
* add-in รู้สาเหตุจริงจากการตรวจเองฝั่ง client อยู่แล้ว)
*/
export function verifyAddinTicket(
ticketData: string,
hmacHex: string,
secret: string,
nowSec: number = Math.floor(Date.now() / 1000),
): { ok: true; ticket: DocverTicket } | { ok: false } {
const verified = verifyAddinTicketHmac(ticketData, hmacHex, secret);
if (!verified.ok) return { ok: false };
if (isTicketExpired(verified.ticket.exp, nowSec)) return { ok: false };
return verified;
}
/** แปลง ticket → claims ของ access_token (uid→userid, uname→username, tid→template) */
export function ticketToDocverClaims(ticket: DocverTicket): DocverTokenClaims {
return { userid: ticket.uid, username: ticket.uname, fid: ticket.fid, template: ticket.tid };