Vladislav Kopnin eb55f47f47 Phase 1 fixes: broken dialogs, score width, status badge, MSK date round-trip
- group/lab/labs: move dialogs/scripts INSIDE the #content fragment (they were
  outside — the layout fragment dropped them, which is why 'add student' did nothing)
- group.html toast had swallowed the dialog (th:if createdStudent) — split properly
- .input-score width no longer overridden by .inline-form .input-sm (10rem min)
- lab page: remove separate 'change status' button — status badge is now a toggle
  button itself (confirm dialog kept)
- DateUtils.localInput/toUtcIso: dates entered in datetime-local are Moscow-local,
  stored as UTC instant, shown back MSK — correct round-trip both ways
- academic parseInstant: naive local datetimes treated as Europe/Moscow
- README/module docs left as-is
2026-09-11 23:11:40 +03:00

LMS

Микросервисная система для проведения практических занятий (Kotlin + Spring Boot + PostgreSQL 18).

Модули

  • libs/common-http — общий формат ошибок и обработчик исключений.
  • libs/security-jwt — выпуск/проверка JWT (RSA) и PasswordEncoder.
  • libs/markdown — серверный рендер markdown со спойлерами и санитизацией.
  • libs/test-support — общая тестовая инфраструктура (Testcontainers, postgres:18).
  • services/identity-service — аккаунты, студенты, группы, зачисления (схема identity).
  • services/academic-service — курсы, статьи, лабораторные, уровни, варианты (схема academic).
  • services/progress-service — уровни студентов, распределение вариантов, работы, оценки (схема progress).
  • services/gateway — Spring Cloud Gateway, маршрутизация и проверка JWT.
  • web — серверный веб-интерфейс (Thymeleaf + htmx), BFF.

Требования

  • JDK 21 (runtime) + Docker (для PostgreSQL 18). Gradle сам скачает toolchain 21 для сборки.
  • Не запускать сервисы на JAVA_HOME=Java 25: на 25 ломается logback внутри fat-jar (NoClassDefFoundError ThrowableProxy), что роняет потоки Tomcat. Скрипт run.sh использует JDK 21 автоматически.

Запуск

./gradlew bootJar -x test    # собрать все сервисы
./run.sh start               # поднять БД + все 5 сервисов на JDK 21
./run.sh status              # проверить здоровье
./run.sh logs web            # посмотреть лог сервиса
./run.sh stop | restart

Можно и без скрипта: docker compose up -d postgres, затем /usr/lib/jvm/java-21-openjdk/bin/java -jar <jar> для каждого сервиса, или ./gradlew :services:identity-service:bootRun и т.д. по одному.

Порты по умолчанию: gateway :8080, identity :8081, academic :8082, progress :8083, web :8090. Интерфейс: http://localhost:8090.

Текущий функционал

Открыть http://localhost:8090. При первом запуске создаётся аккаунт администратора (/setup); далее — вход по логину и паролю.

  • Доступ: 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 с уникальностью в группе; ручное назначение варианта.
  • Материалы (/learn, публичная читалка): главы → разделы → статьи в markdown (код, спойлеры, картинки; санитизация OWASP); импорт ZIP (chapters/N-глава/N-раздел/N-статья.md + assets/); создание/переименование/ удаление глав, разделов, статей; перенос статей между разделами.
  • Студент: видит опубликованные лабы, свой вариант с условием (markdown), сроки сдачи/защиты и оценки.
  • UI: светлая/тёмная тема (сохраняется в localStorage), модальные окна вместо отдельных страниц, фавиконка, адаптивная вёрстка без inline-стилей.

Сборка и тесты

./gradlew build       # сборка всех модулей
./gradlew check       # тесты и проверки

Переменные окружения для БД: LMS_DB_URL, LMS_DB_USER, LMS_DB_PASSWORD.

Description
No description provided
Readme 5.9 MiB
Languages
Kotlin 55.2%
HTML 26.4%
JavaScript 12.5%
CSS 5.2%
Shell 0.5%
Other 0.2%