v4.1.21: Реструктуризация проекта для Synology ARM

- Реструктуризация: src/ разбит на middleware/, utils/, repositories/ (удалены), routes/ (удалены)
- Добавлен src/original-html.ts — полный HTML с reportModal
- Добавлен src/index.tsx.backup — React-компонент с reportModal
- Миграции переименованы (0001_initial_schema.sql)
- Добавлена миграция 0018 (удалена позже)
- Docker: multi-stage build, wrangler.toml
- Frontend: public/static/app.js + style.css
- seed.sql добавлен
- Документация: CHANGELOG, CHANGES_v4.1.0-4.1.9, PROJECT_STRUCTURE
This commit is contained in:
Deploy Bot
2026-01-14 18:37:00 +02:00
parent 4898f5ec7f
commit 64403d6fd6
113 changed files with 19231 additions and 3084 deletions

192
CHANGES_v4.1.9.md Normal file
View File

@@ -0,0 +1,192 @@
# AKNAPROFF v4.1.9 - Fix Notes Permissions (User → View Only)
**Дата:** 2025-12-30
**Версия:** v4.1.9
**Тип:** Permission Fix
---
## Изменение
### Märkused (Notes) - изменены права доступа
**Было (v4.1.8):**
- ✅ Admin: редактирование заметок
- ✅ User (kasutaja): редактирование заметок ❌ **НЕПРАВИЛЬНО**
- ❌ Guest: только просмотр
**Стало (v4.1.9):**
- ✅ Admin: редактирование заметок
- 👁️ User (kasutaja): **только просмотр** (кнопка "Salvesta" скрыта)
- 👁️ Guest: только просмотр
---
## Исправления
### Frontend (public/static/app.js)
1. **openNotesModal():**
- Было: `const readOnly = !canEditProblems()` (user + admin)
- Стало: `const readOnly = !canEditRecords()` (только admin)
2. **saveNotes():**
- Было: `if (!canEditProblems())` (user + admin)
- Стало: `if (!canEditRecords())` (только admin)
### Backend (src/index.tsx)
1. **PATCH /api/records/:id/notes:**
- Изменён middleware: `optionalAuthMiddleware``authMiddleware` (требует авторизации)
- Добавлена проверка роли:
```typescript
const userRole = c.get('role')
if (userRole !== 'admin') {
return c.json({ error: 'Permission denied. Only admin can edit notes.' }, 403)
}
```
2. **PATCH /api/records/:id/problems:**
- Изменён middleware: `optionalAuthMiddleware` → `authMiddleware`
- Добавлена проверка роли:
```typescript
const userRole = c.get('role')
if (userRole !== 'admin' && userRole !== 'user') {
return c.json({ error: 'Permission denied. Only admin and user can edit problems.' }, 403)
}
```
---
## Тестирование
### Backend API Tests
#### ✅ User НЕ может редактировать Notes
```bash
TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
-d '{"username":"kasutaja","password":"tootmine"}' | jq -r .token)
curl -X PATCH http://localhost:3000/api/records/2/notes \
-H "Authorization: Bearer $TOKEN" \
-d '{"notes":"Should not work"}'
# → {"error": "Permission denied. Only admin can edit notes."} ✅ 403
```
#### ✅ User может редактировать Problems
```bash
curl -X PATCH http://localhost:3000/api/records/2/problems \
-H "Authorization: Bearer $TOKEN" \
-d '{"problems":"Test","errorFlags":{"worksheets_error":1}}'
# → {"success": true} ✅ 200
```
#### ✅ Admin может редактировать Notes
```bash
TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
-d '{"username":"admin","password":"demo123"}' | jq -r .token)
curl -X PATCH http://localhost:3000/api/records/2/notes \
-H "Authorization: Bearer $TOKEN" \
-d '{"notes":"Admin can edit"}'
# → {"success": true} ✅ 200
```
### Frontend Tests
- ✅ Admin открывает Notes → поле редактируемое + кнопка "Salvesta" видна
- ✅ User открывает Notes → поле read-only + кнопка "Salvesta" скрыта
- ✅ Guest открывает Notes → поле read-only + кнопка "Salvesta" скрыта
- ✅ User может редактировать Problems (кнопка видна)
---
## Матрица Прав Доступа (Финальная)
| Действие | Admin | User (kasutaja) | Guest |
|----------|-------|-----------------|-------|
| **Просмотр данных** | ✅ | ✅ | ✅ |
| **Märkused (просмотр)** | ✅ | ✅ | ✅ |
| **Märkused (редактирование)** | ✅ | ❌ | ❌ |
| **Probleemid (просмотр)** | ✅ | ✅ | ✅ |
| **Probleemid (редактирование)** | ✅ | ✅ | ❌ |
| **Lisa uus rida** | ✅ | ❌ | ❌ |
| **Редактировать даты** | ✅ | ❌ | ❌ |
| **Удалить запись** | ✅ | ❌ | ❌ |
| **Редактировать все поля** | ✅ | ❌ | ❌ |
---
## Deployment на Production
### Файлы для Копирования
**Быстрый вариант (рекомендуется):**
```bash
scp dist/_worker.js user@server:/path/to/webapp/dist/
docker-compose restart
```
**Полный вариант:**
```bash
scp public/static/app.js user@server:/path/to/webapp/public/static/
scp public/original.html user@server:/path/to/webapp/public/
scp src/original-html.ts user@server:/path/to/webapp/src/
scp src/index.tsx user@server:/path/to/webapp/src/
cd /path/to/webapp && npm run build && docker-compose restart
```
### Проверка после deployment
```bash
# 1. Войти как kasutaja
# 2. Открыть запись → нажать на Märkused (желтая ячейка)
# 3. Проверить: поле read-only, кнопка "Salvesta" скрыта
# 4. Открыть запись → нажать на Probleemid (красная ячейка)
# 5. Проверить: поле редактируемое, кнопка "Salvesta" видна
```
---
## Статус
- **Версия:** v4.1.9
- **Статус:** ✅ Production Ready
- **Production URL:** https://3000-iabcqs9fpouqnd3allaai-82b888ba.sandbox.novita.ai
- **HTTP:** 200 OK
- **JavaScript Errors:** 0
- **База данных:** Не изменена
---
## Changelog
### v4.1.9 (2025-12-30) - Permission Fix
- 🔧 **FIX:** User (kasutaja) теперь может только **просматривать** заметки (было: редактировать)
- 🔧 **FIX:** Добавлены backend проверки роли для `/api/records/:id/notes` (только admin)
- 🔧 **FIX:** Добавлены backend проверки роли для `/api/records/:id/problems` (admin + user)
- 🎨 **UI:** Кнопка "Salvesta" скрыта для user при просмотре заметок
-**VERIFY:** Все права доступа работают корректно (frontend + backend)
---
## Сравнение с v4.1.8
| Изменение | v4.1.8 | v4.1.9 |
|-----------|---------|---------|
| **User редактирует Notes** | ✅ (неправильно) | ❌ (исправлено) |
| **User просматривает Notes** | ✅ | ✅ |
| **User редактирует Problems** | ✅ | ✅ |
| **Backend проверка прав** | ❌ | ✅ |
| **Кнопка "Lisa uus rida" для user** | скрыта | скрыта |
---
## Итог
**Исправлено согласно требованию:**
- User (kasutaja) может только **просматривать** заметки
- Кнопка "Salvesta" скрыта для user в модальном окне заметок
- Backend проверяет роль и возвращает 403 для user при попытке редактирования
- User по-прежнему может редактировать проблемы
🎯 **Готово к deployment на production!**