89 lines
3.8 KiB
JavaScript
89 lines
3.8 KiB
JavaScript
const multer = require('multer');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const sharp = require('sharp');
|
|
|
|
let db;
|
|
|
|
function init(database) { db = database; }
|
|
|
|
function setupRoutes(app, auth) {
|
|
const { authenticateToken, requireAdmin } = auth;
|
|
|
|
const imgDir = path.join(__dirname, '..', '..', 'public', 'img');
|
|
const favDir = path.join(__dirname, '..', '..', 'public');
|
|
if (!fs.existsSync(imgDir)) fs.mkdirSync(imgDir, { recursive: true });
|
|
|
|
const storage = multer.memoryStorage();
|
|
const uploadLogo = multer({
|
|
storage,
|
|
limits: { fileSize: 5 * 1024 * 1024 },
|
|
fileFilter: (req, file, cb) => {
|
|
const allowed = ['.jpg', '.jpeg', '.png', '.webp', '.svg', '.gif', '.bmp'];
|
|
const ext = path.extname(file.originalname).toLowerCase();
|
|
if (!allowed.includes(ext)) return cb(new Error('Недопустимый формат файла'));
|
|
cb(null, true);
|
|
}
|
|
});
|
|
|
|
app.post('/api/admin/settings/logo', authenticateToken, requireAdmin, uploadLogo.single('logo'), async (req, res) => {
|
|
if (!req.file) return res.status(400).json({ error: 'Файл не загружен' });
|
|
|
|
try {
|
|
const ext = path.extname(req.file.originalname).toLowerCase();
|
|
const logoWebp = path.join(imgDir, 'logo.webp');
|
|
const fav32 = path.join(favDir, 'favicon-32x32.png');
|
|
const fav16 = path.join(favDir, 'favicon-16x16.png');
|
|
const apple = path.join(favDir, 'apple-touch-icon.png');
|
|
|
|
const pipeline = sharp(req.file.buffer);
|
|
|
|
if (ext !== '.svg') {
|
|
await pipeline.clone().webp({ quality: 85 }).toFile(logoWebp);
|
|
} else {
|
|
fs.writeFileSync(logoWebp, req.file.buffer);
|
|
}
|
|
|
|
if (ext !== '.svg') {
|
|
await pipeline.clone().resize(32, 32, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } }).png().toFile(fav32);
|
|
await pipeline.clone().resize(16, 16, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } }).png().toFile(fav16);
|
|
await pipeline.clone().resize(180, 180, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } }).png().toFile(apple);
|
|
} else {
|
|
fs.writeFileSync(fav32, req.file.buffer);
|
|
fs.writeFileSync(fav16, req.file.buffer);
|
|
fs.writeFileSync(apple, req.file.buffer);
|
|
}
|
|
|
|
const logoPath = './img/logo.webp';
|
|
db.run(`INSERT INTO settings (key, value) VALUES ('logo_path', ?) ON CONFLICT(key) DO UPDATE SET value = ?`, [logoPath, logoPath]);
|
|
|
|
res.json({ path: logoPath, url: logoPath });
|
|
} catch (e) {
|
|
console.error('Ошибка при обработке логотипа:', e);
|
|
res.status(500).json({ error: 'Ошибка обработки изображения' });
|
|
}
|
|
});
|
|
|
|
app.get('/api/admin/settings', authenticateToken, requireAdmin, (req, res) => {
|
|
db.all(`SELECT * FROM settings ORDER BY id`, (err, rows) => {
|
|
if (err) return res.status(500).json({ error: 'Ошибка БД' });
|
|
const obj = {};
|
|
rows.forEach(r => { obj[r.key] = r.value; });
|
|
res.json(obj);
|
|
});
|
|
});
|
|
|
|
app.put('/api/admin/settings', authenticateToken, requireAdmin, (req, res) => {
|
|
const entries = req.body;
|
|
if (!entries || typeof entries !== 'object') return res.status(400).json({ error: 'Неверные данные' });
|
|
const stmt = db.prepare(`UPDATE settings SET value = ? WHERE key = ?`);
|
|
for (const [key, value] of Object.entries(entries)) {
|
|
stmt.run(String(value), key);
|
|
}
|
|
stmt.finalize();
|
|
res.json({ message: 'Обновлено' });
|
|
});
|
|
}
|
|
|
|
module.exports = { init, setupRoutes };
|