- 单一 Key:API 与 MCP 共用一个 wmh_ Key,凭据迁移至 settings 表(0004 删除 api_credentials) - Markdown:入库时 HTML→Markdown(mailhook 同思路),webhook payload 新增 markdown 字段 - /emails 路由改为 /inboxs 并支持域名筛选;设置按钮移入头像下拉 - 主题切换按钮(头像左侧,亮/暗持久化);设置模态仅 全局 Webhook/账号密码 两 tab 且高度限屏 - 列表操作列按钮加 SVG 图标;mailboxes 去 Webhook 列;最近邮件加收件人列
58 lines
2.2 KiB
TypeScript
58 lines
2.2 KiB
TypeScript
/** 认证与会话测试:登录、错误密码、会话校验、登出、CSRF Origin */
|
|
import { describe, expect, test } from "bun:test";
|
|
import { authedFetch, loginCookie, makeTestEnv } from "./helpers.ts";
|
|
|
|
describe("用户认证(默认 admin/admin)", () => {
|
|
test("正确账密登录并拿到会话", async () => {
|
|
const t = await makeTestEnv();
|
|
const cookie = await loginCookie(t);
|
|
const me = await authedFetch(t, cookie, "http://localhost/api/auth/me");
|
|
expect(me.status).toBe(200);
|
|
const data = (await me.json()) as { user: { username: string } };
|
|
expect(data.user.username).toBe("admin");
|
|
});
|
|
|
|
test("错误密码返回 401", async () => {
|
|
const t = await makeTestEnv();
|
|
const resp = await t.app.fetch(
|
|
new Request("http://localhost/api/auth/login", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username: "admin", password: "wrong" }),
|
|
}),
|
|
t.env,
|
|
);
|
|
expect(resp.status).toBe(401);
|
|
});
|
|
|
|
test("无会话访问受保护接口返回 401", async () => {
|
|
const t = await makeTestEnv();
|
|
const resp = await t.app.fetch(new Request("http://localhost/api/accounts"), t.env);
|
|
expect(resp.status).toBe(401);
|
|
});
|
|
|
|
test("登出后会话失效(clients 清 cookie 后 401)", async () => {
|
|
const t = await makeTestEnv();
|
|
const cookie = await loginCookie(t);
|
|
await authedFetch(t, cookie, "http://localhost/api/auth/logout", { method: "POST" });
|
|
const me = await t.app.fetch(new Request("http://localhost/api/auth/me"), t.env);
|
|
expect(me.status).toBe(401);
|
|
});
|
|
|
|
test("伪造会话 cookie 被拒(签名不匹配)", async () => {
|
|
const t = await makeTestEnv();
|
|
const resp = await authedFetch(t, "wmh_session=eyJhIjoxfQ.deadbeef", "http://localhost/api/auth/me");
|
|
expect(resp.status).toBe(401);
|
|
});
|
|
|
|
test("跨域 Origin 写请求被拒(CSRF)", async () => {
|
|
const t = await makeTestEnv();
|
|
const cookie = await loginCookie(t);
|
|
const resp = await authedFetch(t, cookie, "http://localhost/api/settings/api-key", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json", Origin: "https://evil.example.com" },
|
|
});
|
|
expect(resp.status).toBe(403);
|
|
});
|
|
});
|