fix: classroom review — 11 исправлений из code review

- sessions.js: endSession закрывает classroom_attendance (left_at), чистит classroom_muted
- sessions.js: joinSession восстанавливает mute-состояние при реконнекте
- strokes.js: updateStroke проверяет авторство штриха (не только canDraw)
- strokes.js: clearPage валидирует page_num как положительное целое
- strokes.js: postStrokes ограничивает массив 500 штрихами
- pages.js: duplicatePage сохраняет user_id при копировании штрихов
- pages.js: changePage валидирует page_num
- pages.js: updatePageTemplate делает INSERT OR IGNORE перед UPDATE
- permissions.js: mutePeer сохраняет в classroom_muted; добавлен unmutePeer
- permissions.js: getOnlineStudents не возвращает email
- chat.js: exportChat экранирует переводы строк в именах и сообщениях
- guestClassroom.js: санитизация имени гостя (убираем HTML-символы)
- ws-server.js: mute_peer сохраняет в БД; добавлен обработчик unmute_peer
- routes/classroom.js: rate-limit для cursor/preview/signal/strokes; маршрут DELETE /mute
- migrations/001_classroom_muted.sql: новая таблица classroom_muted
This commit is contained in:
Maxim Dolgolyov
2026-05-07 14:26:19 +03:00
parent 90f6a1d91e
commit c0f20ef020
10 changed files with 85 additions and 27 deletions
+3 -1
View File
@@ -141,7 +141,9 @@ function exportChat(req, res) {
let text = `Чат урока: ${title}\nДата: ${date}\n${'─'.repeat(50)}\n\n`;
messages.forEach(m => {
const ts = m.created_at ? new Date(m.created_at).toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }) : '';
text += `[${ts}] ${m.user_name}: ${m.message || ''}`;
const safeUser = (m.user_name || '').replace(/[\r\n]/g, ' ');
const safeMsg = (m.message || '').replace(/[\r\n]/g, ' ');
text += `[${ts}] ${safeUser}: ${safeMsg}`;
if (m.attachment_url) text += ` [вложение]`;
text += '\n';
});