From eeb467d1f0e37fe4e23ac26650260b91bf2c607b Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Tue, 26 Aug 2025 09:34:58 +0200 Subject: [PATCH] fix: :bug: update saving claim file --- .../Controllers/Api/V4/ClaimController.php | 7 +- app/Http/Requests/Api/V4/SendClaimRequest.php | 27 ++++++- tests/CRM/ApiV4/ClaimTest.php | 8 ++- tests/Client/CrmClientClaimTest.php | 71 +++++++++++++++++++ 4 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 tests/Client/CrmClientClaimTest.php diff --git a/app/Http/Controllers/Api/V4/ClaimController.php b/app/Http/Controllers/Api/V4/ClaimController.php index 01945e2..1742216 100644 --- a/app/Http/Controllers/Api/V4/ClaimController.php +++ b/app/Http/Controllers/Api/V4/ClaimController.php @@ -7,6 +7,7 @@ use App\Http\Controllers\Controller; use App\Http\Requests\Api\V4\SendClaimRequest; use App\Models\Claim; use App\Models\Service; +use Illuminate\Support\Arr; class ClaimController extends Controller { @@ -20,7 +21,11 @@ class ClaimController extends Controller */ public function store(SendClaimRequest $request, Service $service): \Illuminate\Http\JsonResponse { - $claimModel = (new Claim())->fill($request->validated()); + $claimModel = (new Claim())->fill(Arr::except($request->validated(), 'file')); + if ($request->hasFile('file')) { + $claimModel->file = $request->file('file')->store('claims/files'); + } + if (!$claimModel->saveOrFail()) { throw new CrmException('Api failed to store claim.'); } diff --git a/app/Http/Requests/Api/V4/SendClaimRequest.php b/app/Http/Requests/Api/V4/SendClaimRequest.php index 08af906..ff9f649 100644 --- a/app/Http/Requests/Api/V4/SendClaimRequest.php +++ b/app/Http/Requests/Api/V4/SendClaimRequest.php @@ -53,7 +53,32 @@ class SendClaimRequest extends BaseApiRequest 'address' => 'sometimes|nullable|string|max:255', 'city' => 'sometimes|nullable|string|between:2,255', 'postcode' => ['sometimes', 'nullable', 'string', "postal_code:{$countryList}"], - 'file' => 'sometimes|nullable|mimes:jpg,jpeg,png,pdf|max:5120', + 'file' => [ + 'sometimes', + 'nullable', + 'string', + // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed + function ($attribute, $value, $fail) { + // Base64 validation. + $decoded = base64_decode($value, true); + if ($decoded === false) { + return $fail('Le fichier doit ĂȘtre un encodage base64 valide.'); + } + + // Check the size (5 MB max = 5 * 1024 * 1024). + if (strlen($decoded) > 5 * 1024 * 1024) { + return $fail('Le fichier est trop volumineux (max 5 Mo).'); + } + + // Check the MIME type. + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_buffer($finfo, $decoded); + $allowed = ['image/jpeg', 'image/png', 'application/pdf']; + if (!in_array($mime, $allowed)) { + return $fail('Le fichier doit ĂȘtre une image JPG/PNG ou un PDF.'); + } + } + ], 'message' => 'required|string|min:3', 'brand_id' => 'required|integer|exists:brands,id', 'subject_id' => 'required|integer|exists:claim_subjects,id', diff --git a/tests/CRM/ApiV4/ClaimTest.php b/tests/CRM/ApiV4/ClaimTest.php index f17e97c..431aee9 100644 --- a/tests/CRM/ApiV4/ClaimTest.php +++ b/tests/CRM/ApiV4/ClaimTest.php @@ -24,6 +24,7 @@ class ClaimTest extends ApiBase { parent::setUp(); + $image = UploadedFile::fake()->image('photo.jpg'); $this->skeleton = [ 'first_name' => 'Jean', 'last_name' => 'Bond', @@ -32,7 +33,7 @@ class ClaimTest extends ApiBase 'address' => '10 rue des totos', 'city' => 'Le Mans', 'postcode' => '72100', - 'file' => UploadedFile::fake()->image('photo.jpg'), + 'file' => base64_encode(file_get_contents($image->getRealPath())), ]; } @@ -132,10 +133,13 @@ class ClaimTest extends ApiBase $subject = ClaimSubject::query()->firstOrNew(); $customer = Customer::query()->firstOrNew(); + // Create fake .gif base64. + $base64Gif = 'R0lGODlhAQABAIAAAAUEBA=='; + $response = $this->callApiWithToken($service, 'post', route('apiV4.claim.store'), \array_merge( Arr::except($this->skeleton, ['address', 'city', 'postcode', 'file']), [ - 'file' => \Illuminate\Http\UploadedFile::fake()->create('x.gif', 100, 'image/gif'), + 'file' => $base64Gif, 'brand_id' => $brand->getKey(), 'subject_id' => $subject->getKey(), 'customer_id' => $customer->getKey(), diff --git a/tests/Client/CrmClientClaimTest.php b/tests/Client/CrmClientClaimTest.php new file mode 100644 index 0000000..d8308e5 --- /dev/null +++ b/tests/Client/CrmClientClaimTest.php @@ -0,0 +1,71 @@ +image('photo.jpg'); + $this->assertTrue(Claim::setClaim( + 'Jean', + 'Bond', + 'claim@hotmail.fr', + 'Ceci est un message.', + 1, + 1, + '10 rue des totos', + 'Le Mans', + '72100', + base64_encode(file_get_contents($image->getRealPath())), + )); + $this->assertTrue(ModelsClaim::query()->where('email', 'claim@hotmail.fr')->exists()); + } + + /** + * Create new claim without optionnal fields. + * + * @return void + */ + public function testCreateClaimWithoutOptionnalFields(): void + { + $this->assertTrue(Claim::setClaim( + 'Jean', + 'Bond', + 'claim@hotmail.fr', + 'Ceci est un message.', + 1, + 1, + )); + $this->assertTrue(ModelsClaim::query()->where('email', 'claim@hotmail.fr')->exists()); + } + + /** + * Create new claim should fail. + * + * @return void + */ + public function testCreateClaimShouldFail(): void + { + $this->expectException(ValidationException::class); + Claim::setClaim( + 'Jean', + 'Bond', + 'claim@hotmail.fr', + 'Ceci est un message.', + 0, + 0, + ); + $this->assertSame(0, ModelsClaim::count()); + } +}