🔱 Enhanced backdoor with Redis + Directus checks
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Endpoints:
|
* Endpoints:
|
||||||
* GET /api/god/health - Full system health check
|
* GET /api/god/health - Full system health check
|
||||||
|
* GET /api/god/services - Quick service status (all 4 containers)
|
||||||
* GET /api/god/db-status - Database connection test
|
* GET /api/god/db-status - Database connection test
|
||||||
* POST /api/god/sql - Execute raw SQL (dangerous!)
|
* POST /api/god/sql - Execute raw SQL (dangerous!)
|
||||||
* GET /api/god/tables - List all tables
|
* GET /api/god/tables - List all tables
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
|
|
||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import { Pool } from 'pg';
|
import { Pool } from 'pg';
|
||||||
|
import Redis from 'ioredis';
|
||||||
|
|
||||||
// Direct PostgreSQL connection (bypasses Directus)
|
// Direct PostgreSQL connection (bypasses Directus)
|
||||||
const pool = new Pool({
|
const pool = new Pool({
|
||||||
@@ -27,6 +29,9 @@ const pool = new Pool({
|
|||||||
connectionTimeoutMillis: 5000,
|
connectionTimeoutMillis: 5000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Directus URL
|
||||||
|
const DIRECTUS_URL = process.env.PUBLIC_DIRECTUS_URL || 'http://directus:8055';
|
||||||
|
|
||||||
// God Mode Token validation
|
// God Mode Token validation
|
||||||
function validateGodToken(request: Request): boolean {
|
function validateGodToken(request: Request): boolean {
|
||||||
const token = request.headers.get('X-God-Token') ||
|
const token = request.headers.get('X-God-Token') ||
|
||||||
@@ -63,6 +68,8 @@ export const GET: APIRoute = async ({ request, url }) => {
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case 'health':
|
case 'health':
|
||||||
return await getHealth();
|
return await getHealth();
|
||||||
|
case 'services':
|
||||||
|
return await getServices();
|
||||||
case 'db-status':
|
case 'db-status':
|
||||||
return await getDbStatus();
|
return await getDbStatus();
|
||||||
case 'tables':
|
case 'tables':
|
||||||
@@ -72,8 +79,10 @@ export const GET: APIRoute = async ({ request, url }) => {
|
|||||||
default:
|
default:
|
||||||
return json({
|
return json({
|
||||||
message: '🔱 God Mode Backdoor Active',
|
message: '🔱 God Mode Backdoor Active',
|
||||||
|
frontend: 'RUNNING ✅',
|
||||||
endpoints: {
|
endpoints: {
|
||||||
'GET /api/god/health': 'Full system health check',
|
'GET /api/god/health': 'Full system health check',
|
||||||
|
'GET /api/god/services': 'Quick status of all 4 containers',
|
||||||
'GET /api/god/db-status': 'Database connection test',
|
'GET /api/god/db-status': 'Database connection test',
|
||||||
'GET /api/god/tables': 'List all tables',
|
'GET /api/god/tables': 'List all tables',
|
||||||
'GET /api/god/logs': 'Recent work_log entries',
|
'GET /api/god/logs': 'Recent work_log entries',
|
||||||
@@ -121,14 +130,103 @@ export const POST: APIRoute = async ({ request, url }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Quick service status check
|
||||||
|
async function getServices() {
|
||||||
|
const services: Record<string, any> = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
frontend: { status: '✅ RUNNING', note: 'You are seeing this response' }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check PostgreSQL
|
||||||
|
try {
|
||||||
|
const start = Date.now();
|
||||||
|
await pool.query('SELECT 1');
|
||||||
|
services.postgresql = {
|
||||||
|
status: '✅ RUNNING',
|
||||||
|
latency_ms: Date.now() - start
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
services.postgresql = {
|
||||||
|
status: '❌ DOWN',
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Redis
|
||||||
|
try {
|
||||||
|
const redis = new Redis({
|
||||||
|
host: process.env.REDIS_HOST || 'redis',
|
||||||
|
port: 6379,
|
||||||
|
connectTimeout: 3000,
|
||||||
|
maxRetriesPerRequest: 1
|
||||||
|
});
|
||||||
|
const start = Date.now();
|
||||||
|
await redis.ping();
|
||||||
|
services.redis = {
|
||||||
|
status: '✅ RUNNING',
|
||||||
|
latency_ms: Date.now() - start
|
||||||
|
};
|
||||||
|
redis.disconnect();
|
||||||
|
} catch (error: any) {
|
||||||
|
services.redis = {
|
||||||
|
status: '❌ DOWN',
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Directus
|
||||||
|
try {
|
||||||
|
const start = Date.now();
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
||||||
|
|
||||||
|
const response = await fetch(`${DIRECTUS_URL}/server/health`, {
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
services.directus = {
|
||||||
|
status: '✅ RUNNING',
|
||||||
|
latency_ms: Date.now() - start,
|
||||||
|
health: data.status
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
services.directus = {
|
||||||
|
status: '⚠️ UNHEALTHY',
|
||||||
|
http_status: response.status
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
services.directus = {
|
||||||
|
status: '❌ DOWN',
|
||||||
|
error: error.name === 'AbortError' ? 'Timeout (5s)' : error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
const allUp = services.postgresql.status.includes('✅') &&
|
||||||
|
services.redis.status.includes('✅') &&
|
||||||
|
services.directus.status.includes('✅');
|
||||||
|
|
||||||
|
services.summary = allUp ? '✅ ALL SERVICES HEALTHY' : '⚠️ SOME SERVICES DOWN';
|
||||||
|
|
||||||
|
return json(services);
|
||||||
|
}
|
||||||
|
|
||||||
// Health check implementation
|
// Health check implementation
|
||||||
async function getHealth() {
|
async function getHealth() {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
|
|
||||||
const checks: Record<string, any> = {
|
const checks: Record<string, any> = {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
uptime: process.uptime(),
|
uptime_seconds: Math.round(process.uptime()),
|
||||||
memory: process.memoryUsage(),
|
memory: {
|
||||||
|
rss_mb: Math.round(process.memoryUsage().rss / 1024 / 1024),
|
||||||
|
heap_used_mb: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
|
||||||
|
heap_total_mb: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// PostgreSQL check
|
// PostgreSQL check
|
||||||
@@ -136,24 +234,70 @@ async function getHealth() {
|
|||||||
const dbStart = Date.now();
|
const dbStart = Date.now();
|
||||||
const result = await pool.query('SELECT NOW() as time, current_database() as db, current_user as user');
|
const result = await pool.query('SELECT NOW() as time, current_database() as db, current_user as user');
|
||||||
checks.postgresql = {
|
checks.postgresql = {
|
||||||
status: 'healthy',
|
status: '✅ healthy',
|
||||||
latency_ms: Date.now() - dbStart,
|
latency_ms: Date.now() - dbStart,
|
||||||
...result.rows[0]
|
...result.rows[0]
|
||||||
};
|
};
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
checks.postgresql = {
|
checks.postgresql = {
|
||||||
status: 'unhealthy',
|
status: '❌ unhealthy',
|
||||||
error: error.message
|
error: error.message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection pool status
|
// Connection pool status
|
||||||
checks.pool = {
|
checks.pg_pool = {
|
||||||
total: pool.totalCount,
|
total: pool.totalCount,
|
||||||
idle: pool.idleCount,
|
idle: pool.idleCount,
|
||||||
waiting: pool.waitingCount
|
waiting: pool.waitingCount
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Redis check
|
||||||
|
try {
|
||||||
|
const redis = new Redis({
|
||||||
|
host: process.env.REDIS_HOST || 'redis',
|
||||||
|
port: 6379,
|
||||||
|
connectTimeout: 3000,
|
||||||
|
maxRetriesPerRequest: 1
|
||||||
|
});
|
||||||
|
const redisStart = Date.now();
|
||||||
|
const info = await redis.info('server');
|
||||||
|
checks.redis = {
|
||||||
|
status: '✅ healthy',
|
||||||
|
latency_ms: Date.now() - redisStart,
|
||||||
|
version: info.match(/redis_version:([^\r\n]+)/)?.[1]
|
||||||
|
};
|
||||||
|
redis.disconnect();
|
||||||
|
} catch (error: any) {
|
||||||
|
checks.redis = {
|
||||||
|
status: '❌ unhealthy',
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Directus check
|
||||||
|
try {
|
||||||
|
const directusStart = Date.now();
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeout = setTimeout(() => controller.abort(), 5000);
|
||||||
|
|
||||||
|
const response = await fetch(`${DIRECTUS_URL}/server/health`, {
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
checks.directus = {
|
||||||
|
status: response.ok ? '✅ healthy' : '⚠️ unhealthy',
|
||||||
|
latency_ms: Date.now() - directusStart,
|
||||||
|
http_status: response.status
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
checks.directus = {
|
||||||
|
status: '❌ unreachable',
|
||||||
|
error: error.name === 'AbortError' ? 'Timeout (5s)' : error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Directus tables check
|
// Directus tables check
|
||||||
try {
|
try {
|
||||||
const tables = await pool.query(`
|
const tables = await pool.query(`
|
||||||
@@ -163,12 +307,9 @@ async function getHealth() {
|
|||||||
AND table_name LIKE 'directus_%'
|
AND table_name LIKE 'directus_%'
|
||||||
ORDER BY table_name
|
ORDER BY table_name
|
||||||
`);
|
`);
|
||||||
checks.directus = {
|
checks.directus_tables = tables.rows.length;
|
||||||
system_tables: tables.rows.length,
|
|
||||||
tables: tables.rows.map(r => r.table_name)
|
|
||||||
};
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
checks.directus = { status: 'error', error: error.message };
|
checks.directus_tables = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom tables check
|
// Custom tables check
|
||||||
@@ -185,7 +326,7 @@ async function getHealth() {
|
|||||||
tables: tables.rows.map(r => r.table_name)
|
tables: tables.rows.map(r => r.table_name)
|
||||||
};
|
};
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
checks.custom_tables = { status: 'error', error: error.message };
|
checks.custom_tables = { count: 0, error: error.message };
|
||||||
}
|
}
|
||||||
|
|
||||||
checks.total_latency_ms = Date.now() - start;
|
checks.total_latency_ms = Date.now() - start;
|
||||||
|
|||||||
Reference in New Issue
Block a user