Antigravity2api / src /admin /key_manager.js
link0518
重构
b88ce1b
import fs from 'fs/promises';
import path from 'path';
import crypto from 'crypto';
import logger from '../utils/logger.js';
const KEYS_FILE = path.join(process.cwd(), 'data', 'api_keys.json');
// 确保数据目录存在
async function ensureDataDir() {
const dataDir = path.dirname(KEYS_FILE);
try {
await fs.access(dataDir);
} catch {
await fs.mkdir(dataDir, { recursive: true });
}
}
// 生成随机 API 密钥
function generateApiKey() {
return 'sk-' + crypto.randomBytes(32).toString('hex');
}
// 加载所有密钥
export async function loadKeys() {
await ensureDataDir();
try {
const data = await fs.readFile(KEYS_FILE, 'utf-8');
return JSON.parse(data);
} catch (error) {
if (error.code === 'ENOENT') {
return [];
}
throw error;
}
}
// 保存密钥
async function saveKeys(keys) {
await ensureDataDir();
await fs.writeFile(KEYS_FILE, JSON.stringify(keys, null, 2), 'utf-8');
}
// 创建新密钥
export async function createKey(name = '未命名', rateLimit = null, customKey = null) {
const keys = await loadKeys();
if (customKey) {
if (keys.some(k => k.key === customKey)) {
throw new Error('密钥已存在');
}
}
const newKey = {
key: customKey || generateApiKey(),
name,
created: new Date().toISOString(),
lastUsed: null,
requests: 0,
rateLimit: rateLimit || { enabled: false, maxRequests: 100, windowMs: 60000 }, // 默认 100 次/分钟
usage: {} // 用于存储使用记录 { timestamp: count }
};
keys.push(newKey);
await saveKeys(keys);
logger.info(`新密钥已创建: ${name}`);
return newKey;
}
// 删除密钥
export async function deleteKey(keyToDelete) {
const keys = await loadKeys();
const filtered = keys.filter(k => k.key !== keyToDelete);
if (filtered.length === keys.length) {
throw new Error('密钥不存在');
}
await saveKeys(filtered);
logger.info(`密钥已删除: ${keyToDelete.substring(0, 10)}...`);
return true;
}
// 验证密钥
export async function validateKey(keyToCheck) {
const keys = await loadKeys();
const key = keys.find(k => k.key === keyToCheck);
if (key) {
// 更新使用信息
key.lastUsed = new Date().toISOString();
key.requests = (key.requests || 0) + 1;
await saveKeys(keys);
return true;
}
return false;
}
// 获取密钥统计
export async function getKeyStats() {
const keys = await loadKeys();
return {
total: keys.length,
active: keys.filter(k => k.lastUsed).length,
totalRequests: keys.reduce((sum, k) => sum + (k.requests || 0), 0)
};
}
// 更新密钥频率限制
export async function updateKeyRateLimit(keyToUpdate, rateLimit) {
const keys = await loadKeys();
const key = keys.find(k => k.key === keyToUpdate);
if (!key) {
throw new Error('密钥不存在');
}
key.rateLimit = rateLimit;
await saveKeys(keys);
logger.info(`密钥频率限制已更新: ${keyToUpdate.substring(0, 10)}...`);
return key;
}
// 检查频率限制
export async function checkRateLimit(keyToCheck) {
const keys = await loadKeys();
const key = keys.find(k => k.key === keyToCheck);
if (!key) {
return { allowed: false, error: '密钥不存在' };
}
// 如果未启用频率限制,直接允许
if (!key.rateLimit || !key.rateLimit.enabled) {
return { allowed: true };
}
const now = Date.now();
const windowMs = key.rateLimit.windowMs || 60000;
const maxRequests = key.rateLimit.maxRequests || 100;
// 清理过期的使用记录
key.usage = key.usage || {};
const cutoffTime = now - windowMs;
// 计算当前时间窗口内的请求数
let requestCount = 0;
for (const [timestamp, count] of Object.entries(key.usage)) {
if (parseInt(timestamp) >= cutoffTime) {
requestCount += count;
} else {
delete key.usage[timestamp]; // 清理过期记录
}
}
// 检查是否超过限制
if (requestCount >= maxRequests) {
const resetTime = Math.min(...Object.keys(key.usage).map(t => parseInt(t))) + windowMs;
const waitSeconds = Math.ceil((resetTime - now) / 1000);
return {
allowed: false,
error: '请求频率超限',
resetIn: waitSeconds,
limit: maxRequests,
remaining: 0
};
}
// 记录本次请求
const minute = Math.floor(now / 10000) * 10000; // 按10秒分组
key.usage[minute] = (key.usage[minute] || 0) + 1;
await saveKeys(keys);
return {
allowed: true,
limit: maxRequests,
remaining: maxRequests - requestCount - 1
};
}