feat: новая функция

This commit is contained in:
2025-10-30 20:40:37 +03:00
parent 38905bba2a
commit a6593e6f33
11 changed files with 935 additions and 28 deletions

View File

@@ -185,7 +185,7 @@ const isProduction = process.env.NODE_ENV === 'production';
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: isProduction ? 100 : 2000, // 100 запросов в продакшне, 2000 в dev
max: isProduction ? 1000 : 10000, // 1000 запросов в продакшне, 10000 в dev
message: {
error: 'Слишком много запросов, попробуйте позже',
retryAfter: '15 минут'
@@ -201,7 +201,7 @@ const limiter = rateLimit({
// Строгий rate limiting для чувствительных эндпоинтов
const strictLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: isProduction ? 10 : 100, // 10 попыток в продакшне, 100 в разработке
max: isProduction ? 100 : 400, // 100 попыток в продакшне, 400 в разработке
message: {
error: 'Превышен лимит попыток, попробуйте позже',
retryAfter: '15 минут'
@@ -211,6 +211,19 @@ const strictLimiter = rateLimit({
trustProxy: true, // Доверяем nginx proxy
});
// Мягкий rate limiting для RPC настроек (часто запрашиваемых данных)
const rpcSettingsLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 минута
max: isProduction ? 200 : 1000, // 200 запросов в продакшне, 1000 в разработке за минуту
message: {
error: 'Слишком много запросов к RPC настройкам, попробуйте позже',
retryAfter: '1 минута'
},
standardHeaders: true,
legacyHeaders: false,
trustProxy: true,
});
// Статическая раздача загруженных файлов (для dev и prod)
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
app.use('/api/uploads', express.static(path.join(__dirname, 'uploads')));
@@ -247,7 +260,9 @@ app.use('/api/kpp', kppRoutes); // Добавленное использован
app.use('/api/geocoding', geocodingRoutes); // Добавленное использование роута
app.use('/api/dle-v2', dleV2Routes); // Добавляем маршрут DLE v2
app.use('/api/settings', strictLimiter, settingsRoutes); // Строгий rate limiting для настроек
// Применяем разные rate limiters к разным частям настроек
app.use('/api/settings/rpc', rpcSettingsLimiter, settingsRoutes); // Мягкий rate limiting для RPC
app.use('/api/settings', strictLimiter, settingsRoutes); // Строгий rate limiting для остальных настроек
app.use('/api/countries', countriesRoutes); // Добавляем маршрут стран
app.use('/api/russian-classifiers', russianClassifiersRoutes); // Добавляем маршрут российских классификаторов
app.use('/api/ollama', strictLimiter, ollamaRoutes); // Строгий rate limiting для Ollama

View File

@@ -23,6 +23,22 @@ const ollamaConfig = require('../services/ollamaConfig');
// Инициализируем один раз
const TIMEOUTS = ollamaConfig.getTimeouts();
// Получение дефолтного base URL для Ollama (для настроек UI)
router.get('/default-base-url', requireAuth, async (req, res) => {
try {
const defaultBaseUrl = ollamaConfig.getBaseUrl();
const fromEnv = !!process.env.OLLAMA_BASE_URL;
res.json({
baseUrl: defaultBaseUrl,
fromEnv, // флаг, что URL из переменной окружения
priority: fromEnv ? 'environment' : 'default'
});
} catch (error) {
logger.error('Error getting default base URL:', error);
res.status(500).json({ error: 'Failed to get default base URL' });
}
});
// Проверка статуса подключения к Ollama
router.get('/status', requireAuth, async (req, res) => {
try {

View File

@@ -812,6 +812,22 @@ router.get('/encryption-key/status', requireAdmin, async (req, res) => {
}
});
// Получить содержимое ключа шифрования
router.get('/encryption-key', requireAdmin, async (req, res) => {
try {
const encryptionUtils = require('../utils/encryptionUtils');
const encryptionKey = encryptionUtils.getEncryptionKey();
if (encryptionKey) {
res.json({ success: true, key: encryptionKey });
} else {
res.status(404).json({ success: false, message: 'Encryption key not found' });
}
} catch (error) {
logger.error('Ошибка получения ключа шифрования:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Безопасная смена ключа шифрования с перешифровкой данных
router.post('/encryption-key/rotate', requireAdmin, async (req, res) => {

View File

@@ -47,17 +47,30 @@ async function loadSettingsFromDb() {
}
}
/**
* Внутренняя функция: определяет base URL из доступных источников
* Приоритет: кэш из БД > переменная окружения > Docker дефолт
* @returns {string} Базовый URL Ollama
*/
function _getBaseUrlFromSources() {
// Приоритет 1: кэш из БД
if (settingsCache && settingsCache.base_url) {
return settingsCache.base_url;
}
// Приоритет 2: переменная окружения
if (process.env.OLLAMA_BASE_URL) {
return process.env.OLLAMA_BASE_URL;
}
// Приоритет 3: Docker дефолт
return 'http://ollama:11434';
}
/**
* Получает базовый URL для Ollama (синхронная версия)
* @returns {string} Базовый URL Ollama
*/
function getBaseUrl() {
// Приоритет: кэш из БД > Docker дефолт
if (settingsCache && settingsCache.base_url) {
return settingsCache.base_url;
}
// URL по умолчанию для Docker
return 'http://ollama:11434';
return _getBaseUrlFromSources();
}
/**
@@ -69,15 +82,11 @@ async function getBaseUrlAsync() {
if (!settingsCache) {
await loadSettingsFromDb();
}
if (settingsCache && settingsCache.base_url) {
return settingsCache.base_url;
}
} catch (error) {
logger.warn('[ollamaConfig] Failed to load base_url from DB, using default');
}
return 'http://ollama:11434';
return _getBaseUrlFromSources();
}
/**