UserModel.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. namespace Models;
  3. use Libs\Database;
  4. use Libs\Logger;
  5. class UserModel
  6. {
  7. private \PDO $pdo;
  8. public function __construct()
  9. {
  10. $this->pdo = Database::pdo();
  11. }
  12. /**
  13. * Valida credenciais de login e retorna dados do usuário se válido.
  14. *
  15. * @param string $username
  16. * @param string $password Plain-text password para verificar
  17. * @return array|null Dados do usuário (user_id, user_name, etc.) ou null se inválido
  18. */
  19. public function validateLogin(string $email, string $password): ?array
  20. {
  21. $stmt = $this->pdo->prepare("SELECT user_id, company_id, user_name, user_phone, user_email, user_role, user_password FROM \"user\" WHERE user_email = :email AND user_deleted_at = 'infinity'");
  22. $stmt->execute(['email' => mb_strtolower(trim($email))]);
  23. $user = $stmt->fetch(\PDO::FETCH_ASSOC);
  24. if ($user && password_verify($password, $user['user_password'])) {
  25. unset($user['user_password']);
  26. return $user;
  27. }
  28. return null;
  29. }
  30. /**
  31. * Cria um novo usuário com senha hasheada e gera chaves API.
  32. *
  33. * @param string $username
  34. * @param string $password Plain-text password
  35. * @param string $flag Default 'a' para ativo
  36. * @return array|bool Dados do usuário criado (incluindo api_key) ou false em erro
  37. */
  38. public function createUser(int $companyId, string $email, string $password, string $phone, string $role, ?string $name = null)
  39. {
  40. $normalizedEmail = mb_strtolower(trim($email));
  41. $normalizedPhone = trim($phone);
  42. $normalizedRole = trim($role);
  43. $normalizedName = $name !== null ? trim($name) : null;
  44. if ($normalizedName === '') {
  45. $normalizedName = null;
  46. }
  47. $stmt = $this->pdo->prepare('SELECT user_id FROM "user" WHERE user_email = :email');
  48. $stmt->execute(['email' => $normalizedEmail]);
  49. if ($stmt->fetch()) {
  50. return false;
  51. }
  52. $hash = password_hash($password, PASSWORD_DEFAULT);
  53. try {
  54. $stmt = $this->pdo->prepare("INSERT INTO \"user\" (company_id, user_name, user_phone, user_email, user_role, user_password) VALUES (:company_id, :user_name, :user_phone, :user_email, :user_role, :user_password) RETURNING user_id, company_id, user_name, user_phone, user_email, user_role, user_created_at");
  55. $stmt->execute([
  56. 'company_id' => $companyId,
  57. 'user_name' => $normalizedName,
  58. 'user_phone' => $normalizedPhone,
  59. 'user_email' => $normalizedEmail,
  60. 'user_role' => $normalizedRole,
  61. 'user_password' => $hash,
  62. ]);
  63. $createdUser = $stmt->fetch(\PDO::FETCH_ASSOC);
  64. } catch (\PDOException $e) {
  65. Logger::error('Failed to insert user', ['email' => $normalizedEmail, 'error' => $e->getMessage()]);
  66. return false;
  67. }
  68. if (!$createdUser) {
  69. return false;
  70. }
  71. return [
  72. 'user_id' => (int) $createdUser['user_id'],
  73. 'company_id' => (int) $createdUser['company_id'],
  74. 'user_name' => $createdUser['user_name'],
  75. 'user_phone' => $createdUser['user_phone'],
  76. 'user_email' => $createdUser['user_email'],
  77. 'user_role' => $createdUser['user_role'],
  78. 'user_created_at' => $createdUser['user_created_at'],
  79. ];
  80. }
  81. public function getCompanyIdByUserId(int $userId): ?int
  82. {
  83. $stmt = $this->pdo->prepare(
  84. "SELECT company_id
  85. FROM \"user\"
  86. WHERE user_id = :user_id
  87. AND user_deleted_at = 'infinity'
  88. LIMIT 1"
  89. );
  90. $stmt->execute(['user_id' => $userId]);
  91. $companyId = $stmt->fetchColumn();
  92. return $companyId === false ? null : (int) $companyId;
  93. }
  94. public function getAuthenticatedProfile(int $userId): ?array
  95. {
  96. $stmt = $this->pdo->prepare(
  97. 'SELECT
  98. u.user_id,
  99. u.company_id,
  100. u.user_name,
  101. u.user_phone,
  102. u.user_email,
  103. u.user_role,
  104. u.user_created_at,
  105. c.company_name,
  106. c.company_cnpj,
  107. c.company_logo,
  108. c.company_created_at
  109. FROM "user" u
  110. INNER JOIN company c ON c.company_id = u.company_id
  111. WHERE u.user_id = :user_id
  112. AND u.user_deleted_at = \'infinity\'
  113. AND c.company_deleted_at = \'infinity\'
  114. LIMIT 1'
  115. );
  116. $stmt->execute(['user_id' => $userId]);
  117. $user = $stmt->fetch(\PDO::FETCH_ASSOC);
  118. if (!$user) {
  119. return null;
  120. }
  121. return [
  122. 'user_id' => (int) $user['user_id'],
  123. 'company_id' => (int) $user['company_id'],
  124. 'user_name' => $user['user_name'],
  125. 'user_phone' => $user['user_phone'],
  126. 'user_email' => $user['user_email'],
  127. 'user_role' => $user['user_role'],
  128. 'user_created_at' => $user['user_created_at'],
  129. 'company' => [
  130. 'company_id' => (int) $user['company_id'],
  131. 'company_name' => $user['company_name'],
  132. 'company_cnpj' => $user['company_cnpj'],
  133. 'company_logo' => $user['company_logo'],
  134. 'company_created_at' => $user['company_created_at'],
  135. ],
  136. ];
  137. }
  138. public function changePassword(int $userId, string $currentPassword, string $newPassword): string
  139. {
  140. $stmt = $this->pdo->prepare(
  141. "SELECT user_password
  142. FROM \"user\"
  143. WHERE user_id = :user_id
  144. AND user_deleted_at = 'infinity'
  145. LIMIT 1"
  146. );
  147. $stmt->execute(['user_id' => $userId]);
  148. $userPasswordHash = $stmt->fetchColumn();
  149. if (!is_string($userPasswordHash) || $userPasswordHash === '') {
  150. return 'not_found';
  151. }
  152. if (!password_verify($currentPassword, $userPasswordHash)) {
  153. return 'invalid_current_password';
  154. }
  155. $newPasswordHash = password_hash($newPassword, PASSWORD_DEFAULT);
  156. try {
  157. $updateStmt = $this->pdo->prepare(
  158. "UPDATE \"user\"
  159. SET user_password = :user_password
  160. WHERE user_id = :user_id
  161. AND user_deleted_at = 'infinity'"
  162. );
  163. $updateStmt->execute([
  164. 'user_password' => $newPasswordHash,
  165. 'user_id' => $userId,
  166. ]);
  167. } catch (\PDOException $e) {
  168. Logger::error('Failed to update user password', ['user_id' => $userId, 'error' => $e->getMessage()]);
  169. return 'error';
  170. }
  171. return 'updated';
  172. }
  173. }