Files
Investidor-V2/tools/portal-dashboard-active-readonly.php
T
nala 01405cbf8a
tests / ci (push) Canceled after 0s
oportunidades 5
2026-10-10 14:15:28 +02:00

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;