new file: .claude/settings.local.json

new file:   .gitignore
	new file:   backend/.env.example
	new file:   backend/.gitignore
	new file:   backend/ecosystem.config.js
	new file:   backend/nodemon.json
	new file:   backend/package-lock.json
	new file:   backend/package.json
	new file:   backend/src/config/database.ts
	new file:   backend/src/config/dynamicSwagger.ts
	new file:   backend/src/config/environment.ts
	new file:   backend/src/config/swagger.ts
	new file:   backend/src/controllers/apiKeyController.ts
	new file:   backend/src/controllers/authController.ts
	new file:   backend/src/controllers/databaseController.ts
	new file:   backend/src/controllers/databaseManagementController.ts
	new file:   backend/src/controllers/dynamicApiController.ts
	new file:   backend/src/controllers/endpointController.ts
	new file:   backend/src/controllers/folderController.ts
	new file:   backend/src/controllers/logsController.ts
	new file:   backend/src/controllers/userController.ts
	new file:   backend/src/middleware/apiKey.ts
	new file:   backend/src/middleware/auth.ts
	new file:   backend/src/middleware/logging.ts
	new file:   backend/src/migrations/001_initial_schema.sql
	new file:   backend/src/migrations/002_add_logging.sql
	new file:   backend/src/migrations/003_add_scripting.sql
	new file:   backend/src/migrations/004_add_superadmin.sql
	new file:   backend/src/migrations/run.ts
	new file:   backend/src/migrations/seed.ts
	new file:   backend/src/routes/apiKeys.ts
	new file:   backend/src/routes/auth.ts
	new file:   backend/src/routes/databaseManagement.ts
	new file:   backend/src/routes/databases.ts
	new file:   backend/src/routes/dynamic.ts
	new file:   backend/src/routes/endpoints.ts
	new file:   backend/src/routes/folders.ts
	new file:   backend/src/routes/logs.ts
	new file:   backend/src/routes/users.ts
	new file:   backend/src/server.ts
	new file:   backend/src/services/DatabasePoolManager.ts
	new file:   backend/src/services/ScriptExecutor.ts
	new file:   backend/src/services/SqlExecutor.ts
	new file:   backend/src/types/index.ts
	new file:   backend/tsconfig.json
	new file:   frontend/.gitignore
	new file:   frontend/index.html
	new file:   frontend/nginx.conf
	new file:   frontend/package-lock.json
	new file:   frontend/package.json
	new file:   frontend/postcss.config.js
	new file:   frontend/src/App.tsx
	new file:   frontend/src/components/CodeEditor.tsx
This commit is contained in:
GEgorov
2025-10-07 00:04:04 +03:00
commit 8943f5a070
79 changed files with 17032 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
-- Users table
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Folders table (for organizing endpoints)
CREATE TABLE IF NOT EXISTS folders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
parent_id UUID REFERENCES folders(id) ON DELETE CASCADE,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Databases table (target databases for API endpoints)
CREATE TABLE IF NOT EXISTS databases (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL UNIQUE,
type VARCHAR(50) NOT NULL DEFAULT 'postgresql' CHECK (type IN ('postgresql', 'mysql', 'mssql')),
host VARCHAR(255) NOT NULL,
port INTEGER NOT NULL,
database_name VARCHAR(255) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
ssl BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Endpoints table
CREATE TABLE IF NOT EXISTS endpoints (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
method VARCHAR(10) NOT NULL CHECK (method IN ('GET', 'POST', 'PUT', 'DELETE', 'PATCH')),
path VARCHAR(500) NOT NULL UNIQUE,
database_id UUID REFERENCES databases(id) ON DELETE RESTRICT,
sql_query TEXT NOT NULL,
parameters JSONB DEFAULT '[]'::jsonb,
folder_id UUID REFERENCES folders(id) ON DELETE SET NULL,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
is_public BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- API Keys table
CREATE TABLE IF NOT EXISTS api_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
key VARCHAR(500) UNIQUE NOT NULL,
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
permissions JSONB DEFAULT '[]'::jsonb,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP
);
-- Indexes for better performance
CREATE INDEX IF NOT EXISTS idx_folders_parent_id ON folders(parent_id);
CREATE INDEX IF NOT EXISTS idx_folders_user_id ON folders(user_id);
CREATE INDEX IF NOT EXISTS idx_endpoints_folder_id ON endpoints(folder_id);
CREATE INDEX IF NOT EXISTS idx_endpoints_user_id ON endpoints(user_id);
CREATE INDEX IF NOT EXISTS idx_endpoints_database_id ON endpoints(database_id);
CREATE INDEX IF NOT EXISTS idx_endpoints_path ON endpoints(path);
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key);
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
CREATE INDEX IF NOT EXISTS idx_databases_name ON databases(name);
-- Full text search index for endpoints
CREATE INDEX IF NOT EXISTS idx_endpoints_search ON endpoints USING gin(
to_tsvector('english', name || ' ' || description || ' ' || sql_query)
);

