# Архитектура и структура сервиса Документ описывает как организован сервер дипломного проекта: какие слои присутствуют, как они взаимодействуют и где искать ключевые модули. ## Общий обзор Сервис написан на Kotlin с использованием Ktor и разворачивается как Netty-приложение (`Application.kt`). Приложение поднимает инфраструктурные плагины (HTTP, сериализация, безопасность) и регистрирует доменные маршруты. Все функции сгруппированы в повторяющийся паттерн `Controller → Service → Repository → Entity`, что делает поддержку CRUD-операций симметричной во всех доменных областях. Высокоуровневый поток запросов: 1. HTTP-вызов попадает в `Routing.kt`, где маршруты разделены на публичную и админскую зоны (`/api/v1/...`). 2. Контроллер модуля занимается десериализацией запроса, базовой валидацией и формированием ответа. 3. Сервис инкапсулирует бизнес-правила: публикация материалов, фильтрация, проверка прав, подготовка DTO. 4. Репозиторий обращается к PostgreSQL через Ktorm, используя HikariCP-пул соединений. 5. Исключения (`ValidationException`, `NotFoundException`) перехватывает `StatusPages`, что обеспечивает единый контракт ошибок. Графическая схема слоев расположена в `docs/crud-model.svg`. ## Структура каталогов ``` src/main/kotlin ├── app # Bootstrap: Application, Routing, Security, HTTP, Database ├── shared # Переиспользуемые DTO, пагинация, ошибки └── modules # Доменные модули (admin, news, service, serviceCategory, lead) src/main/resources ├── application.yaml # Конфигурация Ktor └── openapi # Спецификации API src/test/kotlin # Зеркало production-пакетов для тестов docs/ ├── crud-model.svg # Диаграмма последовательности CRUD └── architecture.md # Текущий документ ``` ## Инфраструктурный слой (`app/*`) - **Application.module** – точка входа, выстраивает последовательность `configureDatabase → configureHTTP → configureSerialization → configureSecurity → configureRouting`. - **Database.kt** – инициализация пула HikariCP (настройки берутся из `.env`), регистрация `Database` в `Application.attributes`. - **Http.kt** – подключает плагины Ktor (CORS, Compression, CachingHeaders, StatusPages, Swagger UI). Здесь же централизованно обрабатываются исключения. - **Serialization.kt** – `ContentNegotiation` с `kotlinx.serialization`. - **Security.kt** – загрузка параметров JWT из окружения, настройка схемы `admin-auth`, валидация `JWTPrincipal`. - **Routing.kt** – собирает зависимости модулей, подключает публичные маршруты и оборачивает админские роуты в `authenticate("admin-auth")`. ## Доменные модули (`modules/*`) Каждый модуль состоит из четырех файлов: - `Controller.kt` – набор Ktor-маршрутов для публичной и/или админской зоны. - `Service.kt` – бизнес-логика. Например, `NewsService` отвечает за публикацию, пагинацию и преобразование сущностей в DTO, а `ServiceService` поддерживает фильтры по статусу, категории и ценовому диапазону. - `Repository.kt` – слой доступа к данным на Ktorm: построение SQL, пагинация, CRUD-операции, трансформации в `Entity`. - `Entity.kt` / DTO – описания таблиц, модели для сериализации и транспортировки данных. ### Admin Отвечает за регистрацию, авторизацию и управление администраторами. Использует `BcryptPasswordHasher` для хранения паролей и `TokenService` для выпуска JWT. Публичная часть (`/admin/login`) возвращает токен; защищенная (`/admin/*`) требует `admin-auth`. ### News Два набора маршрутов: публичные (`/news`, `/news/{slug}`) и админские (`/admin/news`). Сервис применяет правила публикации и формирует страницы (`Page`). Репозиторий обрабатывает SQL для списков и выборок по `slug`. ### Services и Service Categories `ServiceController` поддерживает сложные фильтры (категория, диапазон цен, статус). `ServiceService` связывает услуги с категориями, обеспечивая получение вложенных DTO. `ServiceCategory*` модули обслуживают справочник категорий и проверяют уникальность `slug`. ### Leads `publicLeadRoutes` принимает заявки с сайта (`POST /leads`), `adminLeadRoutes` предоставляет CRUD для операторов. Сервис выполняет базовую валидацию и поиск по строке `q`. ## Общие компоненты (`shared/*`) - `shared.pagination.Page` – универсальный ответ для списков. - `shared.errors.ValidationException/NotFoundException` – типы, которые перехватываются `StatusPages` и автоматически конвертируются в HTTP-ответ. ## Работа с БД - **База** – PostgreSQL, подключение через Ktorm + HikariCP (`jdbc:postgresql://...`). - **Пулы** – настраиваются через переменные окружения (`DB_HOST`, `DB_POOL_MAX` и т.д.). - **Репозитории** – реализованы вручную на SQL Builder, что дает контроль над запросами и связями между таблицами (`services` ↔ `service_categories`, `news`, `leads`, `admins`). ## Безопасность - Единственная схемa аутентификации – JWT `admin-auth`. - Конфигурация (`JWT_SECRET`, `JWT_ISSUER`, `JWT_AUDIENCE`, `JWT_EXPIRES_MIN`) читается из `.env` или переменных окружения. - Public маршруты доступны без токена, все `admin*Routes` подключены внутри `authenticate`. ## Сборка и эксплуатация - Основные команды Gradle: - `./gradlew run` – локальный сервер. - `./gradlew test` – прогон тестов (обязателен перед пушем). - `./gradlew buildFatJar` – сборка standalone JAR. - `./gradlew buildImage` / `runDocker` – сборка и запуск docker-образа. - Конфигурация HTTP-порта, логирования и OpenAPI лежит в `src/main/resources/application.yaml` и `resources/openapi`. - Для обновления документации добавляйте артефакты в `docs/` (например, текущую архитектурную схему и диаграмму CRUD). ## Тестирование Тесты зеркалируют production-пакеты (`src/test/kotlin/...`). При добавлении новой функциональности рекомендуется: 1. Класть тесты в соответствующий пакет модуля (например, `modules/news/NewsServiceTest.kt`). 2. Проверять ветки успеха, валидации и авторизации. 3. Запускать `./gradlew test` перед коммитом, чтобы убедиться в корректной работе всего набора.