Skip to content
This repository has been archived by the owner on Nov 2, 2020. It is now read-only.

Commit

Permalink
refactor(Validator): Change Validator Provider
Browse files Browse the repository at this point in the history
Validator Provider change from symfony/validator to siriusphp/validation

BREAKING CHANGE: Change Validator Provider
  • Loading branch information
Rhilip committed Mar 12, 2019
1 parent 4e38460 commit 6d56295
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 814 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,20 @@ So that tracker can record the peer's ip address.
| MAILER_FROM | String | The from address of this message. |
| ~~MAILER_FROM_NICKNAME~~ | String | Not use now. |

## Dynamic Config

> Notice: Most Dynamic config note you can found in our config setting Page

// TODO

## Development Help

Some rule or Docs May help you when you rebuild this project:

| Name | Used As | Repo | Docs |
|:--|:--:|:--:|:--:|
| MixPHP | Framework | https://github.com/mix-php/mix-framework/tree/v1 | https://www.kancloud.cn/onanying/mixphp1/379324 ( Chinese Version ) |
| siriusphp/validation | Validator | https://github.com/siriusphp/validation | http://www.sirius.ro/php/sirius/validation/ |
| league/plates | Template system | https://github.com/thephpleague/plates | http://platesphp.com/ |


25 changes: 13 additions & 12 deletions apps/controllers/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ public function actionRegister()
{
if (app()->request->isPost()) {
$user = new UserRegisterForm();
$user->importAttributes(app()->request->post());
$error = $user->validate();
if (count($error) > 0) {
$user->setData(app()->request->post());
$success = $user->validate();
if (!$success) {
return $this->render('errors/action_fail', [
'title' => 'Register Failed',
'msg' => $error->get(0)
'msg' => $user->getError()
]);
} else {
$user->flush(); // Save this user in our database and do clean work~
Expand All @@ -50,12 +50,13 @@ public function actionRegister()
public function actionConfirm()
{
$confirm = new UserConfirmForm();
$confirm->importAttributes(app()->request->get());
$error = $confirm->validate();
if (count($error) > 0) {
$confirm->setData(app()->request->get());
$success = $confirm->validate();
if (!$success) {
// FIXME 'errors/action_fail' should not be touch in AuthController
return $this->render('errors/action_fail', [
'title' => 'Confirm Failed',
'msg' => $error->get(0)
'msg' => $confirm->getError()
]);
} else {
$confirm->flush();
Expand All @@ -75,14 +76,14 @@ public function actionLogin()

if (app()->request->isPost()) {
$login = new UserLoginForm();
$login->importAttributes(app()->request->post());
$error = $login->validate();
$login->setData(app()->request->post());
$success = $login->validate();

if (count($error) > 0) {
if (!$success) {
$login->LoginFail();
return $this->render('auth/login', [
"username" => $login->username,
"error_msg" => $error->get(0),
"error_msg" => $login->getError(),
'left_attempts' => $left_attempts
]);
} else {
Expand Down
9 changes: 4 additions & 5 deletions apps/controllers/TorrentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public function actionUpload()
// TODO Check user upload pos
if (app()->request->isPost()) {
$torrent = new TorrentUploadForm();
$torrent->importAttributes(app()->request->post());
$torrent->importFileAttributes(app()->request->files());
$error = $torrent->validate();
if (count($error) > 0) {
$torrent->setData(app()->request->post());
$torrent->setFileData(app()->request->files());
$success = $torrent->validate();
if (!$success) {
return $this->render('errors/action_fail', ['title' => 'Upload Failed', 'msg' => $torrent->getError()]);
} else {
try {
Expand All @@ -67,7 +67,6 @@ public function actionSearch()
public function actionDetails()
{
$tid = app()->request->get('id');

$torrent = new Torrent($tid);

return $this->render('torrents/details', ['torrent' => $torrent]);
Expand Down
38 changes: 17 additions & 21 deletions apps/models/form/TorrentUploadForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,13 @@

use apps\models\Torrent;

use Rid\Validators\FileTrait;
use Rid\Validators\Validator;

use Rid\Bencode\Bencode;
use Rid\Bencode\ParseErrorException;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class TorrentUploadForm extends Validator
{
use FileTrait;

public $id = 0;

Expand Down Expand Up @@ -49,29 +44,30 @@ class TorrentUploadForm extends Validator


// 规则
public static function rules()
public static function inputRules()
{
return [
'title' => [new Assert\NotBlank(),],
'file' => [new Assert\NotBlank(),], // We use Callback `isValidTorrent` since Assert\File() is broken in this project
'descr' => [new Assert\NotBlank(),],
'uplver' => [new Assert\Choice(['yes', 'no'])]
'title' => 'required',
'file' => [
['required'],
['Upload\Required'],
['Upload\Extension', ['allowed' => 'torrent']],
['Upload\Size', ['size' => app()->config->get("torrent.max_file_size") . 'B']]
],
'descr' => 'required',
'uplver' => [
['InList', ['list' => ['yes', 'no']]]
],
];
}

public static function loadValidatorMetadata(ClassMetadata $metadata)
public static function callbackRules()
{
parent::loadValidatorMetadata($metadata);
$metadata->addConstraint(new Assert\Callback([
'callback' => 'isValidTorrent',
'payload' => ['name' => 'file', 'maxSize' => app()->config->get("torrent.max_file_size"), 'mimeTypes' => 'application/x-bittorrent']
]));
return ['isValidTorrent'];
}

public function isValidTorrent(ExecutionContextInterface $context, $payload)
protected function isValidTorrent()
{
$this->validateFile($context, $payload);

try {
$this->torrent_dict = Bencode::load($this->file->tmpName);
$info = $this->checkTorrentDict($this->torrent_dict, 'info');
Expand Down Expand Up @@ -112,7 +108,7 @@ public function isValidTorrent(ExecutionContextInterface $context, $payload)
}
} catch (ParseErrorException $e) {
// FIXME Fix message of ParseErrorException
$context->buildViolation($e->getMessage())->addViolation();
$this->buildCallbackFailMsg('Bencode', $e->getMessage());
return;
}

Expand Down
21 changes: 7 additions & 14 deletions apps/models/form/UserConfirmForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
use Rid\User\UserInterface;
use Rid\Validators\Validator;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class UserConfirmForm extends Validator
{
Expand All @@ -22,24 +19,20 @@ class UserConfirmForm extends Validator
private $uid;
public $secret;

public static function rules()
public static function inputRules()
{
return [
'secret' => [new Assert\NotBlank()]
'secret' => 'Required',
];
}

public static function loadValidatorMetadata(ClassMetadata $metadata)
public static function callbackRules()
{
parent::loadValidatorMetadata($metadata);
$metadata->addConstraint(new Assert\Callback('validConfirmSecret'));
return ['validConfirmSecret'];
}

public function validConfirmSecret(ExecutionContextInterface $context)
protected function validConfirmSecret()
{
if (is_null($this->secret))
return;

$record = app()->pdo->createCommand(
'SELECT `users_confirm`.`id`,`users_confirm`.`uid`,`users`.`status` FROM `users_confirm`
LEFT JOIN `users` ON `users`.`id` = `users_confirm`.`uid`
Expand All @@ -48,12 +41,12 @@ public function validConfirmSecret(ExecutionContextInterface $context)
])->queryOne();

if ($record == false) { // It means this confirm key is not exist
$context->buildViolation('This confirm key is not exist')->addViolation();
$this->buildCallbackFailMsg('confirm key', 'This confirm key is not exist');
return;
}

if ($record['status'] !== UserInterface::STATUS_PENDING) {
$context->buildViolation('User Already Confirmed')->addViolation();
$this->buildCallbackFailMsg('User', 'User Already Confirmed');
return;
}
$this->uid = $record['uid'];
Expand Down
42 changes: 16 additions & 26 deletions apps/models/form/UserLoginForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
use RobThree\Auth\TwoFactorAuth;
use RobThree\Auth\TwoFactorAuthException;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class UserLoginForm extends Validator
{
Expand Down Expand Up @@ -50,45 +47,37 @@ public function __construct(array $config = [])
$this->cookieName = app()->user->cookieName;
}

public static function rules()
public static function inputRules()
{
return [
'username' => [
new Assert\NotBlank(),
],
'username' => 'required',
'password' => [
new Assert\NotBlank(),
new Assert\Length([
'min' => 6, 'minMessage' => "Password is too Short , should at least {{ limit }} characters",
'max' => 40, 'maxMessage' => 'Password is too Long ( At most {{ limit }} characters )'
]),
new Assert\NotEqualTo(['propertyPath' => 'username', 'message' => 'The password cannot match your username.'])
['required'],
['length', ['min' => 6, 'max' => 40]]
],
];
}

public static function loadValidatorMetadata(ClassMetadata $metadata)
public static function callbackRules()
{
parent::loadValidatorMetadata($metadata);
$metadata->addConstraint(new Assert\Callback('validateCaptcha'));
$metadata->addConstraint(new Assert\Callback('loadUserFromPdo'));
$metadata->addConstraint(new Assert\Callback('isMaxLoginIpReached'));
return ['validateCaptcha', 'loadUserFromPdo', 'isMaxLoginIpReached'];
}

public function loadUserFromPdo(ExecutionContextInterface $context)
protected function loadUserFromPdo()
{
$this->self = app()->pdo->createCommand("SELECT `id`,`username`,`password`,`status`,`opt`,`class` from users WHERE `username` = :uname OR `email` = :email LIMIT 1")->bindParams([
"uname" => $this->username, "email" => $this->username,
])->queryOne();

if (!$this->self) { // User is not exist
$context->buildViolation("This User is not exist in this site.")->addViolation();
/** Notice: We shouldn't tell `This User is not exist in this site.` for user information security. */
$this->buildCallbackFailMsg('User', 'Invalid username/password');
return;
}

// User's password is not correct
if (!password_verify($this->password, $this->self["password"])) {
$context->buildViolation("Invalid username/password")->addViolation();
$this->buildCallbackFailMsg('User', 'Invalid username/password');
return;
}

Expand All @@ -97,27 +86,28 @@ public function loadUserFromPdo(ExecutionContextInterface $context)
try {
$tfa = new TwoFactorAuth(app()->config->get("base.site_name"));
if ($tfa->verifyCode($this->self["opt"], $this->opt) == false) {
$context->buildViolation("2FA Validation failed")->addViolation();
$this->buildCallbackFailMsg('2FA', '2FA Validation failed. Check your device time.');
return;
}
} catch (TwoFactorAuthException $e) {
$context->buildViolation("2FA Validation failed")->addViolation();
$this->buildCallbackFailMsg('2FA', '2FA Validation failed. Tell our support team.');
return;
}
}

// User 's status is banned or pending~
if (in_array($this->self["status"], [UserInterface::STATUS_BANNED, UserInterface::STATUS_PENDING])) {
$context->buildViolation("User account is not confirmed.")->addViolation();
$this->buildCallbackFailMsg('Account', 'User account is not confirmed.');
return;
}
}

public function isMaxLoginIpReached(ExecutionContextInterface $context)
protected function isMaxLoginIpReached()
{
$test_count = app()->redis->hGet('SITE:fail_login_ip_count', app()->request->getClientIp()) ?: 0;
if ($test_count > app()->config->get('security.max_login_attempts')) {
$context->buildViolation("User Max Login Attempts Archived.")->addViolation();
$this->buildCallbackFailMsg('Login Attempts', 'User Max Login Attempts Archived.');
return;
}
}

Expand Down
Loading

0 comments on commit 6d56295

Please sign in to comment.