View File

@@ -0,0 +1,28 @@
-- Add logging fields to endpoints
ALTER TABLE endpoints ADD COLUMN IF NOT EXISTS enable_logging BOOLEAN DEFAULT false;
-- Add logging fields to api_keys
ALTER TABLE api_keys ADD COLUMN IF NOT EXISTS enable_logging BOOLEAN DEFAULT false;
-- Create request_logs table
CREATE TABLE IF NOT EXISTS request_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
endpoint_id UUID REFERENCES endpoints(id) ON DELETE CASCADE,
api_key_id UUID REFERENCES api_keys(id) ON DELETE SET NULL,
method VARCHAR(10) NOT NULL,
path VARCHAR(500) NOT NULL,
request_params JSONB,
request_body JSONB,
response_status INTEGER,
response_data JSONB,
execution_time INTEGER,
error_message TEXT,
ip_address VARCHAR(45),
user_agent TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create index for faster queries
CREATE INDEX IF NOT EXISTS idx_request_logs_endpoint_id ON request_logs(endpoint_id);
CREATE INDEX IF NOT EXISTS idx_request_logs_api_key_id ON request_logs(api_key_id);
CREATE INDEX IF NOT EXISTS idx_request_logs_created_at ON request_logs(created_at DESC);

View File

@@ -0,0 +1,14 @@
-- Добавление поддержки скриптинга для эндпоинтов
-- Добавляем новые колонки для скриптинга
ALTER TABLE endpoints
ADD COLUMN execution_type VARCHAR(20) DEFAULT 'sql' CHECK (execution_type IN ('sql', 'script')),
ADD COLUMN script_language VARCHAR(20) CHECK (script_language IN ('javascript', 'python')),
ADD COLUMN script_code TEXT,
ADD COLUMN script_queries JSONB DEFAULT '[]'::jsonb;
-- Комментарии для документации
COMMENT ON COLUMN endpoints.execution_type IS 'Тип выполнения: sql - простой SQL запрос, script - скрипт с несколькими запросами';
COMMENT ON COLUMN endpoints.script_language IS 'Язык скрипта: javascript или python';
COMMENT ON COLUMN endpoints.script_code IS 'Код скрипта (JS или Python)';
COMMENT ON COLUMN endpoints.script_queries IS 'Массив именованных SQL запросов для использования в скрипте: [{"name": "queryName", "sql": "SELECT ..."}]';

View File

@@ -0,0 +1,8 @@
-- Add is_superadmin field to users table
ALTER TABLE users
ADD COLUMN IF NOT EXISTS is_superadmin BOOLEAN DEFAULT FALSE;
COMMENT ON COLUMN users.is_superadmin IS 'Является ли пользователь супер-администратором с полным доступом';
ALTER TABLE users
DROP COLUMN IF EXISTS email;

View File

@@ -0,0 +1,24 @@
import { mainPool } from '../config/database';
import * as fs from 'fs';
import * as path from 'path';
async function runMigrations() {
console.log('Running migrations...');
try {
const migrationFile = fs.readFileSync(
path.join(__dirname, '001_initial_schema.sql'),
'utf-8'
);
await mainPool.query(migrationFile);
console.log('✅ Migrations completed successfully');
process.exit(0);
} catch (error) {
console.error('❌ Migration failed:', error);
process.exit(1);
}
}
runMigrations();

View File

@@ -0,0 +1,38 @@
import { mainPool } from '../config/database';
import bcrypt from 'bcrypt';
async function seed() {
console.log('🌱 Starting seed...');
try {
// Проверяем, есть ли уже пользователи
const userCheck = await mainPool.query('SELECT COUNT(*) FROM users');
const userCount = parseInt(userCheck.rows[0].count);
if (userCount > 0) {
console.log('⚠️ Users already exist. Skipping seed.');
process.exit(0);
}
// Создаем супер-админа по умолчанию
const passwordHash = await bcrypt.hash('admin', 10);
await mainPool.query(
`INSERT INTO users (username, password_hash, role, is_superadmin)
VALUES ($1, $2, $3, $4)`,
['admin', passwordHash, 'admin', true]
);
console.log('✅ Default superadmin created:');
console.log(' Username: admin');
console.log(' Password: admin');
console.log(' ⚠️ ВАЖНО: Смените пароль после первого входа!');
process.exit(0);
} catch (error) {
console.error('❌ Seed failed:', error);
process.exit(1);
}
}
seed();