Описание изменений

This commit is contained in:
2025-03-19 17:18:03 +03:00
parent 04d027054d
commit 55e4d81c95
75 changed files with 2103 additions and 4861 deletions

View File

@@ -1,39 +0,0 @@
const db = require('../db');
const logger = require('../utils/logger');
const authService = require('../services/auth-service');
/**
* Проверяет токены всех пользователей и обновляет их роли
* @returns {Promise<void>}
*/
async function checkAllUsersTokens() {
try {
// Получаем всех пользователей с кошельками
const walletUsers = await db.query(`
SELECT u.id, ui.identity_value as address
FROM users u
JOIN user_identities ui ON u.id = ui.user_id
WHERE ui.identity_type = 'wallet'
`);
logger.info(`Checking tokens for ${walletUsers.rows.length} users`);
for (const user of walletUsers.rows) {
try {
// Используем существующий метод для проверки токенов и обновления роли
const isAdmin = await authService.checkTokensAndUpdateRole(user.address);
logger.info(`Updated user ${user.id} with address ${user.address}: admin=${isAdmin}`);
} catch (error) {
logger.error(`Error checking tokens for user ${user.id}: ${error.message}`);
}
}
logger.info('Token check completed');
} catch (error) {
logger.error(`Error checking all users tokens: ${error.message}`);
}
}
module.exports = {
checkAllUsersTokens
};

View File

@@ -1,146 +0,0 @@
const { ethers } = require('ethers');
const db = require('../db');
const logger = require('./logger');
const authService = require('../services/auth-service');
const { USER_ROLES, IDENTITY_TYPES } = require('./constants');
// Инициализация провайдера
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL_ETH);
/**
* Проверяет подпись сообщения
* @param {string} nonce - Nonce для проверки
* @param {string} signature - Подпись
* @param {string} address - Адрес кошелька
* @returns {Promise<boolean>} - Результат проверки
*/
async function verifySignature(nonce, signature, address) {
try {
// Создаем сообщение для проверки
const message = `Подпишите это сообщение для аутентификации в DApp for Business. Nonce: ${nonce}`;
// Восстанавливаем адрес из подписи
const recoveredAddress = ethers.verifyMessage(message, signature);
// Сравниваем адреса (приводим к нижнему регистру для надежности)
return recoveredAddress.toLowerCase() === address.toLowerCase();
} catch (error) {
console.error('Error verifying signature:', error);
return false;
}
}
/**
* Проверяет, является ли пользователь администратором
* @param {string} address - Адрес кошелька
* @returns {Promise<boolean>} - Является ли пользователь администратором
*/
async function checkUserRole(address) {
try {
// Проверяем наличие токенов администратора
const isAdmin = await authService.checkAdminTokens(address);
return isAdmin;
} catch (error) {
console.error('Error checking user role:', error);
return false;
}
}
/**
* Проверяет доступ пользователя
* @param {string} walletAddress - Адрес кошелька
* @returns {Promise<Object>} - Информация о доступе
*/
async function checkAccess(walletAddress) {
try {
// Проверяем наличие токенов администратора
const isAdmin = await authService.checkAdminTokens(walletAddress);
// Получаем или создаем пользователя
const userId = await findOrCreateUser(walletAddress);
return {
userId,
isAdmin,
hasAccess: true
};
} catch (error) {
logger.error(`Error checking access: ${error.message}`);
return {
hasAccess: false,
error: error.message
};
}
}
/**
* Находит или создает пользователя по адресу кошелька
* @param {string} address - Адрес кошелька
* @returns {Promise<Object>} - ID пользователя и роль
*/
async function findOrCreateUser(address) {
try {
if (!address) {
throw new Error('Address is required');
}
const normalizedAddress = address.toLowerCase();
// Сначала проверяем в таблице users
const userResult = await db.query(
'SELECT id FROM users WHERE LOWER(address) = $1',
[normalizedAddress]
);
let userId;
let isAdmin = false;
if (userResult.rows.length === 0) {
// Если пользователь не найден, создаем его
const roleResult = await db.query('SELECT id FROM roles WHERE name = $1', ['user']);
if (roleResult.rows.length === 0) {
throw new Error('Role "user" not found');
}
const roleId = roleResult.rows[0].id;
// Создаем пользователя
const newUserResult = await db.query(
'INSERT INTO users (address, role_id, created_at) VALUES ($1, $2, NOW()) RETURNING id',
[normalizedAddress, roleId]
);
userId = newUserResult.rows[0].id;
// Добавляем идентификатор кошелька
await db.query(
'INSERT INTO user_identities (user_id, identity_type, identity_value, created_at) VALUES ($1, $2, $3, NOW())',
[userId, 'wallet', normalizedAddress]
);
} else {
userId = userResult.rows[0].id;
}
// Проверяем, является ли пользователь администратором
isAdmin = await checkUserRole(normalizedAddress);
// Обновляем роль пользователя
const roleNameToSet = isAdmin ? 'admin' : 'user';
const roleToSetResult = await db.query('SELECT id FROM roles WHERE name = $1', [roleNameToSet]);
if (roleToSetResult.rows.length > 0) {
const roleIdToSet = roleToSetResult.rows[0].id;
await db.query('UPDATE users SET role_id = $1 WHERE id = $2', [roleIdToSet, userId]);
}
return { userId, isAdmin };
} catch (error) {
console.error('Error finding or creating user:', error);
throw error;
}
}
module.exports = {
verifySignature,
checkAccess,
findOrCreateUser,
checkUserRole
};

View File

