邮件模板微信化 + 评论老友自动填充 + CF 后台国内线路一键跳
- 邮件模板重做成微信聊天式:灰底、自己评论绿色气泡靠右、对方白色气泡靠左、 40px 圆角方头像(weavatar,邮箱 md5 不外泄)、时间居中、#07C160 主按钮; 布局全嵌套表格(Outlook 稳),表情内联 max-height:28px(修掉「表情太大」)、 配图限宽 100%;管理员主题从「新的评论待审」改成「您有一个新的评论」 - 老友自动填充:新增 /comments/lookup(只回昵称+网址,绝不含邮箱;IP 限速 30 次/10 分钟)+ 主题 comment-autofill 模块(填昵称弹提示、填邮箱自动带出 上次的昵称/网址,事件委托不怕 Artalk 重建编辑器) - CF 后台新增「国内线路」一键跳:/editor/handoff 用共享令牌对时间戳 HMAC 签名 → editor-api /admin/handoff 验签发会话 Cookie(2 分钟有效、防重放), 晚高峰丢包时直达国内机后台免重新登录
This commit is contained in:
1 parent
a8b54f7482
commit
6046eb494c
10 files changed
+443
-87
No files matched your search
@@ -161,6 +161,42 @@ export const publish = (ctx: Ctx) => relayJson(ctx, '/git/publish', 'POST');
|
||||
|
||||
export const sync = (ctx: Ctx) => relay(ctx, '/git/sync', { method: 'POST' });
|
||||
|
||||
// ---------------------------------------------------------------- 一键跳转
|
||||
|
||||
/**
|
||||
* 「国内线路」一键跳转:给后台前端一个**免登录**直达国内机后台的 URL。
|
||||
*
|
||||
* 怎么做到免登录:浏览器直接开 writeapi.usj.cc/admin/ 是要重新输账号密码的
|
||||
* (那边是独立的 Cookie 会话)。这里让 Worker 用共享令牌对当前时间戳做
|
||||
* HMAC 签名,前端拿着签名去 editor-api 的 /admin/handoff 换会话 Cookie ——
|
||||
* 两边本来就共享 EDITOR_TOKEN,等于用已登录的 CF 会话给国内机做了一次担保。
|
||||
*
|
||||
* 安全边界:签名 2 分钟内有效、同一签名只能换一次会话、且只有已登录管理员
|
||||
* 能从 Worker 拿到签名。URL 全程 HTTPS,不含任何账号密码。
|
||||
*/
|
||||
async function hmacHex(secret: string, msg: string): Promise<string> {
|
||||
const enc = new TextEncoder();
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
enc.encode(secret),
|
||||
{ name: 'HMAC', hash: 'SHA-256' },
|
||||
false,
|
||||
['sign'],
|
||||
);
|
||||
const sig = await crypto.subtle.sign('HMAC', key, enc.encode(msg));
|
||||
return [...new Uint8Array(sig)].map((b) => b.toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
|
||||
export async function handoff(ctx: Ctx): Promise<Response> {
|
||||
const deny = await guard(ctx);
|
||||
if (deny) return deny;
|
||||
|
||||
const base = String(ctx.env.EDITOR_API_BASE).replace(/\/+$/, '');
|
||||
const ts = Date.now().toString();
|
||||
const sig = await hmacHex(String(ctx.env.EDITOR_TOKEN), ts);
|
||||
return json({ url: `${base}/api/v2/admin/handoff?ts=${ts}&t=${sig}` });
|
||||
}
|
||||
|
||||
/** 健康检查:让后台能显示「编辑后端是否在线」(同样只认真实会话) */
|
||||
export async function health(ctx: Ctx): Promise<Response> {
|
||||
if (!(await requireAdminSession(ctx))) return fail(403, '需要管理员权限');
|
||||
|
||||
Reference in new issue
Block a user