Implemented validation helper

Dependencies resolved through container
This commit is contained in:
Sergio Brighenti 2020-03-03 17:18:52 +01:00
parent 623de4b5e0
commit db483bb53e
18 changed files with 394 additions and 284 deletions

View file

@ -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
{

View file

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

View file

@ -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'));

View file

@ -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');

View file

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

View file

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

View file

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

View file

@ -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 {

View file

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

View file

@ -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')));

View file

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

View file

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

View file

@ -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)
{

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

View file

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

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

View file

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

View file

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