Описание изменений
This commit is contained in:
22
backend/scripts/check-dependencies.js
Normal file
22
backend/scripts/check-dependencies.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const packageJson = require('../package.json');
|
||||
const dependencies = packageJson.dependencies || {};
|
||||
|
||||
const requiredDependencies = [
|
||||
'express-rate-limit',
|
||||
'winston',
|
||||
'helmet',
|
||||
'csurf'
|
||||
];
|
||||
|
||||
const missingDependencies = requiredDependencies.filter(dep => !dependencies[dep]);
|
||||
|
||||
if (missingDependencies.length > 0) {
|
||||
console.error('Missing dependencies:', missingDependencies);
|
||||
console.error('Please install them with: yarn add ' + missingDependencies.join(' '));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('All required dependencies are installed.');
|
||||
43
backend/scripts/check-state.js
Normal file
43
backend/scripts/check-state.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const accessToken = await hre.ethers.getContractAt(
|
||||
"AccessToken",
|
||||
"0xF352c498cF0857F472dC473E4Dd39551E79B1063"
|
||||
);
|
||||
|
||||
const owner = await accessToken.owner();
|
||||
console.log("Contract owner:", owner);
|
||||
|
||||
// Проверяем все токены и их владельцев
|
||||
console.log("\nAll tokens:");
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
try {
|
||||
const tokenOwner = await accessToken.ownerOf(i);
|
||||
console.log(`Token ${i} owner: ${tokenOwner}`);
|
||||
} catch (error) {
|
||||
if (!error.message.includes("invalid token ID")) {
|
||||
console.log(`Token ${i} error:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем активные токены для всех известных адресов
|
||||
const addresses = [
|
||||
owner,
|
||||
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
|
||||
];
|
||||
|
||||
console.log("\nActive tokens:");
|
||||
for (const address of addresses) {
|
||||
const activeToken = await accessToken.activeTokens(address);
|
||||
console.log(`${address}: Token ${activeToken.toString()}`);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
51
backend/scripts/create-moderator.js
Normal file
51
backend/scripts/create-moderator.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const accessToken = await hre.ethers.getContractAt(
|
||||
"AccessToken",
|
||||
"0xF352c498cF0857F472dC473E4Dd39551E79B1063"
|
||||
);
|
||||
|
||||
const moderatorAddress = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
|
||||
|
||||
try {
|
||||
console.log("\nMinting moderator token...");
|
||||
const mintTx = await accessToken.mintAccessToken(moderatorAddress, 1); // MODERATOR
|
||||
console.log("Waiting for transaction:", mintTx.hash);
|
||||
await mintTx.wait();
|
||||
console.log("Moderator token minted");
|
||||
|
||||
// Проверяем результат
|
||||
const activeToken = await accessToken.activeTokens(moderatorAddress);
|
||||
console.log(`Moderator's active token: ${activeToken}`);
|
||||
|
||||
const role = await accessToken.checkRole(moderatorAddress);
|
||||
console.log(`Moderator role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`);
|
||||
} catch (error) {
|
||||
console.log("Moderator token minting error:", error.message);
|
||||
}
|
||||
|
||||
// Проверяем все активные токены
|
||||
console.log("\nAll active tokens:");
|
||||
const addresses = [
|
||||
await accessToken.owner(),
|
||||
moderatorAddress
|
||||
];
|
||||
|
||||
for (const address of addresses) {
|
||||
try {
|
||||
const activeToken = await accessToken.activeTokens(address);
|
||||
const role = await accessToken.checkRole(address);
|
||||
console.log(`${address}: Token ${activeToken}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`);
|
||||
} catch (error) {
|
||||
console.log(`${address}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error("Script error:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
23
backend/scripts/deploy-access.js
Normal file
23
backend/scripts/deploy-access.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const AccessToken = await hre.ethers.getContractFactory("AccessToken");
|
||||
const accessToken = await AccessToken.deploy();
|
||||
await accessToken.waitForDeployment();
|
||||
|
||||
const address = await accessToken.getAddress();
|
||||
console.log("AccessToken deployed to:", address);
|
||||
|
||||
// Создаем первый админский токен для владельца контракта
|
||||
const [owner] = await hre.ethers.getSigners();
|
||||
const tx = await accessToken.mintAccessToken(owner.address, 0); // 0 = ADMIN
|
||||
await tx.wait();
|
||||
console.log("Admin token minted for:", owner.address);
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
62
backend/scripts/init-db.js
Normal file
62
backend/scripts/init-db.js
Normal file
@@ -0,0 +1,62 @@
|
||||
const { Pool } = require('pg');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
|
||||
});
|
||||
|
||||
async function initDb() {
|
||||
try {
|
||||
console.log('Инициализация базы данных...');
|
||||
|
||||
// Добавляем тестового пользователя
|
||||
await pool.query(`
|
||||
INSERT INTO users (address, is_admin)
|
||||
VALUES ('0xf45aa4917b3775ba37f48aeb3dc1a943561e9e0b', TRUE)
|
||||
ON CONFLICT (address) DO NOTHING
|
||||
`);
|
||||
|
||||
// Добавляем тестовую доску
|
||||
await pool.query(`
|
||||
INSERT INTO kanban_boards (title, description, owner_id, is_public)
|
||||
VALUES (
|
||||
'Тестовая доска',
|
||||
'Описание тестовой доски',
|
||||
(SELECT id FROM users WHERE address = '0xf45aa4917b3775ba37f48aeb3dc1a943561e9e0b'),
|
||||
TRUE
|
||||
)
|
||||
ON CONFLICT DO NOTHING
|
||||
`);
|
||||
|
||||
// Получаем ID доски
|
||||
const boardResult = await pool.query(`
|
||||
SELECT id FROM kanban_boards WHERE title = 'Тестовая доска' LIMIT 1
|
||||
`);
|
||||
|
||||
if (boardResult.rows.length > 0) {
|
||||
const boardId = boardResult.rows[0].id;
|
||||
|
||||
// Добавляем тестовые колонки
|
||||
await pool.query(`
|
||||
INSERT INTO kanban_columns (board_id, title, position)
|
||||
VALUES
|
||||
($1, 'Backlog', 0),
|
||||
($1, 'In Progress', 1),
|
||||
($1, 'Review', 2),
|
||||
($1, 'Done', 3)
|
||||
ON CONFLICT DO NOTHING
|
||||
`, [boardId]);
|
||||
}
|
||||
|
||||
console.log('База данных инициализирована успешно');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при инициализации базы данных:', error);
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
initDb();
|
||||
58
backend/scripts/init-roles.js
Normal file
58
backend/scripts/init-roles.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const accessToken = await hre.ethers.getContractAt(
|
||||
"AccessToken",
|
||||
"0xF352c498cF0857F472dC473E4Dd39551E79B1063"
|
||||
);
|
||||
|
||||
const owner = await accessToken.owner();
|
||||
console.log("Contract owner:", owner);
|
||||
|
||||
// Создаем админский токен для владельца
|
||||
try {
|
||||
const tx = await accessToken.mintAccessToken(owner, 0); // 0 = ADMIN
|
||||
await tx.wait();
|
||||
console.log(`Admin token minted for ${owner}`);
|
||||
|
||||
const role = await accessToken.checkRole(owner);
|
||||
console.log("Owner role:", ["ADMIN", "MODERATOR", "SUPPORT"][role]);
|
||||
} catch (error) {
|
||||
console.log("Admin token minting error:", error.message);
|
||||
}
|
||||
|
||||
// Создаем тестовый токен модератора
|
||||
const moderatorAddress = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; // Тестовый адрес модератора
|
||||
try {
|
||||
const tx = await accessToken.mintAccessToken(moderatorAddress, 1); // 1 = MODERATOR
|
||||
await tx.wait();
|
||||
console.log(`Moderator token minted for ${moderatorAddress}`);
|
||||
|
||||
const role = await accessToken.checkRole(moderatorAddress);
|
||||
console.log("Moderator role:", ["ADMIN", "MODERATOR", "SUPPORT"][role]);
|
||||
} catch (error) {
|
||||
console.log("Moderator token minting error:", error.message);
|
||||
}
|
||||
|
||||
// Проверяем все токены
|
||||
console.log("\nChecking all tokens:");
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
try {
|
||||
const owner = await accessToken.ownerOf(i);
|
||||
const role = await accessToken.checkRole(owner);
|
||||
console.log(`Token ${i}: Owner ${owner}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`);
|
||||
} catch (error) {
|
||||
// Пропускаем несуществующие токены
|
||||
if (!error.message.includes("nonexistent token")) {
|
||||
console.log(`Token ${i} error:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
72
backend/scripts/manage-access.js
Normal file
72
backend/scripts/manage-access.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const accessToken = await hre.ethers.getContractAt(
|
||||
"AccessToken",
|
||||
"0xF352c498cF0857F472dC473E4Dd39551E79B1063" // Адрес нашего контракта
|
||||
);
|
||||
|
||||
// Проверим текущего владельца
|
||||
const owner = await accessToken.owner();
|
||||
console.log("Contract owner:", owner);
|
||||
|
||||
// Проверим роль владельца
|
||||
try {
|
||||
const ownerRole = await accessToken.checkRole(owner);
|
||||
console.log("Owner role:", ["ADMIN", "MODERATOR", "SUPPORT"][ownerRole]);
|
||||
} catch (error) {
|
||||
console.log("Owner role check error:", error.message);
|
||||
}
|
||||
|
||||
// Создадим токен модератора для тестового адреса
|
||||
const moderatorAddress = "0xF45aa4917b3775bA37f48Aeb3dc1a943561e9e0B";
|
||||
try {
|
||||
const tx = await accessToken.mintAccessToken(moderatorAddress, 1); // 1 = MODERATOR
|
||||
await tx.wait();
|
||||
console.log(`Moderator token minted for ${moderatorAddress}`);
|
||||
|
||||
// Проверим роль модератора
|
||||
const modRole = await accessToken.checkRole(moderatorAddress);
|
||||
console.log("Moderator role:", ["ADMIN", "MODERATOR", "SUPPORT"][modRole]);
|
||||
} catch (error) {
|
||||
console.log("Moderator token minting error:", error.message);
|
||||
}
|
||||
|
||||
// Получим все активные токены (с ограничением по блокам)
|
||||
const currentBlock = await hre.ethers.provider.getBlockNumber();
|
||||
const fromBlock = currentBlock - 1000; // Последние 1000 блоков
|
||||
|
||||
const filter = accessToken.filters.Transfer(null, null, null);
|
||||
const events = await accessToken.queryFilter(filter, fromBlock);
|
||||
console.log("\nActive tokens (last 1000 blocks):");
|
||||
for (let event of events) {
|
||||
if (event.args.from === "0x0000000000000000000000000000000000000000") {
|
||||
console.log(`Token ID: ${event.args.tokenId}, Owner: ${event.args.to}`);
|
||||
try {
|
||||
const role = await accessToken.checkRole(event.args.to);
|
||||
console.log(`Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`);
|
||||
} catch (error) {
|
||||
console.log("Role check error:", error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Альтернативный способ - проверить конкретный токен
|
||||
console.log("\nChecking specific tokens:");
|
||||
for (let i = 1; i <= 2; i++) {
|
||||
try {
|
||||
const owner = await accessToken.ownerOf(i);
|
||||
const role = await accessToken.checkRole(owner);
|
||||
console.log(`Token ${i}: Owner ${owner}, Role: ${["ADMIN", "MODERATOR", "SUPPORT"][role]}`);
|
||||
} catch (error) {
|
||||
console.log(`Token ${i} not found or error:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
26
backend/scripts/revoke-all.js
Normal file
26
backend/scripts/revoke-all.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const accessToken = await hre.ethers.getContractAt(
|
||||
"AccessToken",
|
||||
"0xF352c498cF0857F472dC473E4Dd39551E79B1063"
|
||||
);
|
||||
|
||||
// Отзываем все токены от 1 до 3
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
try {
|
||||
const tx = await accessToken.revokeToken(i);
|
||||
await tx.wait();
|
||||
console.log(`Token ${i} revoked`);
|
||||
} catch (error) {
|
||||
console.log(`Token ${i} revoke error:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
68
backend/scripts/run-migrations.js
Normal file
68
backend/scripts/run-migrations.js
Normal file
@@ -0,0 +1,68 @@
|
||||
const { Pool } = require('pg');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
require('dotenv').config();
|
||||
|
||||
// Подключение к БД
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false
|
||||
});
|
||||
|
||||
async function runMigrations() {
|
||||
try {
|
||||
console.log('Запуск миграций...');
|
||||
|
||||
// Создаем таблицу для отслеживания миграций, если её нет
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS migrations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
applied_at TIMESTAMP DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
// Получаем список уже примененных миграций
|
||||
const { rows } = await pool.query('SELECT name FROM migrations');
|
||||
const appliedMigrations = rows.map(row => row.name);
|
||||
|
||||
// Получаем список файлов миграций
|
||||
const migrationsDir = path.join(__dirname, '../migrations');
|
||||
const migrationFiles = fs.readdirSync(migrationsDir)
|
||||
.filter(file => file.endsWith('.sql'))
|
||||
.sort(); // Сортируем файлы по имени
|
||||
|
||||
// Применяем миграции, которые еще не были применены
|
||||
for (const file of migrationFiles) {
|
||||
if (!appliedMigrations.includes(file)) {
|
||||
console.log(`Применение миграции: ${file}`);
|
||||
|
||||
// Читаем содержимое файла миграции
|
||||
const filePath = path.join(migrationsDir, file);
|
||||
const sql = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Выполняем SQL-запросы из файла
|
||||
await pool.query(sql);
|
||||
|
||||
// Записываем информацию о примененной миграции
|
||||
await pool.query(
|
||||
'INSERT INTO migrations (name) VALUES ($1)',
|
||||
[file]
|
||||
);
|
||||
|
||||
console.log(`Миграция ${file} успешно применена`);
|
||||
} else {
|
||||
console.log(`Миграция ${file} уже применена`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Все миграции успешно применены');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при выполнении миграций:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
runMigrations();
|
||||
Reference in New Issue
Block a user