# IP-gate: ограничение доступа на время разработки ## Задача Сайт доступен на реальном домене (через VPS + NPM + Netbird), но находится в активной разработке/тестировании. Нужно ограничить доступ, не мешая разработке и полному тестированию функционала (включая OAuth и webhook-и). ## Решение IP-whitelist на уровне Fastify (`onRequest` хук). Только запросы с разрешённых IP проходят. Внешние webhook-и и OAuth callback-и исключены из проверки. ## Конфигурация ### `.env` ```env SITE_ACCESS_IPS=1.2.3.4,5.6.7.8 ``` - Не задана или пуста — защита **отключена** - IP через запятую, пробелы игнорируются (трим) - `request.ip` возвращает реальный IP клиента благодаря `trustProxy: true` ## Архитектура ### Новый плагин: `server/src/plugins/ip-gate.js` Регистрируется в `server/src/index.js` **перед** всеми маршрутами. ```js fastify.register(async function ipGate(fastify, opts) { fastify.addHook('onRequest', async (request, reply) => { // защита выключена // путь в исключениях // ip в списке // иначе 403 }) }) ``` ### Логика `onRequest` 1. `SITE_ACCESS_IPS` пуст → `return` (пропустить) 2. Путь запроса в списке исключений → `return` 3. `request.ip` есть в `SITE_ACCESS_IPS` → `return` 4. Иначе → `reply.code(403).type('text/html').send(htmlPage)` ### Исключения Маршруты, которые должны работать всегда (их вызывают внешние сервисы, а не браузер тестировщика): | Путь | Причина | |---|---| | `/api/auth/oauth/vk/callback` | VK OAuth callback | | `/api/auth/oauth/yandex/callback` | Yandex OAuth callback | | `/api/webhooks/yookassa` | YooKassa payment webhook | | `/api/admin/notifications/telegram/webhook` | Telegram webhook | Статика (загружается браузером тестировщика, поэтому тоже проверяется): - `/uploads/*` и `/uploads-resized/*` — **не** исключаем, блокируются вместе со всем остальным ### 403-страница HTML-страница с информацией о магазине и статусе разработки: - Название: «Любимый Креатив» - Подзаголовок: «Изделия ручной работы: вещи с характером и вниманием к деталям» - Сообщение: «Сайт находится в разработке и скоро будет доступен» - Показывает IP посетителя (чтобы можно было сообщить для добавления в whitelist) - Минимальная стилизация (чистый HTML + inline CSS, без внешних ресурсов) ## Точки регистрации В `server/src/index.js`: ```js // после trustProxy, перед маршрутами await fastify.register(require('./plugins/ip-gate')) ``` ## Тестирование - **Юнит-тесты**: `server/src/plugins/__tests__/ip-gate.test.js` - IP в списке → запрос проходит - IP не в списке → 403 - Путь-исключение → проходит с любым IP - `SITE_ACCESS_IPS` не задан → защита выключена - Пробелы в списке IP → корректная работа ## Включение/выключение - **Включить**: задать `SITE_ACCESS_IPS` в `.env` - **Выключить**: удалить `SITE_ACCESS_IPS` или оставить пустым - Перезапуск сервера не требуется если используется `node --watch`