Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Bug: Cannot assign bool to property CodeIgniter\Shield\Result::$reason #851

Closed
mshannaq opened this issue Sep 23, 2023 · 5 comments · Fixed by #854
Closed

Bug: Cannot assign bool to property CodeIgniter\Shield\Result::$reason #851

mshannaq opened this issue Sep 23, 2023 · 5 comments · Fixed by #854
Labels
bug Something isn't working

Comments

@mshannaq
Copy link
Contributor

mshannaq commented Sep 23, 2023

PHP Version

8.2

CodeIgniter4 Version

4.4.1

Shield Version

dev-develop

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

mysql

Did you customize Shield?

No

What happened?

IF using another language rather that english for example 'ar' language and try to register account with not secuered password for example testpassword

I got an error which is

Cannot assign bool to property CodeIgniter\Shield\Result::$reason of type ?string [search →](https://www.duckduckgo.com/?q=TypeError+Cannot+assign+bool+to+property+CodeIgniter%5CShield%5CResult%3A%3A%24reason+of+type+%3Fstring)

instead if showing the error The password testpassword has been exposed due to a data breach and has been seen 1,109 times in databases of compromised passwords. if the ci language is english.

trace:

VENDORPATH/codeigniter4/shield/src/Result.php at line 36

* @psalm-param array{success: bool, reason?: string|null, extraInfo?: string|User} $details
30      */
31     public function __construct(array $details)
32     {
33         foreach ($details as $key => $value) {
34             assert(property_exists($this, $key), 'Property "' . $key . '" does not exist.');
35 
36             $this->{$key} = $value;
37         }
38     }
39 
40     /**
41      * Was the result a success?
42      */
43     public function isOK(): bool

Backtrack:

  1. VENDORPATH/codeigniter4/shield/src/Authentication/Passwords/PwnedValidator.php : 73 — CodeIgniter\Shield\Result->__construct ()
     $hits   = $endPos !== false ? (int) substr($range, $startPos, $endPos - $startPos) : (int) substr($range, $startPos);
67 
68         $wording = $hits > 1 ? 'databases' : 'a database';
69 
70         return new Result([
71             'success'   => false,
72             'reason'    => lang('Auth.errorPasswordPwned', [$password, $hits, $wording]),
73             'extraInfo' => lang('Auth.suggestPasswordPwned', [$password]),
74         ]);
75     }
76 }
77
  1. VENDORPATH/codeigniter4/shield/src/Authentication/Passwords.php : 132 — CodeIgniter\Shield\Authentication\Passwords\PwnedValidator->check ()
