PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Model/Behavior/RegisterBehavior.php

http://github.com/CakeDC/users
PHP | 221 lines | 116 code | 23 blank | 82 comment | 9 complexity | f25d32c33ac1307c0fdf94d1ffdfd7be MD5 | raw file
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Copyright 2010 - 2019, Cake Development Corporation (https://www.cakedc.com)
  5. *
  6. * Licensed under The MIT License
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com)
  10. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  11. */
  12. namespace CakeDC\Users\Model\Behavior;
  13. use Cake\Core\Configure;
  14. use Cake\Datasource\EntityInterface;
  15. use Cake\Event\Event;
  16. use Cake\Mailer\MailerAwareTrait;
  17. use Cake\Validation\Validator;
  18. use CakeDC\Users\Exception\TokenExpiredException;
  19. use CakeDC\Users\Exception\UserAlreadyActiveException;
  20. use CakeDC\Users\Exception\UserNotFoundException;
  21. /**
  22. * Covers the user registration
  23. */
  24. class RegisterBehavior extends BaseTokenBehavior
  25. {
  26. use MailerAwareTrait;
  27. /**
  28. * @var bool
  29. */
  30. protected $validateEmail;
  31. /**
  32. * @var bool
  33. */
  34. protected $useTos;
  35. /**
  36. * Constructor hook method.
  37. *
  38. * @param array $config The configuration settings provided to this behavior.
  39. * @return void
  40. */
  41. public function initialize(array $config): void
  42. {
  43. parent::initialize($config);
  44. $this->validateEmail = (bool)Configure::read('Users.Email.validate');
  45. $this->useTos = (bool)Configure::read('Users.Tos.required');
  46. }
  47. /**
  48. * Registers an user.
  49. *
  50. * @param \Cake\Datasource\EntityInterface $user User information
  51. * @param array $data User information
  52. * @param array $options ['tokenExpiration]
  53. * @return bool|\Cake\Datasource\EntityInterface
  54. */
  55. public function register($user, $data, $options)
  56. {
  57. $validateEmail = $options['validate_email'] ?? null;
  58. $tokenExpiration = $options['token_expiration'] ?? null;
  59. $validator = $options['validator'] ?? null;
  60. $user = $this->_table->patchEntity(
  61. $user,
  62. $data,
  63. ['validate' => $validator ?: $this->getRegisterValidators($options)]
  64. );
  65. $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user';
  66. $user->validated = false;
  67. //@todo move updateActive to afterSave?
  68. $user = $this->_updateActive($user, $validateEmail, $tokenExpiration);
  69. $this->_table->isValidateEmail = $validateEmail;
  70. $userSaved = $this->_table->save($user);
  71. if ($userSaved && $validateEmail) {
  72. $this->_sendValidationEmail($user);
  73. }
  74. return $userSaved;
  75. }
  76. /**
  77. * Validates token and return user
  78. *
  79. * @param string $token toke to be validated.
  80. * @param null $callback function that will be returned.
  81. * @throws \CakeDC\Users\Exception\TokenExpiredException when token has expired.
  82. * @throws \CakeDC\Users\Exception\UserNotFoundException when user isn't found.
  83. * @return \Cake\Datasource\EntityInterface $user
  84. */
  85. public function validate($token, $callback = null)
  86. {
  87. $user = $token ? $this->_table->find()
  88. ->select(['token_expires', 'id', 'active', 'token'])
  89. ->where(['token' => $token])
  90. ->first() : null;
  91. if (empty($user)) {
  92. throw new UserNotFoundException(__d('cake_d_c/users', 'User not found for the given token and email.'));
  93. }
  94. if ($user->tokenExpired()) {
  95. throw new TokenExpiredException(__d('cake_d_c/users', 'Token has already expired user with no token'));
  96. }
  97. if (!method_exists($this, (string)$callback)) {
  98. return $user;
  99. }
  100. return $this->_table->{$callback}($user);
  101. }
  102. /**
  103. * Activates an user
  104. *
  105. * @param \Cake\Datasource\EntityInterface $user user object.
  106. * @return mixed User entity or bool false if the user could not be activated
  107. * @throws \CakeDC\Users\Exception\UserAlreadyActiveException
  108. */
  109. public function activateUser(EntityInterface $user)
  110. {
  111. if ($user->active) {
  112. throw new UserAlreadyActiveException(__d('cake_d_c/users', 'User account already validated'));
  113. }
  114. $user->activation_date = new \DateTime();
  115. $user->token_expires = null;
  116. $user->active = true;
  117. $result = $this->_table->save($user);
  118. return $result;
  119. }
  120. /**
  121. * buildValidator
  122. *
  123. * @param \Cake\Event\Event $event event
  124. * @param \Cake\Validation\Validator $validator validator
  125. * @param string $name name
  126. * @return \Cake\Validation\Validator
  127. */
  128. public function buildValidator(Event $event, Validator $validator, $name)
  129. {
  130. if ($name === 'default') {
  131. return $this->_emailValidator($validator, $this->validateEmail);
  132. }
  133. return $validator;
  134. }
  135. /**
  136. * Email validator
  137. *
  138. * @param \Cake\Validation\Validator $validator Validator instance.
  139. * @param bool $validateEmail true when email needs to be required
  140. * @return \Cake\Validation\Validator
  141. */
  142. protected function _emailValidator(Validator $validator, $validateEmail)
  143. {
  144. $this->validateEmail = $validateEmail;
  145. $validator
  146. ->add('email', 'valid', ['rule' => 'email'])
  147. ->notBlank('email', __d('cake_d_c/users', 'This field is required'), function ($context) {
  148. return $this->validateEmail;
  149. });
  150. return $validator;
  151. }
  152. /**
  153. * Tos validator
  154. *
  155. * @param \Cake\Validation\Validator $validator Validator instance.
  156. * @return \Cake\Validation\Validator
  157. */
  158. protected function _tosValidator(Validator $validator)
  159. {
  160. $validator
  161. ->requirePresence('tos', 'create')
  162. ->notBlank('tos');
  163. return $validator;
  164. }
  165. /**
  166. * Returns the list of validators
  167. *
  168. * @param array $options Array of options ['validate_email' => true/false, 'use_tos' => true/false]
  169. * @return \Cake\Validation\Validator
  170. */
  171. public function getRegisterValidators($options)
  172. {
  173. $validateEmail = $options['validate_email'] ?? null;
  174. $useTos = $options['use_tos'] ?? null;
  175. $validator = $this->_table->validationDefault(new Validator());
  176. $validator = $this->_table->validationRegister($validator);
  177. if ($useTos) {
  178. $validator = $this->_tosValidator($validator);
  179. }
  180. if ($validateEmail) {
  181. $validator = $this->_emailValidator($validator, $validateEmail);
  182. }
  183. return $validator;
  184. }
  185. /**
  186. * Wrapper for mailer
  187. *
  188. * @param \Cake\Datasource\EntityInterface $user user
  189. * @return void
  190. */
  191. protected function _sendValidationEmail($user)
  192. {
  193. $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users';
  194. $this
  195. ->getMailer($mailer)
  196. ->send('validation', [$user]);
  197. }
  198. }