Implemented validation helper
Dependencies resolved through container
This commit is contained in:
parent
623de4b5e0
commit
db483bb53e
18 changed files with 394 additions and 284 deletions
|
@ -18,7 +18,6 @@ class AdminController extends Controller
|
|||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function system(Request $request, Response $response): Response
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Controllers\Auth;
|
|||
|
||||
use App\Controllers\Controller;
|
||||
use App\Web\Mail;
|
||||
use App\Web\ValidationChecker;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
|
@ -53,7 +54,7 @@ class PasswordRecoveryController extends Controller
|
|||
]);
|
||||
|
||||
Mail::make()
|
||||
->from('no-reply@'.str_ireplace('www.', '', parse_url($this->config['base_url'], PHP_URL_HOST)), $this->config['app_name'])
|
||||
->from(platform_mail(), $this->config['app_name'])
|
||||
->to(param($request, 'email'))
|
||||
->subject(lang('mail.recover_password', [$this->config['app_name']]))
|
||||
->message(lang('mail.recover_text', [
|
||||
|
@ -104,15 +105,21 @@ class PasswordRecoveryController extends Controller
|
|||
throw new HttpNotFoundException($request);
|
||||
}
|
||||
|
||||
if (param($request, 'password') === null) {
|
||||
$this->session->alert(lang('password_required'), 'danger');
|
||||
$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'),
|
||||
];
|
||||
|
||||
return redirect($response, route('recover.password', ['resetToken' => $resetToken]));
|
||||
}
|
||||
|
||||
if (param($request, 'password') !== param($request, 'password_repeat')) {
|
||||
$this->session->alert(lang('password_match'), 'danger');
|
||||
$this->session->alert($alerts[$rule], 'danger');
|
||||
});
|
||||
|
||||
if ($validator->fails()){
|
||||
return redirect($response, route('recover.password', ['resetToken' => $resetToken]));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
|
||||
namespace App\Controllers\Auth;
|
||||
|
||||
use App\Controllers\Common\ValidateUser;
|
||||
use App\Controllers\Controller;
|
||||
use App\Exceptions\ValidationException;
|
||||
use App\Database\Queries\UserQuery;
|
||||
use App\Web\Mail;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
@ -13,7 +12,6 @@ use Slim\Exception\HttpNotFoundException;
|
|||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
use ValidateUser;
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
|
@ -54,44 +52,26 @@ class RegisterController extends Controller
|
|||
throw new HttpNotFoundException($request);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->validateUser($request, $response, route('register.show'));
|
||||
} catch (ValidationException $e) {
|
||||
return $e->response();
|
||||
}
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count > 0) {
|
||||
$this->session->alert(lang('email_taken'), 'danger');
|
||||
$validator = $this->getUserCreateValidator($request);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect($response, route('register.show'));
|
||||
}
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count > 0) {
|
||||
$this->session->alert(lang('username_taken'), 'danger');
|
||||
|
||||
return redirect($response, route('register.show'));
|
||||
}
|
||||
|
||||
do {
|
||||
$userCode = humanRandomString(5);
|
||||
} while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `user_code` = ?', $userCode)->fetch()->count > 0);
|
||||
|
||||
$token = $this->generateUserUploadToken();
|
||||
$activateToken = bin2hex(random_bytes(16));
|
||||
|
||||
$this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `activate_token`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
|
||||
make(UserQuery::class)->create(
|
||||
param($request, 'email'),
|
||||
param($request, 'username'),
|
||||
password_hash(param($request, 'password'), PASSWORD_DEFAULT),
|
||||
param($request, 'password'),
|
||||
0,
|
||||
0,
|
||||
$userCode,
|
||||
$token,
|
||||
$activateToken,
|
||||
]);
|
||||
(int) $this->getSetting('default_user_quota', -1),
|
||||
$activateToken
|
||||
);
|
||||
|
||||
Mail::make()
|
||||
->from('no-reply@'.str_ireplace('www.', '', parse_url($this->config['base_url'], PHP_URL_HOST)), $this->config['app_name'])
|
||||
->from(platform_mail(), $this->config['app_name'])
|
||||
->to(param($request, 'email'))
|
||||
->subject(lang('mail.activate_account', [$this->config['app_name']]))
|
||||
->message(lang('mail.activate_text', [
|
||||
|
@ -109,12 +89,11 @@ class RegisterController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param string $activateToken
|
||||
* @return Response
|
||||
*/
|
||||
public function activateUser(Request $request, Response $response, string $activateToken): Response
|
||||
public function activateUser(Response $response, string $activateToken): Response
|
||||
{
|
||||
if ($this->session->get('logged', false)) {
|
||||
return redirect($response, route('home'));
|
||||
|
|
|
@ -2,26 +2,22 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Exception\HttpUnauthorizedException;
|
||||
|
||||
class ClientController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getShareXConfig(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, true);
|
||||
$user = make(UserQuery::class)->get($request, $id, true);
|
||||
|
||||
if ($user->token === null || $user->token === '') {
|
||||
$this->session->alert(lang('no_upload_token'), 'danger');
|
||||
|
@ -48,21 +44,18 @@ class ClientController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
* @return Response
|
||||
* @throws \Twig\Error\LoaderError
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getBashScript(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, true);
|
||||
$user = make(UserQuery::class)->get($request, $id, true);
|
||||
|
||||
if ($user->token === null || $user->token === '') {
|
||||
$this->session->alert(lang('no_upload_token'), 'danger');
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
namespace App\Controllers;
|
||||
|
||||
use App\Database\DB;
|
||||
use App\Database\Queries\UserQuery;
|
||||
use App\Web\Lang;
|
||||
use App\Web\Session;
|
||||
use App\Web\ValidationChecker;
|
||||
use App\Web\View;
|
||||
use DI\Container;
|
||||
use DI\DependencyException;
|
||||
use DI\NotFoundException;
|
||||
use Exception;
|
||||
use League\Flysystem\Filesystem;
|
||||
use Monolog\Logger;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Exception\HttpUnauthorizedException;
|
||||
|
||||
/**
|
||||
* @property Session session
|
||||
|
@ -88,12 +89,10 @@ abstract class Controller
|
|||
* @param $fileSize
|
||||
* @param bool $dec
|
||||
* @return bool
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
*/
|
||||
protected function updateUserQuota(Request $request, $userId, $fileSize, $dec = false)
|
||||
{
|
||||
$user = $this->getUser($request, $userId);
|
||||
$user = make(UserQuery::class)->get($request, $userId);
|
||||
|
||||
if ($dec) {
|
||||
$tot = max($user->current_disk_quota - $fileSize, 0);
|
||||
|
@ -113,34 +112,9 @@ abstract class Controller
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @param bool $authorize
|
||||
*
|
||||
* @return mixed
|
||||
* @throws HttpUnauthorizedException
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
*/
|
||||
protected function getUser(Request $request, $id, $authorize = false)
|
||||
{
|
||||
$user = $this->database->query('SELECT * FROM `users` WHERE `id` = ? LIMIT 1', $id)->fetch();
|
||||
|
||||
if (!$user) {
|
||||
throw new HttpNotFoundException($request);
|
||||
}
|
||||
|
||||
if ($authorize && $user->id !== $this->session->get('user_id') && !$this->session->get('admin', false)) {
|
||||
throw new HttpUnauthorizedException($request);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $userId
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function refreshRememberCookie($userId)
|
||||
{
|
||||
|
@ -167,16 +141,30 @@ abstract class Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @param Request $request
|
||||
* @return ValidationChecker
|
||||
*/
|
||||
protected function generateUserUploadToken(): string
|
||||
public function getUserCreateValidator(Request $request)
|
||||
{
|
||||
do {
|
||||
$token = 'token_'.md5(uniqid('', true));
|
||||
} while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `token` = ?', $token)->fetch()->count > 0);
|
||||
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'),
|
||||
];
|
||||
|
||||
return $token;
|
||||
$this->session->alert($alerts[$rule], 'danger');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,8 +38,6 @@ class DashboardController extends Controller
|
|||
{
|
||||
$page = max(0, --$page);
|
||||
|
||||
$query = new MediaQuery($this->database, $this->session->get('admin', false), $this->storage);
|
||||
|
||||
switch (param($request, 'sort', 'time')) {
|
||||
case 'size':
|
||||
$order = MediaQuery::ORDER_SIZE;
|
||||
|
@ -53,7 +51,9 @@ class DashboardController extends Controller
|
|||
break;
|
||||
}
|
||||
|
||||
$query->orderBy($order, param($request, 'order', 'DESC'))
|
||||
/** @var MediaQuery $query */
|
||||
$query = make(MediaQuery::class, ['isAdmin' => (bool) $this->session->get('admin', false)])
|
||||
->orderBy($order, param($request, 'order', 'DESC'))
|
||||
->withUserId($this->session->get('user_id'))
|
||||
->search(param($request, 'search', null))
|
||||
->run($page);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use League\Flysystem\FileNotFoundException;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
@ -16,13 +17,11 @@ class ExportController extends Controller
|
|||
* @param Response $response
|
||||
* @param int|null $id
|
||||
* @return Response
|
||||
* @throws \Slim\Exception\HttpNotFoundException
|
||||
* @throws \Slim\Exception\HttpUnauthorizedException
|
||||
* @throws \ZipStream\Exception\OverflowException
|
||||
*/
|
||||
public function downloadData(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, true);
|
||||
$user = make(UserQuery::class)->get($request, $id, true);
|
||||
|
||||
$medias = $this->database->query('SELECT `uploads`.`filename`, `uploads`.`storage_path` FROM `uploads` WHERE `user_id` = ?', $user->id);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use Intervention\Image\Constraint;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
@ -202,7 +203,7 @@ class MediaController extends Controller
|
|||
$this->updateUserQuota($request, $media->user_id, $size, true);
|
||||
$this->logger->info('User '.$this->session->get('username').' deleted a media.', [$id]);
|
||||
if ($media->user_id === $this->session->get('user_id')) {
|
||||
$user = $this->getUser($request, $media->user_id, true);
|
||||
$user = make(UserQuery::class)->get($request, $id, true);
|
||||
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -3,28 +3,25 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use App\Web\ValidationChecker;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Exception\HttpUnauthorizedException;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
* @return Response
|
||||
* @throws \Twig\Error\LoaderError
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function profile(Request $request, Response $response): Response
|
||||
{
|
||||
$user = $this->getUser($request, $this->session->get('user_id'), true);
|
||||
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'), true);
|
||||
|
||||
return view()->render($response, 'user/edit.twig', [
|
||||
'profile' => true,
|
||||
|
@ -33,28 +30,31 @@ class ProfileController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function profileEdit(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
if (param($request, 'email') === null) {
|
||||
$this->session->alert(lang('email_required'), 'danger');
|
||||
$user = make(UserQuery::class)->get($request, $id, true);
|
||||
|
||||
return redirect($response, route('profile'));
|
||||
}
|
||||
$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'),
|
||||
];
|
||||
|
||||
$user = $this->getUser($request, $id, true);
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count > 0) {
|
||||
$this->session->alert(lang('email_taken'), 'danger');
|
||||
$this->session->alert($alerts[$rule], 'danger');
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect($response, route('profile'));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
|
@ -13,8 +14,6 @@ class SettingController extends Controller
|
|||
* @param Response $response
|
||||
*
|
||||
* @return Response
|
||||
* @throws \Slim\Exception\HttpNotFoundException
|
||||
* @throws \Slim\Exception\HttpUnauthorizedException
|
||||
*/
|
||||
public function saveSettings(Request $request, Response $response): Response
|
||||
{
|
||||
|
@ -27,7 +26,7 @@ class SettingController extends Controller
|
|||
$this->updateSetting('hide_by_default', param($request, 'hide_by_default', 'off'));
|
||||
$this->updateSetting('quota_enabled', param($request, 'quota_enabled', 'off'));
|
||||
|
||||
$user = $this->getUser($request, $this->session->get('user_id'));
|
||||
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'));
|
||||
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
|
||||
|
||||
$this->updateSetting('default_user_quota', stringToBytes(param($request, 'default_user_quota', '1G')));
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Database\Queries\UserQuery;
|
||||
use App\Exceptions\ValidationException;
|
||||
use Exception;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
|
@ -32,8 +33,6 @@ class UploadController extends Controller
|
|||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @return Response
|
||||
* @throws \Slim\Exception\HttpNotFoundException
|
||||
* @throws \Slim\Exception\HttpUnauthorizedException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function uploadWeb(Request $request, Response $response): Response
|
||||
|
@ -47,7 +46,7 @@ class UploadController extends Controller
|
|||
try {
|
||||
$file = $this->validateFile($request, $response);
|
||||
|
||||
$user = $this->getUser($request, $this->session->get('user_id'));
|
||||
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'));
|
||||
|
||||
$this->validateUser($request, $response, $file, $user);
|
||||
} catch (ValidationException $e) {
|
||||
|
@ -76,8 +75,6 @@ class UploadController extends Controller
|
|||
* @param Response $response
|
||||
*
|
||||
* @return Response
|
||||
* @throws \Slim\Exception\HttpNotFoundException
|
||||
* @throws \Slim\Exception\HttpUnauthorizedException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function uploadEndpoint(Request $request, Response $response): Response
|
||||
|
@ -181,7 +178,6 @@ class UploadController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param UploadedFileInterface $file
|
||||
* @param $user
|
||||
|
|
|
@ -2,16 +2,13 @@
|
|||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Exceptions\ValidationException;
|
||||
use App\Validators\ValidateUser;
|
||||
use App\Database\Queries\UserQuery;
|
||||
use App\Web\ValidationChecker;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Exception\HttpUnauthorizedException;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
use ValidateUser;
|
||||
|
||||
const PER_PAGE = 15;
|
||||
|
||||
|
@ -70,27 +67,15 @@ class UserController extends Controller
|
|||
*/
|
||||
public function store(Request $request, Response $response): Response
|
||||
{
|
||||
try {
|
||||
$this->validateUser($request, $response, route('user.create'));
|
||||
} catch (ValidationException $e) {
|
||||
return $e->response();
|
||||
}
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count > 0) {
|
||||
$this->session->alert(lang('email_taken'), 'danger');
|
||||
|
||||
return redirect($response, route('user.create'));
|
||||
}
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count > 0) {
|
||||
$this->session->alert(lang('username_taken'), 'danger');
|
||||
$validator = $this->getUserCreateValidator($request);
|
||||
|
||||
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'), 0, true));
|
||||
$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'));
|
||||
|
@ -101,22 +86,14 @@ class UserController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
do {
|
||||
$userCode = humanRandomString(5);
|
||||
} while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `user_code` = ?', $userCode)->fetch()->count > 0);
|
||||
|
||||
$token = $this->generateUserUploadToken();
|
||||
|
||||
$this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
|
||||
make(UserQuery::class)->create(
|
||||
param($request, 'email'),
|
||||
param($request, 'username'),
|
||||
password_hash(param($request, 'password'), PASSWORD_DEFAULT),
|
||||
param($request, 'password'),
|
||||
param($request, 'is_admin') !== null ? 1 : 0,
|
||||
param($request, 'is_active') !== null ? 1 : 0,
|
||||
$userCode,
|
||||
$token,
|
||||
$maxUserQuota,
|
||||
]);
|
||||
$maxUserQuota
|
||||
);
|
||||
|
||||
$this->session->alert(lang('user_created', [param($request, 'username')]), 'success');
|
||||
$this->logger->info('User '.$this->session->get('username').' created a new user.', [array_diff_key($request->getParsedBody(), array_flip(['password']))]);
|
||||
|
@ -127,19 +104,16 @@ class UserController extends Controller
|
|||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param $id
|
||||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
* @throws \Twig\Error\LoaderError
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
* @throws HttpUnauthorizedException
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
*/
|
||||
public function edit(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, false);
|
||||
$user = make(UserQuery::class)->get($request, $id);
|
||||
|
||||
return view()->render($response, 'user/edit.twig', [
|
||||
'profile' => false,
|
||||
|
@ -155,35 +129,32 @@ class UserController extends Controller
|
|||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
* @throws HttpUnauthorizedException
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
*/
|
||||
public function update(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
try {
|
||||
$this->validateUser($request, $response, route('user.edit', ['id' => $id]));
|
||||
} catch (ValidationException $e) {
|
||||
return $e->response();
|
||||
}
|
||||
$user = make(UserQuery::class)->get($request, $id);
|
||||
|
||||
$user = $this->getUser($request, $id, false);
|
||||
$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'),
|
||||
];
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count > 0) {
|
||||
$this->session->alert(lang('email_taken'), 'danger');
|
||||
|
||||
return redirect($response, route('user.edit', ['id' => $id]));
|
||||
}
|
||||
|
||||
if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ? AND `username` <> ?', [param($request, 'username'), $user->username])->fetch()->count > 0) {
|
||||
$this->session->alert(lang('username_taken'), 'danger');
|
||||
|
||||
return redirect($response, route('user.edit', ['id' => $id]));
|
||||
}
|
||||
|
||||
if ($user->id === $this->session->get('user_id') && param($request, 'is_admin') === null) {
|
||||
$this->session->alert(lang('cannot_demote'), 'danger');
|
||||
$this->session->alert($alerts[$rule], 'danger');
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect($response, route('user.edit', ['id' => $id]));
|
||||
}
|
||||
|
||||
|
@ -200,26 +171,15 @@ class UserController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if (param($request, 'password') !== null && !empty(param($request, 'password'))) {
|
||||
$this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [
|
||||
param($request, 'email'),
|
||||
param($request, 'username'),
|
||||
password_hash(param($request, 'password'), PASSWORD_DEFAULT),
|
||||
param($request, 'is_admin') !== null ? 1 : 0,
|
||||
param($request, 'is_active') !== null ? 1 : 0,
|
||||
$user->max_disk_quota,
|
||||
$user->id,
|
||||
]);
|
||||
} else {
|
||||
$this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [
|
||||
param($request, 'email'),
|
||||
param($request, 'username'),
|
||||
param($request, 'is_admin') !== null ? 1 : 0,
|
||||
param($request, 'is_active') !== null ? 1 : 0,
|
||||
$user->max_disk_quota,
|
||||
$user->id,
|
||||
]);
|
||||
}
|
||||
make(UserQuery::class)->update(
|
||||
$user->id,
|
||||
param($request, 'email'),
|
||||
param($request, 'username'),
|
||||
param($request, 'password'),
|
||||
param($request, 'is_admin') !== null ? 1 : 0,
|
||||
param($request, 'is_active') !== null ? 1 : 0,
|
||||
$user->max_disk_quota
|
||||
);
|
||||
|
||||
if ($user->id === $this->session->get('user_id')) {
|
||||
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
|
||||
|
@ -240,13 +200,10 @@ class UserController extends Controller
|
|||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
* @throws HttpUnauthorizedException
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
*/
|
||||
public function delete(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, false);
|
||||
$user = make(UserQuery::class)->get($request, $id);
|
||||
|
||||
if ($user->id === $this->session->get('user_id')) {
|
||||
$this->session->alert(lang('cannot_delete'), 'danger');
|
||||
|
@ -268,24 +225,15 @@ class UserController extends Controller
|
|||
* @param int $id
|
||||
*
|
||||
* @return Response
|
||||
* @throws HttpUnauthorizedException
|
||||
*
|
||||
* @throws HttpNotFoundException
|
||||
*/
|
||||
public function refreshToken(Request $request, Response $response, int $id): Response
|
||||
{
|
||||
$user = $this->getUser($request, $id, true);
|
||||
|
||||
$token = $this->generateUserUploadToken();
|
||||
|
||||
$this->database->query('UPDATE `users` SET `token`=? WHERE `id` = ?', [
|
||||
$token,
|
||||
$user->id,
|
||||
]);
|
||||
$query = make(UserQuery::class);
|
||||
$user = $query->get($request, $id, true);
|
||||
|
||||
$this->logger->info('User '.$this->session->get('username')." refreshed token of user $user->id.");
|
||||
|
||||
$response->getBody()->write($token);
|
||||
$response->getBody()->write($query->refreshToken($user->id));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
|
|
@ -42,17 +42,28 @@ class MediaQuery
|
|||
/**
|
||||
* MediaQuery constructor.
|
||||
*
|
||||
* @param DB $db
|
||||
* @param bool $isAdmin
|
||||
* @param Filesystem $storage
|
||||
* @param DB $db
|
||||
* @param bool $isAdmin
|
||||
* @param Filesystem $storage
|
||||
*/
|
||||
public function __construct(DB $db, bool $isAdmin, Filesystem $storage)
|
||||
public function __construct(DB $db, Filesystem $storage, bool $isAdmin)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->isAdmin = $isAdmin;
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DB $db
|
||||
* @param bool $isAdmin
|
||||
* @param Filesystem $storage
|
||||
* @return MediaQuery
|
||||
*/
|
||||
public static function make(DB $db, Filesystem $storage, bool $isAdmin)
|
||||
{
|
||||
return new self($db, $storage, $isAdmin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
|
@ -66,8 +77,8 @@ class MediaQuery
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string|null $type
|
||||
* @param string $mode
|
||||
* @param string|null $type
|
||||
* @param string $mode
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@ -80,7 +91,7 @@ class MediaQuery
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param string $text
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@ -92,7 +103,8 @@ class MediaQuery
|
|||
}
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
* @param int $page
|
||||
* @return MediaQuery|void
|
||||
*/
|
||||
public function run(int $page)
|
||||
{
|
||||
|
@ -150,10 +162,12 @@ class MediaQuery
|
|||
}
|
||||
$media->extension = pathinfo($media->filename, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
* @param int $page
|
||||
*/
|
||||
private function runWithOrderBySize(int $page)
|
||||
{
|
||||
|
|
147
app/Database/Queries/UserQuery.php
Normal file
147
app/Database/Queries/UserQuery.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Database\Queries;
|
||||
|
||||
|
||||
use App\Database\DB;
|
||||
use App\Web\Session;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Exception\HttpUnauthorizedException;
|
||||
|
||||
class UserQuery
|
||||
{
|
||||
/**
|
||||
* @var DB
|
||||
*/
|
||||
private $database;
|
||||
/**
|
||||
* @var Session
|
||||
*/
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* UserQuery constructor.
|
||||
* @param DB $db
|
||||
* @param Session|null $session
|
||||
*/
|
||||
public function __construct(DB $db, ?Session $session)
|
||||
{
|
||||
$this->database = $db;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DB $db
|
||||
* @param Session|null $session
|
||||
* @return UserQuery
|
||||
*/
|
||||
public static function make(DB $db, Session $session = null)
|
||||
{
|
||||
return new self($db, $session);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @param bool $authorize
|
||||
* @return mixed
|
||||
* @throws HttpNotFoundException
|
||||
* @throws HttpUnauthorizedException
|
||||
*/
|
||||
public function get(Request $request, $id, $authorize = false)
|
||||
{
|
||||
$user = $this->database->query('SELECT * FROM `users` WHERE `id` = ? LIMIT 1', $id)->fetch();
|
||||
|
||||
if (!$user) {
|
||||
throw new HttpNotFoundException($request);
|
||||
}
|
||||
|
||||
if ($authorize) {
|
||||
if ($this->session === null) {
|
||||
throw new \InvalidArgumentException('The session is null.');
|
||||
}
|
||||
|
||||
if ($user->id !== $this->session->get('user_id') && !$this->session->get('admin', false)) {
|
||||
throw new HttpUnauthorizedException($request);
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
public function create(string $email, string $username, string $password, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1, string $activateToken = null)
|
||||
{
|
||||
do {
|
||||
$userCode = humanRandomString(5);
|
||||
} while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `user_code` = ?', $userCode)->fetch()->count > 0);
|
||||
|
||||
$token = $this->generateUserUploadToken();
|
||||
|
||||
return $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`, `max_disk_quota`, `activate_token`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', [
|
||||
$email,
|
||||
$username,
|
||||
password_hash($password, PASSWORD_DEFAULT),
|
||||
$isAdmin,
|
||||
$isActive,
|
||||
$userCode,
|
||||
$token,
|
||||
$maxUserQuota,
|
||||
$activateToken,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update($id, string $email, string $username, string $password = null, int $isAdmin = 0, int $isActive = 0, int $maxUserQuota = -1)
|
||||
{
|
||||
if (!empty($password)) {
|
||||
$this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [
|
||||
$email,
|
||||
$username,
|
||||
password_hash($password, PASSWORD_DEFAULT),
|
||||
$isAdmin,
|
||||
$isActive,
|
||||
$maxUserQuota,
|
||||
$id,
|
||||
]);
|
||||
} else {
|
||||
$this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=? WHERE `id` = ?', [
|
||||
$email,
|
||||
$username,
|
||||
$isAdmin,
|
||||
$isActive,
|
||||
$maxUserQuota,
|
||||
$id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return string
|
||||
*/
|
||||
public function refreshToken($id)
|
||||
{
|
||||
$token = $this->generateUserUploadToken();
|
||||
|
||||
$this->database->query('UPDATE `users` SET `token`=? WHERE `id` = ?', [
|
||||
$token,
|
||||
$id,
|
||||
]);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function generateUserUploadToken(): string
|
||||
{
|
||||
do {
|
||||
$token = 'token_'.md5(uniqid('', true));
|
||||
} while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `token` = ?', $token)->fetch()->count > 0);
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Validators;
|
||||
|
||||
use App\Exceptions\ValidationException;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
trait ValidateUser
|
||||
{
|
||||
|
||||
/**
|
||||
* Partially validate a manager user request
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param $routeOnFail
|
||||
* @return bool
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validateUser(Request $request, Response $response, $routeOnFail)
|
||||
{
|
||||
if (param($request, 'email') === null && !filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL)) {
|
||||
$this->session->alert(lang('email_required'), 'danger');
|
||||
|
||||
throw new ValidationException(redirect($response, $routeOnFail));
|
||||
}
|
||||
|
||||
if (param($request, 'username') === null) {
|
||||
$this->session->alert(lang('username_required'), 'danger');
|
||||
|
||||
throw new ValidationException(redirect($response, $routeOnFail));
|
||||
}
|
||||
|
||||
if (param($request, 'password') === null) {
|
||||
$this->session->alert(lang('password_required'), 'danger');
|
||||
|
||||
throw new ValidationException(redirect($response, $routeOnFail));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
55
app/Web/ValidationChecker.php
Normal file
55
app/Web/ValidationChecker.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Web;
|
||||
|
||||
|
||||
class ValidationChecker
|
||||
{
|
||||
protected $rules = [];
|
||||
protected $failClosure;
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
if (is_callable($this->failClosure)) {
|
||||
($this->failClosure)($rule);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -157,6 +157,22 @@ if (!function_exists('resolve')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!function_exists('make')) {
|
||||
/**
|
||||
* Resolve a service from de DI container.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $params
|
||||
* @return mixed
|
||||
*/
|
||||
function make(string $class, array $params = [])
|
||||
{
|
||||
global $app;
|
||||
|
||||
return $app->getContainer()->make($class, $params);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('view')) {
|
||||
/**
|
||||
* Render a view to the response body.
|
||||
|
@ -455,3 +471,16 @@ if (!function_exists('dsnFromConfig')) {
|
|||
return $config['db']['connection'].':'.$dsn;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('platform_mail')) {
|
||||
/**
|
||||
* Return the system no-reply mail.
|
||||
*
|
||||
* @param string $mailbox
|
||||
* @return string
|
||||
*/
|
||||
function platform_mail($mailbox = 'no-reply'): string
|
||||
{
|
||||
return $mailbox.'@'.str_ireplace('www.', '', parse_url(resolve('config')['base_url'], PHP_URL_HOST));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ var app = {
|
|||
$('#themes').mousedown(app.loadThemes);
|
||||
$('.checkForUpdatesButton').click(app.checkForUpdates);
|
||||
|
||||
$('.alert').fadeTo(4000, 500).slideUp(500, function () {
|
||||
$('.alert').fadeTo(10000, 500).slideUp(500, function () {
|
||||
$('.alert').slideUp(500);
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue