forked from boos/BoosAPI
feat: 实现全局模型白名单功能 (#301)
* feat: 实现全局模型白名单功能 ## 功能概述 实现全局模型白名单,允许管理员配置只启用特定模型的路由,实现精细化的模型访问控制。 ## 主要变更 ### 后端实现 - config.ts: 新增 globalAllowedModels 配置项 - settings.ts: - 新增 RuntimeSettingsBody 类型支持 - 实现数据库加载和持久化 - 配置变更自动触发路由重建 - modelService.ts: - 在路由重建中添加白名单过滤逻辑 - 大小写不敏感匹配,自动trim空格 - 空白名单时允许所有模型(向后兼容) - stats.ts: - 候选API过滤 models/modelsWithoutToken/modelsMissingTokenGroups ### 前端实现 - Settings.tsx: - 新增"全局模型白名单"配置卡片 - 支持手动输入和点击选择两种添加方式 - 绿色徽章显示已选模型,支持删除 - 保存后自动触发路由重建 ## 技术特性 - ✅ 向后兼容(默认为空数组,允许所有模型) - ✅ 大小写不敏感匹配 - ✅ 自动trim和去重 - ✅ 输入验证(类型检查、空值过滤) - ✅ 配置变更自动重建路由 ## 测试验证 - 白名单为空时所有模型可见 - 白名单有值时只显示白名单模型 - 路由重建正确过滤模型 - 候选API正确返回过滤结果 - 前端UI交互正常 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: add getModelTokenCandidates mock to Settings tests * fix: add getModelTokenCandidates mock to proxy-transport test --------- Co-authored-by: Ding <ding@local> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -956,10 +956,23 @@ export async function rebuildTokenRoutesFromAvailability() {
|
||||
// Load global brand filter
|
||||
const blockedBrandRules = getBlockedBrandRules(config.globalBlockedBrands);
|
||||
|
||||
// Load global allowed models whitelist
|
||||
const globalAllowedModels = new Set(
|
||||
config.globalAllowedModels.map((m) => m.toLowerCase().trim()).filter(Boolean),
|
||||
);
|
||||
|
||||
function isModelAllowedByWhitelist(modelName: string): boolean {
|
||||
// If whitelist is empty, allow all models (backward compatible)
|
||||
if (globalAllowedModels.size === 0) return true;
|
||||
// Check if model is in whitelist (case-insensitive)
|
||||
return globalAllowedModels.has(modelName.toLowerCase().trim());
|
||||
}
|
||||
|
||||
const modelCandidates = new Map<string, Map<string, { accountId: number; tokenId: number | null }>>();
|
||||
const addModelCandidate = (modelNameRaw: string | null | undefined, accountId: number, tokenId: number | null, siteId: number) => {
|
||||
const modelName = (modelNameRaw || '').trim();
|
||||
if (!modelName) return;
|
||||
if (!isModelAllowedByWhitelist(modelName)) return;
|
||||
if (isModelDisabledForSite(siteId, modelName)) return;
|
||||
if (blockedBrandRules.length > 0 && isModelBlockedByBrand(modelName, blockedBrandRules)) return;
|
||||
if (!modelCandidates.has(modelName)) modelCandidates.set(modelName, new Map());
|
||||
|
||||
Reference in New Issue
Block a user