api de gestion de ticket, basé sur php-crud-api. Le but est de décorrélé les outils de gestion des données, afin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DbAuthMiddleware.php 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. namespace Tqdev\PhpCrudApi\Middleware;
  3. use Psr\Http\Message\ResponseInterface;
  4. use Psr\Http\Message\ServerRequestInterface;
  5. use Psr\Http\Server\RequestHandlerInterface;
  6. use Tqdev\PhpCrudApi\Column\ReflectionService;
  7. use Tqdev\PhpCrudApi\Controller\Responder;
  8. use Tqdev\PhpCrudApi\Database\GenericDB;
  9. use Tqdev\PhpCrudApi\Middleware\Base\Middleware;
  10. use Tqdev\PhpCrudApi\Middleware\Router\Router;
  11. use Tqdev\PhpCrudApi\Record\Condition\ColumnCondition;
  12. use Tqdev\PhpCrudApi\Record\ErrorCode;
  13. use Tqdev\PhpCrudApi\Record\OrderingInfo;
  14. use Tqdev\PhpCrudApi\RequestUtils;
  15. class DbAuthMiddleware extends Middleware
  16. {
  17. private $reflection;
  18. private $db;
  19. private $ordering;
  20. public function __construct(Router $router, Responder $responder, array $properties, ReflectionService $reflection, GenericDB $db)
  21. {
  22. parent::__construct($router, $responder, $properties);
  23. $this->reflection = $reflection;
  24. $this->db = $db;
  25. $this->ordering = new OrderingInfo();
  26. }
  27. public function process(ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface
  28. {
  29. if (session_status() == PHP_SESSION_NONE) {
  30. if (!headers_sent()) {
  31. $sessionName = $this->getProperty('sessionName', '');
  32. if ($sessionName) {
  33. session_name($sessionName);
  34. }
  35. session_start();
  36. }
  37. }
  38. $path = RequestUtils::getPathSegment($request, 1);
  39. $method = $request->getMethod();
  40. if ($method == 'POST' && in_array($path, ['login', 'register', 'password'])) {
  41. $body = $request->getParsedBody();
  42. $username = isset($body->username) ? $body->username : '';
  43. $password = isset($body->password) ? $body->password : '';
  44. $newPassword = isset($body->newPassword) ? $body->newPassword : '';
  45. $tableName = $this->getProperty('usersTable', 'users');
  46. $table = $this->reflection->getTable($tableName);
  47. $usernameColumnName = $this->getProperty('usernameColumn', 'username');
  48. $usernameColumn = $table->getColumn($usernameColumnName);
  49. $passwordColumnName = $this->getProperty('passwordColumn', 'password');
  50. $passwordLength = $this->getProperty('passwordLength', '12');
  51. $pkName = $table->getPk()->getName();
  52. $registerUser = $this->getProperty('registerUser', '');
  53. $condition = new ColumnCondition($usernameColumn, 'eq', $username);
  54. $returnedColumns = $this->getProperty('returnedColumns', '');
  55. if (!$returnedColumns) {
  56. $columnNames = $table->getColumnNames();
  57. } else {
  58. $columnNames = array_map('trim', explode(',', $returnedColumns));
  59. $columnNames[] = $passwordColumnName;
  60. $columnNames[] = $pkName;
  61. $columnNames = array_values(array_unique($columnNames));
  62. }
  63. $columnOrdering = $this->ordering->getDefaultColumnOrdering($table);
  64. if ($path == 'register') {
  65. if (!$registerUser) {
  66. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
  67. }
  68. if (strlen($password) < $passwordLength) {
  69. return $this->responder->error(ErrorCode::PASSWORD_TOO_SHORT, $passwordLength);
  70. }
  71. $users = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, 0, 1);
  72. if (!empty($users)) {
  73. return $this->responder->error(ErrorCode::USER_ALREADY_EXIST, $username);
  74. }
  75. $data = json_decode($registerUser, true);
  76. $data = is_array($data) ? $data : [];
  77. $data[$usernameColumnName] = $username;
  78. $data[$passwordColumnName] = password_hash($password, PASSWORD_DEFAULT);
  79. $this->db->createSingle($table, $data);
  80. $users = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, 0, 1);
  81. foreach ($users as $user) {
  82. unset($user[$passwordColumnName]);
  83. return $this->responder->success($user);
  84. }
  85. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
  86. }
  87. if ($path == 'login') {
  88. $users = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, 0, 1);
  89. foreach ($users as $user) {
  90. if (password_verify($password, $user[$passwordColumnName]) == 1) {
  91. if (!headers_sent()) {
  92. session_regenerate_id(true);
  93. }
  94. unset($user[$passwordColumnName]);
  95. $_SESSION['user'] = $user;
  96. return $this->responder->success($user);
  97. }
  98. }
  99. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
  100. }
  101. if ($path == 'password') {
  102. if ($username != ($_SESSION['user'][$usernameColumnName] ?? '')) {
  103. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
  104. }
  105. if (strlen($newPassword) < $passwordLength) {
  106. return $this->responder->error(ErrorCode::PASSWORD_TOO_SHORT, $passwordLength);
  107. }
  108. $users = $this->db->selectAll($table, $columnNames, $condition, $columnOrdering, 0, 1);
  109. foreach ($users as $user) {
  110. if (password_verify($password, $user[$passwordColumnName]) == 1) {
  111. if (!headers_sent()) {
  112. session_regenerate_id(true);
  113. }
  114. $data = [$passwordColumnName => password_hash($newPassword, PASSWORD_DEFAULT)];
  115. $this->db->updateSingle($table, $data, $user[$pkName]);
  116. unset($user[$passwordColumnName]);
  117. return $this->responder->success($user);
  118. }
  119. }
  120. return $this->responder->error(ErrorCode::AUTHENTICATION_FAILED, $username);
  121. }
  122. }
  123. if ($method == 'POST' && $path == 'logout') {
  124. if (isset($_SESSION['user'])) {
  125. $user = $_SESSION['user'];
  126. unset($_SESSION['user']);
  127. if (session_status() != PHP_SESSION_NONE) {
  128. session_destroy();
  129. }
  130. return $this->responder->success($user);
  131. }
  132. return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
  133. }
  134. if ($method == 'GET' && $path == 'me') {
  135. if (isset($_SESSION['user'])) {
  136. return $this->responder->success($_SESSION['user']);
  137. }
  138. return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
  139. }
  140. if (!isset($_SESSION['user']) || !$_SESSION['user']) {
  141. $authenticationMode = $this->getProperty('mode', 'required');
  142. if ($authenticationMode == 'required') {
  143. return $this->responder->error(ErrorCode::AUTHENTICATION_REQUIRED, '');
  144. }
  145. }
  146. return $next->handle($request);
  147. }
  148. }