From c5af9eb12876ff5e7f8531f288c4f84095434c9a Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Tue, 22 Sep 2026 16:13:47 +0100 Subject: [PATCH] M3 Integration fixes pass 27 --- .../StoreDocumentationDocumentRequest.php | 29 ++++++++++++++++--- .../UpdateDocumentationDocumentRequest.php | 29 ++++++++++++++++--- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Modules/Documentation/Http/Requests/StoreDocumentationDocumentRequest.php b/Modules/Documentation/Http/Requests/StoreDocumentationDocumentRequest.php index c4d811c3..2566659f 100755 --- a/Modules/Documentation/Http/Requests/StoreDocumentationDocumentRequest.php +++ b/Modules/Documentation/Http/Requests/StoreDocumentationDocumentRequest.php @@ -3,11 +3,14 @@ namespace Modules\Documentation\Http\Requests; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Http\UploadedFile; use Illuminate\Validation\Rule; use Modules\Documentation\Models\DocumentationDocument; class StoreDocumentationDocumentRequest extends FormRequest { + private const MAX_UPLOAD_BYTES = 1_048_576; + /** * Determine whether the user is authorized to make this request. */ @@ -23,8 +26,6 @@ class StoreDocumentationDocumentRequest extends FormRequest */ public function rules(): array { - $maxUploadKb = 1024; - return [ 'documentation_category_id' => ['nullable', 'integer', 'exists:documentation_categories,id'], 'title' => ['required', 'string', 'max:220'], @@ -35,9 +36,29 @@ class StoreDocumentationDocumentRequest extends FormRequest 'is_featured' => ['nullable', 'boolean'], 'version' => ['required', 'string', 'max:50'], 'reference' => ['nullable', 'string', 'max:100'], - 'attachment' => ['nullable', 'file', 'max:' . $maxUploadKb, 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], + 'attachment' => ['nullable', 'file', $this->uploadSizeRule(), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], 'attachments' => ['nullable', 'array'], - 'attachments.*' => ['file', 'max:' . $maxUploadKb, 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], + 'attachments.*' => ['file', $this->uploadSizeRule(), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], ]; } + + /** + * Enforce the upload ceiling in bytes instead of relying on Laravel's + * file `max` rule, keeping the security boundary explicit. + * + * @return \Closure(string, mixed, \Closure(string): void): void + */ + private function uploadSizeRule(): \Closure + { + return static function (string $attribute, mixed $value, \Closure $fail): void { + if (! $value instanceof UploadedFile || ! $value->isValid()) { + return; + } + + $size = $value->getSize(); + if ($size === false || $size > self::MAX_UPLOAD_BYTES) { + $fail(sprintf('The %s must not be larger than 1 MB.', $attribute)); + } + }; + } } diff --git a/Modules/Documentation/Http/Requests/UpdateDocumentationDocumentRequest.php b/Modules/Documentation/Http/Requests/UpdateDocumentationDocumentRequest.php index d1b9bdd6..a88b0f8c 100755 --- a/Modules/Documentation/Http/Requests/UpdateDocumentationDocumentRequest.php +++ b/Modules/Documentation/Http/Requests/UpdateDocumentationDocumentRequest.php @@ -3,11 +3,14 @@ namespace Modules\Documentation\Http\Requests; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Http\UploadedFile; use Illuminate\Validation\Rule; use Modules\Documentation\Models\DocumentationDocument; class UpdateDocumentationDocumentRequest extends FormRequest { + private const MAX_UPLOAD_BYTES = 1_048_576; + /** * Determine whether the user is authorized to make this request. */ @@ -23,8 +26,6 @@ class UpdateDocumentationDocumentRequest extends FormRequest */ public function rules(): array { - $maxUploadKb = 1024; - /** @var DocumentationDocument|null $document */ $document = $this->route('document'); @@ -38,10 +39,30 @@ class UpdateDocumentationDocumentRequest extends FormRequest 'is_featured' => ['nullable', 'boolean'], 'version' => ['required', 'string', 'max:50'], 'reference' => ['nullable', 'string', 'max:100'], - 'attachment' => ['nullable', 'file', 'max:' . $maxUploadKb, 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], + 'attachment' => ['nullable', 'file', $this->uploadSizeRule(), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], 'attachments' => ['nullable', 'array'], - 'attachments.*' => ['file', 'max:' . $maxUploadKb, 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], + 'attachments.*' => ['file', $this->uploadSizeRule(), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))], 'remove_attachment' => ['nullable', 'boolean'], ]; } + + /** + * Enforce the upload ceiling in bytes instead of relying on Laravel's + * file `max` rule, keeping the security boundary explicit. + * + * @return \Closure(string, mixed, \Closure(string): void): void + */ + private function uploadSizeRule(): \Closure + { + return static function (string $attribute, mixed $value, \Closure $fail): void { + if (! $value instanceof UploadedFile || ! $value->isValid()) { + return; + } + + $size = $value->getSize(); + if ($size === false || $size > self::MAX_UPLOAD_BYTES) { + $fail(sprintf('The %s must not be larger than 1 MB.', $attribute)); + } + }; + } }