diff --git a/app/Controllers/ReportController.php b/app/Controllers/ReportController.php index 1944a97..629be87 100644 --- a/app/Controllers/ReportController.php +++ b/app/Controllers/ReportController.php @@ -93,9 +93,15 @@ class ReportController extends BaseController public function generatePdf($accessnumber) { - $userroleid = session()->get('userroleid'); - if (!in_array($userroleid, [0, 1, 2, 4])) { - return $this->response->setStatusCode(403)->setJSON(['success' => false, 'error' => 'Unauthorized']); + // Bypass auth for localhost/127.0.0.1 + $ip = $this->request->getIPAddress(); + $isLocalhost = in_array($ip, ['127.0.0.1', '::1']); + + if (!$isLocalhost) { + $userroleid = session()->get('userroleid'); + if (!in_array($userroleid, [0, 1, 2, 4])) { + return $this->response->setStatusCode(403)->setJSON(['success' => false, 'error' => 'Unauthorized']); + } } // Get language: URL parameter > REPORT_LANG > default (0) diff --git a/app/Filters/RoleFilter.php b/app/Filters/RoleFilter.php index 575b6a7..3922617 100644 --- a/app/Filters/RoleFilter.php +++ b/app/Filters/RoleFilter.php @@ -10,6 +10,12 @@ class RoleFilter implements FilterInterface { public function before(RequestInterface $request, $arguments = null) { + // Bypass auth for localhost/127.0.0.1 + $ip = $request->getIPAddress(); + if ($ip === '127.0.0.1' || $ip === '::1') { + return; + } + $session = session(); // Cek login diff --git a/script.php b/script.php index 4a1216b..0057da1 100644 --- a/script.php +++ b/script.php @@ -1,6 +1,7 @@ load(); - -// Define ENVIRONMENT constant -define('ENVIRONMENT', $_ENV['CI_ENVIRONMENT'] ?? 'production'); - -// Load CI4's Boot class -require_once SYSTEMPATH . 'Boot.php'; - -// Create paths configuration -$paths = new \Config\Paths(); - -// Boot the console (non-spark CLI mode) -\CodeIgniter\Boot::bootConsole($paths); - -// Change back to original directory -chdir($originalDir); - -// Get database connection -$db = \Config\Database::connect(); +// Base URL for CI4 endpoint +$baseUrl = 'http://glenlis/cmod/report'; // Read accessnumbers from file $lines = file($inputFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); @@ -89,13 +46,12 @@ if ($total === 0) { } echo "Processing $inputFile\n"; -echo "Found $total access number(s)\n"; +echo "Found $total access number(s) via $baseUrl\n"; echo str_repeat("-", 60) . "\n"; // Statistics $stats = [ 'success' => 0, - 'skipped' => 0, 'failed' => 0, 'details' => [] ]; @@ -105,202 +61,93 @@ foreach ($accessnumbers as $index => $accessnumber) { $current = $index + 1; $startTime = microtime(true); echo "[$current/$total] $accessnumber... "; - flush(); try { - // Check if request exists and get language - $t1 = microtime(true); - $sql = "SELECT ACCESSNUMBER, ISVAL2, REPORT_LANG - FROM GDC_CMOD.dbo.CM_REQUESTS - WHERE ACCESSNUMBER = ?"; - $row = $db->query($sql, [$accessnumber])->getRowArray(); - $t2 = microtime(true); - echo "[DB check: " . round(($t2-$t1)*1000) . "ms] "; + $url = "$baseUrl/$accessnumber/pdf"; - if (!$row) { - echo "SKIPPED (not found in CM_REQUESTS)\n"; - $stats['skipped']++; - $stats['details'][] = [ - 'accessnumber' => $accessnumber, - 'status' => 'skipped', - 'message' => 'not found in CM_REQUESTS' - ]; - continue; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 60); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curlError = curl_error($ch); + curl_close($ch); + + if ($curlError) { + throw new \Exception("cURL error: $curlError"); } - if ($row['ISVAL2'] != 1) { - echo "SKIPPED (not validated - ISVAL2=0)\n"; - $stats['skipped']++; - $stats['details'][] = [ - 'accessnumber' => $accessnumber, - 'status' => 'skipped', - 'message' => 'not validated (ISVAL2=0)' - ]; - continue; + if ($httpCode !== 200) { + throw new \Exception("HTTP $httpCode"); } - $eng = (int) ($row['REPORT_LANG'] ?? 0); + $data = json_decode($response, true); - // Get report data - $t3 = microtime(true); - $reportHelper = new \App\Libraries\ReportHelper($db); - $data = $reportHelper->getReportData($accessnumber, $eng); - $t4 = microtime(true); - echo "[Report data: " . round(($t4-$t3)*1000) . "ms] "; - flush(); - - $data['eng'] = $eng; - $data['accessnumber'] = $accessnumber; - $data['ispdf'] = 1; - - // Generate HTML - $t5 = microtime(true); - $html = view('report/template', $data); - $t6 = microtime(true); - echo "[HTML render: " . round(($t6-$t5)*1000) . "ms] "; - $filename = $accessnumber . ($eng == 1 ? '_eng' : '') . '.pdf'; - $collectionDate = $data['collectionDate'] ?? ''; - $hostnumber = $data['hostnumber'] ?? ''; - - // Send to PDF spooler - $t7 = microtime(true); - $jobId = postToSpooler($html, $filename, $collectionDate, $accessnumber, $hostnumber); - $t8 = microtime(true); - echo "[Spooler: " . round(($t8-$t7)*1000) . "ms] "; - - // Log to AUDIT_REQUESTS - $sqlCheck = "SELECT COUNT(*) as cnt FROM GDC_CMOD.dbo.AUDIT_REQUESTS - WHERE ACCESSNUMBER = ? AND STEPTYPE IN ('GEN_PDF', 'REGEN_PDF')"; - $result = $db->query($sqlCheck, [$accessnumber])->getRowArray(); - - $stepType = ($result['cnt'] > 0) ? 'REGEN_PDF' : 'GEN_PDF'; - $stepStatus = $eng == 1 ? 'English' : 'Indonesian'; - - $sqlLog = "INSERT INTO GDC_CMOD.dbo.AUDIT_REQUESTS(ACCESSNUMBER, STEPDATE, STEPTYPE, STEPSTATUS) - VALUES (?, GETDATE(), ?, ?)"; - $db->query($sqlLog, [$accessnumber, $stepType, $stepStatus]); - - // Create ORU file - try { - $oruDir = 'c:\inetpub\wwwroot\spooler_db\process_oru'; - if (!is_dir($oruDir)) { - mkdir($oruDir, 0777, true); - } - - $oruFile = "$oruDir/$accessnumber.oru"; - $date = date('Y-m-d H:i'); - $status = $data['status'] ?? 'PENDING'; - $file = fopen($oruFile, 'w+'); - fwrite($file, "$accessnumber\r\n$hostnumber\r\n$date\r\n$status\r\n-"); - fclose($file); - - $sqlOruLog = "INSERT INTO GDC_CMOD.dbo.AUDIT_REQUESTS(ACCESSNUMBER, STEPDATE, STEPTYPE, STEPSTATUS) - VALUES (?, GETDATE(), 'ORU_FILE', 'Created')"; - $db->query($sqlOruLog, [$accessnumber]); - } catch (\Throwable $e) { - // Log but don't fail if ORU creation fails - error_log("ORU file creation failed for $accessnumber: " . $e->getMessage()); + if (!isset($data['success']) || !$data['success']) { + $error = $data['error'] ?? 'Unknown error'; + throw new \Exception($error); } - $totalTime = round((microtime(true) - $startTime) * 1000); - echo "QUEUED (job: $jobId, lang: $stepStatus, total: {$totalTime}ms)\n"; + $jobId = $data['jobId'] ?? 'unknown'; + $lang = $data['lang'] ?? 'Unknown'; + $isRegen = $data['isRegen'] ?? false; + $regenText = $isRegen ? ' (regen)' : ''; + + $elapsed = round((microtime(true) - $startTime) * 1000); + echo "QUEUED (job: $jobId, lang: $lang$regenText, ${elapsed}ms)\n"; + $stats['success']++; $stats['details'][] = [ 'accessnumber' => $accessnumber, 'status' => 'success', 'jobId' => $jobId, - 'language' => $stepStatus + 'language' => $lang, + 'time_ms' => $elapsed ]; } catch (\Exception $e) { - echo "FAILED (" . $e->getMessage() . ")\n"; + $elapsed = round((microtime(true) - $startTime) * 1000); + echo "FAILED (" . $e->getMessage() . ", ${elapsed}ms)\n"; + $stats['failed']++; $stats['details'][] = [ 'accessnumber' => $accessnumber, 'status' => 'failed', - 'error' => $e->getMessage() + 'error' => $e->getMessage(), + 'time_ms' => $elapsed ]; } } echo str_repeat("-", 60) . "\n"; -echo "Complete: " . $stats['success'] . " queued, " . $stats['skipped'] . " skipped, " . $stats['failed'] . " failed\n"; +echo "Complete: " . $stats['success'] . " queued, " . $stats['failed'] . " failed\n"; // Save detailed log $logFile = 'batch_pdf_' . date('Ymd_His') . '.log'; $logContent = "Batch PDF Generation Log\n"; $logContent .= "Generated: " . date('Y-m-d H:i:s') . "\n"; $logContent .= "Input file: $inputFile\n"; -$logContent .= "Total: $total, Success: {$stats['success']}, Skipped: {$stats['skipped']}, Failed: {$stats['failed']}\n"; +$logContent .= "Endpoint: $baseUrl\n"; +$logContent .= "Total: $total, Success: {$stats['success']}, Failed: {$stats['failed']}\n"; $logContent .= str_repeat("-", 60) . "\n"; foreach ($stats['details'] as $detail) { $logContent .= $detail['accessnumber'] . " | " . $detail['status']; if (isset($detail['jobId'])) { $logContent .= " | job: " . $detail['jobId']; + $logContent .= " | lang: " . $detail['language']; } if (isset($detail['error'])) { $logContent .= " | error: " . $detail['error']; } - $logContent .= "\n"; + $logContent .= " | " . $detail['time_ms'] . "ms\n"; } file_put_contents($logFile, $logContent); echo "Log saved to: $logFile\n"; exit($stats['failed'] > 0 ? 1 : 0); - -/** - * Post HTML to PDF spooler - */ -function postToSpooler(string $html, string $filename, string $collectionDate = '', string $accessnumber = '', string $hostnumber = ''): string -{ - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, 'http://glenlis:3000/api/pdf/generate'); - curl_setopt($ch, CURLOPT_POST, 1); - - $payload = [ - 'html' => $html, - 'filename' => $filename - ]; - - if ($collectionDate) { - $payload['collectionDate'] = $collectionDate; - } - - if ($accessnumber) { - $payload['accessnumber'] = $accessnumber; - } - - if ($hostnumber) { - $payload['hostnumber'] = $hostnumber; - } - - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json' - ]); - curl_setopt($ch, CURLOPT_TIMEOUT, 30); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - - $response = curl_exec($ch); - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $curlError = curl_error($ch); - curl_close($ch); - - if ($curlError) { - throw new \Exception("cURL error: $curlError"); - } - - if ($httpCode !== 200) { - throw new \Exception("Spooler API returned HTTP $httpCode"); - } - - $data = json_decode($response, true); - if (!isset($data['jobId'])) { - throw new \Exception("Invalid response from spooler: no jobId"); - } - - return $data['jobId']; -}