# 🔌 REST API Все эндпоинты имеют префикс `/api/`. Ответы возвращаются в формате JSON. --- ## Аутентификация ### `POST /api/auth/login` Вход в систему. **Тело запроса:** ```json { "username": "admin", "password": "admin" } ``` **Успешный ответ (200):** ```json { "success": true, "message": "OK", "token": "550e8400-e29b-41d4-a716-446655440000", "role": "ADMIN", "redirect": "/admin/" } ``` **Ошибка (401):** ```json { "success": false, "message": "Неверное имя пользователя или пароль", "token": null, "role": null, "redirect": null } ``` > После получения токена клиент должен передавать его в заголовке: `Authorization: Bearer ` --- ## Пользователи ### `GET /api/users` Список всех пользователей. **Ответ:** ```json [ { "id": 1, "username": "admin", "role": "ADMIN", "fullName": "Иванов Админ Иванович", "jobTitle": "Доцент", "departmentName": "Кафедра ИБ" }, { "id": 2, "username": "Тестовый преподаватель", "role": "TEACHER", "fullName": "Петров Препод Петрович", "jobTitle": "Профессор", "departmentName": "Кафедра ВТ" } ] ``` ### `GET /api/users/teachers` Список только преподавателей (роль `TEACHER`). ### `GET /api/users/teachers/{departmentId}` Список преподавателей привязанных к конкретной кафедре (роль `TEACHER`, код кафедры `departmentId`). ### `POST /api/users` Создание пользователя. **Тело запроса:** ```json { "username": "teacher1", "password": "password", "role": "TEACHER", "fullName": "Test Teacher", "jobTitle": "Proffessor", "departmentId": 1 } ``` **Валидация:** - `username` — обязателен и уникален - `password` — минимум 4 символа - `role` — `ADMIN`, `TEACHER` или `STUDENT` - `fullName` — обязателен - `departmentId` — обязателен ### `DELETE /api/users/{id}` Удаление пользователя. --- ## Расписание (Lessons) ### `GET /api/users/lessons` Список всех занятий с разрешёнными именами (преподаватель, группа, дисциплина, аудитория). **Ответ:** ```json [ { "id": 1, "teacherName": "Тестовый преподаватель", "groupName": "ИВТ-21-1", "classroomName": "101 Ленинская", "educationFormName": "Бакалавриат", "subjectName": "Высшая математика", "typeLesson": "Лекция", "lessonFormat": "Очно", "day": "Понедельник", "week": "Верхняя", "time": "11:40 - 13:10" } ] ``` ### `GET /api/users/lessons/{teacherId}` Занятия конкретного преподавателя. ### `POST /api/users/lessons/create` Создание занятия. **Тело запроса:** ```json { "teacherId": 2, "groupId": 1, "subjectId": 1, "lessonFormat": "Очно", "typeLesson": "Лекция", "classroomId": 1, "day": "Понедельник", "week": "Верхняя", "time": "11:40 - 13:10" } ``` **Валидация:** | Поле | Правило | |------|---------| | `teacherId` | Обязателен, ≠ 0 | | `groupId` | Обязателен, ≠ 0 | | `subjectId` | Обязателен, ≠ 0 | | `lessonFormat` | `Очно` или `Онлайн` | | `typeLesson` | `Лекция`, `Практическая работа`, `Лабораторная работа` | | `classroomId` | Обязателен, ≠ 0 | | `day` | Пн–Сб (на русском) | | `week` | `Верхняя`, `Нижняя`, `Обе` | | `time` | Обязателен | ### `PUT /api/users/lessons/update/{lessonId}` Обновление занятия. Поддерживает partial update — передаются только изменённые поля. **Тело ответа:** ```json { "id": 5, "teacherId": 1, "groupId": 1, "subjectId": 2, "LessonFormat": "Онлайн", "typeLesson": "Практическая работа", "classroomId": 3, "day": "Понедельник", "week": "Верхняя", "time": "9:40 - 11:10", "updatedFields": { "teacherId": 1, "subjectId": 2, "lessonFormat": "Онлайн", "classroomId": 3, "day": "Понедельник", "time": "9:40 - 11:10" }, "message": "Занятие успешно обновлено" } ``` ### `DELETE /api/users/lessons/delete/{lessonId}` Удаление занятия. ### `GET /api/users/lessons/ping` Проверка доступности контроллера. Возвращает строку `pong`. --- ## Группы ### `GET /api/groups` Список всех групп. **Ответ:** ```json [ { "id": 1, "name": "ИВТ-21-1", "groupSize": 25, "educationFormId": 1, "educationFormName": "Бакалавриат", "departmentId": 1, "course": 3, "specialityCode": 1 } ] ``` ### `GET /api/groups/{departmentId}` Список всех групп привязанных к конкретной кафедре. ### `POST /api/groups` Создание группы. ```json { "name": "ИВТ-11", "groupSize": 12, "educationFormId": 1, "departmentId": 1, "course": 2, "specialityCode": 1 } ``` ### `DELETE /api/groups/{id}` Удаление группы. --- ## Аудитории ### `GET /api/classrooms` Список аудиторий с привязанным оборудованием. **Ответ:** ```json [ { "id": 1, "name": "101 Ленинская", "capacity": 120, "isAvailable": true, "equipments": [ { "id": 1, "name": "Проектор" }, { "id": 4, "name": "Интерактивная доска" } ] } ] ``` ### `POST /api/classrooms` Создание аудитории. ```json { "name": "404 Лаборатория", "capacity": 30, "isAvailable": true, "equipmentIds": [1, 2, 3] } ``` ### `PUT /api/classrooms/{id}` Обновление аудитории (partial update). ### `DELETE /api/classrooms/{id}` Удаление аудитории. --- ## Дисциплины ### `GET /api/subjects` Список всех дисциплин. ```json { "name": "Физика", "code": null, "departmentId": 1 } ``` ### `GET /api/subjects/{departmentId}` Список всех дисциплин привязанных к кафедре. ### `POST /api/subjects` ```json { "name": "Физика", "code": null, "departmentId": 1 } ``` ### `DELETE /api/subjects/{id}` Удаление дисциплины. --- ## Оборудование ### `GET /api/equipments` Список всего оборудования. ### `POST /api/equipments` ```json { "name": "3D-принтер" } ``` ### `DELETE /api/equipments/{id}` Удаление оборудования. --- ## Формы обучения ### `GET /api/education-forms` Список форм обучения. **Ответ:** ```json [ { "id": 1, "name": "Бакалавриат" }, { "id": 2, "name": "Магистратура" } ] ``` ### `POST /api/education-forms` ```json { "name": "Аспирантура" } ``` ### `DELETE /api/education-forms/{id}` Удаление формы обучения. **Невозможно**, если к ней привязаны группы. --- ## Привязка «Преподаватель ↔ Дисциплина» ### `GET /api/teacher-subjects` Список всех привязок. **Ответ:** ```json [ { "userId": 2, "userName": "Тестовый преподаватель", "subjectId": 1, "subjectName": "Высшая математика" } ] ``` ### `POST /api/teacher-subjects` ```json { "userId": 2, "subjectId": 3 } ``` ### `DELETE /api/teacher-subjects` ```json { "userId": 2, "subjectId": 3 } ``` --- ## Управление тенантами (Базы данных) ### `GET /api/database/status` Статус текущего подключения (определяется по домену запроса). **Ответ:** ```json { "tenant": "default", "connected": true, "configured": true, "name": "Default", "url": "jdbc:postgresql://db:5432/app_db" } ``` ### `GET /api/database/tenants` Список всех тенантов. ### `POST /api/database/tenants` Добавление нового тенанта. ```json { "name": "СВФУ", "domain": "swsu", "url": "jdbc:postgresql://db-host:5432/swsu_db", "username": "dbuser", "password": "dbpass" } ``` **Логика:** 1. Создаёт HikariCP пул для нового тенанта 2. Запускает Flyway миграции на его БД 3. Обновляет Kubernetes ConfigMap ### `DELETE /api/database/tenants/{domain}` Удаление тенанта. ### `POST /api/database/test` Тест подключения к произвольной БД (без регистрации тенанта). ```json { "url": "jdbc:postgresql://host:5432/testdb", "username": "user", "password": "pass" } ``` **Ответ:** ```json { "success": true, "message": "Подключение успешно!" } ``` --- ## Коды ответов | Код | Описание | |-----|----------| | `200` | Успех | | `400` | Ошибка валидации (с `message` в теле) | | `401` | Неверные учётные данные | | `404` | Ресурс / тенант не найден | | `500` | Внутренняя ошибка сервера |