125             ]);
126         }
127 
128         foreach ($this->config->passwordValidators as $className) {
129             /** @var ValidatorInterface $class */
130             $class = new $className($this->config);
131 
132             $result = $class->check($password, $user);
133             if (! $result->isOk()) {
134                 return $result;
135             }
136         }
137 
138         return new Result([
139             'success' => true,


  1. VENDORPATH/codeigniter4/shield/src/Authentication/Passwords/ValidationRules.php : 46 — CodeIgniter\Shield\Authentication\Passwords->check ()
39         if (function_exists('auth') && auth()->user()) {
40             $user = auth()->user();
41         } else {
42             /** @phpstan-ignore-next-line */
43             $user = empty($data) ? $this->buildUserFromRequest() : $this->buildUserFromData($data);
44         }
45 
46         $result = $checker->check($value, $user);
47 
48         if (! $result->isOk()) {
49             if (empty($data)) {
50                 $error1 = $result->reason();
51             } else {
52                 $error2 = $result->reason();
53             }
  1. SYSTEMPATH/Validation/Validation.php : 309 — CodeIgniter\Shield\Authentication\Passwords\ValidationRules->strong_password ()
302                     if (! method_exists($set, $rule)) {
303                         continue;
304                     }
305 
306                     $found  = true;
307                     $passed = $param === false
308                         ? $set->{$rule}($value, $error)
309                         : $set->{$rule}($value, $param, $data, $error, $field);
310 
311                     break;
312                 }
313 
314                 // If the rule wasn't found anywhere, we
315                 // should throw an exception so the developer can find it.
316                 if (! $found) {
  1. SYSTEMPATH/Validation/Validation.php : 195 — CodeIgniter\Validation\Validation->processRules ()
188             if (strpos($field, '*') !== false) {
189                 // Process multiple fields
190                 foreach ($values as $dotField => $value) {
191                     $this->processRules($dotField, $setup['label'] ?? $field, $value, $rules, $data, $field);
192                 }
193             } else {
194                 // Process single field
195                 $this->processRules($field, $setup['label'] ?? $field, $values, $rules, $data);
196             }
197         }
198 
199         if ($this->getErrors() === []) {
200             // Store data that was actually validated.
201             $this->validated = DotArrayFilter::run(
202                 array_keys($this->rules),
  1. SYSTEMPATH/Controller.php : 165 — CodeIgniter\Validation\Validation->run ()
158      * @param array        $messages An array of custom error messages
159      * @param string|null  $dbGroup  The database group to use
160      */
161     protected function validateData(array $data, $rules, array $messages = [], ?string $dbGroup = null): bool
162     {
163         $this->setValidator($rules, $messages);
164 
165         return $this->validator->run($data, null, $dbGroup);
166     }
167 
168     /**
169      * @param array|string $rules
170      */
171     private function setValidator($rules, array $messages): void
172     {
  1. VENDORPATH/codeigniter4/shield/src/Controllers/RegisterController.php : 103 — CodeIgniter\Controller->validateData ()
96 
 97         $users = $this->getUserProvider();
 98 
 99         // Validate here first, since some things,
100         // like the password, can only be validated properly here.
101         $rules = $this->getValidationRules();
102 
103         if (! $this->validateData($this->request->getPost(), $rules, [], config('Auth')->DBGroup)) {
104             return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
105         }
106 
107         // Save the user
108         $allowedPostFields = array_keys($rules);
109         $user              = $this->getUserEntity();
110         $user->fill($this->request->getPost($allowedPostFields));
  1. SYSTEMPATH/CodeIgniter.php : 919 — CodeIgniter\Shield\Controllers\RegisterController->registerAction ()
912     protected function runController($class)
913     {
914         // This is a Web request or PHP CLI request
915         $params = $this->router->params();
916 
917         $output = method_exists($class, '_remap')
918             ? $class->_remap($this->method, ...$params)
919             : $class->{$this->method}(...$params);
920 
921         $this->benchmark->stop('controller');
922 
923         return $output;
924     }
925 
926     /**
  1. SYSTEMPATH/CodeIgniter.php : 494 — CodeIgniter\CodeIgniter->runController ()
487             if (! method_exists($controller, '_remap') && ! is_callable([$controller, $this->method], false)) {
488                 throw PageNotFoundException::forMethodNotFound($this->method);
489             }
490 
491             // Is there a "post_controller_constructor" event?
492             Events::trigger('post_controller_constructor');
493 
494             $returned = $this->runController($controller);
495         } else {
496             $this->benchmark->stop('controller_constructor');
497             $this->benchmark->stop('controller');
498         }
499 
500         // If $returned is a string, then the controller output something,
501         // probably a view, instead of echoing it directly. Send it along
  1. SYSTEMPATH/CodeIgniter.php : 353 — CodeIgniter\CodeIgniter->handleRequest ()
346 
347         $this->getRequestObject();
348         $this->getResponseObject();
349 
350         $this->spoofRequestMethod();
351 
352         try {
353             $this->response = $this->handleRequest($routes, config(Cache::class), $returnResponse);
354         } catch (ResponsableInterface|DeprecatedRedirectException $e) {
355             $this->outputBufferingEnd();
356             if ($e instanceof DeprecatedRedirectException) {
357                 $e = new RedirectException($e->getMessage(), $e->getCode(), $e);
358             }
359 
360             $this->response = $e->getResponse();
  1. FCPATH/index.php : 79 — CodeIgniter\CodeIgniter->run ()
72  *---------------------------------------------------------------
73  * LAUNCH THE APPLICATION
74  *---------------------------------------------------------------
75  * Now that everything is set up, it's time to actually fire
76  * up the engines and make this app do its thang.
77  */
78 
79 $app->run();
80 
81 // Save Config Cache
82 // $factoriesCache->save('config');
83 // ^^^ Uncomment this line if you want to use Config Caching.
84 
85 // Exits the application, setting the exit code for CLI-based applications
86 // that might be watching.

Steps to Reproduce

change ci langaue to any other language rather than english - for example arabic

try to register a new user with easy password eg testpassword

Expected Output

the correctt is return ti register form with error The password testpassword has been exposed due to a data breach and has been seen 1,109 times in databases of compromised passwords.

Anything else?

No response

@mshannaq mshannaq added the bug Something isn't working label Sep 23, 2023
@mshannaq
Copy link
Contributor Author

That was happend to me in normal shiled when I try to register a new account while Iam on arabic language.

and also happened to me when I try ti check the validation of password strength when trying to change the user password using the following code in Controller:

namespace App\Controllers
use CodeIgniter\Shield\Authentication\Passwords;
use Config\Services;
//....
//....
//....
class Account extends BaseController
{
    public function changepwdAction()
        {
            /////.........
            $newPassword        = $this->request->getPost('newPassword');
            
           $data_to_be_validated = [
            'newPassword' => $newPassword,
            ];

           $rules = [
            'newPassword' => 'required|' . Passwords::getMaxLengthRule() . '|strong_password[]',
           ];
 
          $this->validation->setRules($rules);

          if (! $this->validation->run($data_to_be_validated) ){
              //error password
              dd(        $errors = $this->validation->getErrors());
           }


    }

}

@kenjis
Copy link
Member

kenjis commented Sep 24, 2023

I tried with ja. But I cannot reproduce the error.
Screenshot 2023-09-24 9 56 36

diff --git a/app/Config/App.php b/app/Config/App.php
index 186bfa8..ad8651e 100644
--- a/app/Config/App.php
+++ b/app/Config/App.php
@@ -70,7 +70,7 @@ class App extends BaseConfig
      * strings (like currency markers, numbers, etc), that your program
      * should run under for this request.
      */
-    public string $defaultLocale = 'en';
+    public string $defaultLocale = 'ja';
 
     /**
      * --------------------------------------------------------------------------
@@ -97,7 +97,7 @@ class App extends BaseConfig
      *
      * @var string[]
      */
-    public array $supportedLocales = ['en'];
+    public array $supportedLocales = ['en', 'ja'];
 
     /**
      * --------------------------------------------------------------------------
diff --git a/app/Config/Auth.php b/app/Config/Auth.php
index efb55f7..7ba22e4 100644
--- a/app/Config/Auth.php
+++ b/app/Config/Auth.php
@@ -262,7 +262,7 @@ class Auth extends ShieldAuth
         CompositionValidator::class,
         NothingPersonalValidator::class,
         DictionaryValidator::class,
-        // PwnedValidator::class,
+        PwnedValidator::class,
     ];
 
     /**

@kenjis
Copy link
Member

kenjis commented Sep 24, 2023

@mshannaq I was able to reproduce with ar.
lang('Auth.errorPasswordPwned', [$password, $hits, $wording]) returns false.

@kenjis
Copy link
Member

kenjis commented Sep 24, 2023

The translation string does not seem to be correct. At least, PHP's MessageFormatter::formatMessage() cannot process.

'errorPasswordPwned' => 'تم الكشف عن كلمة المرور {0} بسبب اختراق البيانات وشوهدت {1 ، عدد} مرة في {2} في كلمات المرور المخترقة.',

@kenjis kenjis changed the title Bug: Cannot assign bool to property Bug: Cannot assign bool to property CodeIgniter\Shield\Result::$reason Sep 24, 2023
@mshannaq
Copy link
Contributor Author

mshannaq commented Sep 24, 2023

I fiexed it in arabic language by

- 'errorPasswordLength'       => 'يجب أن تتكون كلمات المرور من {0 ، number} من الأحرف على الأقل.',
+ 'errorPasswordLength'       => 'يجب أن تتكون كلمات المرور من {0} من الأحرف على الأقل.',

by removng {0 ، number} and keep it {0}

also in

-     'errorPasswordPwned'        => 'تم الكشف عن كلمة المرور {0} بسبب اختراق البيانات وشوهدت {1 ، عدد} مرة في {2} في كلمات المرور المخترقة.',

+ 'errorPasswordPwned'        => 'تم الكشف عن كلمة المرور {0} بسبب اختراق البيانات وشوهدت {1} مرة في {2} في كلمات المرور المخترقة.'

It is not correct as number is variable , I will change the translating text to use number not the translate of number
e.g. {1, number} not {1, عدد}

@mshannaq mshannaq mentioned this issue Sep 24, 2023
5 tasks
datamweb added a commit that referenced this issue Sep 24, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants