From 5ebe2b7eeb0efc4eb9f58748450608dec8ffb9c6 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 20 Mar 2024 09:22:31 +0900 Subject: [PATCH 1/2] refactor: improve Validation error message for placeholder --- system/Validation/Validation.php | 4 ++- .../StrictRules/DatabaseRelatedRulesTest.php | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/system/Validation/Validation.php b/system/Validation/Validation.php index af7cae093bb9..491bccf0599e 100644 --- a/system/Validation/Validation.php +++ b/system/Validation/Validation.php @@ -790,7 +790,9 @@ protected function fillPlaceholders(array $rules, array $data): array // Check if the validation rule for the placeholder exists if ($placeholderRules === null) { throw new LogicException( - 'No validation rules for the placeholder: ' . $field + 'No validation rules for the placeholder: "' . $field + . '". You must set the validation rules for the field.' + . ' See .' ); } diff --git a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php index 5083bec69fe8..7cf1e8f78deb 100644 --- a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php +++ b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php @@ -17,6 +17,7 @@ use Config\Database; use Config\Services; use InvalidArgumentException; +use LogicException; use Tests\Support\Validation\TestRules; /** @@ -139,6 +140,34 @@ public function testIsUniqueWithIgnoreValuePlaceholder(): void $this->assertTrue($this->validation->run($data)); } + public function testIsUniqueWithPlaceholderAndNoValidationRulesForIt(): void + { + $this->expectException(LogicException::class); + $this->expectExceptionMessage('No validation rules for the placeholder: "id". You must set the validation rules for the field.'); + + $this->hasInDatabase('user', [ + 'name' => 'Derek', + 'email' => 'derek@world.co.uk', + 'country' => 'GB', + ]); + + $row = Database::connect() + ->table('user') + ->limit(1) + ->get() + ->getRow(); + + $data = [ + 'id' => $row->id, + 'email' => 'derek@world.co.uk', + ]; + + $this->validation->setRules([ + 'email' => 'is_unique[user.email,id,{id}]', + ]); + $this->validation->run($data); + } + public function testIsUniqueByManualRun(): void { Database::connect() From 56990e6bf5c28b0d69fddd11a64dad928f20ab77 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 20 Mar 2024 09:23:09 +0900 Subject: [PATCH 2/2] docs: improve note for Validation placeholder --- user_guide_src/source/libraries/validation.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/libraries/validation.rst b/user_guide_src/source/libraries/validation.rst index c7c8449562a5..f99f5879256f 100644 --- a/user_guide_src/source/libraries/validation.rst +++ b/user_guide_src/source/libraries/validation.rst @@ -517,15 +517,18 @@ Validation Placeholders ======================= The Validation class provides a simple method to replace parts of your rules based on data that's being passed into it. This -sounds fairly obscure but can be especially handy with the ``is_unique`` validation rule. Placeholders are simply +sounds fairly obscure but can be especially handy with the ``is_unique`` validation rule. + +Placeholders are simply the name of the field (or array key) that was passed in as ``$data`` surrounded by curly brackets. It will be replaced by the **value** of the matched incoming field. An example should clarify this: .. literalinclude:: validation/020.php :lines: 2- -.. note:: Since v4.3.5, you must set the validation rules for the placeholder - field (the ``id`` field in the sample code above) for security. +.. warning:: Since v4.3.5, you must set the validation rules for the placeholder + field (the ``id`` field in the sample code above) for security reasons. Because + attackers can send any data to your application. In this set of rules, it states that the email address should be unique in the database, except for the row that has an id matching the placeholder's value. Assuming that the form POST data had the following: