Phase 7: deployment, data import, UI hardening and security fixes

Docker/prod deployment:
- multi-stage Dockerfile (JDK21 build, JRE21 run), docker-compose.prod.yml,
  nginx config for lms.our-place.ru, deploy.sh; DEPLOY/IMPORT guides (UI flow)
- Fix Docker 401: LMS_JWT_JWK_SET_URI for academic/progress; forward-headers

Variant distribution (lab page only):
- round-robin by student level, shared random queue across selected groups,
  least-used variants, manual pins always preserved; occupied/dup labels
- setup page: single form + one «Сохранить всё», batch level/variant for
  selected students (checkboxes)

Grades, defense, materials:
- publication gate + comment lists; defense CSV import (2/3 cols, quotes)
- additional task after defense ("начать заново"); enroll/unenroll students
  from group page; temporary-password lock (no navigation until changed) and
  persistent "Смена пароля"; forced change once
- chapter page /learn/{c}; header: LMS home, Войти, user -> dashboard,
  compact theme toggle; responsive mobile header
- markdown: single newlines are soft breaks; highlight.js with light/dark themes
- lab/content imports ZIP-only (lab.yaml+README+variants/assets,
  chapters tree+assets); duplicate lab numbers rejected; variant ordering
  and date defaults honored

Fixes:
- 500 on student create (@MapsId set before persist); broken dialogs/JS refs in group page
This commit is contained in:
2026-09-14 22:01:46 +03:00
parent 08830c67f1
commit d04207302a
58 changed files with 3967 additions and 884 deletions

View File

@@ -38,6 +38,33 @@
Порты по умолчанию: gateway `:8080`, identity `:8081`, academic `:8082`,
progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
## Запуск в Docker (для сервера)
На сервере Java не нужна: всё собирается и работает в контейнерах (multi-stage
`Dockerfile`, сборка на JDK 21, запуск на JRE 21).
```bash
cp .env.prod.example .env.prod # заполнить LMS_DB_PASSWORD
./deploy/deploy.sh up # сборка + запуск (postgres, 5 сервисов)
./deploy/deploy.sh logs web
./deploy/deploy.sh ps
./deploy/deploy.sh down
```
Наружу публикуется только web на `127.0.0.1:8090`; reverse proxy — nginx
(конфиг и полная инструкция по деплою на `lms.our-place.ru` в
[`deploy/DEPLOY.md`](deploy/DEPLOY.md) и `deploy/nginx/lms.our-place.ru.conf`).
## Наполнение данными
Порядок ввода данных (всё через админку): `/setup` → администратор; импорт групп
(`.xls`, логин = студенческий номер, временный пароль со сменой при первом входе);
импорт лабораторной ZIP'ом (`lab.yaml` + `README.md` + `variants/*.md`); «Распределить»
— случайная раздача по кругам в рамках уровня; оценки/защита — на странице группы;
учебные материалы — статьи или ZIP (`chapters/…`, доступны гостям).
Подробный пошаговый порядок — в [`deploy/IMPORT.md`](deploy/IMPORT.md).
## Текущий функционал
Открыть `http://localhost:8090`. При первом запуске создаётся аккаунт
@@ -46,15 +73,24 @@ progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
- **Доступ**: JWT (RSA, ключи identity генерирует при первом старте и хранит в БД),
проверка токена на gateway, роли ADMIN/STUDENT, CSRF на всех POST-формах,
session fixation-защита; вход студента с обязательной сменой пароля.
- **Группы и студенты**: создание groups, импорт `.xls/.xlsx/.csv`, ручное
добавление студента (генерация пароля), выгрузка логинов XLSX/CSV, сброс пароля;
на странице группы — баллы по каждой лабе и средний балл.
- **Лабораторные**: импорт ZIP (`lab.yaml` + `README.md` + `variants/*.md` c
front-matter) и старого JSON; создание через UI с произвольным числом уровней;
просмотр/редактирование условия (markdown), вариантов, дат; статусы
draft/published (клик по бейджу меняет); даты выводятся в московском времени.
- **Распределение вариантов**: по уровню студента на лабу (по умолчанию — самый
простой), round-robin с уникальностью в группе; ручное назначение варианта.
- **Группы и студенты**: создание групп, импорт `.xls/.xlsx/.csv`, ручное
добавление студента (генерация пароля) и «Добавить существующего» (перевод из
другой группы), «Отчислить из группы», выгрузка логинов XLSX/CSV, сброс пароля.
- **Лабораторные**: импорт ZIP (`lab.yaml` + `README.md` + `variants/*.md` +
`assets/`); создание через UI с произвольным числом уровней; единая форма
настроек с одной кнопкой «Сохранить всё»; статусы draft/published
(клик по бейджу меняет); даты в московском времени.
- **Распределение вариантов** (только на странице лабы): «Распределить» с
выбором групп; раздача случайная и равномерная — студенты выбранных групп
идут общей очередью, вариант берётся со своего уровня, пока в уровне есть
невыданные — без повторов, затем выдаются наименее занятые; ручные
закрепления сохраняются всегда. На странице лабы — список назначений по
группам (уровень/вариант каждому), массовые операции чекбоксами, индикаторы
«выдано/всего». Матрица на странице группы — просмотр (вариант, сдача) +
оценки/защита, управление раздачей оттуда убрано.
- **Индивидуальные задания (защита)**: на странице группы — назначение/изменение
задания, импорт CSV (2 или 3 колонки, с кавычками и `\n`), выдача кода,
«доп. задание: начать заново» после завершения защиты.
- **Материалы** (`/learn`, публичная читалка): главы → разделы → статьи в
markdown (код, спойлеры, картинки; санитизация OWASP); импорт ZIP
(`chapters/N-глава/N-раздел/N-статья.md` + `assets/`); создание/переименование/
@@ -62,9 +98,16 @@ progress `:8083`, web `:8090`. Интерфейс: `http://localhost:8090`.
- **Студент**: дашборд успеваемости (сдано, средний балл, лучшая/слабая оценка),
карточки опубликованных лаб, страница лабы: условие, свой вариант, сдача
файлов (zip/.c, переотправка до дедлайна, история, скачивание последней),
комментарий преподавателя к оценке, защита по одноразовому коду (30 мин).
- **Комментарии к оценкам**: тональность (pos/neu/neg), хранятся в БД,
автоподсказки при вводе ранжируются по частоте использования; видны студенту чипсами.
оценка и комментарии отдельным блоком, защита по одноразовому коду (30 мин).
- **Публикация оценок**: в группе по каждой лабе — кнопка «опубликовать»; студент
видит оценку и комментарии только после публикации (публикуется вся группа).
- **Комментарии к оценкам**: тональность (positive/negative/neutral), на странице
студента — ненумерованными списками в трёх колонках, хранятся в БД,
автоподсказки при вводе ранжируются по частоте использования.
- **Архив сдач группы**: одна кнопка «Скачать все работы» — ZIP со всеми
последними решениями группы, разложенными по лабам и студентам.
- **Материалы** `/learn` доступны без входа; аккордеон глав: свёрнуты все,
открыта последняя.
- UI: светлая/тёмная тема (сохраняется в localStorage), модальные окна вместо
отдельных страниц, аккордеоны глав/разделов в `/learn`, фавиконка,
адаптивная вёрстка без inline-стилей.