Spaces:
Running
Running
File size: 3,026 Bytes
4badc3b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | /**
* 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();
};
}
|