# UniVerse

UniVerse — backend (ASP.NET Core) для университетской платформы расписания, лекций, отзывов и геймификации.

[Документация API](backend/UniVerse.Api/openapi.json)  
[Документация бекнда](docs/backend.md)  

## Что внутри

- Расписание/события и сущности: курсы, лекции, аудитории (locations)
- Отзывы студентов с фоновым LLM-анализом (качество/тональность/теги)
- Геймификация: XP/уровни, монеты, достижения
- JWT-аутентификация и роли (`Admin`, `Teacher`, `Student`)
- Swagger/OpenAPI в Development

## Технологии

- .NET 10 / ASP.NET Core
- PostgreSQL + EF Core (Npgsql)
- Serilog
- Swagger (Swashbuckle)

## Структура репозитория

Код backend лежит в папке `backend/` и собран в solution `backend/UniVerse.sln`:

- `backend/UniVerse.Api` — Web API (контроллеры, middleware, background services)
- `backend/UniVerse.Application` — DTO, интерфейсы сервисов, маппинги
- `backend/UniVerse.Domain` — доменные сущности/enum/исключения
- `backend/UniVerse.Infrastructure` — EF Core, миграции, реализации сервисов, внешние клиенты

## Требования

- .NET SDK 10 (`dotnet --version` должен показать `10.x`)
- PostgreSQL 14+ (или Docker для поднятия Postgres)

## Конфигурация

Основные настройки лежат в `backend/UniVerse.Api/appsettings.json`:

- `ConnectionStrings:DefaultConnection` — строка подключения к Postgres
- `Jwt:*` — секрет/issuer/audience и сроки жизни токенов
- `Cors:Origins` — origin’ы фронтенда
- `Llm:*` — настройки LLM (OpenAI-compatible)
- `ModeusApi:*` — настройки интеграции с Modeus

Можно переопределять через переменные окружения в формате `Section__Key`, например:

- `ConnectionStrings__DefaultConnection`
- `Jwt__Secret`
- `Llm__ApiKey`
- `ModeusApi__ApiKey`

## Быстрый старт (локально)

1) Поднять Postgres (пример через Docker):

```bash
docker run --rm --name universe-postgres \
	-e POSTGRES_DB=universe \
	-e POSTGRES_USER=postgres \
	-e POSTGRES_PASSWORD=postgres \
	-p 5432:5432 \
	postgres:18
```

2) Применить миграции (первый раз потребуется `dotnet-ef`):

```bash
dotnet tool install --global dotnet-ef

cd backend
dotnet ef database update \
	--project UniVerse.Infrastructure \
	--startup-project UniVerse.Api
```

3) Запустить API:

```bash
cd backend
dotnet run --project UniVerse.Api --launch-profile http
```

По умолчанию (профиль `http`) API поднимется на `http://localhost:5019`.
Swagger UI доступен в Development по адресу: `http://localhost:5019/swagger`.

## Запуск в Docker

В `backend/UniVerse.Api/Dockerfile` настроена сборка контейнера API.

```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
```

Примечание: на Linux `host.docker.internal` может быть недоступен — проще запускать Postgres тоже в Docker и соединять контейнеры в одной сети.

## Аутентификация

- `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`

Для Microsoft Entra ID нужны настройки (через env или appsettings): `AzureAd:TenantId`, `AzureAd:ClientId`, `AzureAd:ClientSecret` (и при необходимости `AzureAd:Instance`, `AzureAd:RedirectUri`, `AzureAd:PostLoginRedirectUri`).

Большинство методов API защищены `[Authorize]`.

## Фоновый LLM-анализ отзывов

Сервис `LlmProcessingBackgroundService` раз в ~2 минуты берёт отзывы со статусом `Pending` и прогоняет через LLM-клиент.
LLM-ключ задаётся через `Llm:ApiKey`.

Если ключ не задан или внешний сервис недоступен — анализ будет ретраиться, а ошибки логироваться.

## Интеграция с Modeus

Эндпоинты синхронизации доступны только администратору:

- `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.

## Тестирование

В проекте настроено модульное и интеграционное тестирование (папка `backend/UniVerse.Api.Tests`):

- **xUnit** в качестве основного фреймворка для тестирования.
- **NSubstitute** для создания заглушек (моков) зависимостей сервисов.
- Используется `WebApplicationFactory` (`ApiWebApplicationFactory.cs`) для поднятия интеграционного тестового сервера с подменой БД на `InMemory` и отключенными фоновыми сервисами (например, LLM-интеграциями) для изоляции.
- Реализованы полные тесты ролевой модели и авторизации (`EndpointAuthorizationTests.cs`), надежно проверяющие все API-конечные точки на политики доступа от имени различных ролей (`Admin`, `Teacher`, `Student`, `Anonymous`).

Запуск тестов:

```bash
cd backend
dotnet test
```

