Ver Fonte

Replaced validation system

Sergio Brighenti há 5 anos atrás
pai
commit
5606224339

+ 68 - 0
app/Controllers/Auth/AuthController.php

@@ -0,0 +1,68 @@
+<?php
+
+
+namespace App\Controllers\Auth;
+
+use App\Controllers\Controller;
+use App\Web\Session;
+use App\Web\ValidationHelper;
+use Psr\Http\Message\ServerRequestInterface as Request;
+
+
+abstract class AuthController extends Controller
+{
+
+    protected function checkRecaptcha(ValidationHelper $validator, Request $request)
+    {
+        $validator->callIf($this->getSetting('recaptcha_enabled') === 'on', function (Session $session) use (&$request) {
+            $recaptcha = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$this->getSetting('recaptcha_secret_key').'&response='.param($request, 'recaptcha_token')));
+
+            if ($recaptcha->success && $recaptcha->score < 0.5) {
+                $session->alert(lang('recaptcha_failed'), 'danger');
+                return false;
+            }
+            return true;
+        });
+        return $validator;
+    }
+
+
+    /**
+     * @return bool|false|resource
+     */
+    public function ldapConnect()
+    {
+        if (!extension_loaded('ldap')) {
+            $this->logger->error('The LDAP extension is not loaded.');
+            return false;
+        }
+
+        $server = ldap_connect($this->config['ldap']['host'], $this->config['ldap']['port']);
+
+        if ($server) {
+            ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3);
+            ldap_set_option($server, LDAP_OPT_REFERRALS, 0);
+            ldap_set_option($server, LDAP_OPT_NETWORK_TIMEOUT, 10);
+        }
+
+        return $server;
+    }
+
+    /**
+     * @param  string  $username
+     * @return string
+     */
+    protected function getLdapRdn(string $username)
+    {
+        $bindString = 'uid='.addslashes($username);
+        if ($this->config['ldap']['user_domain'] !== null) {
+            $bindString .= ','.$this->config['ldap']['user_domain'];
+        }
+
+        if ($this->config['ldap']['base_domain'] !== null) {
+            $bindString .= ','.$this->config['ldap']['base_domain'];
+        }
+
+        return $bindString;
+    }
+}

+ 17 - 47
app/Controllers/Auth/LoginController.php

@@ -2,13 +2,12 @@
 
 namespace App\Controllers\Auth;
 
-use App\Controllers\Controller;
 use App\Database\Queries\UserQuery;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 
-class LoginController extends Controller
+class LoginController extends AuthController
 {
     /**
      * @param  Response  $response
@@ -41,13 +40,11 @@ class LoginController extends Controller
      */
     public function login(Request $request, Response $response): Response
     {
-        if ($this->getSetting('recaptcha_enabled') === 'on') {
-            $recaptcha = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$this->getSetting('recaptcha_secret_key').'&response='.param($request, 'recaptcha_token')));
+        /** @var ValidationHelper $validator */
+        $validator = make(ValidationHelper::class);
 
-            if ($recaptcha->success && $recaptcha->score < 0.5) {
-                $this->session->alert(lang('recaptcha_failed'), 'danger');
-                return redirect($response, route('login'));
-            }
+        if ($this->checkRecaptcha($validator, $request)->fails()) {
+            return redirect($response, route('login'));
         }
 
         $username = param($request, 'username');
@@ -57,30 +54,21 @@ class LoginController extends Controller
             $user = $this->ldapLogin($request, $username, param($request, 'password'), $user);
         }
 
-        $validator = ValidationChecker::make()
-            ->rules([
-                'login' => $user && password_verify(param($request, 'password'), $user->password),
-                'maintenance' => !isset($this->config['maintenance']) || !$this->config['maintenance'] || $user->is_admin ?? false,
-                'user_active' => $user->active ?? false,
-            ])
-            ->onFail(function ($rule) {
-                $alerts = [
-                    'login' => lang('bad_login'),
-                    'maintenance' => lang('maintenance_in_progress'),
-                    'user_active' => lang('account_disabled'),
-                ];
-
-                $this->session->alert($alerts[$rule], $rule === 'maintenance' ? 'info' : 'danger');
-            });
+        $validator
+            ->alertIf(!$user || !password_verify(param($request, 'password'), $user->password), 'bad_login')
+            ->alertIf(isset($this->config['maintenance']) && $this->config['maintenance'] && !($user->is_admin ?? true), 'maintenance_in_progress', 'info')
+            ->alertIf(!($user->active ?? false), 'account_disabled');
+
         if ($validator->fails()) {
             return redirect($response, route('login'));
         }
 
