483 lines
9.8 KiB
Markdown
483 lines
9.8 KiB
Markdown
# 🔌 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 <token>`
|
||
|
||
---
|
||
|
||
## Пользователи
|
||
|
||
### `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` | Внутренняя ошибка сервера |
|