Replaced validation system
This commit is contained in:
parent
f215dc70e8
commit
5606224339
11 changed files with 249 additions and 293 deletions
68
app/Controllers/Auth/AuthController.php
Normal file
68
app/Controllers/Auth/AuthController.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]));
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'));
|
||||||
|
|
|
@ -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'),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'],
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
app/Web/ValidationHelper.php
Normal file
68
app/Web/ValidationHelper.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue