UI rework: modal dialogs, inline lab editing, manual creation, content management

- Dashboard: real stats (groups, students, labs, average grade), labs/groups
  summary lists, no placeholder tile
- Lab page: view + edit combined — metadata form in modal, condition rendered
  as markdown, per-level variant tables with add/edit/delete dialogs,
  level rename/delete, student level/variant selectors with group filter
- Labs list: create-lab dialog with manual level entry (code; title lines)
- Groups: create-group dialog, add-student dialog (auto password, toast card)
- Content: public /learn reader is the single place; admin buttons (new
  article with chapter/section create-or-select, rename/delete chapters and
  sections, move articles between sections, import zip) appear for admins;
  removed separate 'Контент' admin section
- Buttons use btn classes instead of nav-link
- Favicon: generated SVG book icon
- Security: CSRF synchronizer token interceptor (replaced spring-security in
  web which broke logback under nested jars), session regenerated on login,
  hardened session cookie, gateway actuator limited to health,info
- Jackson 3: nullable-safe request DTOs for labs (FAIL_ON_NULL_FOR_PRIMITIVES)
- academic: POST /labs (manual create with levels), level add/rename/delete,
  content chapters/sections CRUD, article create/move/delete endpoints
This commit is contained in:
2026-09-11 16:00:56 +03:00
parent cca20b5416
commit 08890875e5
45 changed files with 2435 additions and 86 deletions

View File

@@ -45,7 +45,8 @@ class JwtAuthenticationFilter(private val jwtDecoder: JwtDecoder) : GlobalFilter
path == "/api/v1/auth/login" ||
path == "/api/v1/auth/setup" ||
path == "/api/v1/auth/health" ||
path == "/api/v1/auth/jwks.json"
path == "/api/v1/auth/jwks.json" ||
path.startsWith("/api/v1/content/")
private fun bearerToken(exchange: ServerWebExchange): String? {
val header = exchange.request.headers.getFirst("Authorization") ?: return null

View File

@@ -16,7 +16,7 @@ spring:
- id: academic
uri: ${LMS_ACADEMIC_URI:http://localhost:8082}
predicates:
- Path=/api/v1/courses/**,/api/v1/articles/**,/api/v1/labs/**,/api/v1/assets/**
- Path=/api/v1/courses/**,/api/v1/articles/**,/api/v1/labs,/api/v1/labs/**,/api/v1/assets/**,/api/v1/content/**
- id: progress
uri: ${LMS_PROGRESS_URI:http://localhost:8083}
predicates:
@@ -26,7 +26,7 @@ management:
endpoints:
web:
exposure:
include: health,info,gateway
include: health,info
endpoint:
health:
probes: