From 57006dd481e8167308f7dc98e0f5578ab26fe54d Mon Sep 17 00:00:00 2001 From: Sergey Karmanov Date: Tue, 2 Jun 2026 23:11:23 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8E=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 340 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 235 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index a99ab92..0d3f874 100644 --- a/README.md +++ b/README.md @@ -1,165 +1,295 @@ # UniVerse -UniVerse — backend (ASP.NET Core) для университетской платформы расписания, лекций, отзывов и геймификации. +UniVerse - веб-платформа для открытых межнаправленческих лекций университета. Система помогает студентам находить занятия других направлений, записываться на них, получать напоминания, оставлять отзывы, а преподавателям и администраторам - видеть аналитику посещаемости и качества обратной связи. -[Документация API](backend/UniVerse.Api/openapi.json) -[Документация бекнда](docs/backend.md) +Проект состоит из Vue 3 frontend, ASP.NET Core backend и PostgreSQL-хранилища. Backend предоставляет REST API, интегрируется с Microsoft Entra ID, Modeus API и OpenAI-compatible LLM, а frontend реализует отдельные сценарии для ролей `Student`, `Teacher` и `Admin`. -## Что внутри +- [OpenAPI snapshot](backend/UniVerse.Api/openapi.json) +- [Backend notes](docs/backend.md) +- [Frontend E2E tests](docs/playwright-tests.md) +- [Load testing](docs/load-testing-k6.md) -- Расписание/события и сущности: курсы, лекции, аудитории (locations) -- Отзывы студентов с фоновым LLM-анализом (качество/тональность/теги) -- Геймификация: XP/уровни, монеты, достижения -- JWT-аутентификация и роли (`Admin`, `Teacher`, `Student`) -- Swagger/OpenAPI в Development +## Возможности -## Технологии +### Для студента -- .NET 10 / ASP.NET Core -- PostgreSQL + EF Core (Npgsql) -- Serilog -- Swagger (Swashbuckle) +- Каталог открытых лекций с поиском, фильтрацией, карточками и деталями занятия. +- Запись на лекцию и отмена записи с учетом лимитов мест и персонального лимита активных записей. +- Личный дашборд: ближайшие лекции, прогресс уровня, XP, монеты, достижения и статистика. +- Мои лекции: список записей, скачивание `.ics` для одной лекции или всего расписания, ссылка календарной подписки. +- Отзывы о лекциях с оценкой `Like`, `Neutral`, `Dislike`. +- Уведомления и профиль пользователя. -## Структура репозитория +### Для преподавателя -Код backend лежит в папке `backend/` и собран в solution `backend/UniVerse.sln`: +- Дашборд преподавателя по своим занятиям. +- Просмотр списка лекций и записей. +- Аналитика отзывов: тональность, информативность, теги LLM и агрегированные показатели. +- Работа с отзывами без раскрытия лишних персональных данных студентам. -- `backend/UniVerse.Api` — Web API (контроллеры, middleware, background services) -- `backend/UniVerse.Application` — DTO, интерфейсы сервисов, маппинги -- `backend/UniVerse.Domain` — доменные сущности/enum/исключения -- `backend/UniVerse.Infrastructure` — EF Core, миграции, реализации сервисов, внешние клиенты +### Для администратора + +- Административная панель со статистикой пользователей, лекций, записей и ожидающих LLM-анализа отзывов. +- Управление пользователями: роли `Student`, `Teacher`, `Admin`, блокировка и разблокировка аккаунтов. +- Управление лекциями и создание новых занятий. +- Синхронизация расписания, аудиторий и преподавателей из Modeus. +- Модерация отзывов, повторный запуск LLM-анализа и настройка промпта. +- Управление курсами, тегами, локациями и достижениями через API. + +### Платформенные функции + +- Microsoft Entra ID login и dev-login для локальной разработки. +- JWT access token и refresh flow через cookie. +- Ролевая защита маршрутов frontend и endpoint-level авторизация backend. +- Фоновая очередь анализа отзывов через LLM. +- Геймификация: XP, уровни, монеты, достижения и транзакции. +- Email-уведомления и планировщик Quartz. +- Rate limiting, Serilog, Prometheus metrics и Swagger UI в Development. +- Aspire AppHost для совместного локального запуска API и Vite frontend. +- Docker Compose для production-окружения с backend, frontend и PostgreSQL. + +## Архитектура + +```mermaid +flowchart LR + Student[Student UI] --> Frontend[Vue 3 frontend] + Teacher[Teacher UI] --> Frontend + Admin[Admin UI] --> Frontend + + Frontend -->|/api/v1 JSON| Api[ASP.NET Core Web API] + Api --> Auth[Auth and RBAC] + Api --> App[Application services] + App --> Domain[Domain model] + App --> Infra[Infrastructure] + Infra --> Db[(PostgreSQL)] + Infra --> Llm[OpenAI-compatible LLM] + Infra --> Modeus[Modeus schedule API] + Infra --> Mail[SMTP email] + + Api --> Quartz[Quartz jobs] + Quartz --> Mail + Api --> Metrics[Prometheus /metrics] +``` + +Backend следует Clean Architecture: + +- `UniVerse.Api` - controllers, middleware, Swagger, DI, background services. +- `UniVerse.Application` - DTO, interfaces, service contracts, mappings, prompts. +- `UniVerse.Domain` - entities, enums, domain exceptions, domain services. +- `UniVerse.Infrastructure` - EF Core, migrations, external clients, notification and business service implementations. +- `UniVerse.AppHost` - Aspire host для локального запуска API и frontend. +- `UniVerse.Api.Tests` - unit и integration tests. + +Frontend построен на Vue 3, TypeScript, Vite, Pinia и Vue Router: + +- `src/views/student` - кабинет студента, каталог, карточка лекции, мои лекции, отзывы, профиль, уведомления. +- `src/views/teacher` - кабинет преподавателя, лекции, аналитика. +- `src/views/admin` - дашборд, пользователи, лекции, отзывы. +- `src/api` - typed API client, DTO-типы и мапперы. +- `src/components/ui` и `src/components/layout` - переиспользуемые UI и layout-компоненты. + +## Сценарий записи и анализа отзыва + +```mermaid +sequenceDiagram + actor S as Student + participant UI as Vue frontend + participant API as UniVerse API + participant DB as PostgreSQL + participant Q as ReviewAnalysisQueue + participant LLM as LLM API + participant G as GamificationService + + S->>UI: Выбирает открытую лекцию + UI->>API: POST /api/v1/lectures/{id}/enroll + API->>DB: Проверяет лимиты и сохраняет запись + API-->>UI: 204 No Content + S->>UI: Оставляет отзыв + UI->>API: POST /api/v1/reviews + API->>DB: Сохраняет отзыв со статусом Pending + API->>Q: Ставит отзыв в очередь анализа + Q->>LLM: Анализ качества, тональности и тегов + LLM-->>Q: Результат анализа + Q->>DB: Обновляет отзыв + Q->>G: Начисляет XP, монеты и достижения + G->>DB: Сохраняет транзакции и награды +``` + +Основные группы таблиц: + +- Пользователи и доступ: `users`, `user_roles`, `student_profiles`, `teacher_profiles`, `refresh_tokens`. +- Расписание: `courses`, `lectures`, `locations`, `tags`, `course_tags`. +- Участие и обратная связь: `lecture_enrollments`, `reviews`, `review_prompt_settings`. +- Геймификация: `achievements`, `user_achievements`, `coin_transactions`, `level_thresholds`. +- Уведомления: `user_notifications`. + +## API + +Базовый префикс: `/api/v1`. + +- `/auth` - Microsoft login, dev-login, refresh, logout, текущий пользователь. +- `/users` - профиль, статистика, роли, активность, записи, достижения, транзакции, `.ics`. +- `/lectures` - каталог лекций, CRUD, запись, посещаемость, отзывы по лекции. +- `/reviews` - создание, список, модерация, повторный анализ, настройка LLM-промпта. +- `/courses` - курсы и привязка тегов. +- `/tags` - теги и дерево тегов. +- `/locations` - аудитории и локации. +- `/achievements` - каталог достижений. +- `/notifications` - уведомления, отметка прочтения, отправка и планирование. +- `/sync` - синхронизация расписания, аудиторий и преподавателей из Modeus. + +В Development Swagger UI доступен по адресу `http://localhost:5019/api/docs`. + +## Стек + +### Frontend + +- Vue 3, TypeScript, Vite. +- Pinia, Vue Router. +- Playwright E2E tests. +- Nginx для production-раздачи и проксирования. + +### Backend + +- .NET 10, ASP.NET Core Web API. +- EF Core 10, Npgsql, PostgreSQL. +- Swashbuckle/OpenAPI. +- Serilog, Prometheus, ASP.NET Core Rate Limiting. +- Quartz для отложенных уведомлений. +- Aspire AppHost. +- xUnit, NSubstitute, WebApplicationFactory. + +### Интеграции + +- Microsoft Entra ID. +- Modeus schedule API. +- OpenAI-compatible LLM API. +- SMTP email. ## Требования -- .NET SDK 10 (`dotnet --version` должен показать `10.x`) -- PostgreSQL 14+ (или Docker для поднятия Postgres) +- .NET SDK 10.x. +- Node.js `^20.19.0 || >=22.12.0`. +- pnpm. +- PostgreSQL 17+ или Docker. +- Для production - Docker Engine и Docker Compose. ## Конфигурация -Основные настройки лежат в `backend/UniVerse.Api/appsettings.json`: +Backend читает настройки из `backend/UniVerse.Api/appsettings.json`, `appsettings.Development.json` и переменных окружения в формате `Section__Key`. -- `ConnectionStrings:DefaultConnection` — строка подключения к Postgres -- `Jwt:*` — секрет/issuer/audience и сроки жизни токенов -- `Cors:Origins` — origin’ы фронтенда -- `Llm:*` — настройки LLM (OpenAI-compatible) -- `ModeusApi:*` — настройки интеграции с Modeus +Основные секции: -Можно переопределять через переменные окружения в формате `Section__Key`, например: +- `ConnectionStrings:DefaultConnection` - подключение к PostgreSQL. +- `Jwt:*` - issuer, audience, secret и сроки жизни токенов. +- `AzureAd:*` - Microsoft Entra ID. +- `Cors:Origins` - разрешенные origin frontend. +- `RateLimiting:*` - глобальный fixed-window limiter. +- `Llm:*` - base URL, API key, model и параметры анализа отзывов. +- `ModeusApi:*` - base URL, API key и timeout. +- `Email:Smtp:*` - SMTP-настройки для уведомлений. -- `ConnectionStrings__DefaultConnection` -- `Jwt__Secret` -- `Llm__ApiKey` -- `ModeusApi__ApiKey` +Frontend использует переменные: -## Быстрый старт (локально) +- `VITE_API_BASE_URL` - базовый адрес API, по умолчанию `/api`. +- `VITE_API_PROXY_TARGET` - target для Vite proxy при запуске через Aspire. +- `VITE_AUTH_RETURN_URL` - frontend callback URL, по умолчанию `/auth/callback`. -1) Поднять Postgres (пример через Docker): +## Быстрый старт + +### 1. Установить зависимости frontend + +```bash +pnpm -C frontend install +``` + +### 2. Поднять PostgreSQL ```bash docker run --rm --name universe-postgres \ - -e POSTGRES_DB=universe \ - -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ - -p 5432:5432 \ - postgres:18 + -e POSTGRES_DB=universe \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -p 5432:5432 \ + postgres:18 ``` -2) Применить миграции (первый раз потребуется `dotnet-ef`): +### 3. Применить миграции ```bash dotnet tool install --global dotnet-ef cd backend dotnet ef database update \ - --project UniVerse.Infrastructure \ - --startup-project UniVerse.Api + --project UniVerse.Infrastructure \ + --startup-project UniVerse.Api ``` -3) Запустить API: +### 4. Запустить backend ```bash -cd backend -dotnet run --project UniVerse.Api --launch-profile http +dotnet run --project backend/UniVerse.Api --launch-profile http ``` -По умолчанию (профиль `http`) API поднимется на `http://localhost:5019`. -Swagger UI доступен в Development по адресу: `http://localhost:5019/swagger`. +API по умолчанию слушает `http://localhost:5019`. -## Запуск в Docker - -В `backend/UniVerse.Api/Dockerfile` настроена сборка контейнера API. +### 5. Запустить frontend ```bash -cd backend -docker build -f UniVerse.Api/Dockerfile -t universe-api . - -docker run --rm -p 8080:8080 \ - -e ASPNETCORE_URLS=http://+:8080 \ - -e ConnectionStrings__DefaultConnection="Host=host.docker.internal;Port=5432;Database=universe;Username=postgres;Password=postgres" \ - universe-api +pnpm -C frontend dev ``` -Примечание: на Linux `host.docker.internal` может быть недоступен — проще запускать Postgres тоже в Docker и соединять контейнеры в одной сети. +Vite frontend по умолчанию слушает `http://localhost:5173` и проксирует `/api` на `http://localhost:5019`. -## Аутентификация +## Запуск через Aspire -- `POST /api/v1/auth/login/dev` — дев-логин (только в `Development`). Удобно для локальной разработки. -- `GET /api/v1/auth/login/microsoft` — старт входа через Microsoft Entra ID (бэкенд сам делает редирект на Microsoft). -- `GET /api/v1/auth/callback/microsoft` — callback, куда Microsoft возвращает `code`. -- `POST /api/v1/auth/login/microsoft` — обмен `authorizationCode` на токены (полезно для интеграций/ручных тестов). Тело: `{ "authorizationCode": "...", "redirectUri"?: "..." }`. -- `POST /api/v1/auth/refresh`, `POST /api/v1/auth/logout`, `GET /api/v1/auth/me` +Aspire AppHost запускает API и Vite frontend вместе: -Для Microsoft Entra ID нужны настройки (через env или appsettings): `AzureAd:TenantId`, `AzureAd:ClientId`, `AzureAd:ClientSecret` (и при необходимости `AzureAd:Instance`, `AzureAd:RedirectUri`, `AzureAd:PostLoginRedirectUri`). +```bash +pnpm -C frontend install +dotnet run --project backend/UniVerse.AppHost/UniVerse.AppHost.csproj +``` -Большинство методов API защищены `[Authorize]`. +Frontend обычно доступен на `http://localhost:5173`. Target API передается во frontend через `VITE_API_PROXY_TARGET`. -## Фоновый LLM-анализ отзывов +## Docker Compose -Сервис `LlmProcessingBackgroundService` раз в ~2 минуты берёт отзывы со статусом `Pending` и прогоняет через LLM-клиент. -LLM-ключ задаётся через `Llm:ApiKey`. +Production compose описан в `docker-compose-prod.yml`: -Если ключ не задан или внешний сервис недоступен — анализ будет ретраиться, а ошибки логироваться. +- `app` - ASP.NET Core backend. +- `frontend` - собранный Vue frontend и Nginx. +- `db` - PostgreSQL. -## Интеграция с Modeus +Перед запуском задайте переменные окружения для PostgreSQL, JWT, Microsoft auth, CORS и внешних интеграций: -Эндпоинты синхронизации доступны только администратору: +```bash +docker compose -f docker-compose-prod.yml up -d +``` -- `POST /api/v1/sync/schedule` -- `POST /api/v1/sync/rooms` -- `POST /api/v1/sync/employees` -- `GET /api/v1/sync/status` - -Ключ (если нужен) задаётся через `ModeusApi:ApiKey`. - -## Карта API (high-level) - -Базовый префикс: `/api/v1`. - -- `/auth` — логин/refresh/logout/me -- `/users` — профиль/статистика/достижения/транзакции (часть методов — только `Admin`) -- `/courses` — курсы и теги (CRUD в основном для `Admin`) -- `/lectures` — лекции, записи, посещаемость, отзывы -- `/reviews` — отзывы (создание студентом; модерация/реанализ для `Admin`) -- `/tags` — теги + дерево тегов -- `/locations` — аудитории/локации -- `/achievements` — достижения -- `/sync` — синхронизация с внешним расписанием (только `Admin`) - -Точные схемы запросов/ответов удобнее смотреть в Swagger. +Тестовый compose находится в `docker-compose-test.yml`. ## Тестирование -В проекте настроено модульное и интеграционное тестирование (папка `backend/UniVerse.Api.Tests`): - -- **xUnit** в качестве основного фреймворка для тестирования. -- **NSubstitute** для создания заглушек (моков) зависимостей сервисов. -- Используется `WebApplicationFactory` (`ApiWebApplicationFactory.cs`) для поднятия интеграционного тестового сервера с подменой БД на `InMemory` и отключенными фоновыми сервисами (например, LLM-интеграциями) для изоляции. -- Реализованы полные тесты ролевой модели и авторизации (`EndpointAuthorizationTests.cs`), надежно проверяющие все API-конечные точки на политики доступа от имени различных ролей (`Admin`, `Teacher`, `Student`, `Anonymous`). - -Запуск тестов: +Backend: ```bash -cd backend -dotnet test +dotnet test backend/UniVerse.sln ``` +Frontend type-check и production build: + +```bash +pnpm -C frontend build +``` + +Frontend E2E с mock API: + +```bash +pnpm -C frontend test:e2e +``` + +Load testing helper: + +```bash +node frontend/scripts/loadtest-endpoints.js +``` \ No newline at end of file