modified: backend/src/controllers/databaseManagementController.ts

modified:   backend/src/controllers/dynamicApiController.ts
	modified:   backend/src/controllers/endpointController.ts
	new file:   backend/src/migrations/005_add_aql_support.sql
	new file:   backend/src/services/AqlExecutor.ts
	modified:   backend/src/types/index.ts
	modified:   frontend/src/components/EndpointModal.tsx
	modified:   frontend/src/pages/Databases.tsx
	modified:   frontend/src/types/index.ts
This commit is contained in:
GEgorov
2025-10-07 19:33:50 +03:00
parent 7d8fddfe4f
commit 713e9ba7f7
9 changed files with 793 additions and 147 deletions

View File

@@ -7,7 +7,10 @@ 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'
`SELECT id, name, type, host, port, database_name, username, ssl, is_active,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers,
created_at, updated_at
FROM databases ORDER BY name`
);
res.json(result.rows);
@@ -22,7 +25,10 @@ export const getDatabase = async (req: AuthRequest, res: Response) => {
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',
`SELECT id, name, type, host, port, database_name, username, ssl, is_active,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers,
created_at, updated_at
FROM databases WHERE id = $1`,
[id]
);
@@ -39,26 +45,58 @@ export const getDatabase = async (req: AuthRequest, res: Response) => {
export const createDatabase = async (req: AuthRequest, res: Response) => {
try {
const { name, type, host, port, database_name, username, password, ssl } = req.body;
const {
name, type, host, port, database_name, username, password, ssl,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers
} = req.body;
if (!name || !host || !port || !database_name || !username || !password) {
return res.status(400).json({ error: 'Не заполнены обязательные поля' });
const dbType = type || 'postgresql';
// Валидация для обычных БД
if (dbType !== 'aql') {
if (!name || !host || !port || !database_name || !username || !password) {
return res.status(400).json({ error: 'Не заполнены обязательные поля' });
}
} else {
// Валидация для AQL
if (!name || !aql_base_url) {
return res.status(400).json({ error: 'Не заполнены обязательные поля для AQL базы' });
}
}
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)
`INSERT INTO databases (
name, type, host, port, database_name, username, password, ssl, is_active,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, true, $9, $10, $11, $12)
RETURNING *`,
[name, type || 'postgresql', host, port, database_name, username, password, ssl || false]
[
name,
dbType,
host || '',
port || 0,
database_name || '',
username || '',
password || '',
ssl || false,
aql_base_url || null,
aql_auth_type || null,
aql_auth_value || null,
aql_headers ? JSON.stringify(aql_headers) : null
]
);
const newDb = result.rows[0];
// Добавить пул подключений
await databasePoolManager.reloadPool(newDb.id);
// Добавить пул подключений (только для не-AQL баз)
if (dbType !== 'aql') {
await databasePoolManager.reloadPool(newDb.id);
}
// Не возвращаем пароль
delete newDb.password;
delete newDb.aql_auth_value; // Также не возвращаем auth value
res.status(201).json(newDb);
} catch (error: any) {
@@ -73,13 +111,16 @@ export const createDatabase = async (req: AuthRequest, res: Response) => {
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;
const {
name, type, host, port, database_name, username, password, ssl, is_active,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers
} = req.body;
// Если пароль не передан, не обновляем его
// Если пароль/auth не передан, не обновляем его
let query;
let params;
if (password) {
if (password || aql_auth_value) {
query = `
UPDATE databases
SET name = COALESCE($1, name),
@@ -88,14 +129,22 @@ export const updateDatabase = async (req: AuthRequest, res: Response) => {
port = COALESCE($4, port),
database_name = COALESCE($5, database_name),
username = COALESCE($6, username),
password = $7,
password = COALESCE($7, password),
ssl = COALESCE($8, ssl),
is_active = COALESCE($9, is_active),
aql_base_url = COALESCE($10, aql_base_url),
aql_auth_type = COALESCE($11, aql_auth_type),
aql_auth_value = COALESCE($12, aql_auth_value),
aql_headers = COALESCE($13, aql_headers),
updated_at = CURRENT_TIMESTAMP
WHERE id = $10
RETURNING id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at
WHERE id = $14
RETURNING id, name, type, host, port, database_name, username, ssl, is_active,
aql_base_url, aql_auth_type, aql_headers, created_at, updated_at
`;
params = [name, type, host, port, database_name, username, password, ssl, is_active, id];
params = [
name, type, host, port, database_name, username, password || aql_auth_value, ssl, is_active,
aql_base_url, aql_auth_type, aql_auth_value, aql_headers ? JSON.stringify(aql_headers) : null, id
];
} else {
query = `
UPDATE databases
@@ -107,11 +156,18 @@ export const updateDatabase = async (req: AuthRequest, res: Response) => {
username = COALESCE($6, username),
ssl = COALESCE($7, ssl),
is_active = COALESCE($8, is_active),
aql_base_url = COALESCE($9, aql_base_url),
aql_auth_type = COALESCE($10, aql_auth_type),
aql_headers = COALESCE($11, aql_headers),
updated_at = CURRENT_TIMESTAMP
WHERE id = $9
RETURNING id, name, type, host, port, database_name, username, ssl, is_active, created_at, updated_at
WHERE id = $12
RETURNING id, name, type, host, port, database_name, username, ssl, is_active,
aql_base_url, aql_auth_type, aql_headers, created_at, updated_at
`;
params = [name, type, host, port, database_name, username, ssl, is_active, id];
params = [
name, type, host, port, database_name, username, ssl, is_active,
aql_base_url, aql_auth_type, aql_headers ? JSON.stringify(aql_headers) : null, id
];
}
const result = await mainPool.query(query, params);
@@ -120,8 +176,10 @@ export const updateDatabase = async (req: AuthRequest, res: Response) => {
return res.status(404).json({ error: 'База данных не найдена' });
}
// Перезагрузить пул
await databasePoolManager.reloadPool(id);
// Перезагрузить пул (только для не-AQL баз)
if (result.rows[0].type !== 'aql') {
await databasePoolManager.reloadPool(id);
}
res.json(result.rows[0]);
} catch (error: any) {
@@ -172,12 +230,33 @@ export const testDatabaseConnection = async (req: AuthRequest, res: Response) =>
try {
const { id } = req.params;
const isConnected = await databasePoolManager.testConnection(id);
// Получаем тип БД
const dbResult = await mainPool.query('SELECT type FROM databases WHERE id = $1', [id]);
res.json({
success: isConnected,
message: isConnected ? 'Подключение успешно' : 'Ошибка подключения',
});
if (dbResult.rows.length === 0) {
return res.status(404).json({ success: false, error: 'База данных не найдена' });
}
const dbType = dbResult.rows[0].type;
if (dbType === 'aql') {
// Для AQL используем aqlExecutor
const { aqlExecutor } = require('../services/AqlExecutor');
const result = await aqlExecutor.testConnection(id);
res.json({
success: result.success,
message: result.success ? 'Подключение успешно' : result.error || 'Ошибка подключения',
});
} else {
// Для обычных БД используем databasePoolManager
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: 'Ошибка тестирования подключения' });