Files
DLE/backend/utils/access-check.js

197 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { ethers } = require('ethers');
require('dotenv').config();
const db = require('../db');
const contractArtifact = require('../artifacts/contracts/MyContract.sol/MyContract.json');
const contractABI = contractArtifact.abi;
const logger = require('./logger');
const { getContract } = require('./contracts');
// Проверяем наличие необходимых переменных окружения
if (!process.env.ACCESS_TOKEN_ADDRESS) {
console.error('ACCESS_TOKEN_ADDRESS не указан в .env файле');
}
if (!process.env.ETHEREUM_NETWORK_URL) {
console.error('ETHEREUM_NETWORK_URL не указан в .env файле');
}
// Подключение к контракту
const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NETWORK_URL);
let accessToken;
try {
const AccessTokenABI = require('../artifacts/contracts/AccessToken.sol/AccessToken.json').abi;
accessToken = new ethers.Contract(process.env.ACCESS_TOKEN_ADDRESS, AccessTokenABI, provider);
} catch (error) {
console.error('Ошибка инициализации контракта AccessToken:', error);
}
/**
* Проверяет доступ и роль пользователя
* @param {string} address - Ethereum адрес пользователя
* @returns {Promise<{hasAccess: boolean, role: string|null}>}
*/
async function checkAccess(address) {
try {
if (!address || !accessToken) {
return { hasAccess: false, role: null };
}
// Проверяем активный токен
const activeTokenId = await accessToken.activeTokens(address);
if (activeTokenId.toString() === '0') {
return { hasAccess: false, role: null };
}
// Получаем роль
const roleId = await accessToken.checkRole(address);
const roles = ['ADMIN', 'MODERATOR', 'SUPPORT'];
const role = roles[roleId];
return {
hasAccess: true,
role,
tokenId: activeTokenId.toString(),
};
} catch (error) {
console.error('Access check error:', error);
return { hasAccess: false, role: null };
}
}
// Функция для проверки, является ли пользователь администратором
async function checkIfAdmin(address) {
try {
console.log('Проверка прав администратора для адреса:', address);
// Проверяем в базе данных
const result = await db.query('SELECT is_admin FROM users WHERE address = $1', [address]);
if (result.rows.length === 0) {
console.log(`Пользователь с адресом ${address} не найден в базе данных`);
return false;
}
const isAdmin = result.rows[0].is_admin;
console.log(`Пользователь с адресом ${address} имеет статус администратора:`, isAdmin);
return isAdmin;
} catch (error) {
console.error('Ошибка при проверке прав администратора:', error);
return false;
}
}
/**
* Проверяет баланс токенов пользователя и обновляет его роль
* @param {string} address - Адрес кошелька пользователя
* @returns {Promise<boolean>} - Имеет ли пользователь права администратора
*/
async function checkTokenBalanceAndUpdateRole(address) {
try {
// Получение контракта токенов
const accessTokenContract = await getContract('AccessToken');
// Проверка баланса
const balance = await accessTokenContract.balanceOf(address);
// Минимальное количество токенов для прав администратора
const minTokens = ethers.utils.parseUnits(process.env.MIN_ADMIN_TOKENS || "1", 18);
const isAdmin = balance.gte(minTokens);
// Получение ID пользователя по адресу кошелька
const userResult = await db.query(`
SELECT u.id FROM users u
JOIN user_identities ui ON u.id = ui.user_id
WHERE ui.identity_type = 'wallet' AND ui.identity_value = $1
`, [address.toLowerCase()]);
if (userResult.rows.length > 0) {
const userId = userResult.rows[0].id;
// Получение ID роли
const roleResult = await db.query(
'SELECT id FROM roles WHERE name = $1',
[isAdmin ? 'admin' : 'user']
);
if (roleResult.rows.length > 0) {
const roleId = roleResult.rows[0].id;
// Обновление роли пользователя
await db.query(
'UPDATE users SET role_id = $1, last_token_check = NOW() WHERE id = $2',
[roleId, userId]
);
logger.info(`Updated user ${userId} role to ${isAdmin ? 'admin' : 'user'} based on token balance`);
}
}
return isAdmin;
} catch (error) {
logger.error(`Error checking token balance for ${address}: ${error.message}`);
return false;
}
}
/**
* Получает информацию о пользователе, включая его роль
* @param {number} userId - ID пользователя
* @returns {Promise<Object>} - Информация о пользователе
*/
async function getUserInfo(userId) {
try {
const result = await db.query(`
SELECT u.id, u.username, u.preferred_language, r.name as role
FROM users u
LEFT JOIN roles r ON u.role_id = r.id
WHERE u.id = $1
`, [userId]);
if (result.rows.length === 0) {
return null;
}
return result.rows[0];
} catch (error) {
logger.error(`Error getting user info for ${userId}: ${error.message}`);
return null;
}
}
/**
* Запускает проверку токенов для всех пользователей
*/
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 token balances for ${walletUsers.rows.length} users`);
for (const user of walletUsers.rows) {
// Проверка баланса токенов
const hasTokens = await checkTokenBalanceAndUpdateRole(user.address);
logger.info(`User ${user.id} with address ${user.address}: admin=${hasTokens}`);
}
} catch (error) {
logger.error(`Error checking token balances: ${error.message}`);
}
}
module.exports = {
checkAccess,
checkIfAdmin,
checkTokenBalanceAndUpdateRole,
getUserInfo,
checkAllUsersTokens
};