Controller.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace App\Controllers;
  3. use App\Database\DB;
  4. use App\Database\Queries\UserQuery;
  5. use App\Web\Lang;
  6. use App\Web\Session;
  7. use App\Web\ValidationChecker;
  8. use App\Web\View;
  9. use DI\Container;
  10. use DI\DependencyException;
  11. use DI\NotFoundException;
  12. use Exception;
  13. use League\Flysystem\Filesystem;
  14. use Monolog\Logger;
  15. use Psr\Http\Message\ServerRequestInterface as Request;
  16. /**
  17. * @property Session session
  18. * @property View view
  19. * @property DB database
  20. * @property Logger|null logger
  21. * @property Filesystem|null storage
  22. * @property Lang lang
  23. * @property array config
  24. */
  25. abstract class Controller
  26. {
  27. /** @var Container */
  28. protected $container;
  29. public function __construct(Container $container)
  30. {
  31. $this->container = $container;
  32. }
  33. /**
  34. * @param $name
  35. *
  36. * @return mixed|null
  37. * @throws NotFoundException
  38. *
  39. * @throws DependencyException
  40. */
  41. public function __get($name)
  42. {
  43. if ($this->container->has($name)) {
  44. return $this->container->get($name);
  45. }
  46. return null;
  47. }
  48. /**
  49. * @param $key
  50. * @param null $default
  51. * @return object
  52. */
  53. protected function getSetting($key, $default = null)
  54. {
  55. return $this->database->query('SELECT `value` FROM `settings` WHERE `key` = '.$this->database->getPdo()->quote($key))->fetch()->value ?? $default;
  56. }
  57. /**
  58. * @param $current
  59. * @param $max
  60. */
  61. protected function setSessionQuotaInfo($current, $max)
  62. {
  63. $this->session->set('current_disk_quota', humanFileSize($current));
  64. if ($this->getSetting('quota_enabled', 'off') === 'on') {
  65. if ($max < 0) {
  66. $this->session->set('max_disk_quota', '∞');
  67. $this->session->set('percent_disk_quota', null);
  68. } else {
  69. $this->session->set('max_disk_quota', humanFileSize($max));
  70. $this->session->set('percent_disk_quota', round(($current * 100) / $max));
  71. }
  72. } else {
  73. $this->session->set('max_disk_quota', null);
  74. $this->session->set('percent_disk_quota', null);
  75. }
  76. }
  77. /**
  78. * @param Request $request
  79. * @param $userId
  80. * @param $fileSize
  81. * @param bool $dec
  82. * @return bool
  83. */
  84. protected function updateUserQuota(Request $request, $userId, $fileSize, $dec = false)
  85. {
  86. $user = make(UserQuery::class)->get($request, $userId);
  87. if ($dec) {
  88. $tot = max($user->current_disk_quota - $fileSize, 0);
  89. } else {
  90. $tot = $user->current_disk_quota + $fileSize;
  91. if ($this->getSetting('quota_enabled') === 'on' && $user->max_disk_quota > 0 && $user->max_disk_quota < $tot) {
  92. return false;
  93. }
  94. }
  95. $this->database->query('UPDATE `users` SET `current_disk_quota`=? WHERE `id` = ?', [
  96. $tot,
  97. $user->id,
  98. ]);
  99. return true;
  100. }
  101. /**
  102. * @param $userId
  103. * @throws Exception
  104. */
  105. protected function refreshRememberCookie($userId)
  106. {
  107. $selector = bin2hex(random_bytes(8));
  108. $token = bin2hex(random_bytes(32));
  109. $expire = time() + 604800; // a week
  110. $this->database->query('UPDATE `users` SET `remember_selector`=?, `remember_token`=?, `remember_expire`=? WHERE `id`=?', [
  111. $selector,
  112. password_hash($token, PASSWORD_DEFAULT),
  113. date('Y-m-d\TH:i:s', $expire),
  114. $userId,
  115. ]);
  116. // Workaround for php <= 7.3
  117. if (PHP_VERSION_ID < 70300) {
  118. setcookie('remember', "{$selector}:{$token}", $expire, '; SameSite=Lax', '', false, true);
  119. } else {
  120. setcookie('remember', "{$selector}:{$token}", [
  121. 'expires' => $expire,
  122. 'httponly' => true,
  123. 'samesite' => 'Lax',
  124. ]);
  125. }
  126. }
  127. /**
  128. * @param Request $request
  129. * @return ValidationChecker
  130. */
  131. public function getUserCreateValidator(Request $request)
  132. {
  133. return ValidationChecker::make()
  134. ->rules([
  135. 'email.required' => filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL) !== false,
  136. 'username.required' => !empty(param($request, 'username')),
  137. 'password.required' => !empty(param($request, 'password')),
  138. 'email.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count == 0,
  139. 'username.unique' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count == 0,
  140. ])
  141. ->onFail(function ($rule) {
  142. $alerts = [
  143. 'email.required' => lang('email_required'),
  144. 'username.required' => lang('username_required'),
  145. 'password.required' => lang('password_required'),
  146. 'email.unique' => lang('email_taken'),
  147. 'username.unique' => lang('username_taken'),
  148. ];
  149. $this->session->alert($alerts[$rule], 'danger');
  150. });
  151. }
  152. }