Spaces:
Running
Running
| /** | |
| * Shared API key and admin-access helpers. | |
| */ | |
| import { config } from '../config.js'; | |
| import { createOpenAIError } from '../format/openai-compat.js'; | |
| import { logger } from '../utils/logger.js'; | |
| export function extractProvidedApiKey(req) { | |
| const authHeader = req.headers['authorization']; | |
| const xApiKey = req.headers['x-api-key']; | |
| if (authHeader && authHeader.startsWith('Bearer ')) { | |
| return authHeader.substring(7); | |
| } | |
| if (xApiKey) { | |
| return xApiKey; | |
| } | |
| return ''; | |
| } | |
| export function extractWebuiPassword(req) { | |
| return req.headers['x-webui-password'] || req.query.password || ''; | |
| } | |
| export function hasValidApiKey(req) { | |
| return Boolean(config.apiKey) && extractProvidedApiKey(req) === config.apiKey; | |
| } | |
| export function hasAdminAccess(req) { | |
| if (hasValidApiKey(req)) { | |
| return true; | |
| } | |
| if (config.webuiPassword && extractWebuiPassword(req) === config.webuiPassword) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| export function requireAdminAccess(req, res, next) { | |
| if (hasAdminAccess(req)) { | |
| return next(); | |
| } | |
| logger.warn(`[API] Unauthorized admin request from ${req.ip} to ${req.method} ${req.originalUrl}`); | |
| return res.status(401).json({ | |
| type: 'error', | |
| error: { | |
| type: 'authentication_error', | |
| message: 'Authentication required' | |
| } | |
| }); | |
| } | |
| export function createV1ApiKeyMiddleware() { | |
| return (req, res, next) => { | |
| if (!config.apiKey) { | |
| logger.error('[API] PROXY_API_KEY is not configured; rejecting /v1 request'); | |
| const isOpenAIEndpoint = req.path === '/chat/completions' || req.path === '/models'; | |
| if (isOpenAIEndpoint) { | |
| return res.status(503).json(createOpenAIError('Proxy API key is not configured', { | |
| type: 'api_error', | |
| code: 'service_unavailable' | |
| })); | |
| } | |
| return res.status(503).json({ | |
| type: 'error', | |
| error: { | |
| type: 'api_error', | |
| message: 'Proxy API key is not configured' | |
| } | |
| }); | |
| } | |
| const providedKey = extractProvidedApiKey(req); | |
| if (!providedKey || providedKey !== config.apiKey) { | |
| logger.warn(`[API] Unauthorized request from ${req.ip}, invalid API key`); | |
| const isOpenAIEndpoint = req.path === '/chat/completions' || req.path === '/models'; | |
| if (isOpenAIEndpoint) { | |
| return res.status(401).json(createOpenAIError('Invalid or missing API key', { | |
| type: 'authentication_error', | |
| code: 'invalid_api_key' | |
| })); | |
| } | |
| return res.status(401).json({ | |
| type: 'error', | |
| error: { | |
| type: 'authentication_error', | |
| message: 'Invalid or missing API key' | |
| } | |
| }); | |
| } | |
| next(); | |
| }; | |
| } | |