ваше сообщение коммита

This commit is contained in:
2025-09-02 15:33:18 +03:00
parent c007c0b296
commit a6360ccd2e
21 changed files with 1269 additions and 316 deletions

View File

@@ -483,6 +483,105 @@ router.get('/email-settings', requireAdmin, async (req, res) => {
}
});
// Обновить настройки Email
router.put('/email-settings', requireAdmin, async (req, res, next) => {
try {
const {
imap_host,
imap_port,
imap_user,
imap_password,
smtp_host,
smtp_port,
smtp_user,
smtp_password,
from_email,
is_active
} = req.body;
// Валидация обязательных полей
if (!imap_host || !imap_port || !imap_user || !imap_password ||
!smtp_host || !smtp_port || !smtp_user || !smtp_password || !from_email) {
return res.status(400).json({
success: false,
error: 'Все поля обязательны для заполнения'
});
}
const settings = {
imap_host,
imap_port: parseInt(imap_port),
imap_user,
imap_password,
smtp_host,
smtp_port: parseInt(smtp_port),
smtp_user,
smtp_password,
from_email,
is_active: is_active !== undefined ? is_active : true,
updated_at: new Date()
};
const result = await emailBotService.saveEmailSettings(settings);
res.json({ success: true, data: result });
} catch (error) {
logger.error('Ошибка при обновлении email настроек:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Тест email функциональности
router.post('/email-settings/test', requireAdmin, async (req, res, next) => {
try {
const { test_email } = req.body;
if (!test_email) {
return res.status(400).json({
success: false,
error: 'test_email обязателен для тестирования'
});
}
// Отправляем тестовое письмо
const result = await emailBotService.sendEmail(
test_email,
'Тест Email системы DLE',
'Это тестовое письмо для проверки работы email системы. Если вы его получили, значит настройки работают корректно!'
);
res.json({
success: true,
message: 'Тестовое письмо отправлено успешно',
data: result
});
} catch (error) {
logger.error('Ошибка при тестировании email:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Тест IMAP подключения
router.post('/email-settings/test-imap', requireAdmin, async (req, res, next) => {
try {
const result = await emailBotService.testImapConnection();
res.json(result);
} catch (error) {
logger.error('Ошибка при тестировании IMAP подключения:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Тест SMTP подключения
router.post('/email-settings/test-smtp', requireAdmin, async (req, res, next) => {
try {
const result = await emailBotService.testSmtpConnection();
res.json(result);
} catch (error) {
logger.error('Ошибка при тестировании SMTP подключения:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Получить список всех email (для ассистента)
router.get('/email-settings/list', requireAdmin, async (req, res) => {
try {
@@ -503,6 +602,35 @@ router.get('/telegram-settings', requireAdmin, async (req, res, next) => {
}
});
// Обновить настройки Telegram-бота
router.put('/telegram-settings', requireAdmin, async (req, res, next) => {
try {
const { bot_token, bot_username, webhook_url, is_active } = req.body;
// Валидация обязательных полей
if (!bot_token || !bot_username) {
return res.status(400).json({
success: false,
error: 'bot_token и bot_username обязательны'
});
}
const settings = {
bot_token,
bot_username,
webhook_url: webhook_url || null,
is_active: is_active !== undefined ? is_active : true,
updated_at: new Date()
};
const result = await telegramBot.saveTelegramSettings(settings);
res.json({ success: true, data: result });
} catch (error) {
logger.error('Ошибка при обновлении настроек Telegram:', error);
res.status(500).json({ success: false, error: error.message });
}
});
// Получить список всех Telegram-ботов (для ассистента)
router.get('/telegram-settings/list', requireAdmin, async (req, res, next) => {
try {

View File

@@ -40,7 +40,8 @@ router.post('/logo', auth.requireAuth, auth.requireAdmin, upload.single('logo'),
if (!req.file) return res.status(400).json({ success: false, message: 'Файл не получен' });
const rel = path.posix.join('uploads', 'logos', path.basename(req.file.filename));
const urlPath = `/uploads/logos/${path.basename(req.file.filename)}`;
return res.json({ success: true, data: { path: rel, url: urlPath } });
const fullUrl = `http://localhost:8000${urlPath}`;
return res.json({ success: true, data: { path: rel, url: fullUrl } });
} catch (e) {
return res.status(500).json({ success: false, message: e.message });
}

View File

@@ -213,7 +213,7 @@ router.get('/', requireAuth, async (req, res, next) => {
// --- Формируем ответ ---
const contacts = users.map(u => ({
id: u.id,
name: null, // Имена теперь только в зашифрованных колонках
name: [u.first_name, u.last_name].filter(Boolean).join(' ').trim() || null,
email: u.email || null,
telegram: u.telegram || null,
wallet: u.wallet || null,
@@ -446,9 +446,19 @@ router.get('/:id', async (req, res, next) => {
for (const id of identitiesResult.rows) {
identityMap[id.provider] = id.provider_id;
}
// Получаем имя пользователя из зашифрованных полей
const nameResult = await query('SELECT CASE WHEN first_name_encrypted IS NULL OR first_name_encrypted = \'\' THEN NULL ELSE decrypt_text(first_name_encrypted, $2) END as first_name, CASE WHEN last_name_encrypted IS NULL OR last_name_encrypted = \'\' THEN NULL ELSE decrypt_text(last_name_encrypted, $2) END as last_name FROM users WHERE id = $1', [userId, encryptionKey]);
let fullName = null;
if (nameResult.rows.length > 0) {
const firstName = nameResult.rows[0].first_name || '';
const lastName = nameResult.rows[0].last_name || '';
fullName = [firstName, lastName].filter(Boolean).join(' ').trim() || null;
}
res.json({
id: user.id,
name: null, // Пока не используем имена
name: fullName,
email: identityMap.email || null,
telegram: identityMap.telegram || null,
wallet: identityMap.wallet || null,