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.

227 lines
5.2 KiB

  1. <?php
  2. namespace backend\models;
  3. use Yii;
  4. use yii\base\NotSupportedException;
  5. use yii\behaviors\TimestampBehavior;
  6. use yii\db\ActiveRecord;
  7. use yii\web\IdentityInterface;
  8. /**
  9. * User model
  10. *
  11. * @property integer $id
  12. * @property string $username
  13. * @property string $password_hash
  14. * @property string $password_reset_token
  15. * @property string $verification_token
  16. * @property string $email
  17. * @property string $auth_key
  18. * @property integer $status
  19. * @property integer $created_at
  20. * @property integer $updated_at
  21. * @property string $password write-only password
  22. */
  23. class User extends ActiveRecord implements IdentityInterface
  24. {
  25. const STATUS_DELETED = 0;
  26. const STATUS_ACTIVE = 10;
  27. /**
  28. * {@inheritdoc}
  29. */
  30. public static function tableName()
  31. {
  32. return '{{auth_user}}';
  33. }
  34. /**
  35. * {@inheritdoc}
  36. */
  37. public function behaviors()
  38. {
  39. return [
  40. [
  41. 'class' => TimestampBehavior::className(),
  42. 'createdAtAttribute' => 'created_at',
  43. 'updatedAtAttribute' => 'updated_at',
  44. 'value' => function () {
  45. return time();
  46. },
  47. ],
  48. ];
  49. }
  50. /**
  51. * {@inheritdoc}
  52. */
  53. public function rules()
  54. {
  55. return [
  56. ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
  57. ];
  58. }
  59. public function beforeSave($insert)
  60. {
  61. if ($insert) {
  62. $this->email = $this->username . '@example.com';
  63. $this->generateAuthKey();
  64. $this->setPassword(Yii::$app->security->generateRandomString());
  65. }
  66. return parent::beforeSave($insert);
  67. }
  68. /**
  69. * {@inheritdoc}
  70. */
  71. public static function findIdentity($id)
  72. {
  73. return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
  74. }
  75. /**
  76. * {@inheritdoc}
  77. */
  78. public static function findIdentityByAccessToken($token, $type = null)
  79. {
  80. throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
  81. }
  82. /**
  83. * Finds user by username
  84. *
  85. * @param string $username
  86. * @return static|null
  87. */
  88. public static function findByUsername($username)
  89. {
  90. return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
  91. }
  92. /**
  93. * Finds user by password reset token
  94. *
  95. * @param string $token password reset token
  96. * @return static|null
  97. */
  98. public static function findByPasswordResetToken($token)
  99. {
  100. if (!static::isPasswordResetTokenValid($token)) {
  101. return null;
  102. }
  103. return static::findOne([
  104. 'password_reset_token' => $token,
  105. 'status' => self::STATUS_ACTIVE,
  106. ]);
  107. }
  108. /**
  109. * Finds user by verification email token
  110. *
  111. * @param string $token verify email token
  112. * @return static|null
  113. */
  114. public static function findByVerificationToken($token)
  115. {
  116. return static::findOne([
  117. 'verification_token' => $token,
  118. 'status' => self::STATUS_INACTIVE
  119. ]);
  120. }
  121. /**
  122. * Finds out if password reset token is valid
  123. *
  124. * @param string $token password reset token
  125. * @return bool
  126. */
  127. public static function isPasswordResetTokenValid($token)
  128. {
  129. if (empty($token)) {
  130. return false;
  131. }
  132. $timestamp = (int)substr($token, strrpos($token, '_') + 1);
  133. $expire = Yii::$app->params['user.passwordResetTokenExpire'];
  134. return $timestamp + $expire >= time();
  135. }
  136. /**
  137. * {@inheritdoc}
  138. */
  139. public function getId()
  140. {
  141. return $this->getPrimaryKey();
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function getAuthKey()
  147. {
  148. return $this->auth_key;
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function validateAuthKey($authKey)
  154. {
  155. return $this->getAuthKey() === $authKey;
  156. }
  157. /**
  158. * Validates password
  159. *
  160. * @param string $password password to validate
  161. * @return bool if password provided is valid for current user
  162. */
  163. public function validatePassword($password)
  164. {
  165. return Yii::$app->security->validatePassword($password, $this->password_hash);
  166. }
  167. /**
  168. * Generates password hash from password and sets it to the model
  169. *
  170. * @param string $password
  171. */
  172. public function setPassword($password)
  173. {
  174. $this->password_hash = Yii::$app->security->generatePasswordHash($password);
  175. }
  176. /**
  177. * Generates "remember me" authentication key
  178. */
  179. public function generateAuthKey()
  180. {
  181. $this->auth_key = Yii::$app->security->generateRandomString();
  182. }
  183. /**
  184. * Generates new password reset token
  185. */
  186. public function generatePasswordResetToken()
  187. {
  188. $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
  189. }
  190. public function generateEmailVerificationToken()
  191. {
  192. $this->verification_token = Yii::$app->security->generateRandomString() . '_' . time();
  193. }
  194. /**
  195. * Removes password reset token
  196. */
  197. public function removePasswordResetToken()
  198. {
  199. $this->password_reset_token = null;
  200. }
  201. }