FIX_TPA_CLAM_FILE_DOWNLOAD
This commit is contained in:
parent
6c4af860f5
commit
c86019f214
@ -22,6 +22,9 @@ class Acl
|
|||||||
'#^/getSSORedirectUrl#' => ['public' => true],
|
'#^/getSSORedirectUrl#' => ['public' => true],
|
||||||
'#^/getEmployeePolicy#' => ['public' => true],
|
'#^/getEmployeePolicy#' => ['public' => true],
|
||||||
'#^/downloadFileTableFile#' => ['public' => true],
|
'#^/downloadFileTableFile#' => ['public' => true],
|
||||||
|
'#^/storage/file-download#' => ['public' => true],
|
||||||
|
'#^/fileDownload#' => ['public' => true],
|
||||||
|
'#^/downloadClaimFile#' => ['public' => true],
|
||||||
'#^/swagger#' => ['roles' => [ADMIN_ROLE_ID]],
|
'#^/swagger#' => ['roles' => [ADMIN_ROLE_ID]],
|
||||||
'#^/getEmployeeActiveOrInactivePolicy#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],
|
'#^/getEmployeeActiveOrInactivePolicy#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],
|
||||||
'#^/test/chartbrewDashboardDemo#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],
|
'#^/test/chartbrewDashboardDemo#' => ['roles' => [ADMIN_ROLE_ID, HEAD_ROLE_ID]],
|
||||||
|
|||||||
@ -38,6 +38,9 @@ $routes->group('/storage/files', ['filter' => 'authMVC'], function ($routes) {
|
|||||||
$routes->get('list', 'StorageFilesController::listFiles');
|
$routes->get('list', 'StorageFilesController::listFiles');
|
||||||
$routes->get('folders', 'StorageFilesController::folders');
|
$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('/visitOffBoardCheck', 'EmployeeController::visitOffBoardCheck');
|
||||||
$routes->get('/metaDashboardDemo', 'TestingController::metaDashboardDemo');
|
$routes->get('/metaDashboardDemo', 'TestingController::metaDashboardDemo');
|
||||||
$routes->get('/apacheSuperSetDemo', 'TestingController::apacheSuperSetDemo');
|
$routes->get('/apacheSuperSetDemo', 'TestingController::apacheSuperSetDemo');
|
||||||
|
|||||||
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Controllers;
|
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
|
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> */
|
/** @return list<string> */
|
||||||
private function localUploadFolders(): array
|
private function localUploadFolders(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@ -579,7 +579,8 @@ if (! function_exists('storage_claim_file_Upload')) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a TPA-facing download URL for a claim file.
|
* 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')) {
|
if (! function_exists('storage_claim_file_download_url')) {
|
||||||
function storage_claim_file_download_url(string $diskName, $fileId = null, int $expirationMinutes = 360): string
|
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';
|
$uploadPath = WRITEPATH . 'uploads/claim_files';
|
||||||
$storage = \Config\Services::getFileStorageService();
|
$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->usesS3()) {
|
||||||
if (! $storage->exists($uploadPath, $diskName)) {
|
if (! $storage->exists($uploadPath, $diskName)) {
|
||||||
log_message('error', 'storage_claim_file_download_url | missing on S3 | ' . $diskName);
|
log_message('error', 'storage_claim_file_download_url | missing on S3 | ' . $diskName);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $storage->getPresignedUrl($uploadPath, $diskName, max(1, $expirationMinutes));
|
// No file id: folder+file download endpoint
|
||||||
if (($result['success'] ?? false) && ! empty($result['url'])) {
|
return base_url('storage/file-download') . '?folder=claim_files&file=' . rawurlencode($diskName);
|
||||||
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 '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$localPath = $storage->resolveLocalPath($uploadPath, $diskName);
|
$localPath = $storage->resolveLocalPath($uploadPath, $diskName);
|
||||||
@ -615,11 +625,7 @@ if (! function_exists('storage_claim_file_download_url')) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($fileId !== null && $fileId !== '') {
|
return base_url('storage/file-download') . '?folder=claim_files&file=' . rawurlencode($diskName);
|
||||||
return base_url('downloadClaimFile/' . $fileId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user