feat(database): init database folder frontend and permission

This commit is contained in:
ymy
2026-07-23 23:41:11 +08:00
parent 5df1900ca8
commit 4021e58d5d
67 changed files with 9436 additions and 150 deletions
+40
View File
@@ -0,0 +1,40 @@
/**
* 文件路径安全单测(Metis 安全红线:穿越/.git/分隔符/深度)。
*/
import { describe, expect, it } from "vitest";
import { validateFilePath, FILE_PATH_MAX_DEPTH, FILE_PATH_MAX_LENGTH } from "../../src/database/filelib/fileService.js";
import { FileLibError } from "../../src/database/filelib/model.js";
describe("validateFilePath · 路径安全", () => {
it("正常相对路径通过(含 CJK 与多级)", () => {
expect(validateFilePath("a.md")).toBe("a.md");
expect(validateFilePath("docs/讲义/第一课.md")).toBe("docs/讲义/第一课.md");
expect(validateFilePath("a/b/c/d.txt")).toBe("a/b/c/d.txt");
});
it("拒绝穿越:.. 段、绝对路径", () => {
expect(() => validateFilePath("../x")).toThrowError(FileLibError);
expect(() => validateFilePath("a/../../x")).toThrowError(FileLibError);
expect(() => validateFilePath("/etc/passwd")).toThrowError(FileLibError);
});
it("拒绝 .git 段与点段", () => {
expect(() => validateFilePath(".git")).toThrowError(FileLibError);
expect(() => validateFilePath("a/.git/config")).toThrowError(FileLibError);
expect(() => validateFilePath("./a.md")).toThrowError(FileLibError);
});
it("拒绝反斜杠、控制字符、空段(双斜杠/尾斜杠)", () => {
expect(() => validateFilePath("a\\b.md")).toThrowError(FileLibError);
expect(() => validateFilePath("a\nb.md")).toThrowError(FileLibError);
expect(() => validateFilePath("a//b.md")).toThrowError(FileLibError);
expect(() => validateFilePath("a/b/")).toThrowError(FileLibError);
});
it("拒绝空路径、超长、超深", () => {
expect(() => validateFilePath("")).toThrowError(FileLibError);
expect(() => validateFilePath("a".repeat(FILE_PATH_MAX_LENGTH + 1))).toThrowError(FileLibError);
expect(() => validateFilePath(Array(FILE_PATH_MAX_DEPTH + 1).fill("d").join("/"))).toThrowError(FileLibError);
expect(validateFilePath(Array(FILE_PATH_MAX_DEPTH).fill("d").join("/"))).toContain("d/");
});
});