52 lines
3.5 KiB
Markdown
52 lines
3.5 KiB
Markdown
# Phase 3: БД + API (custom_sims)
|
|
|
|
**Status:** ⬜ Not Started
|
|
**Parent plan:** [PLAN.md](./PLAN.md)
|
|
**Domain:** backend
|
|
|
|
## Objective
|
|
Сохранение custom-симуляций: таблица БД, CRUD API под авторизацией с проверкой владения,
|
|
серверная валидация спеки. После фазы спека сохраняется/грузится/удаляется через API.
|
|
|
|
## Tasks
|
|
- [ ] Миграция `backend/src/db/migrations/0NN_custom_sims.sql` (следующий свободный номер):
|
|
таблица `custom_sims` (id, owner_id FK users ON DELETE CASCADE, title, description, subject,
|
|
grade, cat, spec_json TEXT, status TEXT 'draft|published' DEFAULT 'draft', version INT,
|
|
created_at, updated_at) + индекс по owner_id, status.
|
|
- [ ] Контроллер `backend/src/controllers/customSimController.js`: list (own + published), get,
|
|
create, update, remove. Владение проверяется на mutate (owner или admin).
|
|
- [ ] Серверная валидация спеки `validateSpec(spec)`: размер JSON, `specVersion`, лимиты
|
|
(число params/objects, глубина строк-выражений), типы объектов из whitelist, строки-подписи
|
|
обрезаются/санитизируются. Отказ с 400 при нарушении. ⛔ Никакого исполнения спеки на сервере.
|
|
- [ ] Роуты `backend/src/routes/customSims.js`: `GET /api/custom-sims` (свои+published),
|
|
`GET /api/custom-sims/:id`, `POST /` (teacher/admin), `PUT /:id`, `DELETE /:id`. Смонтировать в server.js под authMiddleware + фича-гейт при необходимости.
|
|
- [ ] Клиент `js/api.js`: `customSimsList/Get/Create/Update/Delete` + добавить в `window.LS`.
|
|
- [ ] Тесты `backend/tests/custom-sims.test.js`: CRUD, ownership (403 чужой), валидация (400 кривая спека). Использовать `seedRow()` паттерн (устойчив к дрейфу схемы).
|
|
|
|
## Files to Modify/Create
|
|
- `backend/src/db/migrations/0NN_custom_sims.sql` (new)
|
|
- `backend/src/controllers/customSimController.js` (new)
|
|
- `backend/src/routes/customSims.js` (new)
|
|
- `backend/src/server.js` — монтирование роутера (modify)
|
|
- `js/api.js` — клиентские методы (modify)
|
|
- `backend/tests/custom-sims.test.js` (new)
|
|
|
|
## Acceptance Criteria
|
|
- POST сохраняет спеку, GET возвращает свои+published, PUT/DELETE только владельцу/админу (403 иначе).
|
|
- Кривая/огромная спека → 400. Тесты зелёные (в пределах baseline).
|
|
- `npm run migrate` применяет таблицу; роут не отдаёт SPA-fallback после рестарта.
|
|
|
|
## Notes
|
|
- node:sqlite (DatabaseSync), НЕ better-sqlite3.
|
|
- Спека хранится как TEXT(JSON); парс/валидация — на входе.
|
|
- Не делать blanket `router.use(requireRole('admin'))` — read-роуты auth-only, мутации — inline requireRole.
|
|
|
|
## Review Checklist
|
|
- [ ] Все задачи выполнены
|
|
- [ ] Ownership и валидация спеки покрыты тестами
|
|
- [ ] Миграция идемпотентна (IF NOT EXISTS / INSERT OR IGNORE где надо)
|
|
- [ ] `npm run lint:routes` чисто; тесты в пределах baseline
|
|
|
|
## Handoff to Next Phase
|
|
<!-- Заполняет реализатор -->
|