diff --git a/backend/server.js b/backend/server.js index 5222895..8e28d5e 100644 --- a/backend/server.js +++ b/backend/server.js @@ -301,10 +301,14 @@ app.post('/api/ip-ranges', writeLimiter, ipRangesRoutes.post); // === JSON DATA ROUTES (используют фабрики) === // Servers -const SERVER_TYPES = ['jumphost', 'exit']; +const SERVER_TYPES = ['jumphost', 'exit', 'bgp', 'dns']; +const TYPES_NEED_TUNNEL = ['jumphost', 'exit']; // Типы, которым нужен туннель +const TYPES_NEED_GATEWAYS = ['jumphost', 'exit']; // Типы, которым нужны gateways + const serversRoutes = createJsonDataRoutes('servers.json', (server, i) => { - if (!server.ip || !server.dns || !server.country || !server.provider || !server.tunnel) { - return `Server at index ${i} is missing required fields`; + // Базовые обязательные поля + if (!server.ip || !server.dns || !server.country || !server.provider) { + return `Server at index ${i} is missing required fields (ip, dns, country, provider)`; } const normalizedType = String(server.type || '').toLowerCase(); @@ -312,7 +316,13 @@ const serversRoutes = createJsonDataRoutes('servers.json', (server, i) => { return `Server at index ${i} has invalid type (allowed: ${SERVER_TYPES.join(', ')})`; } - if (normalizedType === 'jumphost' || normalizedType === 'exit') { + // Туннель обязателен только для jumphost и exit + if (TYPES_NEED_TUNNEL.includes(normalizedType) && !server.tunnel) { + return `Server at index ${i} (${normalizedType}) requires tunnel type`; + } + + // Gateways обязательны только для jumphost и exit + if (TYPES_NEED_GATEWAYS.includes(normalizedType)) { if (!Array.isArray(server.gateways) || server.gateways.length === 0) { return `Server at index ${i} must have gateways for type ${normalizedType}`; } diff --git a/frontend/src/components/server/ServerCard.jsx b/frontend/src/components/server/ServerCard.jsx index a4b8a4c..9e8d4b2 100644 --- a/frontend/src/components/server/ServerCard.jsx +++ b/frontend/src/components/server/ServerCard.jsx @@ -10,9 +10,12 @@ import { IconNetwork, IconCloud, IconRouter, - IconArrowsRightLeft + IconArrowsRightLeft, + IconRoute, + IconWorldWww } from '@tabler/icons-react'; import { useState } from 'react'; +import { needsTunnel } from '../../utils/serverUtils.js'; // Преобразование кода страны в emoji-флаг function countryToFlag(isoCode) { @@ -42,10 +45,20 @@ export default function ServerCard({ }) { const [expanded, setExpanded] = useState(false); - const isExit = server.type === 'exit'; + const serverType = (server.type || 'jumphost').toLowerCase(); const primaryGateway = server.gateways?.find(g => g.primary)?.name || server.gateway || ''; const connectionsCount = server.gateways?.length || 0; const serverName = server.dns?.split('.')[0] || server.ip; + const showTunnel = needsTunnel(serverType); + + // Конфигурация отображения типов серверов + const typeConfig = { + jumphost: { label: 'JUMP', color: 'blue', icon: IconRouter }, + exit: { label: 'EXIT', color: 'red', icon: IconArrowsRightLeft }, + bgp: { label: 'BGP', color: 'purple', icon: IconRoute }, + dns: { label: 'DNS', color: 'cyan', icon: IconWorldWww }, + }; + const currentTypeConfig = typeConfig[serverType] || typeConfig.jumphost; return (
{server.dns || server.ip}
-
-