first commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
const express = require('express');
|
||||
const db = require('../db');
|
||||
const requireModerator = require('../middleware/requireModerator');
|
||||
const router = express.Router();
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const uploadDir = path.join(__dirname, '../../uploads');
|
||||
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => cb(null, uploadDir),
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname);
|
||||
const name = Date.now() + '-' + Math.round(Math.random() * 1e6) + ext;
|
||||
cb(null, name);
|
||||
}
|
||||
});
|
||||
const ALLOWED_MIME_TYPES = [
|
||||
'image/jpeg', 'image/png',
|
||||
'video/mp4', 'video/quicktime'
|
||||
];
|
||||
const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20 МБ
|
||||
|
||||
const upload = multer({
|
||||
storage,
|
||||
limits: { fileSize: MAX_FILE_SIZE },
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (ALLOWED_MIME_TYPES.includes(file.mimetype)) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Недопустимый тип файла'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Получить все блоки для вкладки
|
||||
router.get('/:tab', async (req, res) => {
|
||||
const { tab } = req.params;
|
||||
if (!['info', 'union'].includes(tab)) return res.status(400).json({ message: 'Некорректная вкладка' });
|
||||
try {
|
||||
const [rows] = await db.query('SELECT * FROM content_blocks WHERE tab = ? ORDER BY created_at ASC', [tab]);
|
||||
res.json(rows);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
||||
// Загрузка файла (image/video)
|
||||
router.post('/:tab/upload', requireModerator, upload.single('file'), (req, res) => {
|
||||
if (!req.file) return res.status(400).json({ message: 'Файл не загружен' });
|
||||
const relPath = '/uploads/' + req.file.filename;
|
||||
res.json({ path: relPath });
|
||||
});
|
||||
|
||||
// Добавить новый блок
|
||||
router.post('/:tab', requireModerator, async (req, res) => {
|
||||
const { tab } = req.params;
|
||||
const { content } = req.body;
|
||||
if (!['info', 'union'].includes(tab)) return res.status(400).json({ message: 'Некорректная вкладка' });
|
||||
try {
|
||||
const [result] = await db.query(
|
||||
'INSERT INTO content_blocks (tab, type, content, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, NOW(), NOW())',
|
||||
[tab, 'text', content, req.session.userId]
|
||||
);
|
||||
res.json({ id: result.insertId });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
||||
// Обновить блок
|
||||
router.put('/:tab/:id', requireModerator, async (req, res) => {
|
||||
const { tab, id } = req.params;
|
||||
const { content } = req.body;
|
||||
if (!['info', 'union'].includes(tab)) return res.status(400).json({ message: 'Некорректная вкладка' });
|
||||
try {
|
||||
await db.query(
|
||||
'UPDATE content_blocks SET content = ?, updated_at = NOW() WHERE id = ? AND tab = ?',
|
||||
[content, id, tab]
|
||||
);
|
||||
res.json({ message: 'Обновлено' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
||||
// Удалить блок
|
||||
router.delete('/:tab/:id', requireModerator, async (req, res) => {
|
||||
const { tab, id } = req.params;
|
||||
if (!['info', 'union'].includes(tab)) return res.status(400).json({ message: 'Некорректная вкладка' });
|
||||
try {
|
||||
await db.query('DELETE FROM content_blocks WHERE id = ? AND tab = ?', [id, tab]);
|
||||
res.json({ message: 'Удалено' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,81 @@
|
||||
const express = require('express');
|
||||
const bcrypt = require('bcrypt');
|
||||
const db = require('../db');
|
||||
const router = express.Router();
|
||||
const logger = require('../../logger');
|
||||
const rateLimit = require('express-rate-limit');
|
||||
const csurf = require('csurf');
|
||||
|
||||
const csrfProtection = csurf({ cookie: false });
|
||||
|
||||
const loginLimiter = rateLimit({
|
||||
windowMs: 30 * 60 * 1000, // 30 минут
|
||||
max: 10,
|
||||
message: { message: 'Слишком много попыток входа. Попробуйте позже.' },
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false
|
||||
});
|
||||
|
||||
router.get('/csrf-token', csrfProtection, (req, res) => {
|
||||
res.json({ csrfToken: req.csrfToken() });
|
||||
});
|
||||
|
||||
router.post('/moder-login', loginLimiter, async (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
logger.info(`[LOGIN] Попытка входа: ${username}`);
|
||||
try {
|
||||
logger.info('[LOGIN] Проверка подключения к базе...');
|
||||
const [rows] = await db.query('SELECT * FROM users WHERE username = ?', [username]);
|
||||
logger.info(`[LOGIN] Результат поиска пользователя: ${rows.length > 0 ? 'найден' : 'не найден'}`);
|
||||
if (!rows.length) {
|
||||
logger.warn(`[LOGIN] Пользователь не найден: ${username}`);
|
||||
return res.status(401).json({ message: 'Неверный логин или пароль' });
|
||||
}
|
||||
const user = rows[0];
|
||||
if (!user.password_hash) {
|
||||
logger.error('[LOGIN] Отсутствует password_hash в БД');
|
||||
return res.status(500).json({ message: 'Ошибка сервера: некорректные данные пользователя' });
|
||||
}
|
||||
logger.info('[LOGIN] Сравнение пароля через bcrypt...');
|
||||
const match = await bcrypt.compare(password, user.password_hash);
|
||||
logger.info(`[LOGIN] Результат сравнения пароля: ${match}`);
|
||||
if (!match) {
|
||||
logger.warn(`[LOGIN] Неверный пароль для пользователя: ${username}`);
|
||||
return res.status(401).json({ message: 'Неверный логин или пароль' });
|
||||
}
|
||||
try {
|
||||
req.session.isModerator = true;
|
||||
req.session.userId = user.id;
|
||||
req.session.username = user.username;
|
||||
logger.info('[LOGIN] Сессия установлена:', {
|
||||
isModerator: req.session.isModerator,
|
||||
userId: req.session.userId,
|
||||
username: req.session.username
|
||||
});
|
||||
res.json({ message: 'OK' });
|
||||
logger.info('[LOGIN] Ответ отправлен');
|
||||
} catch (e) {
|
||||
logger.error('[LOGIN] Ошибка при установке сессии или отправке ответа:', e);
|
||||
res.status(500).json({ message: 'Ошибка сервера (сессия)' });
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('[LOGIN] Ошибка авторизации:', err);
|
||||
res.status(500).json({ message: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/moder-logout', (req, res) => {
|
||||
req.session.destroy(() => {
|
||||
res.json({ message: 'OK' });
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/check-session', (req, res) => {
|
||||
if (req.session && req.session.isModerator) {
|
||||
res.json({ ok: true });
|
||||
} else {
|
||||
res.status(401).json({ ok: false });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user