67 lines
6.2 KiB
PHP
67 lines
6.2 KiB
PHP
<?php
|
|
|
|
use Illuminate\Foundation\Bootstrap\LoadConfiguration;
|
|
use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables;
|
|
|
|
// Configuration, permission eligibility, installation and asset metadata only.
|
|
// Do not boot providers/HTTP sessions against the active environment.
|
|
require dirname(__DIR__).'/vendor/autoload.php';
|
|
$root = dirname(__DIR__);
|
|
$app = require $root.'/bootstrap/app.php';
|
|
(new LoadEnvironmentVariables)->bootstrap($app);
|
|
(new LoadConfiguration)->bootstrap($app);
|
|
$config = $app->make('config');
|
|
$connection = $config->get('database.connections.'.$config->get('database.default'));
|
|
if (($connection['driver'] ?? null) !== 'pgsql' || ! empty($connection['url'])) {
|
|
throw new RuntimeException('Explicit PostgreSQL configuration required for read-only diagnosis.');
|
|
}
|
|
$pdo = new PDO('pgsql:host='.$connection['host'].';port='.$connection['port'].';dbname='.$connection['database'], $connection['username'], $connection['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
|
$pdo->exec('BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY');
|
|
try {
|
|
$identity = $pdo->query("SELECT current_database() AS database,inet_server_port() AS port,current_setting('transaction_read_only') AS read_only")->fetch(PDO::FETCH_ASSOC);
|
|
$managers = $config->get('portal.managers', []);
|
|
$accounts = [];
|
|
foreach ($pdo->query('SELECT id,email,email_verified_at FROM users ORDER BY id') as $user) {
|
|
$listed = in_array(strtolower($user['email']), $managers, true);
|
|
if ($listed || in_array((int) $user['id'], [13, 18], true)) {
|
|
$accounts[] = ['id' => (int) $user['id'], 'listed_manager' => $listed, 'email_verified' => $user['email_verified_at'] !== null, 'manage_portal' => $listed && $user['email_verified_at'] !== null];
|
|
}
|
|
}
|
|
$columns = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_schema='public' AND table_name='opportunities'")->fetchAll(PDO::FETCH_COLUMN);
|
|
$migrations = $pdo->query("SELECT migration FROM migrations WHERE migration LIKE '%opportunity_management%' OR migration LIKE '%opportunity_resources%' OR migration LIKE '%prepare_investor_path%' OR migration LIKE '%internal_virtual_desk%' OR migration LIKE '%extend_desk_investor_guidance%'")->fetchAll(PDO::FETCH_COLUMN);
|
|
$counts = $pdo->query('SELECT status,count(*) AS total FROM opportunities WHERE deleted_at IS NULL GROUP BY status ORDER BY status')->fetchAll(PDO::FETCH_ASSOC);
|
|
$resourcesInstalled = $pdo->query("SELECT to_regclass('public.opportunity_images') IS NOT NULL")->fetchColumn();
|
|
$profilesInstalled = $pdo->query("SELECT to_regclass('public.portal_role_assignments') IS NOT NULL")->fetchColumn();
|
|
$pathInstalled = $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='investor_journeys' AND column_name='path_definition_id')")->fetchColumn();
|
|
$pathDetails = ['migration' => '2026_10_09_190000_prepare_investor_path', 'ledger' => in_array('2026_10_09_190000_prepare_investor_path', $migrations, true),
|
|
'journey_path_definition_column' => (bool) $pathInstalled,
|
|
'step_path_detail_column' => (bool) $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='journey_steps' AND column_name='path_detail')")->fetchColumn(),
|
|
'definitions' => $pdo->query("SELECT id,status,md5(schema_snapshot::text) AS snapshot_md5 FROM questionnaire_versions WHERE code='investor-path-19'")->fetchAll(PDO::FETCH_ASSOC)];
|
|
$geometryTable = $pdo->query("SELECT to_regclass('public.geo_geometries') IS NOT NULL")->fetchColumn();
|
|
$geometryCount = $geometryTable ? (int) $pdo->query('SELECT count(*) FROM geo_geometries WHERE deleted_at IS NULL')->fetchColumn() : null;
|
|
} finally {
|
|
$pdo->exec('ROLLBACK');
|
|
}
|
|
$manifestPath = $root.'/public/build/manifest.json';
|
|
$manifest = json_decode(file_get_contents($manifestPath), true, 512, JSON_THROW_ON_ERROR);
|
|
$assets = [];
|
|
foreach (['resources/js/app.tsx', 'resources/js/pages/dashboard.tsx', 'resources/js/pages/management/opportunities.tsx', 'resources/js/pages/management/opportunity-draft.tsx'] as $entry) {
|
|
$file = $manifest[$entry]['file'] ?? null;
|
|
$bytes = $file ? file_get_contents($root.'/public/build/'.$file) : '';
|
|
$assets[$entry] = ['file' => $file, 'sha256' => hash('sha256', $bytes), 'management_label' => str_contains($bytes, 'Gestão de Oportunidades'), 'new_label' => str_contains($bytes, 'Nova oportunidade'), 'old_create_label' => str_contains($bytes, 'Criar oportunidade')];
|
|
}
|
|
$proof = ['captured_at' => gmdate('c'), 'identity' => $identity, 'configured_app_url' => $config->get('app.url'), 'config_cached' => $app->configurationIsCached(),
|
|
'routes_cached' => is_file($app->getCachedRoutesPath()), 'public_hot_present' => is_file($root.'/public/hot'), 'manager_configuration_count' => count($managers), 'accounts' => $accounts,
|
|
'management_installed' => in_array('management_version', $columns, true), 'resource_extension_installed' => (bool) $resourcesInstalled, 'dashboard_increment_enabled' => (bool) $config->get('portal.opportunity_dashboard_access_enabled'), 'migrations' => $migrations, 'opportunities' => $counts,
|
|
'investor_path_installed' => (bool) $pathInstalled, 'path_190000_evidence' => $pathDetails, 'active_geometry_count' => $geometryCount, 'specialized_increment_enabled' => (bool) $config->get('portal.opportunity_specialized_drafts_enabled'),
|
|
'profile_authorization_installed' => (bool) $profilesInstalled, 'profile_access_enabled' => (bool) $config->get('portal.profile_access_enabled'),
|
|
'session_configuration' => array_intersect_key($config->get('session'), array_flip(['driver', 'cookie', 'domain', 'path', 'secure', 'same_site'])),
|
|
'manifest_sha256' => hash_file('sha256', $manifestPath), 'assets' => $assets, 'current_browser_actor_known' => false, 'active_writes' => 0];
|
|
$dir = $root.'/storage/app/private/investmoz-v2/portal-audit';
|
|
$path = $dir.'/dashboard-active-readonly.json';
|
|
if (is_file($path)) {
|
|
copy($path, $dir.'/dashboard-active-readonly-'.gmdate('Ymd_His').'.json');
|
|
}
|
|
file_put_contents($path, json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
|
|
echo json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR).PHP_EOL;
|