Replaced validation system

This commit is contained in:
Sergio Brighenti 2020-04-04 19:29:00 +02:00
parent f215dc70e8
commit 5606224339
11 changed files with 249 additions and 293 deletions

View file

@ -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;
}
}

View file

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

View file

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

View file

@ -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()) { if ($validator->fails()) {
return redirect($response, route('register.show')); return redirect($response, route('register.show'));

View file

@ -6,7 +6,7 @@ use App\Database\DB;
use App\Database\Queries\UserQuery; use App\Database\Queries\UserQuery;
use App\Web\Lang; use App\Web\Lang;
use App\Web\Session; use App\Web\Session;
use App\Web\ValidationChecker; use App\Web\ValidationHelper;
use App\Web\View; use App\Web\View;
use DI\Container; use DI\Container;
use DI\DependencyException; use DI\DependencyException;
@ -71,15 +71,12 @@ abstract class Controller
$this->session->set('current_disk_quota', humanFileSize($current)); $this->session->set('current_disk_quota', humanFileSize($current));
if ($this->getSetting('quota_enabled', 'off') === 'on') { if ($this->getSetting('quota_enabled', 'off') === 'on') {
if ($max < 0) { if ($max < 0) {
$this->session->set('max_disk_quota', '∞'); $this->session->set('max_disk_quota', '∞')->set('percent_disk_quota', null);
$this->session->set('percent_disk_quota', null);
} else { } else {
$this->session->set('max_disk_quota', humanFileSize($max)); $this->session->set('max_disk_quota', humanFileSize($max))->set('percent_disk_quota', round(($current * 100) / $max));
$this->session->set('percent_disk_quota', round(($current * 100) / $max));
} }
} else { } else {
$this->session->set('max_disk_quota', null); $this->session->set('max_disk_quota', null)->set('percent_disk_quota', null);
$this->session->set('percent_disk_quota', null);
} }
} }
@ -143,49 +140,14 @@ abstract class Controller
/** /**
* @param Request $request * @param Request $request
* @return ValidationChecker * @return ValidationHelper
*/ */
public function getUserCreateValidator(Request $request) public function getUserCreateValidator(Request $request)
{ {
return ValidationChecker::make() return make(ValidationHelper::class)
->rules([ ->alertIf(empty(param($request, 'username')), 'username_required')
'email.required' => filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL) !== false, ->alertIf(!filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL), 'email_required')
'username.required' => !empty(param($request, 'username')), ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count != 0, 'email_taken')
'password.required' => !empty(param($request, 'password')), ->alertIf($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count != 0, 'username_taken');
'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;
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -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;
}
}

View file

@ -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;
}
}