@@ -11,6 +11,7 @@ use App\Models\LandAssistanceCase;
|
||||
use App\Services\CountryCatalogue;
|
||||
use App\Services\InterestSubmission;
|
||||
use App\Services\InvestmentGeography;
|
||||
use App\Services\VerifiedDocumentBinary;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -257,7 +258,9 @@ class LandAssistanceController extends Controller
|
||||
'media_type' => (string) $file->getMimeType(),
|
||||
'storage_key' => $stored,
|
||||
'sha256' => hash_file('sha256', Storage::disk('local')->path($stored)),
|
||||
// No antivirus engine is configured in this project; fail closed until an operator scans it.
|
||||
'size_bytes' => $file->getSize(),
|
||||
'uploaded_by' => $request->user()->id,
|
||||
// The configured scanner releases only the exact original hash after a clean result.
|
||||
'status' => 'quarantined',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
@@ -282,22 +285,20 @@ class LandAssistanceController extends Controller
|
||||
: back()->with('status', 'Documento privado anexado; a revisão ainda está pendente.');
|
||||
}
|
||||
|
||||
public function download(Request $request, string $id, string $attachment): BinaryFileResponse
|
||||
public function download(Request $request, string $id, string $attachment): \Illuminate\Http\Response|BinaryFileResponse
|
||||
{
|
||||
$this->owned($request, $id);
|
||||
$case = $this->owned($request, $id);
|
||||
$document = DB::table('land_assistance_documents as link')->join('documents as document', 'document.id', '=', 'link.document_id')
|
||||
->where('link.case_id', $id)->where('link.id', $attachment)->where('document.status', 'active')->whereNull('document.deleted_at')
|
||||
->where('document.malware_scan_status', 'clean')->whereColumn('document.malware_scanned_sha256', 'document.sha256')
|
||||
->first(['document.file_name', 'document.storage_key', 'document.sha256', 'document.malware_scanned_sha256']);
|
||||
->first(['document.*']);
|
||||
abort_if($document === null, 404);
|
||||
$root = realpath(Storage::disk('local')->path(''));
|
||||
$path = realpath(Storage::disk('local')->path($document->storage_key));
|
||||
abort_unless($root && $path && str_starts_with($path, $root.DIRECTORY_SEPARATOR) && is_file($path), 404);
|
||||
$checksum = hash_file('sha256', $path);
|
||||
abort_unless(is_string($checksum) && hash_equals($document->sha256, $checksum)
|
||||
&& hash_equals($document->sha256, (string) $document->malware_scanned_sha256), 404);
|
||||
$response = app(VerifiedDocumentBinary::class)->respond($document);
|
||||
DB::table('audit_events')->insert(['source_system' => 'land-assistance', 'entity_type' => 'documents', 'entity_id' => $document->id,
|
||||
'actor_user_id' => $request->user()->id, 'action' => 'document_downloaded', 'data_classification' => 'restricted',
|
||||
'after_data' => json_encode(['case_id' => $case->id, 'attachment_id' => $attachment], JSON_THROW_ON_ERROR)]);
|
||||
|
||||
return response()->download($path, basename($document->file_name), ['Cache-Control' => 'private, no-store', 'X-Content-Type-Options' => 'nosniff']);
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function print(Request $request, string $id): Response
|
||||
|
||||
Reference in New Issue
Block a user