validate([ 'document_type' => ['required', Rule::in(['license', 'tax', 'conflict', 'other'])], 'file' => ['required', 'file', 'mimes:pdf,jpg,jpeg,png', 'extensions:pdf,jpg,jpeg,png', 'min:1', 'max:2048'], ]); $file = $request->file('file'); abort_unless($file instanceof UploadedFile, 422); $path = $file->store($supplier->tenant_id.'/'.$supplier->id, 'supplier_documents'); abort_if($path === false, 500); try { DB::transaction(function () use ($request, $supplier, $workflow, $data, $file, $path) { $supplier = Supplier::query()->lockForUpdate()->findOrFail($supplier->id); $before = $supplier->toArray(); $name = Str::substr(Str::replaceMatches('/[^\pL\pN ._()-]/u', '_', basename(str_replace('\\', '/', $file->getClientOriginalName()))), 0, 180); $document = $supplier->documents()->create([ 'tenant_id' => $supplier->tenant_id, 'uploaded_by' => $request->user()->id, 'document_type' => $data['document_type'], 'original_name' => $name, 'path' => $path, 'mime_type' => $file->getMimeType(), 'size' => $file->getSize(), 'sha256' => hash_file('sha256', $file->getPathname()), ]); $supplier->update(['status' => 'pending', 'reviewed_by' => null, 'review_comment' => null, 'last_changed_by' => $request->user()->id, 'version' => $supplier->version + 1]); $workflow->audit($request->user(), 'supplier.document_uploaded', null, $before, ['supplier' => $supplier->toArray(), 'document' => $document->toArray()]); }); } catch (Throwable $exception) { Storage::disk('supplier_documents')->delete($path); throw $exception; } return back(); } public function download(Request $request, Supplier $supplier, SupplierDocument $document, RequisitionWorkflow $workflow): StreamedResponse { Gate::authorize('viewDocuments', $supplier); abort_unless($document->supplier_id === $supplier->id, 404); $disk = Storage::disk('supplier_documents'); abort_unless($disk->exists($document->path), 404); $workflow->audit($request->user(), 'supplier.document_downloaded', null, null, ['supplier_id' => $supplier->id, 'document_id' => $document->id, 'name' => $document->original_name]); return $disk->download($document->path, $document->original_name, [ 'Content-Type' => 'application/octet-stream', 'X-Content-Type-Options' => 'nosniff', 'Cache-Control' => 'private, no-store', 'Content-Security-Policy' => "default-src 'none'; sandbox", ]); } }