500d796573
Component Workers: - Deploys if_control, switch, filter, merge, try_catch, wait, set, array_ops, string_ops, number_ops, date_ops, validate_json, ai_transform_compile, ai_transform_run, foreach_control as independent Workers, backing cypher-executor's SVC_* service bindings (fast internal RPC for logic components). cypher-executor routing: - New routes: /auth (recipe resolution), /credentials (CRUD), /webhooks/named (user-friendly alias for cmp_/rec_ hashes). - auth-recipe-seeds.ts: 20 pre-built platform auth recipes (Google Sheets, Gmail, Telegram, etc.) seeded into RECIPES KV. - graph-executor + cypher-handlers + search-nodes updated for the new resolution chain. - scripts/seed-auth-recipes.ts: one-shot tool to push seeds to KV. - wrangler.toml: 15 SVC_* bindings wired to the new logic Workers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
// POST /register — API Key 發放
|
|
// email → HMAC-SHA256(email, ENCRYPTION_KEY) → api_key (ak_ 前綴)
|
|
// 同一個 email 永遠得到相同的 Key,無需資料庫
|
|
|
|
import { Hono } from 'hono';
|
|
import type { Bindings } from '../types';
|
|
|
|
export const registerRouter = new Hono<{ Bindings: Bindings }>();
|
|
|
|
registerRouter.post('/register', async (c) => {
|
|
let email: string;
|
|
try {
|
|
const body = await c.req.json() as { email?: string };
|
|
email = (body.email ?? '').trim().toLowerCase();
|
|
} catch {
|
|
return c.json({ success: false, error: 'request body 必須為 JSON' }, 400);
|
|
}
|
|
|
|
if (!email || !email.includes('@')) {
|
|
return c.json({ success: false, error: 'email 格式不正確' }, 400);
|
|
}
|
|
|
|
const encryptionKey = c.env.ENCRYPTION_KEY;
|
|
if (!encryptionKey || encryptionKey.length < 32) {
|
|
return c.json({ success: false, error: 'server configuration error' }, 500);
|
|
}
|
|
|
|
// HMAC-SHA256(email, ENCRYPTION_KEY) → hex → 取前 32 字元 → ak_ 前綴
|
|
const keyData = new TextEncoder().encode(encryptionKey.slice(0, 32));
|
|
const msgData = new TextEncoder().encode(email);
|
|
|
|
const cryptoKey = await crypto.subtle.importKey(
|
|
'raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
|
|
);
|
|
const sig = await crypto.subtle.sign('HMAC', cryptoKey, msgData);
|
|
const hex = Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
const apiKey = 'ak_' + hex.slice(0, 32);
|
|
|
|
return c.json({
|
|
success: true,
|
|
api_key: apiKey,
|
|
encryption_key: encryptionKey, // 用戶需要此 key 才能加密上傳 credential
|
|
email,
|
|
message: 'API Key 已發放,請妥善保存。相同 email 永遠得到相同的 Key。',
|
|
});
|
|
});
|