9.3 KiB
9.3 KiB
Состояние проекта на 2026-05-30 14:43 (ветка sonnet)
Репозитории
| Репо | URL | Ветка | Локальный путь |
|---|---|---|---|
| Код приложения | https://gitea.services.ngcloud.ru/Nail/ipwhitelist-app.git |
sonnet | /home/naeel/ipwhitelist-app |
| Документация | https://gitea.services.ngcloud.ru/Nail/IPWhiteList.git |
main | /home/naeel/IPWhiteList |
Стек
Node.js + Express + EJS + PostgreSQL + pg pool + jsonwebtoken
Деплой
- URL:
https://white.nodejsk8s.dev.nubes.ru - DEV_MODE=true (мок-аутентификация)
- ⚠️ Нужен передеплой Nubes для ветки sonnet
БД
write.bde8229b-1381-4330-b24b-727ad73fcb44.dev.nubes.ru- user:
super, db:ipwhitelist - Миграция от 2026-05-30 применена (CHECK, UNIQUE, индексы)
Что сделано в ветке sonnet (4 коммита поверх master)
1. src/validators.js — CIDR агрегация
aggregateCIDRs(cidrs)— суммаризация: merge пересекающихся + смежных диапазонов → минимальный набор CIDR- Вспомогательные:
numToIP(n),rangeToCIDRs(start, end) - Экспортируется и используется в
/export
2. src/auth.js — admin-роль
ADMIN_CLIENT_ID=process.env.ADMIN_CLIENT_ID || 'WZ01112'req.user.isAdmin— определяется поclientId === ADMIN_CLIENT_IDDEV_ADMIN=trueв.env→ admin-права в dev-режимеrequireAdminmiddleware — 403 для не-admin
3. src/queries.js — новые функции
getCompanyById(id)— компания по числовому PKgetAllCompanies()— все компании +active_count(LEFT JOIN)setLimit(companyId, newLimit)— установить/сбросить (null) индивидуальный лимитgetAudit()— обновлён: JOIN с companies (поляcompany_name,client_id)
4. server.js — новые роуты
/export— публичный (до auth.middleware), возвращает агрегированный список всех компанийGET /— admin: видит все компании с переключателем?company=XPOST /edit/:id— редактирование записи (admin + user)GET /audit— журнал аудита (только admin)GET /admin— управление лимитами (только admin)POST /admin/limit/:companyId— изменить/сбросить лимит компанииbackUrl()— хелпер для редиректа обратно с учётом контекста admin/user
5. views/index.ejs
- Admin-панель выбора компании (dropdown + быстрые ссылки на Аудит/Лимиты)
- Кнопки Аудит/Лимиты/Выйти в header для admin
- Кнопка "Изменить" в таблице (открывает edit modal)
- Edit modal — overlay с формой, закрывается по Escape/backdrop
- Скрытый
company_idв формах add/delete для корректной admin-ветки
6. views/audit.ejs — новый
- Таблица журнала аудита с фильтром по компании
- Цветные badges (CREATE/UPDATE/DELETE)
- old_value → new_value стрелочкой
7. views/admin.ejs — новый
- Таблица всех компаний: client_id, active_count, лимит
- Прогресс-бар использования (зелёный/янтарный/красный)
- Форма изменения лимита с подтверждением; кнопка ↺ сброс на дефолт
Не сделано (production-hardening, не баги)
- helmet (X-Frame-Options, CSP, HSTS)
- rate-limit на POST /add, /delete, /export
- CSRF-токены в формах
- JWT-верификация через внешний JWKS (нужен URL от девопсов)
- Multi-company (нужен формат claims от платформы — массив clientId?)
Мёртвый код (не критично)
isSubnetOf()в validators.js — определена, не используется, не экспортируется
Для прода
Выставить в .env:
NODE_ENV=production
JWKS_URL=<auth-api JWKS URL>
ADMIN_CLIENT_ID=<clientId администратора>
DEFAULT_LIMIT=15
Репозитории
| Репо | URL | Ветка | Локальный путь |
|---|---|---|---|
| Код приложения | https://gitea.services.ngcloud.ru/Nail/ipwhitelist-app.git |
master | /home/naeel/ipwhitelist-app |
| Документация | https://gitea.services.ngcloud.ru/Nail/IPWhiteList.git |
main | /home/naeel/IPWhiteList |
Стек
Node.js + Express + EJS + PostgreSQL + pg pool + jsonwebtoken
Деплой
- URL:
https://white.nodejsk8s.dev.nubes.ru - DEV_MODE=true (мок-аутентификация)
- ⚠️ Код запушен, но Nubes не передеплоил — крутится старая версия
БД
write.bde8229b-1381-4330-b24b-727ad73fcb44.dev.nubes.ru- user:
super, db:ipwhitelist - Миграция от 2026-05-30 применена (CHECK, UNIQUE, индексы)
Что сделано (запушено)
1. src/validators.js — исправлены 3 бага
- Запрещённые диапазоны:
isSubnetOf→overlaps(обход через суперсеть/22) - Маска:
parseInt('24abc')глотал мусор → строгая проверка/^\d{1,2}$/ - Множественные слэши:
10.0.0.0/24/8теперь отклоняется
2. src/queries.js — транзакции + гонки
createEntry,updateEntry,deleteEntry— внутри транзакции сSELECT ... FOR UPDATEgetOrCreateCompany— атомарныйINSERT ... ON CONFLICTgetLimit—!= nullвместо||(custom_limit=0 не игнорируется)logAudit— принимает клиента транзакции (пишется атомарно)getExportCIDRs— фильтр поcompanyIddeleteEntry—company_idв WHERE
3. src/auth.js — новый. Мок JWT-аутентификация
- Генерирует RSA-ключи при старте
- JWKS endpoint:
/.well-known/jwks.json verifyJWT(token)— RS256, issuer:mock-auth-apiissueJWT(claims)— выпускает токен с claims как в HAR (ClientID,company_id,company_name,email)- Middleware: извлекает JWT из cookie (
jwt) илиAuthorization: Bearer - DEV_MODE: при
DEV_MODE=true && NODE_ENV!=production— обход auth - Для прода: выставить
JWKS_URL=https://auth-api.../jwks→ switches to external verification
4. views/login.ejs — новый. Мок-страница входа
- Выбор из 3 пользователей (admin WZ01112, тест WZ01325, компания 2 WZ02001)
- В проде заменяется на редирект в Keycloak
5. server.js
cookie-parserдля чтения JWT из cookie/healthz— выше auth (k8s probe)/loginGET/POST — мок-логин/logout— чистит cookie/export— только для своей компании (с авторизацией)req.query.errorчитаетсяurlencoded({ limit: '32kb' })
6. sql/schema.sql
- UNIQUE INDEX на активный
(company_id, value_cidr)WHERE deleted_at IS NULL - CHECK на
value_cidrформат - CHECK на
audit_log.action IN ('CREATE','UPDATE','DELETE') - CHECK на
custom_limit IS NULL OR >= 0 - FK:
ON DELETE RESTRICT - Составной индекс
(company_id, created_at DESC)на audit_log - Индекс
(company_id, created_at DESC)на whitelist_entries
7. views/index.ejs
pattern+maxlength="18"+titleна инпуте value
Ревью (/home/naeel/IPWhiteList/research/)
| Файл | Что |
|---|---|
REVIEW-SUMMARY.md |
Сводка всех находок (11 критических, 21 средний) |
opus-review-validators.md |
1 критичный + 2 средних |
opus-review-queries.md |
3 гонки + audit + getLimit |
opus-review-server.md |
JWT без подписи, 401, CSRF, /export |
opus-review-schema.md |
UNIQUE, CIDR, FK, индексы |
opus-review-ejs.md |
CSRF, clickjacking, client-валидация |
auth-flow.md |
Анализ HAR: claims, цепочка auth-api |
Не сделано (production-hardening, не баги)
- helmet (X-Frame-Options, CSP, HSTS)
- rate-limit на POST /add, /delete, /export
- CSRF-токены в формах
- JWT-верификация через внешний JWKS (нужен URL от девопсов)
- Admin-признак в токене (нужен пример токена админа)
- Multi-company (нужен формат claims от платформы)
Для прода
Выставить в .env:
NODE_ENV=production
JWKS_URL=<auth-api JWKS URL>
Всё остальное работает без изменений.