-        $this->session->set('logged', true);
-        $this->session->set('user_id', $user->id);
-        $this->session->set('username', $user->username);
-        $this->session->set('admin', $user->is_admin);
-        $this->session->set('copy_raw', $user->copy_raw);
+        $this->session->set('logged', true)
+            ->set('user_id', $user->id)
+            ->set('username', $user->username)
+            ->set('admin', $user->is_admin)
+            ->set('copy_raw', $user->copy_raw);
+
         $this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
 
         $this->session->alert(lang('welcome', [$user->username]), 'info');
@@ -159,22 +147,4 @@ class LoginController extends Controller
 
         return $dbUser;
     }
-
-    /**
-     * @param  string  $username
-     * @return string
-     */
-    private function getLdapRdn(string $username)
-    {
-        $bindString = 'uid='.addslashes($username);
-        if ($this->config['ldap']['user_domain'] !== null) {
-            $bindString .= ','.$this->config['ldap']['user_domain'];
-        }
-
-        if ($this->config['ldap']['base_domain'] !== null) {
-            $bindString .= ','.$this->config['ldap']['base_domain'];
-        }
-
-        return $bindString;
-    }
 }

+ 5 - 14
app/Controllers/Auth/PasswordRecoveryController.php

@@ -5,7 +5,7 @@ namespace App\Controllers\Auth;
 
 use App\Controllers\Controller;
 use App\Web\Mail;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 use Slim\Exception\HttpNotFoundException;
@@ -105,19 +105,10 @@ class PasswordRecoveryController extends Controller
             throw new HttpNotFoundException($request);
         }
 
-        $validator = ValidationChecker::make()
-            ->rules([
-                'password.required' => !empty(param($request, 'password')),
-                'password.match' => param($request, 'password') === param($request, 'password_repeat'),
-            ])
-            ->onFail(function ($rule) {
-                $alerts = [
-                    'password.required' => lang('password_required'),
-                    'password.match' => lang('password_match'),
-                ];
-
-                $this->session->alert($alerts[$rule], 'danger');
-            });
+        /** @var ValidationHelper $validator */
+        $validator = make(ValidationHelper::class)
+            ->alertIf(empty(param($request, 'password')), 'password_required')
+            ->alertIf(param($request, 'password') !== param($request, 'password_repeat'), 'password_match');
 
         if ($validator->fails()) {
             return redirect($response, route('recover.password', ['resetToken' => $resetToken]));

+ 1 - 1
app/Controllers/Auth/RegisterController.php

@@ -63,7 +63,7 @@ class RegisterController extends Controller
             }
         }
 
-        $validator = $this->getUserCreateValidator($request);
+        $validator = $this->getUserCreateValidator($request)->alertIf(empty(param($request, 'password')), 'password_required');
 
         if ($validator->fails()) {
             return redirect($response, route('register.show'));

+ 10 - 48
app/Controllers/Controller.php

@@ -6,7 +6,7 @@ use App\Database\DB;
 use App\Database\Queries\UserQuery;
 use App\Web\Lang;
 use App\Web\Session;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use App\Web\View;
 use DI\Container;
 use DI\DependencyException;
@@ -71,15 +71,12 @@ abstract class Controller
         $this->session->set('current_disk_quota', humanFileSize($current));
         if ($this->getSetting('quota_enabled', 'off') === 'on') {
             if ($max < 0) {
-                $this->session->set('max_disk_quota', '∞');
-                $this->session->set('percent_disk_quota', null);
+                $this->session->set('max_disk_quota', '∞')->set('percent_disk_quota', null);
             } else {
-                $this->session->set('max_disk_quota', humanFileSize($max));
-                $this->session->set('percent_disk_quota', round(($current * 100) / $max));
+                $this->session->set('max_disk_quota', humanFileSize($max))->set('percent_disk_quota', round(($current * 100) / $max));
             }
         } else {
-            $this->session->set('max_disk_quota', null);
-            $this->session->set('percent_disk_quota', null);
+            $this->session->set('max_disk_quota', null)->set('percent_disk_quota', null);
         }
     }
 
