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

This commit is contained in:
2025-08-04 14:16:05 +03:00
parent e30d672c52
commit df37507bbe
22 changed files with 421 additions and 273 deletions

View File

@@ -17,6 +17,7 @@ const logger = require('../utils/logger');
const auth = require('../middleware/auth');
const path = require('path');
const fs = require('fs');
const ethers = require('ethers'); // Added ethers for private key validation
/**
* @route POST /api/dle-v2
@@ -28,8 +29,8 @@ router.post('/', auth.requireAuth, auth.requireAdmin, async (req, res, next) =>
const dleParams = req.body;
logger.info('Получен запрос на создание DLE v2:', dleParams);
// Если параметр partners не был передан явно, используем адрес авторизованного пользователя
if (!dleParams.partners || dleParams.partners.length === 0) {
// Если параметр initialPartners не был передан явно, используем адрес авторизованного пользователя
if (!dleParams.initialPartners || dleParams.initialPartners.length === 0) {
// Проверяем, есть ли в сессии адрес кошелька пользователя
if (!req.user || !req.user.walletAddress) {
return res.status(400).json({
@@ -39,11 +40,11 @@ router.post('/', auth.requireAuth, auth.requireAdmin, async (req, res, next) =>
}
// Используем адрес авторизованного пользователя
dleParams.partners = [req.user.address || req.user.walletAddress];
dleParams.initialPartners = [req.user.address || req.user.walletAddress];
// Если суммы не указаны, используем значение по умолчанию (100% токенов)
if (!dleParams.amounts || dleParams.amounts.length === 0) {
dleParams.amounts = ['1000000'];
if (!dleParams.initialAmounts || dleParams.initialAmounts.length === 0) {
dleParams.initialAmounts = ['1000000000000000000000000']; // 1,000,000 токенов
}
}
@@ -91,23 +92,40 @@ router.get('/', auth.requireAuth, async (req, res, next) => {
});
/**
* @route GET /api/dle-v2/defaults
* @desc Получить настройки по умолчанию для DLE v2
* @access Private (только для авторизованных пользователей)
* @route GET /api/dle-v2/default-params
* @desc Получить параметры по умолчанию для создания DLE v2
* @access Private
*/
router.get('/defaults', auth.requireAuth, async (req, res, next) => {
// Возвращаем настройки по умолчанию, которые будут использоваться
// при заполнении формы на фронтенде
res.json({
success: true,
data: {
votingDelay: 1, // 1 блок задержки перед началом голосования
votingPeriod: 45818, // ~1 неделя в блоках (при 13 секундах на блок)
proposalThreshold: '100000', // 100,000 токенов
quorumPercentage: 4, // 4% от общего количества токенов
minTimelockDelay: 2 // 2 дня
}
});
router.get('/default-params', auth.requireAuth, async (req, res, next) => {
try {
const defaultParams = {
name: '',
symbol: '',
location: '',
coordinates: '',
jurisdiction: 1,
oktmo: 45000000000,
okvedCodes: [],
kpp: 770101001,
quorumPercentage: 51,
initialPartners: [],
initialAmounts: [],
supportedChainIds: [1, 137, 56, 42161],
currentChainId: 1
};
res.json({
success: true,
data: defaultParams
});
} catch (error) {
logger.error('Ошибка при получении параметров по умолчанию:', error);
res.status(500).json({
success: false,
message: error.message || 'Произошла ошибка при получении параметров по умолчанию'
});
}
});
/**
@@ -170,4 +188,74 @@ router.delete('/:dleAddress', auth.requireAuth, auth.requireAdmin, async (req, r
}
});
/**
* @route POST /api/dle-v2/validate-private-key
* @desc Валидировать приватный ключ и получить адрес кошелька
* @access Private
*/
router.post('/validate-private-key', auth.requireAuth, async (req, res, next) => {
try {
const { privateKey } = req.body;
if (!privateKey) {
return res.status(400).json({
success: false,
message: 'Приватный ключ не передан'
});
}
// Логируем входящий ключ (только для отладки)
logger.info('Получен приватный ключ для валидации:', privateKey);
logger.info('Длина входящего ключа:', privateKey.length);
try {
// Очищаем ключ от префикса 0x если есть
const cleanKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;
// Логируем очищенный ключ (только для отладки)
logger.info('Очищенный ключ:', cleanKey);
logger.info('Длина очищенного ключа:', cleanKey.length);
// Проверяем длину и формат (64 символа в hex)
if (cleanKey.length !== 64 || !/^[a-fA-F0-9]+$/.test(cleanKey)) {
logger.error('Некорректный формат ключа. Длина:', cleanKey.length, 'Формат:', /^[a-fA-F0-9]+$/.test(cleanKey));
return res.status(400).json({
success: false,
message: 'Некорректный формат приватного ключа'
});
}
// Генерируем адрес из приватного ключа
const wallet = new ethers.Wallet('0x' + cleanKey);
const address = wallet.address;
// Логируем сгенерированный адрес
logger.info('Сгенерированный адрес из приватного ключа:', address);
res.json({
success: true,
data: {
isValid: true,
address: address,
error: null
}
});
} catch (error) {
logger.error('Ошибка при генерации адреса из приватного ключа:', error);
res.status(400).json({
success: false,
message: 'Некорректный приватный ключ'
});
}
} catch (error) {
logger.error('Ошибка при валидации приватного ключа:', error);
res.status(500).json({
success: false,
message: error.message || 'Произошла ошибка при валидации приватного ключа'
});
}
});
module.exports = router;

View File

@@ -213,7 +213,7 @@ router.get('/', requireAuth, async (req, res, next) => {
// --- Формируем ответ ---
const contacts = users.map(u => ({
id: u.id,
name: [u.first_name, u.last_name].filter(Boolean).join(' ') || null,
name: null, // Имена теперь только в зашифрованных колонках
email: u.email || null,
telegram: u.telegram || null,
wallet: u.wallet || null,
@@ -418,22 +418,37 @@ router.get('/:id', async (req, res, next) => {
}
try {
// Получаем ключ шифрования
const fs = require('fs');
const path = require('path');
let encryptionKey = 'default-key';
try {
const keyPath = path.join(__dirname, '../ssl/keys/full_db_encryption.key');
if (fs.existsSync(keyPath)) {
encryptionKey = fs.readFileSync(keyPath, 'utf8').trim();
}
} catch (keyError) {
console.error('Error reading encryption key:', keyError);
}
const query = db.getQuery();
// Получаем пользователя
const userResult = await query('SELECT id, decrypt_text(first_name_encrypted, $2) as first_name, decrypt_text(last_name_encrypted, $2) as last_name, created_at, preferred_language, is_blocked FROM users WHERE id = $1', [userId, encryptionKey]);
const userResult = await query('SELECT id, created_at, preferred_language, is_blocked FROM users WHERE id = $1', [userId]);
if (userResult.rows.length === 0) {
return res.status(404).json({ error: 'User not found' });
}
const user = userResult.rows[0];
// Получаем идентификаторы
const identitiesResult = await query('SELECT decrypt_text(provider_encrypted, $2) as provider, decrypt_text(provider_id_encrypted, $2) as provider_id FROM user_identities WHERE user_id = $1', [userId, encryptionKey]);
const identitiesResult = await query('SELECT CASE WHEN provider_encrypted IS NULL OR provider_encrypted = \'\' THEN NULL ELSE decrypt_text(provider_encrypted, $2) END as provider, CASE WHEN provider_id_encrypted IS NULL OR provider_id_encrypted = \'\' THEN NULL ELSE decrypt_text(provider_id_encrypted, $2) END as provider_id FROM user_identities WHERE user_id = $1', [userId, encryptionKey]);
const identityMap = {};
for (const id of identitiesResult.rows) {
identityMap[id.provider] = id.provider_id;
}
res.json({
id: user.id,
name: [user.first_name, user.last_name].filter(Boolean).join(' ') || null,
name: null, // Пока не используем имена
email: identityMap.email || null,
telegram: identityMap.telegram || null,
wallet: identityMap.wallet || null,
@@ -545,9 +560,9 @@ router.post('/import', requireAuth, async (req, res) => {
].filter(Boolean);
for (const idn of identities) {
// Проверяем, есть ли уже такой идентификатор у пользователя
const exists = await dbq('SELECT 1 FROM user_identities WHERE user_id = $1 AND provider = $2 AND provider_id = $3', [userId, idn.provider, idn.provider_id]);
const exists = await dbq('SELECT 1 FROM user_identities WHERE user_id = $1 AND provider_encrypted = encrypt_text($2, $4) AND provider_id_encrypted = encrypt_text($3, $4)', [userId, idn.provider, idn.provider_id, encryptionKey]);
if (!exists.rows.length) {
await dbq('INSERT INTO user_identities (user_id, provider, provider_id) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING', [userId, idn.provider, idn.provider_id]);
await dbq('INSERT INTO user_identities (user_id, provider_encrypted, provider_id_encrypted) VALUES ($1, encrypt_text($2, $4), encrypt_text($3, $4)) ON CONFLICT DO NOTHING', [userId, idn.provider, idn.provider_id, encryptionKey]);
}
}
} catch (e) {