Files
api_builder/backend/src/controllers/databaseManagementController.ts
GEgorov 8943f5a070 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
2025-10-07 00:04:04 +03:00

186 lines
6.6 KiB
TypeScript
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.

import { Response } from 'express';
import { AuthRequest } from '../middleware/auth';
import { mainPool } from '../config/database';
import { databasePoolManager } from '../services/DatabasePoolManager';
// Только админы могут управлять базами данных
export const getDatabases = async (req: AuthRequest, res: Response) => {
try {
const result = await mainPool.query(
'SELECT id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at FROM databases ORDER BY name'
);
res.json(result.rows);
} catch (error) {
console.error('Get databases error:', error);
res.status(500).json({ error: 'Ошибка получения списка баз данных' });
}
};
export const getDatabase = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const result = await mainPool.query(
'SELECT id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at FROM databases WHERE id = $1',
[id]
);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'База данных не найдена' });
}
res.json(result.rows[0]);
} catch (error) {
console.error('Get database error:', error);
res.status(500).json({ error: 'Ошибка получения базы данных' });
}
};
export const createDatabase = async (req: AuthRequest, res: Response) => {
try {
const { name, type, host, port, database_name, username, password, ssl } = req.body;
if (!name || !host || !port || !database_name || !username || !password) {
return res.status(400).json({ error: 'Не заполнены обязательные поля' });
}
const result = await mainPool.query(
`INSERT INTO databases (name, type, host, port, database_name, username, password, ssl, is_active)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, true)
RETURNING *`,
[name, type || 'postgresql', host, port, database_name, username, password, ssl || false]
);
const newDb = result.rows[0];
// Добавить пул подключений
await databasePoolManager.reloadPool(newDb.id);
// Не возвращаем пароль
delete newDb.password;
res.status(201).json(newDb);
} catch (error: any) {
console.error('Create database error:', error);
if (error.code === '23505') {
return res.status(400).json({ error: 'База данных с таким именем уже существует' });
}
res.status(500).json({ error: 'Ошибка создания базы данных' });
}
};
export const updateDatabase = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const { name, type, host, port, database_name, username, password, ssl, is_active } = req.body;
// Если пароль не передан, не обновляем его
let query;
let params;
if (password) {
query = `
UPDATE databases
SET name = COALESCE($1, name),
type = COALESCE($2, type),
host = COALESCE($3, host),
port = COALESCE($4, port),
database_name = COALESCE($5, database_name),
username = COALESCE($6, username),
password = $7,
ssl = COALESCE($8, ssl),
is_active = COALESCE($9, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $10
RETURNING id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at
`;
params = [name, type, host, port, database_name, username, password, ssl, is_active, id];
} else {
query = `
UPDATE databases
SET name = COALESCE($1, name),
type = COALESCE($2, type),
host = COALESCE($3, host),
port = COALESCE($4, port),
database_name = COALESCE($5, database_name),
username = COALESCE($6, username),
ssl = COALESCE($7, ssl),
is_active = COALESCE($8, is_active),
updated_at = CURRENT_TIMESTAMP
WHERE id = $9
RETURNING id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at
`;
params = [name, type, host, port, database_name, username, ssl, is_active, id];
}
const result = await mainPool.query(query, params);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'База данных не найдена' });
}
// Перезагрузить пул
await databasePoolManager.reloadPool(id);
res.json(result.rows[0]);
} catch (error: any) {
console.error('Update database error:', error);
if (error.code === '23505') {
return res.status(400).json({ error: 'База данных с таким именем уже существует' });
}
res.status(500).json({ error: 'Ошибка обновления базы данных' });
}
};
export const deleteDatabase = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
// Проверяем, используется ли база данных в эндпоинтах
const endpointCheck = await mainPool.query(
'SELECT COUNT(*) FROM endpoints WHERE database_id = $1',
[id]
);
if (parseInt(endpointCheck.rows[0].count) > 0) {
return res.status(400).json({
error: 'Невозможно удалить базу данных, используемую в эндпоинтах'
});
}
const result = await mainPool.query(
'DELETE FROM databases WHERE id = $1 RETURNING id',
[id]
);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'База данных не найдена' });
}
// Удалить пул
databasePoolManager.removePool(id);
res.json({ message: 'База данных удалена успешно' });
} catch (error) {
console.error('Delete database error:', error);
res.status(500).json({ error: 'Ошибка удаления базы данных' });
}
};
export const testDatabaseConnection = async (req: AuthRequest, res: Response) => {
try {
const { id } = req.params;
const isConnected = await databasePoolManager.testConnection(id);
res.json({
success: isConnected,
message: isConnected ? 'Подключение успешно' : 'Ошибка подключения',
});
} catch (error) {
console.error('Test connection error:', error);
res.status(500).json({ error: 'Ошибка тестирования подключения' });
}
};