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
|
|
@ -4,6 +4,7 @@ import { afterEach, describe, expect, it } from "vitest";
|
|||
import {
|
||||
issueDocverToken,
|
||||
parseTokenRequestBody,
|
||||
requireDocumentApiKey,
|
||||
requireDocverApiKey,
|
||||
requireDocverBearer,
|
||||
verifyDocverLoginToken,
|
||||
|
|
@ -31,12 +32,16 @@ function ok<T>(result: { ok: boolean } & T): asserts result is { ok: true } & T
|
|||
// --- env save/restore — require* อ่าน env ตอนเรียก ไม่ใช่ตอน module load
|
||||
const HAD_API_KEY = Object.prototype.hasOwnProperty.call(process.env, "DOCVER_API_KEY");
|
||||
const ORIG_API_KEY = process.env.DOCVER_API_KEY;
|
||||
const HAD_EXTERNAL_KEY = Object.prototype.hasOwnProperty.call(process.env, "EXTERNAL_API_KEY");
|
||||
const ORIG_EXTERNAL_KEY = process.env.EXTERNAL_API_KEY;
|
||||
const HAD_SECRET = Object.prototype.hasOwnProperty.call(process.env, "DOCVER_TOKEN_SECRET");
|
||||
const ORIG_SECRET = process.env.DOCVER_TOKEN_SECRET;
|
||||
|
||||
afterEach(() => {
|
||||
if (HAD_API_KEY) process.env.DOCVER_API_KEY = ORIG_API_KEY;
|
||||
else delete process.env.DOCVER_API_KEY;
|
||||
if (HAD_EXTERNAL_KEY) process.env.EXTERNAL_API_KEY = ORIG_EXTERNAL_KEY;
|
||||
else delete process.env.EXTERNAL_API_KEY;
|
||||
if (HAD_SECRET) process.env.DOCVER_TOKEN_SECRET = ORIG_SECRET;
|
||||
else delete process.env.DOCVER_TOKEN_SECRET;
|
||||
});
|
||||
|
|
@ -176,6 +181,59 @@ describe("requireDocverApiKey", () => {
|
|||
});
|
||||
});
|
||||
|
||||
// requireDocumentApiKey — auth ของ GET /api/documents/latest: x-api-key เทียบ
|
||||
// DOCVER_API_KEY หรือ EXTERNAL_API_KEY ตัวใดตัวหนึ่ง (ต่างจาก /token)
|
||||
describe("requireDocumentApiKey", () => {
|
||||
function setKeys(docver: string | undefined, external: string | undefined): void {
|
||||
if (docver === undefined) delete process.env.DOCVER_API_KEY;
|
||||
else process.env.DOCVER_API_KEY = docver;
|
||||
if (external === undefined) delete process.env.EXTERNAL_API_KEY;
|
||||
else process.env.EXTERNAL_API_KEY = external;
|
||||
}
|
||||
|
||||
it("ทั้งคู่ไม่ตั้ง / ว่าง / ช่องว่างล้วน = 401 fail closed ทุกกรณี", async () => {
|
||||
for (const [docver, external] of [
|
||||
[undefined, undefined],
|
||||
["", ""],
|
||||
[" ", " "],
|
||||
] as const) {
|
||||
setKeys(docver, external);
|
||||
const res = requireDocumentApiKey(reqWithKey("test-key"));
|
||||
expect(res?.status, `${docver}/${external}`).toBe(401);
|
||||
expect(await bodyOf(res!)).toEqual({ error: "ระบบยังไม่ได้ตั้งค่า API key" });
|
||||
}
|
||||
});
|
||||
|
||||
it("ตั้งอันเดียวตัวไหนก็ผ่านเมื่อ key ตรงตัวนั้น · ตั้งทั้งคู่ตรงอันที่สองก็ผ่าน", () => {
|
||||
setKeys("docver-key", undefined);
|
||||
expect(requireDocumentApiKey(reqWithKey("docver-key"))).toBeNull();
|
||||
expect(requireDocumentApiKey(reqWithKey("external-key"))?.status).toBe(401);
|
||||
|
||||
setKeys(undefined, "external-key");
|
||||
expect(requireDocumentApiKey(reqWithKey("external-key"))).toBeNull();
|
||||
expect(requireDocumentApiKey(reqWithKey("docver-key"))?.status).toBe(401);
|
||||
|
||||
setKeys("docver-key", "external-key");
|
||||
expect(requireDocumentApiKey(reqWithKey("external-key"))).toBeNull();
|
||||
});
|
||||
|
||||
it("ไม่ใส่ header กับ key ผิด ต้องได้ 401 ข้อความเดียวกันเป๊ะ (กัน enumerate)", async () => {
|
||||
setKeys("docver-key", "external-key");
|
||||
const missing = requireDocumentApiKey(reqWithKey());
|
||||
const wrong = requireDocumentApiKey(reqWithKey("not-any-key"));
|
||||
expect(missing?.status).toBe(401);
|
||||
expect(wrong?.status).toBe(401);
|
||||
expect(await bodyOf(missing!)).toEqual(await bodyOf(wrong!));
|
||||
});
|
||||
|
||||
it("env มี whitespace รอบ ๆ ก็ trim ให้เทียบได้ทั้งสองตัว", () => {
|
||||
setKeys(" docver-key ", undefined);
|
||||
expect(requireDocumentApiKey(reqWithKey("docver-key"))).toBeNull();
|
||||
setKeys(undefined, " external-key ");
|
||||
expect(requireDocumentApiKey(reqWithKey("external-key"))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("requireDocverBearer", () => {
|
||||
it("ทุกกรณีพ้นสภาพ (ไม่มี header / ไม่ใช่ Bearer / token เน่า / หมดอายุ / secret ไม่ตั้ง) = 401 ข้อความเดียวกัน", async () => {
|
||||
const deniedBodies = new Set<string>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue