docs: этап 5 — курсовые материалы
This commit is contained in:
@@ -280,6 +280,15 @@ CREATE UNIQUE INDEX courses_title_lower_uidx ON courses (lower(title));
|
||||
Сервис дополнительно проверяет название без учёта регистра и возвращает `409`
|
||||
на дубликат; индекс закрывает гонку между проверкой и вставкой.
|
||||
|
||||
**V11 — аудитория глобальных глав (реальный файл `V11__global_audience_all.sql`)**
|
||||
```sql
|
||||
-- Глобальные главы доступны публично; курсовые остаются с audience = NULL.
|
||||
UPDATE academic.chapters SET audience = 'ALL' WHERE course_id IS NULL AND audience IS NULL;
|
||||
```
|
||||
Backfill нужен для глав, созданных до появления правила: публичное дерево
|
||||
показывает только глобальные главы с `audience = 'ALL'`. Новые глобальные главы
|
||||
создаются и импортируются сразу с `audience = 'ALL'`.
|
||||
|
||||
**Post-bootstrap шаг academic (вне Flyway) — курс C: завершение привязки лаб**
|
||||
```sql
|
||||
-- Выполняется сервисом CourseBootstrapService после переноса данных, когда все
|
||||
|
||||
@@ -202,12 +202,12 @@
|
||||
|
||||
Номера уточняются при реализации, чтобы не конфликтовать с максимумами master
|
||||
(identity V3, **academic V5**, progress V12). Максимумы этой ветки:
|
||||
identity V9, **academic V10**, progress V13 (+V14 при необходимости аудита).
|
||||
identity V9, **academic V11**, progress V13 (+V14 при необходимости аудита).
|
||||
|
||||
| Сервис | Миграции | Содержание |
|
||||
|---|---|---|
|
||||
| identity | V4–V9 | роли, поля групп, статусы студентов, `membership_history`, `promotion_runs/items`, `accounts.status` |
|
||||
| academic | V6–V10 + post-bootstrap step | курсы, преподаватели, группы курса, `labs.course_id` (nullable), материалы курса/аудитории, частичные индексы, активы; `V10` — уникальный индекс `lower(title)` по курсам; `SET NOT NULL` — post-bootstrap шаг вне Flyway |
|
||||
| academic | V6–V11 + post-bootstrap step | курсы, преподаватели, группы курса, `labs.course_id` (nullable), материалы курса/аудитории, частичные индексы, активы; `V10` — уникальный индекс `lower(title)` по курсам; `V11` — backfill `audience='ALL'` для глобальных глав; `SET NOT NULL` — post-bootstrap шаг вне Flyway |
|
||||
| progress | V13 (+ V14 при необходимости аудита) | `grade_comments.author_account_id`, `lab_grades.updated_by_account_id`, индекс `lab_grades(lab_id)`; аудит скачиваний — этап 6 |
|
||||
|
||||
### Переход со старой feature-миграции V10 на V13
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
- Миграции:
|
||||
- identity `V4–V9`: роли, группы-когорты, статусы студентов, повышение,
|
||||
история членства, статусы аккаунтов;
|
||||
- academic `V6–V10`: курсы, преподаватели, группы курса, `labs.course_id`,
|
||||
- academic `V6–V11`: курсы, преподаватели, группы курса, `labs.course_id`,
|
||||
материалы курса/аудитории, индексы активов; `V10` (уникальный индекс
|
||||
`lower(title)` по курсам) добавлена на этапе 2, после этого отчёта;
|
||||
`V11` backfill-ом проставляет `audience='ALL'` глобальным главам;
|
||||
- progress `V13`: автор комментария и последнего изменения оценки.
|
||||
- Preflight-скрипты:
|
||||
- `deploy/preflight/groups-courses.sql` — до миграций;
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
- `V8__chapters_course.sql` — `chapters.course_id/audience`, частичные индексы slug.
|
||||
- `V9__article_assets_indexes.sql` — индекс `article_assets(article_id)`.
|
||||
- `V10__course_title_unique.sql` — уникальный индекс `lower(title)` по курсам.
|
||||
- `V11__global_audience_all.sql` — backfill `audience='ALL'` для глобальных глав.
|
||||
|
||||
## 2. API
|
||||
|
||||
|
||||
38
docs/15-stage5-course-materials.md
Normal file
38
docs/15-stage5-course-materials.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Этап 5. Материалы курса
|
||||
|
||||
**Статус:** реализовано в academic-service и web (без изменения identity/progress).
|
||||
|
||||
## Что изменилось
|
||||
|
||||
- Публичные `/api/v1/content/tree` и `/api/v1/content/{chapter}/{section}/{article}`
|
||||
отдают только **глобальные** главы (`course_id IS NULL`) с аудиторией `ALL`.
|
||||
Курсовые главы через публичный контракт больше не доступны.
|
||||
- Материалы курса открываются по `/api/v1/courses/{courseId}/content/...` и требуют
|
||||
аутентификации. Доступ проверяется через `CourseAccessService`:
|
||||
админ — любой курс, преподаватель — только назначенный, студент — только курс
|
||||
активной группы.
|
||||
- Администратор и преподаватель курса видят скрытые главы/разделы/статьи;
|
||||
студент — только опубликованные.
|
||||
- В браузере материалы курса открываются по `/learn/course/{course_no}` и
|
||||
`/learn/course/{course_no}/{chapter}/{section}/{article}`. Анонимный пользователь
|
||||
перенаправляется на `/login`, чужой курс даёт `403`.
|
||||
- Ссылки на материалы курса добавлены в кабинеты студента (карточки лабораторных),
|
||||
преподавателя и администратора.
|
||||
- Админский просмотр и авторство глобальных материалов (`treeAll`, `/api/v1/content/all/...`,
|
||||
`/learn` для админа) сохранены.
|
||||
- Новые глобальные главы создаются и импортируются с `audience = "ALL"`.
|
||||
Миграция `V11__global_audience_all.sql` backfill-ом проставляет `ALL` старым
|
||||
глобальным главам; курсовые главы остаются с `audience = NULL`.
|
||||
|
||||
## Остающийся разрыв: активы
|
||||
|
||||
Публичный прокси активов `/api/v1/content/assets/{name}` и прокси web
|
||||
`/api/v1/content/assets/{name}` **не изменялись**. Активы по-прежнему не привязаны
|
||||
к главе/статье и не наследуют курсовую видимость. Для этапа 6 нужно:
|
||||
|
||||
- связать `article_assets` со статьёй/главой и проверять доступ по токену;
|
||||
- отдавать картинки курсовых статей только авторизованным пользователям курса;
|
||||
- предусмотреть отдельный безопасный путь для публичных `ALL`-материалов.
|
||||
|
||||
В рамках этапа 5 это осознанно не реализуется, чтобы не ломать существующие
|
||||
публичные ссылки на изображения.
|
||||
Reference in New Issue
Block a user