@@ -1,105 +0,0 @@
const { ethers } = require('ethers');
const fs = require('fs');
const path = require('path');
const logger = require('./logger');
// Инициализация провайдера
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
// Путь к директории с ABI контрактов
const contractsDir = path.join(__dirname, '../artifacts/contracts/AccessToken.sol');
// Получение ABI контракта
const accessTokenJSON = require('../artifacts/contracts/AccessToken.sol/AccessToken.json');
const accessTokenABI = accessTokenJSON.abi;
// Проверка, что ABI является массивом
if (!Array.isArray(accessTokenABI)) {
console.error('ABI is not an array:', accessTokenABI);
// Если ABI не является массивом, создайте массив вручную
const manualABI = [
"function mintAccessToken(address to, uint8 role) public",
"function checkRole(address user) public view returns (uint8)",
"function revokeToken(uint256 tokenId) public",
// Добавьте другие функции, которые вам нужны
];
// Создание экземпляра контракта с ручным ABI
const contractAddress = process.env.ACCESS_TOKEN_ADDRESS;
const accessTokenContract = new ethers.Contract(contractAddress, manualABI, provider);
module.exports = {
accessTokenContract,
getContract,
provider
};
} else {
// Если ABI является массивом, используйте его
const contractAddress = process.env.ACCESS_TOKEN_ADDRESS;
const accessTokenContract = new ethers.Contract(contractAddress, accessTokenABI, provider);
module.exports = {
accessTokenContract,
getContract,
provider
};
}
// Кэш для хранения экземпляров контрактов
const contractsCache = {};
/**
* Получает экземпляр контракта по его имени
* @param {string} contractName - Имя контракта
* @returns {Promise<ethers.Contract>} - Экземпляр контракта
*/
async function getContract(contractName) {
try {
console.log(`Getting contract: ${contractName}`);
// Проверяем, есть ли контракт в кэше
if (contractsCache[contractName]) {
console.log(`Using cached contract: ${contractName}`);
return contractsCache[contractName];
}
// Получаем адрес контракта из переменных окружения
const contractAddress = process.env.ACCESS_TOKEN_ADDRESS; // или ACCESS_TOKEN_CONTRACT_ADDRESS
if (!contractAddress) {
throw new Error(`Contract address for ${contractName} not found in environment variables`);
}
// Путь к файлу с ABI контракта
const abiPath = path.join(contractsDir, `${contractName}.json`);
// Проверяем, существует ли файл с ABI
if (!fs.existsSync(abiPath)) {
throw new Error(`ABI file for ${contractName} not found at ${abiPath}`);
}
// Читаем ABI из файла
const abiJson = fs.readFileSync(abiPath, 'utf8');
const contractJSON = JSON.parse(abiJson);
const abi = contractJSON.abi; // Получаем ABI из свойства abi
console.log(`ABI for ${contractName}:`, abi);
// Проверяем, что ABI является массивом
if (!Array.isArray(abi)) {
console.error(`ABI for ${contractName} is not an array:`, abi);
throw new Error(`ABI for ${contractName} is not an array`);
}
// Создаем экземпляр контракта
const contract = new ethers.Contract(contractAddress, abi, provider);
// Сохраняем контракт в кэше
contractsCache[contractName] = contract;
return contract;
} catch (error) {
logger.error(`Ошибка при получении контракта ${contractName}: ${error.message}`);
throw error;
}
}

View File

@@ -1,90 +0,0 @@
const db = require('../db');
const logger = require('./logger');
/**
* Связывает идентификатор с пользователем
* @param {number} userId - ID пользователя
* @param {string} identityType - Тип идентификатора ('ethereum', 'telegram', 'email')
* @param {string} identityValue - Значение идентификатора
* @returns {Promise<boolean>} - Результат операции
*/
async function linkIdentity(userId, identityType, identityValue) {
try {
// Проверяем, существует ли уже такой идентификатор
const existingResult = await db.query(
'SELECT * FROM user_identities WHERE identity_type = $1 AND identity_value = $2',
[identityType, identityValue]
);
if (existingResult.rows.length > 0) {
// Если идентификатор уже связан с другим пользователем, возвращаем ошибку
if (existingResult.rows[0].user_id !== userId) {
console.warn(`Identity ${identityType}:${identityValue} already linked to another user`);
return false;
}
// Если идентификатор уже связан с этим пользователем, ничего не делаем
return true;
}
// Добавляем новую связь
await db.query(
'INSERT INTO user_identities (user_id, identity_type, identity_value, created_at) VALUES ($1, $2, $3, NOW())',
[userId, identityType, identityValue]
);
console.log(`Successfully linked ${identityType}:${identityValue} to user ${userId}`);
return true;
} catch (error) {
console.error('Error linking identity:', error);
return false;
}
}
/**
* Получает ID пользователя по идентификатору
* @param {string} identityType - Тип идентификатора ('ethereum', 'telegram', 'email')
* @param {string} identityValue - Значение идентификатора
* @returns {Promise<number|null>} - ID пользователя или null, если не найден
*/
async function getUserIdByIdentity(identityType, identityValue) {
try {
const result = await db.query(
'SELECT user_id FROM user_identities WHERE identity_type = $1 AND identity_value = $2',
[identityType, identityValue]
);
if (result.rows.length === 0) {
return null;
}
return result.rows[0].user_id;
} catch (error) {
console.error('Error getting user ID by identity:', error);
return null;
}
}
/**
* Получает все идентификаторы пользователя
* @param {number} userId - ID пользователя
* @returns {Promise<Array|null>} - Массив идентификаторов или null в случае ошибки
*/
async function getUserIdentities(userId) {
try {
const result = await db.query(
'SELECT identity_type, identity_value FROM user_identities WHERE user_id = $1',
[userId]
);
return result.rows;
} catch (error) {
console.error('Error getting user identities:', error);
return null;
}
}
module.exports = {
linkIdentity,
getUserIdByIdentity,
getUserIdentities,
};