Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m21s
259 lines
7.8 KiB
JavaScript
259 lines
7.8 KiB
JavaScript
/**
|
|
* Роуты для управления IPSec паролями
|
|
* Пароли хранятся в S3 в зашифрованном виде
|
|
*/
|
|
|
|
const { sendError, sendOk } = require('../middleware/errorHandler');
|
|
const { readS3TextObject, writeS3JsonObject, deleteS3Object } = require('../services/s3Service');
|
|
const { encrypt, decrypt } = require('../utils/encryption');
|
|
|
|
const S3_KEY = 'network-config/ipsec-passwords.json';
|
|
|
|
/**
|
|
* GET /api/ipsec-passwords - получить список паролей (без расшифровки)
|
|
*/
|
|
async function getIpsecPasswords(req, res) {
|
|
try {
|
|
const data = await readS3TextObject(S3_KEY).catch(() => ({ body: '[]' }));
|
|
let passwords = [];
|
|
|
|
try {
|
|
passwords = JSON.parse(data.body || '[]');
|
|
if (!Array.isArray(passwords)) {
|
|
passwords = [];
|
|
}
|
|
} catch (parseError) {
|
|
passwords = [];
|
|
}
|
|
|
|
// Возвращаем список паролей БЕЗ расшифровки (только метаданные)
|
|
const result = passwords.map(p => ({
|
|
id: p.id,
|
|
name: p.name || '',
|
|
description: p.description || '',
|
|
createdAt: p.createdAt || null,
|
|
updatedAt: p.updatedAt || null,
|
|
// НЕ возвращаем зашифрованный пароль
|
|
}));
|
|
|
|
res.json(result);
|
|
} catch (error) {
|
|
console.error('Error reading IPSec passwords:', error);
|
|
return sendError(res, 500, 'Error reading IPSec passwords', 'E_S3');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET /api/ipsec-passwords/:id - получить конкретный пароль (расшифрованный)
|
|
*/
|
|
async function getIpsecPassword(req, res) {
|
|
const { id } = req.params;
|
|
|
|
try {
|
|
const data = await readS3TextObject(S3_KEY).catch(() => ({ body: '[]' }));
|
|
let passwords = [];
|
|
|
|
try {
|
|
passwords = JSON.parse(data.body || '[]');
|
|
if (!Array.isArray(passwords)) {
|
|
passwords = [];
|
|
}
|
|
} catch (parseError) {
|
|
passwords = [];
|
|
}
|
|
|
|
const password = passwords.find(p => p.id === id);
|
|
if (!password) {
|
|
return sendError(res, 404, 'IPSec password not found', 'E_NOT_FOUND');
|
|
}
|
|
|
|
// Расшифровываем пароль для возврата
|
|
let decryptedPassword = '';
|
|
try {
|
|
decryptedPassword = decrypt(password.encryptedPassword || '');
|
|
} catch (decryptError) {
|
|
console.error('Error decrypting password:', decryptError);
|
|
return sendError(res, 500, 'Error decrypting password', 'E_DECRYPT');
|
|
}
|
|
|
|
res.json({
|
|
id: password.id,
|
|
name: password.name || '',
|
|
description: password.description || '',
|
|
password: decryptedPassword, // Расшифрованный пароль
|
|
createdAt: password.createdAt || null,
|
|
updatedAt: password.updatedAt || null,
|
|
});
|
|
} catch (error) {
|
|
console.error('Error reading IPSec password:', error);
|
|
return sendError(res, 500, 'Error reading IPSec password', 'E_S3');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/ipsec-passwords - создать новый пароль
|
|
*/
|
|
async function createIpsecPassword(req, res) {
|
|
const { name, password, description } = req.body;
|
|
|
|
if (!name || !password) {
|
|
return sendError(res, 400, 'Name and password are required', 'E_BAD_REQUEST');
|
|
}
|
|
|
|
try {
|
|
// Читаем текущие пароли
|
|
const data = await readS3TextObject(S3_KEY).catch(() => ({ body: '[]' }));
|
|
let passwords = [];
|
|
|
|
try {
|
|
passwords = JSON.parse(data.body || '[]');
|
|
if (!Array.isArray(passwords)) {
|
|
passwords = [];
|
|
}
|
|
} catch (parseError) {
|
|
passwords = [];
|
|
}
|
|
|
|
// Проверяем, нет ли уже пароля с таким именем
|
|
if (passwords.some(p => p.name === name)) {
|
|
return sendError(res, 400, 'Password with this name already exists', 'E_DUPLICATE');
|
|
}
|
|
|
|
// Шифруем пароль
|
|
const encryptedPassword = encrypt(password);
|
|
|
|
// Создаем новый пароль
|
|
const newPassword = {
|
|
id: `ipsec-${Date.now()}-${Math.random().toString(16).slice(2, 8)}`,
|
|
name: String(name).trim(),
|
|
description: String(description || '').trim(),
|
|
encryptedPassword,
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
passwords.push(newPassword);
|
|
|
|
// Сохраняем в S3
|
|
const meta = await writeS3JsonObject(S3_KEY, passwords);
|
|
|
|
// Возвращаем без расшифрованного пароля
|
|
res.json({
|
|
id: newPassword.id,
|
|
name: newPassword.name,
|
|
description: newPassword.description,
|
|
createdAt: newPassword.createdAt,
|
|
updatedAt: newPassword.updatedAt,
|
|
});
|
|
} catch (error) {
|
|
console.error('Error creating IPSec password:', error);
|
|
return sendError(res, 500, 'Error creating IPSec password', 'E_S3');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PUT /api/ipsec-passwords/:id - обновить пароль
|
|
*/
|
|
async function updateIpsecPassword(req, res) {
|
|
const { id } = req.params;
|
|
const { name, password, description } = req.body;
|
|
|
|
try {
|
|
// Читаем текущие пароли
|
|
const data = await readS3TextObject(S3_KEY).catch(() => ({ body: '[]' }));
|
|
let passwords = [];
|
|
|
|
try {
|
|
passwords = JSON.parse(data.body || '[]');
|
|
if (!Array.isArray(passwords)) {
|
|
passwords = [];
|
|
}
|
|
} catch (parseError) {
|
|
passwords = [];
|
|
}
|
|
|
|
const index = passwords.findIndex(p => p.id === id);
|
|
if (index === -1) {
|
|
return sendError(res, 404, 'IPSec password not found', 'E_NOT_FOUND');
|
|
}
|
|
|
|
// Проверяем уникальность имени (если изменилось)
|
|
if (name && name !== passwords[index].name) {
|
|
if (passwords.some(p => p.id !== id && p.name === name)) {
|
|
return sendError(res, 400, 'Password with this name already exists', 'E_DUPLICATE');
|
|
}
|
|
}
|
|
|
|
// Обновляем пароль
|
|
if (name !== undefined) {
|
|
passwords[index].name = String(name).trim();
|
|
}
|
|
if (description !== undefined) {
|
|
passwords[index].description = String(description || '').trim();
|
|
}
|
|
if (password !== undefined) {
|
|
passwords[index].encryptedPassword = encrypt(password);
|
|
}
|
|
passwords[index].updatedAt = new Date().toISOString();
|
|
|
|
// Сохраняем в S3
|
|
const meta = await writeS3JsonObject(S3_KEY, passwords);
|
|
|
|
// Возвращаем без расшифрованного пароля
|
|
res.json({
|
|
id: passwords[index].id,
|
|
name: passwords[index].name,
|
|
description: passwords[index].description,
|
|
createdAt: passwords[index].createdAt,
|
|
updatedAt: passwords[index].updatedAt,
|
|
});
|
|
} catch (error) {
|
|
console.error('Error updating IPSec password:', error);
|
|
return sendError(res, 500, 'Error updating IPSec password', 'E_S3');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/ipsec-passwords/:id - удалить пароль
|
|
*/
|
|
async function deleteIpsecPassword(req, res) {
|
|
const { id } = req.params;
|
|
|
|
try {
|
|
// Читаем текущие пароли
|
|
const data = await readS3TextObject(S3_KEY).catch(() => ({ body: '[]' }));
|
|
let passwords = [];
|
|
|
|
try {
|
|
passwords = JSON.parse(data.body || '[]');
|
|
if (!Array.isArray(passwords)) {
|
|
passwords = [];
|
|
}
|
|
} catch (parseError) {
|
|
passwords = [];
|
|
}
|
|
|
|
const filtered = passwords.filter(p => p.id !== id);
|
|
|
|
if (filtered.length === passwords.length) {
|
|
return sendError(res, 404, 'IPSec password not found', 'E_NOT_FOUND');
|
|
}
|
|
|
|
// Сохраняем в S3
|
|
const meta = await writeS3JsonObject(S3_KEY, filtered);
|
|
|
|
res.json({ success: true });
|
|
} catch (error) {
|
|
console.error('Error deleting IPSec password:', error);
|
|
return sendError(res, 500, 'Error deleting IPSec password', 'E_S3');
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getIpsecPasswords,
|
|
getIpsecPassword,
|
|
createIpsecPassword,
|
|
updateIpsecPassword,
|
|
deleteIpsecPassword,
|
|
};
|