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.

LuUsersBusiness.php 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: robin
  5. * Date: 7/2/16
  6. * Time: 10:15 PM
  7. */
  8. namespace Luticate\Auth\Business;
  9. use Luticate\Auth\DataAccess\LuUserDataAccess;
  10. use Luticate\Auth\Dbo\Users\LuUsersAddDbo;
  11. use Luticate\Auth\Dbo\Users\LuUsersDbo;
  12. use Luticate\Auth\Dbo\Users\LuUsersEditDbo;
  13. use Luticate\Auth\Dbo\Users\LuUsersLiteDbo;
  14. use Luticate\Auth\Dbo\Users\LuUsersLoginDbo;
  15. use Luticate\Auth\Dbo\Users\LuUsersLoginResultDbo;
  16. use Luticate\Utils\Business\LuBusiness;
  17. use Luticate\Utils\Dbo\LuPaginatedDbo;
  18. use Luticate\Utils\Dbo\LuQueryDbo;
  19. class LuUsersBusiness extends LuBusiness
  20. {
  21. const KEY_USER_ID = "user_id";
  22. const KEY_SALT = "salt";
  23. const KEY_DATA = "data";
  24. /**
  25. * @return LuUserDataAccess
  26. */
  27. protected static function getDataAccess()
  28. {
  29. return new LuUserDataAccess();
  30. }
  31. protected function badPassword()
  32. {
  33. static::unauthorized("Bad username/password");
  34. }
  35. public function hashPassword(string $password)
  36. {
  37. return password_hash($password, PASSWORD_BCRYPT);
  38. }
  39. public function verifyPassword(string $password, string $hash)
  40. {
  41. return password_verify($password, $hash);
  42. }
  43. public function checkPasswordRequirements(string $password)
  44. {
  45. if (strlen($password) < 5) { //TODO: add a setting
  46. self::badInput("Password must have at least 5 characters");
  47. }
  48. }
  49. public function getSalt($length = 10)
  50. {
  51. $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  52. $charactersLength = strlen($characters);
  53. $randomString = '';
  54. for ($i = 0; $i < $length; $i++) {
  55. $randomString .= $characters[rand(0, $charactersLength - 1)];
  56. }
  57. return $randomString;
  58. }
  59. public function getToken(LuUsersDbo $user, $data = null)
  60. {
  61. $session_time = 30;//TODO add a setting
  62. return JwtHelper::encode(array(
  63. self::KEY_USER_ID => $user->getId(),
  64. self::KEY_SALT => $user->getSalt(),
  65. self::KEY_DATA => $data
  66. ), $session_time);
  67. }
  68. public function login(LuUsersLoginDbo $login)
  69. {
  70. $user = static::getDataAccess()->getByUsernameOrEmail($login->getUsername());
  71. if (is_null($user))
  72. self::badPassword();
  73. if (!self::verifyPassword($login->getPassword(), $user->getPassword()))
  74. self::badPassword();
  75. /**
  76. * @var $result LuUsersLoginResultDbo
  77. */
  78. $result = $user->castAs(LuUsersLoginResultDbo::class);
  79. $result->setToken(self::getToken($user));
  80. return $result;
  81. }
  82. public function logout(LuUsersDbo $user)
  83. {
  84. if ($user->getId() != 0) {
  85. $user->setSalt(self::getSalt());
  86. static::getDataAccess()->editSingleById($user);
  87. }
  88. return true;
  89. }
  90. public function getSingleLiteById($userId)
  91. {
  92. /**
  93. * @var $user LuUsersDbo
  94. */
  95. $user = static::getById($userId);
  96. return $user->toLite();
  97. }
  98. /**
  99. * @param LuQueryDbo $query
  100. * @return LuPaginatedDbo
  101. */
  102. public function getAllLite(LuQueryDbo $query)
  103. {
  104. return static::getDataAccess()->getAll($query)->map(function($user)
  105. {
  106. /**
  107. * @var $user LuUsersDbo
  108. */
  109. return $user->toLite();
  110. });
  111. }
  112. public function add(LuUsersAddDbo $user)
  113. {
  114. static::checkPasswordRequirements($user->getPassword());
  115. if (filter_var($user->getUsername(), FILTER_VALIDATE_EMAIL)) {
  116. self::badInput("Username can not be an email");
  117. }
  118. if (!preg_match("/^[A-Za-z0-9\\-_\\.]+$/", $user->getUsername())) {
  119. self::badInput("Username can only contain letters (A-Z a-z), numbers (0-9), hyphen (-), underscore (_) and dot (.)");
  120. }
  121. if (!filter_var($user->getEmail(), FILTER_VALIDATE_EMAIL)) {
  122. self::badInput("Invalid email address");
  123. }
  124. $existingUser = static::getDataAccess()->getByUsernameOrEmail($user->getUsername());
  125. if ($existingUser != null) {
  126. self::badInput("Username already exists");
  127. }
  128. $existingUser = static::getDataAccess()->getByUsernameOrEmail($user->getEmail());
  129. if ($existingUser != null) {
  130. self::badInput("Email already used");
  131. }
  132. $user->setPassword(self::hashPassword($user->getPassword()));
  133. $user->setExternalAuth(null);
  134. $user->setProfileId(null);
  135. /**
  136. * @var LuUsersDbo $newUser
  137. */
  138. $newUser = $user->castAs(LuUsersDbo::class);
  139. $newUser->setSalt(static::getSalt());
  140. $id = static::getDataAccess()->addSingleId($newUser);
  141. return self::getById($id);
  142. }
  143. public function del(int $userId)
  144. {
  145. $user = static::getSingleLiteById($userId);
  146. if ($userId != 0) {
  147. static::deleteById($user->getId());
  148. }
  149. return $user;
  150. }
  151. public function edit(int $userId, LuUsersEditDbo $user)
  152. {
  153. $existingUser = static::getSingleLiteById($userId);
  154. if (!filter_var($user->getEmail(), FILTER_VALIDATE_EMAIL)) {
  155. self::badInput("Invalid email address");
  156. }
  157. $anotherExistingUser = static::getDataAccess()->getByUsernameOrEmail($user->getEmail());
  158. if ($anotherExistingUser != null && $anotherExistingUser->getId() != $existingUser->getId()) {
  159. self::badInput("Email already used");
  160. }
  161. $existingUser->setEmail($user->getEmail());
  162. $existingUser->setFirstname($user->getFirstname());
  163. $existingUser->setLastname($user->getLastname());
  164. static::getDataAccess()->editSingleById($existingUser);
  165. return static::getSingleLiteById($existingUser->getId());
  166. }
  167. public function setPassword(int $userId, string $password)
  168. {
  169. $this->checkPasswordRequirements($password);
  170. /**
  171. * @var $existingUser LuUsersDbo
  172. */
  173. $existingUser = static::getDataAccess()->getSingleById($userId);
  174. $existingUser->setPassword(static::hashPassword($password));
  175. $existingUser->setSalt(static::getSalt());
  176. static::getDataAccess()->editSingleById($existingUser);
  177. return true;
  178. }
  179. public function setPasswordMe(LuUsersDbo $_user, string $password, string $oldPassword)
  180. {
  181. $loginDbo = new LuUsersLoginDbo();
  182. $loginDbo->setUsername($_user->getUsername());
  183. $loginDbo->setPassword($oldPassword);
  184. static::login($loginDbo);
  185. return static::setPassword($_user->getId(), $password);
  186. }
  187. }