UserController.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <?php
  2. namespace App\Controllers;
  3. use Psr\Http\Message\ResponseInterface as Response;
  4. use Psr\Http\Message\ServerRequestInterface as Request;
  5. use Slim\Exception\HttpNotFoundException;
  6. use Slim\Exception\HttpUnauthorizedException;
  7. class UserController extends Controller
  8. {
  9. const PER_PAGE = 15;
  10. /**
  11. * @param Response $response
  12. * @param int|null $page
  13. *
  14. * @throws \Twig\Error\LoaderError
  15. * @throws \Twig\Error\RuntimeError
  16. * @throws \Twig\Error\SyntaxError
  17. *
  18. * @return Response
  19. */
  20. public function index(Response $response, int $page = 0): Response
  21. {
  22. $page = max(0, --$page);
  23. $users = $this->database->query('SELECT * FROM `users` LIMIT ? OFFSET ?', [self::PER_PAGE, $page * self::PER_PAGE])->fetchAll();
  24. $pages = $this->database->query('SELECT COUNT(*) AS `count` FROM `users`')->fetch()->count / self::PER_PAGE;
  25. return view()->render($response,
  26. 'user/index.twig',
  27. [
  28. 'users' => $users,
  29. 'next' => $page < floor($pages),
  30. 'previous' => $page >= 1,
  31. 'current_page' => ++$page,
  32. ]
  33. );
  34. }
  35. /**
  36. * @param Response $response
  37. *
  38. * @throws \Twig\Error\LoaderError
  39. * @throws \Twig\Error\RuntimeError
  40. * @throws \Twig\Error\SyntaxError
  41. *
  42. * @return Response
  43. */
  44. public function create(Response $response): Response
  45. {
  46. return view()->render($response, 'user/create.twig');
  47. }
  48. /**
  49. * @param Request $request
  50. * @param Response $response
  51. *
  52. * @return Response
  53. */
  54. public function store(Request $request, Response $response): Response
  55. {
  56. if (param($request, 'email') === null && !filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL)) {
  57. $this->session->alert(lang('email_required'), 'danger');
  58. return redirect($response, route('user.create'));
  59. }
  60. if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ?', param($request, 'email'))->fetch()->count > 0) {
  61. $this->session->alert(lang('email_taken'), 'danger');
  62. return redirect($response, route('user.create'));
  63. }
  64. if (param($request, 'username') === null) {
  65. $this->session->alert(lang('username_required'), 'danger');
  66. return redirect($response, route('user.create'));
  67. }
  68. if (param($request, 'password') === null) {
  69. $this->session->alert(lang('password_required'), 'danger');
  70. return redirect($response, route('user.create'));
  71. }
  72. if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ?', param($request, 'username'))->fetch()->count > 0) {
  73. $this->session->alert(lang('username_taken'), 'danger');
  74. return redirect($response, route('user.create'));
  75. }
  76. do {
  77. $userCode = humanRandomString(5);
  78. } while ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `user_code` = ?', $userCode)->fetch()->count > 0);
  79. $token = $this->generateUserUploadToken();
  80. $this->database->query('INSERT INTO `users`(`email`, `username`, `password`, `is_admin`, `active`, `user_code`, `token`) VALUES (?, ?, ?, ?, ?, ?, ?)', [
  81. param($request, 'email'),
  82. param($request, 'username'),
  83. password_hash(param($request, 'password'), PASSWORD_DEFAULT),
  84. param($request, 'is_admin') !== null ? 1 : 0,
  85. param($request, 'is_active') !== null ? 1 : 0,
  86. $userCode,
  87. $token,
  88. ]);
  89. $this->session->alert(lang('user_created', [param($request, 'username')]), 'success');
  90. $this->logger->info('User '.$this->session->get('username').' created a new user.', [array_diff_key($request->getParsedBody(), array_flip(['password']))]);
  91. return redirect($response, route('user.index'));
  92. }
  93. /**
  94. * @param Request $request
  95. * @param Response $response
  96. * @param $id
  97. *
  98. * @throws HttpNotFoundException
  99. * @throws \Twig\Error\LoaderError
  100. * @throws \Twig\Error\RuntimeError
  101. * @throws \Twig\Error\SyntaxError
  102. * @throws HttpUnauthorizedException
  103. *
  104. * @return Response
  105. */
  106. public function edit(Request $request, Response $response, int $id): Response
  107. {
  108. $user = $this->getUser($request, $id, false);
  109. return view()->render($response, 'user/edit.twig', [
  110. 'profile' => false,
  111. 'user' => $user,
  112. ]);
  113. }
  114. /**
  115. * @param Request $request
  116. * @param Response $response
  117. * @param int $id
  118. *
  119. * @throws HttpNotFoundException
  120. * @throws HttpUnauthorizedException
  121. *
  122. * @return Response
  123. */
  124. public function update(Request $request, Response $response, int $id): Response
  125. {
  126. $user = $this->getUser($request, $id, false);
  127. if (param($request, 'email') === null && !filter_var(param($request, 'email'), FILTER_VALIDATE_EMAIL)) {
  128. $this->session->alert(lang('email_required'), 'danger');
  129. return redirect($response, route('user.edit', ['id' => $id]));
  130. }
  131. if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `email` = ? AND `email` <> ?', [param($request, 'email'), $user->email])->fetch()->count > 0) {
  132. $this->session->alert(lang('email_taken'), 'danger');
  133. return redirect($response, route('user.edit', ['id' => $id]));
  134. }
  135. if (param($request, 'username') === null) {
  136. $this->session->alert(lang('username_required'), 'danger');
  137. return redirect($response, route('user.edit', ['id' => $id]));
  138. }
  139. if ($this->database->query('SELECT COUNT(*) AS `count` FROM `users` WHERE `username` = ? AND `username` <> ?', [param($request, 'username'), $user->username])->fetch()->count > 0) {
  140. $this->session->alert(lang('username_taken'), 'danger');
  141. return redirect($response, route('user.edit', ['id' => $id]));
  142. }
  143. if ($user->id === $this->session->get('user_id') && param($request, 'is_admin') === null) {
  144. $this->session->alert(lang('cannot_demote'), 'danger');
  145. return redirect($response, route('user.edit', ['id' => $id]));
  146. }
  147. if (param($request, 'password') !== null && !empty(param($request, 'password'))) {
  148. $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `password`=?, `is_admin`=?, `active`=? WHERE `id` = ?', [
  149. param($request, 'email'),
  150. param($request, 'username'),
  151. password_hash(param($request, 'password'), PASSWORD_DEFAULT),
  152. param($request, 'is_admin') !== null ? 1 : 0,
  153. param($request, 'is_active') !== null ? 1 : 0,
  154. $user->id,
  155. ]);
  156. } else {
  157. $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=? WHERE `id` = ?', [
  158. param($request, 'email'),
  159. param($request, 'username'),
  160. param($request, 'is_admin') !== null ? 1 : 0,
  161. param($request, 'is_active') !== null ? 1 : 0,
  162. $user->id,
  163. ]);
  164. }
  165. $this->session->alert(lang('user_updated', [param($request, 'username')]), 'success');
  166. $this->logger->info('User '.$this->session->get('username')." updated $user->id.", [
  167. array_diff_key((array) $user, array_flip(['password'])),
  168. array_diff_key($request->getParsedBody(), array_flip(['password'])),
  169. ]);
  170. return redirect($response, route('user.index'));
  171. }
  172. /**
  173. * @param Request $request
  174. * @param Response $response
  175. * @param int $id
  176. *
  177. * @throws HttpNotFoundException
  178. * @throws HttpUnauthorizedException
  179. *
  180. * @return Response
  181. */
  182. public function delete(Request $request, Response $response, int $id): Response
  183. {
  184. $user = $this->getUser($request, $id, false);
  185. if ($user->id === $this->session->get('user_id')) {
  186. $this->session->alert(lang('cannot_delete'), 'danger');
  187. return redirect($response, route('user.index'));
  188. }
  189. $this->database->query('DELETE FROM `users` WHERE `id` = ?', $user->id);
  190. $this->session->alert(lang('user_deleted'), 'success');
  191. $this->logger->info('User '.$this->session->get('username')." deleted $user->id.");
  192. return redirect($response, route('user.index'));
  193. }
  194. /**
  195. * @param Request $request
  196. * @param Response $response
  197. * @param int $id
  198. *
  199. * @throws HttpNotFoundException
  200. * @throws HttpUnauthorizedException
  201. *
  202. * @return Response
  203. */
  204. public function refreshToken(Request $request, Response $response, int $id): Response
  205. {
  206. $user = $this->getUser($request, $id, true);
  207. $token = $this->generateUserUploadToken();
  208. $this->database->query('UPDATE `users` SET `token`=? WHERE `id` = ?', [
  209. $token,
  210. $user->id,
  211. ]);
  212. $this->logger->info('User '.$this->session->get('username')." refreshed token of user $user->id.");
  213. $response->getBody()->write($token);
  214. return $response;
  215. }
  216. }