FIX_TPA_CLAM_FILE_DOWNLOAD

This commit is contained in:
VENKATESHWARAN 2026-07-16 11:38:19 +05:30
parent 6c4af860f5
commit c86019f214
4 changed files with 120 additions and 17 deletions

View File

@ -22,6 +22,9 @@ class Acl
'#^/getSSORedirectUrl#' => ['public' => true],
'#^/getEmployeePolicy#' => ['public' => true],
'#^/downloadFileTableFile#' => ['public' => true],
'#^/storage/file-download#' => ['public' => true],
'#^/fileDownload#' => ['public' => true],
'#^/downloadClaimFile#' => ['public' => true],
'#^/swagger#' => ['roles' => [ADMIN_ROLE_ID]],
'#^/getEmployeeActiveOrInactivePolicy#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],
'#^/test/chartbrewDashboardDemo#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],

View File

@ -38,6 +38,9 @@ $routes->group('/storage/files', ['filter' => 'authMVC'], function ($routes) {
$routes->get('list', 'StorageFilesController::listFiles');
$routes->get('folders', 'StorageFilesController::folders');
});
// Force download (attachment) — public so TPA can fetch claim docs
$routes->get('storage/file-download/claim/(:segment)', 'StorageFilesController::forceDownloadClaim/$1');
$routes->get('storage/file-download', 'StorageFilesController::forceDownloadByFolderFile');
$routes->get('/visitOffBoardCheck', 'EmployeeController::visitOffBoardCheck');
$routes->get('/metaDashboardDemo', 'TestingController::metaDashboardDemo');
$routes->get('/apacheSuperSetDemo', 'TestingController::apacheSuperSetDemo');

View File

@ -2,8 +2,11 @@
namespace App\Controllers;
use App\Models\ClaimFilesModel;
use CodeIgniter\Exceptions\PageNotFoundException;
/**
* Browse S3 upload-bucket objects folder-wise with paginated search UI.
* Browse S3 upload-bucket objects + file-download (attachment) APIs.
*/
class StorageFilesController extends AdminController
{
@ -158,6 +161,94 @@ class StorageFilesController extends AdminController
]);
}
/**
* GET /storage/file-download/claim/{md5(id)}
* Streams claim_files row by MD5(id) as attachment (never inline).
*/
public function forceDownloadClaim($md5Id = null)
{
helper('utility');
$md5Id = strtolower(trim((string) $md5Id));
if ($md5Id === '' || ! preg_match('/^[a-f0-9]{32}$/', $md5Id)) {
throw PageNotFoundException::forPageNotFound();
}
$claimFiles = new ClaimFilesModel();
$record = $claimFiles
->where('MD5(CAST(id AS CHAR))', $md5Id)
->where('is_active', 1)
->first();
if (empty($record)) {
throw PageNotFoundException::forPageNotFound();
}
$diskName = ! empty($record['url'])
? basename((string) $record['url'])
: basename((string) ($record['file_name'] ?? ''));
if ($diskName === '') {
throw PageNotFoundException::forPageNotFound();
}
$downloadAs = storage_upload_display_name($diskName);
return $this->streamAttachment(WRITEPATH . 'uploads/claim_files', $diskName, $downloadAs);
}
/**
* GET /storage/file-download?folder=claim_files&file=xxx.pdf
* Streams any storage module object as attachment (never inline).
*/
public function forceDownloadByFolderFile()
{
helper('utility');
$folder = basename(str_replace('\\', '/', trim((string) $this->request->getGet('folder'))));
$file = basename(str_replace('\\', '/', trim((string) $this->request->getGet('file'))));
if (
$folder === '' || $folder === '.' || $folder === '..'
|| $file === '' || $file === '.' || $file === '..'
|| preg_match('/[^a-zA-Z0-9_\-]/', $folder)
|| preg_match('/[\\\\\\/]/', $file)
) {
throw PageNotFoundException::forPageNotFound();
}
$uploadPath = WRITEPATH . 'uploads' . DIRECTORY_SEPARATOR . $folder;
$downloadAs = storage_upload_display_name($file);
return $this->streamAttachment($uploadPath, $file, $downloadAs);
}
/**
* Stream file bytes with attachment disposition (never inline / never S3 redirect).
*/
private function streamAttachment(string $uploadPath, string $diskName, string $downloadAs)
{
$storage = \Config\Services::getFileStorageService();
$result = $storage->download($uploadPath, $diskName);
if (! ($result['success'] ?? false)) {
throw PageNotFoundException::forPageNotFound();
}
if (! empty($result['path']) && is_file($result['path'])) {
return $this->response
->download($result['path'], null)
->setFileName($downloadAs);
}
if (! empty($result['content'])) {
return $this->response
->download($downloadAs, $result['content'])
->setFileName($downloadAs);
}
throw PageNotFoundException::forPageNotFound();
}
/** @return list<string> */
private function localUploadFolders(): array
{

View File

@ -579,7 +579,8 @@ if (! function_exists('storage_claim_file_Upload')) {
/**
* Build a TPA-facing download URL for a claim file.
* Prefers an S3 presigned URL; falls back to app downloadClaimFile/{id} for local mode.
* Prefers Nhance file-download API (attachment stream from local/S3).
* Falls back to folder+file URL when file id is missing.
*/
if (! function_exists('storage_claim_file_download_url')) {
function storage_claim_file_download_url(string $diskName, $fileId = null, int $expirationMinutes = 360): string
@ -592,22 +593,31 @@ if (! function_exists('storage_claim_file_download_url')) {
$uploadPath = WRITEPATH . 'uploads/claim_files';
$storage = \Config\Services::getFileStorageService();
// Prefer app file-download URL when claim_files id is known (TPA-safe, attachment).
if ($fileId !== null && $fileId !== '') {
if ($storage->usesS3()) {
if (! $storage->exists($uploadPath, $diskName)) {
log_message('error', 'storage_claim_file_download_url | missing on S3 | ' . $diskName);
return '';
}
} else {
$localPath = $storage->resolveLocalPath($uploadPath, $diskName);
if (! is_file($localPath)) {
return '';
}
}
return base_url('storage/file-download/claim/' . md5((string) (int) $fileId));
}
if ($storage->usesS3()) {
if (! $storage->exists($uploadPath, $diskName)) {
log_message('error', 'storage_claim_file_download_url | missing on S3 | ' . $diskName);
return '';
}
$result = $storage->getPresignedUrl($uploadPath, $diskName, max(1, $expirationMinutes));
if (($result['success'] ?? false) && ! empty($result['url'])) {
return (string) $result['url'];
}
log_message('error', 'storage_claim_file_download_url | presign failed | ' . json_encode([
'disk_name' => $diskName,
'message' => $result['message'] ?? null,
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
return '';
// No file id: folder+file download endpoint
return base_url('storage/file-download') . '?folder=claim_files&file=' . rawurlencode($diskName);
}
$localPath = $storage->resolveLocalPath($uploadPath, $diskName);
@ -615,11 +625,7 @@ if (! function_exists('storage_claim_file_download_url')) {
return '';
}
if ($fileId !== null && $fileId !== '') {
return base_url('downloadClaimFile/' . $fileId);
}
return '';
return base_url('storage/file-download') . '?folder=claim_files&file=' . rawurlencode($diskName);
}
}