49 lines
2.1 KiB
PHP
49 lines
2.1 KiB
PHP
<?php
|
|||
|
|
/**
|
||
|
|
* GET /api/health.php — deployment self-check (no secrets or PII in the output).
|
||
|
|
* Safe to leave enabled; reveals only booleans and version strings.
|
||
|
|
*/
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
require_once __DIR__ . '/lib/bootstrap.php';
|
||
|
|
|
||
|
|
Api::requireMethod('GET');
|
||
|
|
|
||
|
|
$checks = [];
|
||
|
|
$checks['php'] = PHP_VERSION;
|
||
|
|
$checks['extensions'] = [
|
||
|
|
'curl' => extension_loaded('curl'),
|
||
|
|
'pdo_sqlite' => extension_loaded('pdo_sqlite'),
|
||
|
|
'pdo_mysql' => extension_loaded('pdo_mysql'),
|
||
|
|
'json' => extension_loaded('json'),
|
||
|
|
'mbstring' => extension_loaded('mbstring'),
|
||
|
|
'openssl' => extension_loaded('openssl'),
|
||
|
|
];
|
||
|
|
$checks['private_dir_found'] = is_dir(Config::privateDir());
|
||
|
|
$checks['env_file_found'] = is_readable(Config::privateDir() . '/.env');
|
||
|
|
$checks['data_dir_writable'] = is_writable(Config::dataDir());
|
||
|
|
$checks['logs_dir_writable'] = is_writable(Config::privateDir() . '/logs') || is_writable(Config::privateDir());
|
||
|
|
$checks['integration_mode'] = Config::mode();
|
||
|
|
$checks['mailchimp_configured'] = Config::get('MAILCHIMP_API_KEY') !== null && Config::get('MAILCHIMP_AUDIENCE_ID') !== null;
|
||
|
|
$checks['sinch_configured'] = Config::get('SINCH_API_KEY') !== null && Config::get('SINCH_API_SECRET') !== null;
|
||
|
|
$checks['geoip_provider'] = Config::get('GEOIP_PROVIDER', 'ipapi_co');
|
||
|
|
$checks['geocode_provider'] = Config::get('GEOCODE_PROVIDER', 'zippopotam');
|
||
|
|
$checks['turnstile_enabled'] = Config::get('TURNSTILE_SECRET_KEY') !== null;
|
||
|
|
$checks['https'] = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
|
||
|
|
|
||
|
|
try {
|
||
|
|
Db::pdo();
|
||
|
|
$checks['database'] = 'ok (' . Db::pdo()->getAttribute(PDO::ATTR_DRIVER_NAME) . ')';
|
||
|
|
} catch (Throwable $e) {
|
||
|
|
$checks['database'] = 'error';
|
||
|
|
Log::error('Health: database failed', ['error' => $e->getMessage()]);
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
$checks['campuses_loaded'] = count(Campuses::all());
|
||
|
|
} catch (Throwable $e) {
|
||
|
|
$checks['campuses_loaded'] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
$ok = $checks['private_dir_found'] && $checks['data_dir_writable'] && $checks['database'] !== 'error' && $checks['campuses_loaded'] > 0 && $checks['extensions']['curl'];
|
||
|
|
Api::json(['ok' => $ok, 'checks' => $checks], $ok ? 200 : 500);
|