Skip to content

refactor: validation rules #861

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 30, 2023
20 changes: 16 additions & 4 deletions docs/customization/validation_rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ Shield has the following rules for registration by default:
],
'password' => [
'label' => 'Auth.password',
'rules' => 'required|max_byte[72]|strong_password[]',
'rules' => [
'required',
'max_byte[72]',
'strong_password[]',
],
'errors' => [
'max_byte' => 'Auth.errorPasswordTooLongBytes'
]
Expand Down Expand Up @@ -98,8 +102,13 @@ Similar to the process for validation rules in the **Registration** section, you
//--------------------------------------------------------------------
public $login = [
// 'username' => [
// 'label' => 'Auth.username',
// 'rules' => 'required|max_length[30]|min_length[3]|regex_match[/\A[a-zA-Z0-9\.]+\z/]',
// 'label' => 'Auth.username',
// 'rules' => [
// 'required',
// 'max_length[30]',
// 'min_length[3]',
// 'regex_match[/\A[a-zA-Z0-9\.]+\z/]',
// ],
// ],
'email' => [
'label' => 'Auth.email',
Expand All @@ -111,7 +120,10 @@ public $login = [
],
'password' => [
'label' => 'Auth.password',
'rules' => 'required|max_byte[72]',
'rules' => [
'required',
'max_byte[72]',
],
'errors' => [
'max_byte' => 'Auth.errorPasswordTooLongBytes',
]
Expand Down
6 changes: 3 additions & 3 deletions src/Commands/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use CodeIgniter\Shield\Entities\User as UserEntity;
use CodeIgniter\Shield\Exceptions\UserNotFoundException;
use CodeIgniter\Shield\Models\UserModel;
use CodeIgniter\Shield\Validation\RegistrationValidationRules;
use CodeIgniter\Shield\Validation\ValidationRules;
use Config\Services;

class User extends BaseCommand
Expand Down Expand Up @@ -219,9 +219,9 @@ private function setTables(): void

private function setValidationRules(): void
{
$validationRules = new RegistrationValidationRules();
$validationRules = new ValidationRules();

$rules = $validationRules->get();
$rules = $validationRules->getRegistrationRules();

// Remove `strong_password` because it only supports use cases
// to check the user's own password.
Expand Down
28 changes: 19 additions & 9 deletions src/Config/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,26 +203,36 @@ class Auth extends BaseConfig
* The validation rules for username
* --------------------------------------------------------------------
*
* @var string[]
* Do not use string rules like `required|valid_email`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok,
shouldn't the changes be applied to the documentation?

//     'rules' => 'required|max_length[30]|min_length[3]|regex_match[/\A[a-zA-Z0-9\.]+\z/]',
'rules' => 'required|max_byte[72]',
// and ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

*
* @var array<string, array<int, string>|string>
*/
public array $usernameValidationRules = [
'required',
'max_length[30]',
'min_length[3]',
'regex_match[/\A[a-zA-Z0-9\.]+\z/]',
'label' => 'Auth.username',
'rules' => [
'required',
'max_length[30]',
'min_length[3]',
'regex_match[/\A[a-zA-Z0-9\.]+\z/]',
],
];

/**
* --------------------------------------------------------------------
* The validation rules for email
* --------------------------------------------------------------------
*
* @var string[]
* Do not use string rules like `required|valid_email`.
*
* @var array<string, array<int, string>|string>
*/
public array $emailValidationRules = [
'required',
'max_length[254]',
'valid_email',
'label' => 'Auth.email',
'rules' => [
'required',
'max_length[254]',
'valid_email',
],
];

/**
Expand Down
22 changes: 4 additions & 18 deletions src/Controllers/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
use App\Controllers\BaseController;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\Shield\Authentication\Authenticators\Session;
use CodeIgniter\Shield\Authentication\Passwords;
use CodeIgniter\Shield\Traits\Viewable;
use CodeIgniter\Shield\Validation\ValidationRules;

class LoginController extends BaseController
{
Expand Down Expand Up @@ -82,23 +82,9 @@ public function loginAction(): RedirectResponse
*/
protected function getValidationRules(): array
{
return setting('Validation.login') ?? [
// 'username' => [
// 'label' => 'Auth.username',
// 'rules' => config('Auth')->usernameValidationRules,
// ],
'email' => [
'label' => 'Auth.email',
'rules' => config('Auth')->emailValidationRules,
],
'password' => [
'label' => 'Auth.password',
'rules' => 'required|' . Passwords::getMaxLengthRule(),
'errors' => [
'max_byte' => 'Auth.errorPasswordTooLongBytes',
],
],
];
$rules = new ValidationRules();

return $rules->getLoginRules();
}

/**
Expand Down
5 changes: 1 addition & 4 deletions src/Controllers/MagicLinkController.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,7 @@ private function recordLoginAttempt(
protected function getValidationRules(): array
{
return [
'email' => [
'label' => 'Auth.email',
'rules' => config('Auth')->emailValidationRules,
],
'email' => config('Auth')->emailValidationRules,
];
}
}
6 changes: 3 additions & 3 deletions src/Controllers/RegisterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use CodeIgniter\Shield\Exceptions\ValidationException;
use CodeIgniter\Shield\Models\UserModel;
use CodeIgniter\Shield\Traits\Viewable;
use CodeIgniter\Shield\Validation\RegistrationValidationRules;
use CodeIgniter\Shield\Validation\ValidationRules;
use Psr\Log\LoggerInterface;

/**
Expand Down Expand Up @@ -167,8 +167,8 @@ protected function getUserEntity(): User
*/
protected function getValidationRules(): array
{
$rules = new RegistrationValidationRules();
$rules = new ValidationRules();

return $rules->get();
return $rules->getRegistrationRules();
}
}
59 changes: 0 additions & 59 deletions src/Validation/RegistrationValidationRules.php

This file was deleted.

89 changes: 89 additions & 0 deletions src/Validation/ValidationRules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

declare(strict_types=1);

namespace CodeIgniter\Shield\Validation;

use CodeIgniter\Shield\Authentication\Passwords;
use CodeIgniter\Shield\Config\Auth;

class ValidationRules
{
private Auth $config;

/**
* Auth Table names
*/
private array $tables;

public function __construct()
{
/** @var Auth $authConfig */
$authConfig = config('Auth');

$this->config = $authConfig;
$this->tables = $this->config->tables;
}

public function getRegistrationRules(): array
{
helper('setting');

$setting = setting('Validation.registration');
if ($setting !== null) {
return $setting;
}

$usernameRules = $this->config->usernameValidationRules;
$usernameRules['rules'][] = sprintf(
'is_unique[%s.username]',
$this->tables['users']
);

$emailRules = $this->config->emailValidationRules;
$emailRules['rules'][] = sprintf(
'is_unique[%s.secret]',
$this->tables['identities']
);

$passwordRules = $this->getPasswordRules();
$passwordRules['rules'][] = 'strong_password[]';

return [
'username' => $usernameRules,
'email' => $emailRules,
'password' => $passwordRules,
'password_confirm' => $this->getPasswordConfirmRules(),
];
}

public function getLoginRules(): array
{
helper('setting');

return setting('Validation.login') ?? [
// 'username' => $this->config->usernameValidationRules,
'email' => $this->config->emailValidationRules,
'password' => $this->getPasswordRules(),
];
}

public function getPasswordRules(): array
{
return [
'label' => 'Auth.password',
'rules' => ['required', Passwords::getMaxLengthRule()],
'errors' => [
'max_byte' => 'Auth.errorPasswordTooLongBytes',
],
];
}

public function getPasswordConfirmRules(): array
{
return [
'label' => 'Auth.passwordConfirm',
'rules' => 'required|matches[password]',
];
}
}