Files
wmailhub/tests/auth.test.ts
T
bigcode 421cfb2f04 feat: v1.1.0 账号化重构 + 三级 Webhook + 设置中心 + Vite 工具链
- 账号化:节点更名账号,/nodes -> /accounts;添加账号直达 Cloudflare OAuth,自动创建账号并同步账号下全部域名(catch-all 邮箱随同步创建)
- 域名:移除手工添加;点击域名『设置 Email Workers』= 部署账号级 Email Worker + Email Routing + catch-all;支持按账号筛选
- Webhook 三级模型:邮箱 -> 域名 -> 全局,收信取第一个命中者;支持自定义请求头与 key(默认 Authorization: Bearer <key>,兼做 X-WmailHub-Signature 签名);独立 webhooks 实体与 /webhooks、/keys 页面删除,Key 管理收进设置模态窗口
- 设置中心:全局 Webhook / 默认 Node Ingress 地址 / 修改密码 / API & MCP Keys(生成、撤销、删除)
- UI:Header 标题副标题紧凑化(修复溢出),LOGO 加版本号 tag(v1.1.0 取自 package.json),各列表页搜索框
- 工具链:前端构建 Bun.build -> Vite(vite 8 + @vitejs/plugin-react)
- 后端:/api/settings、POST /api/domains/:id/setup、0002 迁移(投递行固化三级目标配置);MCP 去 list_webhooks(5 工具);迁移执行器加 _migrations 记录
- 测试:44/44(新增 settings 套件、webhook 三级优先级/SSRF/签名);UI 冒烟 11/11
2026-09-30 11:37:38 +08:00

59 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/keys", {
method: "POST",
headers: { "Content-Type": "application/json", Origin: "https://evil.example.com" },
body: JSON.stringify({ kind: "api" }),
});
expect(resp.status).toBe(403);
});
});