@@ -143,49 +140,14 @@ abstract class Controller
 
     /**
      * @param  Request  $request
-     * @return ValidationChecker
+     * @return ValidationHelper
      */
     public function getUserCreateValidator(Request $request)
     {
-        return ValidationChecker::make()
-            ->rules([
-                'email.required' => filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL) !== false,
-                'username.required' => !empty(param($request, 'username')),
-                'password.required' => !empty(param($request, 'password')),
-                'email.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count == 0,
-                'username.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count == 0,
-            ])
-            ->onFail(function ($rule) {
-                $alerts = [
-                    'email.required' => lang('email_required'),
-                    'username.required' => lang('username_required'),
-                    'password.required' => lang('password_required'),
-                    'email.unique' => lang('email_taken'),
-                    'username.unique' => lang('username_taken'),
-                ];
-
-                $this->session->alert($alerts[$rule], 'danger');
-            });
-    }
-
-    /**
-     * @return bool|false|resource
-     */
-    public function ldapConnect()
-    {
-        if (!extension_loaded('ldap')) {
-            $this->logger->error('The LDAP extension is not loaded.');
-            return false;
-        }
-
-        $server = ldap_connect($this->config['ldap']['host'], $this->config['ldap']['port']);
-
-        if ($server) {
-            ldap_set_option($server, LDAP_OPT_PROTOCOL_VERSION, 3);
-            ldap_set_option($server, LDAP_OPT_REFERRALS, 0);
-            ldap_set_option($server, LDAP_OPT_NETWORK_TIMEOUT, 10);
-        }
-
-        return $server;
+        return make(ValidationHelper::class)
+            ->alertIf(empty(param($request, 'username')), 'username_required')
+            ->alertIf(!filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL), 'email_required')
+            ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count != 0, 'email_taken')
+            ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count != 0, 'username_taken');
     }
 }

+ 7 - 17
app/Controllers/ProfileController.php

@@ -4,7 +4,7 @@
 namespace App\Controllers;
 
 use App\Database\Queries\UserQuery;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 
@@ -25,7 +25,7 @@ class ProfileController extends Controller
 
         return view()->render($response, 'user/edit.twig', [
             'profile' => true,
-            'user'    => $user,
+            'user' => $user,
         ]);
     }
 
@@ -40,19 +40,10 @@ class ProfileController extends Controller
     {
         $user = make(UserQuery::class)->get($request, $id, true);
 
-        $validator = ValidationChecker::make()
-            ->rules([
-                'email.required' => filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL),
-                'email.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count == 0,
-            ])
-            ->onFail(function ($rule) {
-                $alerts = [
-                    'email.required' => lang('email_required'),
-                    'email.unique' => lang('email_taken'),
-                ];
-
-                $this->session->alert($alerts[$rule], 'danger');
-            });
+        /** @var ValidationHelper $validator */
+        $validator = make(ValidationHelper::class)
+            ->alertIf(!filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL), 'email_required')
+            ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count != 0, 'email_taken');
 
         if ($validator->fails()) {
             return redirect($response, route('profile'));
@@ -75,8 +66,7 @@ class ProfileController extends Controller
             ]);
         }
 
-        $this->session->set('copy_raw', param($request, 'copy_raw') !== null ? 1 : 0);
-        $this->session->alert(lang('profile_updated'), 'success');
+        $this->session->set('copy_raw', param($request, 'copy_raw') !== null ? 1 : 0)->alert(lang('profile_updated'), 'success');
         $this->logger->info('User '.$this->session->get('username')." updated profile of $user->id.");
 
         return redirect($response, route('profile'));

+ 11 - 11
app/Controllers/TagController.php

@@ -4,7 +4,7 @@
 namespace App\Controllers;
 
 use App\Database\Queries\TagQuery;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 use Slim\Exception\HttpBadRequestException;
@@ -12,7 +12,6 @@ use Slim\Exception\HttpNotFoundException;
 
 class TagController extends Controller
 {
-    const PER_MEDIA_LIMIT = 10;
 
     /**
      * @param  Request  $request
@@ -22,7 +21,7 @@ class TagController extends Controller
      */
     public function addTag(Request $request, Response $response): Response
     {
-        $validator = $this->validateTag($request);
+        $validator = $this->validateTag($request)->failIf(empty(param($request, 'tag')));
 
         if ($validator->fails()) {
             throw new HttpBadRequestException($request);
@@ -48,7 +47,7 @@ class TagController extends Controller
      */
     public function removeTag(Request $request, Response $response): Response
     {
-        $validator = $this->validateTag($request)->removeRule('tag.notEmpty');
+        $validator = $this->validateTag($request);
 
         if ($validator->fails()) {
             throw new HttpBadRequestException($request);
@@ -65,14 +64,15 @@ class TagController extends Controller
         return $response;
     }
 
+    /**
+     * @param  Request  $request
+     * @return ValidationHelper
+     */
     protected function validateTag(Request $request)
     {
-        return ValidationChecker::make()
-            ->rules([
-                'tag.notEmpty' => !empty(param($request, 'tag')),
-                'mediaId.notEmpty' => !empty(param($request, 'mediaId')),
-                'media.exists' => $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `id` = ?', param($request, 'mediaId'))->fetch()->count > 0,
-                'sameUserOrAdmin' => $this->session->get('admin', false) || $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', param($request, 'mediaId'))->fetch()->user_id === $this->session->get('user_id'),
-            ]);
+        return make(ValidationHelper::class)
+            ->failIf(empty(param($request, 'mediaId')))
+            ->failIf($this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `id` = ?', param($request, 'mediaId'))->fetch()->count == 0)
+            ->failIf($this->session->get('admin', false) || $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', param($request, 'mediaId'))->fetch()->user_id !== $this->session->get('user_id'));
     }
 }

+ 49 - 59
app/Controllers/UserController.php

@@ -4,7 +4,7 @@ namespace App\Controllers;
 
 use App\Database\Queries\UserQuery;
 use App\Web\Mail;
-use App\Web\ValidationChecker;
+use App\Web\ValidationHelper;
 use League\Flysystem\FileNotFoundException;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
@@ -69,26 +69,26 @@ class UserController extends Controller
      */
     public function store(Request $request, Response $response): Response
     {
-        $validator = $this->getUserCreateValidator($request);
-        $hasPassword = $validator->removeRule('password.required');
+        $maxUserQuota = -1;
+        $validator = $this->getUserCreateValidator($request)
+            ->callIf($this->getSetting('quota_enabled') === 'on', function ($session) use (&$maxUserQuota, &$request) {
+                $maxUserQuota = param($request, 'max_user_quota', humanFileSize($this->getSetting('default_user_quota'), 0, true));
+                if (!preg_match('/([0-9]+[K|M|G|T])|(\-1)/i', $maxUserQuota)) {
+                    $session->alert(lang('invalid_quota', 'danger'));
+                    return false;
+                }
+
+                if ($maxUserQuota !== '-1') {
+                    $maxUserQuota = stringToBytes($maxUserQuota);
+                }
+
+                return true;
+            });
 
         if ($validator->fails()) {
             return redirect($response, route('user.create'));
         }
 
-        $maxUserQuota = -1;
-        if ($this->getSetting('quota_enabled') === 'on') {
-            $maxUserQuotaStr = param($request, 'max_user_quota', humanFileSize($this->getSetting('default_user_quota', -1), 0, true));
-            if (!preg_match('/([0-9]+[K|M|G|T])|(\-1)/i', $maxUserQuotaStr)) {
-                $this->session->alert(lang('invalid_quota', 'danger'));
-                return redirect($response, route('user.create'));
-            }
-
-            if ($maxUserQuotaStr !== '-1') {
-                $maxUserQuota = stringToBytes($maxUserQuotaStr);
-            }
-        }
-
         make(UserQuery::class)->create(
             param($request, 'email'),
             param($request, 'username'),
@@ -102,7 +102,16 @@ class UserController extends Controller
         );
 
         if (param($request, 'send_notification') !== null) {
-            $this->sendCreateNotification($hasPassword, $request);
+            $resetToken = null;
+            if (!empty(param($request, 'password'))) {
+                $resetToken = bin2hex(random_bytes(16));
+
+                $this->database->query('UPDATE `users` SET `reset_token`=? WHERE `id` = ?', [
+                    $resetToken,
+                    $this->database->getPdo()->lastInsertId(),
+                ]);
+            }
+            $this->sendCreateNotification($request, $resetToken);
         }
 
         $this->session->alert(lang('user_created', [param($request, 'username')]), 'success');
@@ -143,44 +152,33 @@ class UserController extends Controller
     public function update(Request $request, Response $response, int $id): Response
     {
         $user = make(UserQuery::class)->get($request, $id);
+        $user->max_disk_quota = -1;
 
-        $validator = ValidationChecker::make()
-            ->rules([
-                'email.required' => filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL),
-                'username.required' => !empty(param($request, 'username')),
-                'email.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count == 0,
-                'username.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ? AND `username` <> ?', [param($request, 'username'), $user->username])->fetch()->count == 0,
-                'demote' => !($user->id === $this->session->get('user_id') && param($request, 'is_admin') === null),
-            ])
-            ->onFail(function ($rule) {
-                $alerts = [
-                    'email.required' => lang('email_required'),
-                    'username.required' => lang('username_required'),
-                    'email.unique' => lang('email_taken'),
-                    'username.unique' => lang('username_taken'),
-                    'demote' => lang('cannot_demote'),
-                ];
-
-                $this->session->alert($alerts[$rule], 'danger');
+        /** @var ValidationHelper $validator */
+        $validator = make(ValidationHelper::class)
+            ->alertIf(!filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL), 'email_required')
+            ->alertIf(empty(param($request, 'username')), 'username_required')
+            ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count != 0, 'email_taken')
+            ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ? AND `username` <> ?', [param($request, 'username'), $user->username])->fetch()->count != 0, 'username_taken')
+            ->alertIf($user->id === $this->session->get('user_id') && param($request, 'is_admin') === null, 'cannot_demote')
+            ->callIf($this->getSetting('quota_enabled') === 'on', function ($session) use (&$user, &$request) {
+                $maxUserQuota = param($request, 'max_user_quota', humanFileSize($this->getSetting('default_user_quota'), 0, true));
+                if (!preg_match('/([0-9]+[K|M|G|T])|(\-1)/i', $maxUserQuota)) {
+                    $session->alert(lang('invalid_quota', 'danger'));
+                    return false;
+                }
+
+                if ($maxUserQuota !== '-1') {
+                    $user->max_disk_quota = stringToBytes($maxUserQuota);
+                }
+
+                return true;
             });
 
         if ($validator->fails()) {
             return redirect($response, route('user.edit', ['id' => $id]));
         }
 
-        $user->max_disk_quota = -1;
-        if ($this->getSetting('quota_enabled') === 'on') {
-            $maxUserQuota = param($request, 'max_user_quota', humanFileSize($this->getSetting('default_user_quota'), 0, true));
-            if (!preg_match('/([0-9]+[K|M|G|T])|(\-1)/i', $maxUserQuota)) {
-                $this->session->alert(lang('invalid_quota', 'danger'));
-                return redirect($response, route('user.create'));
-            }
-
-            if ($maxUserQuota !== '-1') {
-                $user->max_disk_quota = stringToBytes($maxUserQuota);
-            }
-        }
-
         make(UserQuery::class)->update(
             $user->id,
             param($request, 'email'),
@@ -281,13 +279,12 @@ class UserController extends Controller
     }
 
     /**
-     * @param $hasPassword
      * @param $request
-     * @throws \Exception
+     * @param  null  $resetToken
      */
-    private function sendCreateNotification($hasPassword, $request)
+    private function sendCreateNotification($request, $resetToken = null)
     {
-        if ($hasPassword) {
+        if (empty(param($request, 'password'))) {
             $message = lang('mail.new_account_text_with_pw', [
                 param($request, 'username'),
                 $this->config['app_name'],
@@ -297,13 +294,6 @@ class UserController extends Controller
                 route('login.show'),
             ]);
         } else {
-            $resetToken = bin2hex(random_bytes(16));
-
-            $this->database->query('UPDATE `users` SET `reset_token`=? WHERE `id` = ?', [
-                $resetToken,
-                $this->database->getPdo()->lastInsertId(),
-            ]);
-
             $message = lang('mail.new_account_text_with_reset', [
                 param($request, 'username'),
                 $this->config['app_name'],

+ 15 - 10
app/Web/Session.php

@@ -9,8 +9,8 @@ class Session
     /**
      * Session constructor.
      *
-     * @param string $name
-     * @param string $path
+     * @param  string  $name
+     * @param  string  $path
      *
      * @throws Exception
      */
@@ -34,10 +34,10 @@ class Session
             }
 
             $started = @session_start([
-                'name'            => $name,
-                'save_path'       => $path,
+                'name' => $name,
+                'save_path' => $path,
                 'cookie_httponly' => true,
-                'gc_probability'  => 25,
+                'gc_probability' => 25,
                 'cookie_samesite' => 'Lax', // works only for php  >= 7.3
             ]);
 
@@ -68,9 +68,10 @@ class Session
     /**
      * Clear all session stored values.
      */
-    public function clear(): void
+    public function clear(): Session
     {
         $_SESSION = [];
+        return $this;
     }
 
     /**
@@ -99,7 +100,7 @@ class Session
      * Returned a value given a key.
      *
      * @param $key
-     * @param null $default
+     * @param  null  $default
      *
      * @return mixed
      */
@@ -113,21 +114,25 @@ class Session
      *
      * @param $key
      * @param $value
+     * @return Session
      */
-    public function set($key, $value): void
+    public function set($key, $value): Session
     {
         $_SESSION[$key] = $value;
+        return $this;
     }
 
     /**
      * Set a flash alert.
      *
      * @param $message
-     * @param string $type
+     * @param  string  $type
+     * @return Session
      */
-    public function alert($message, string $type = 'info'): void
+    public function alert($message, string $type = 'info'): Session
     {
         $_SESSION['_flash'][] = [$type => $message];
+        return $this;
     }
 
     /**

+ 0 - 88
app/Web/ValidationChecker.php

@@ -1,88 +0,0 @@
-<?php
-
-
-namespace App\Web;
-
-class ValidationChecker
-{
-    protected $rules = [];
-    protected $failClosure;
-    protected $lastRule;
-
-    /**
-     * @return ValidationChecker
-     */
-    public static function make()
-    {
-        return new self();
-    }
-
-    /**
-     * @param  array  $rules
-     * @return $this
-     */
-    public function rules(array $rules)
-    {
-        $this->rules = $rules;
-        return $this;
-    }
-
-    /**
-     * @param  callable  $closure
-     * @return $this
-     */
-    public function onFail(callable $closure)
-    {
-        $this->failClosure = $closure;
-        return $this;
-    }
-
-    /**
-     * @return bool
-     */
-    public function fails()
-    {
-        foreach ($this->rules as $rule => $condition) {
-            if (!$condition) {
-                $this->lastRule = $rule;
-                if (is_callable($this->failClosure)) {
-                    ($this->failClosure)($rule);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @param  string  $key
-     * @return ValidationChecker
-     */
-    public function removeRule(string $key)
-    {
-        $this->rules[$key];
-
-        unset($this->rules[$key]);
-
-        return $this;
-    }
-
-    /**
-     * @param  string  $key
-     * @param $condition
-     * @return ValidationChecker
-     */
-    public function addRule(string $key, $condition)
-    {
-        $this->rules[$key] = $condition;
-        return $this;
-    }
-
-    /**
-     * @return mixed
-     */
-    public function getLastRule()
-    {
-        return $this->lastRule;
-    }
-}

+ 68 - 0
app/Web/ValidationHelper.php

@@ -0,0 +1,68 @@
+<?php
+
+
+namespace App\Web;
+
+
+class ValidationHelper
+{
+    /**
+     * @var Session
+     */
+    protected $session;
+    /**
+     * @var bool
+     */
+    protected $failed;
+
+    /**
+     * Validator constructor.
+     * @param  Session  $session
+     */
+    public function __construct(Session $session)
+    {
+        $this->session = $session;
+
+        $this->failed = false;
+    }
+
+    public function alertIf(bool $condition, string $alert, string $type = 'danger')
+    {
+        if (!$this->failed && $condition) {
+            $this->failed = true;
+            $this->session->alert(lang($alert), $type);
+
+        }
+
+        return $this;
+    }
+
+    public function failIf(bool $condition)
+    {
+        if (!$this->failed && $condition) {
+            $this->failed = true;
+        }
+
+        return $this;
+    }
+
+    public function callIf(bool $condition, callable $closure)
+    {
+        if (!$this->failed && $condition) {
+            do {
+                $result = $closure($this->session);
+                if (is_callable($result)) {
+                    $closure = $result;
+                }
+            } while (!is_bool($result));
+            $this->failed = !$result;
+        }
+
+        return $this;
+    }
+
+    public function fails()
+    {
+        return $this->failed;
+    }
+}