This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace yii2mod\user\models; |
||
4 | |||
5 | use Yii; |
||
6 | use yii\base\NotSupportedException; |
||
7 | use yii\behaviors\TimestampBehavior; |
||
8 | use yii\db\ActiveRecord; |
||
9 | use yii\helpers\ArrayHelper; |
||
10 | use yii\web\IdentityInterface; |
||
11 | use yii2mod\user\models\enums\UserStatus; |
||
12 | use yii2mod\user\traits\EventTrait; |
||
13 | |||
14 | /** |
||
15 | * Class UserModel |
||
16 | * |
||
17 | * @property int $id |
||
18 | * @property string $username |
||
19 | * @property string $password_hash |
||
20 | * @property string $password_reset_token |
||
21 | * @property string $email |
||
22 | * @property string $auth_key |
||
23 | * @property int $status |
||
24 | * @property int $created_at |
||
25 | * @property int $updated_at |
||
26 | * @property int $last_login |
||
27 | * @property string $password write-only password |
||
28 | */ |
||
29 | class UserModel extends ActiveRecord implements IdentityInterface |
||
30 | { |
||
31 | use EventTrait; |
||
32 | |||
33 | /** |
||
34 | * Event is triggered before creating a user. |
||
35 | * Triggered with \yii2mod\user\events\CreateUserEvent. |
||
36 | */ |
||
37 | const BEFORE_CREATE = 'beforeCreate'; |
||
38 | |||
39 | /** |
||
40 | * Event is triggered after creating a user. |
||
41 | * Triggered with \yii2mod\user\events\CreateUserEvent. |
||
42 | */ |
||
43 | const AFTER_CREATE = 'afterCreate'; |
||
44 | |||
45 | /** |
||
46 | * @var string plain password |
||
47 | */ |
||
48 | public $plainPassword; |
||
49 | |||
50 | /** |
||
51 | * @inheritdoc |
||
52 | */ |
||
53 | public static function tableName() |
||
54 | { |
||
55 | return '{{%user}}'; |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * @inheritdoc |
||
60 | */ |
||
61 | View Code Duplication | public function rules() |
|
62 | { |
||
63 | return [ |
||
64 | [['username', 'email'], 'required'], |
||
65 | ['email', 'unique', 'message' => Yii::t('yii2mod.user', 'This email address has already been taken.')], |
||
66 | ['username', 'unique', 'message' => Yii::t('yii2mod.user', 'This username has already been taken.')], |
||
67 | ['username', 'string', 'min' => 2, 'max' => 255], |
||
68 | ['email', 'email'], |
||
69 | ['email', 'string', 'max' => 255], |
||
70 | ['plainPassword', 'string', 'min' => 6], |
||
71 | ['plainPassword', 'required', 'on' => 'create'], |
||
72 | ['status', 'default', 'value' => UserStatus::ACTIVE], |
||
73 | ['status', 'in', 'range' => UserStatus::getConstantsByName()], |
||
74 | ]; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * @inheritdoc |
||
79 | */ |
||
80 | public function attributeLabels() |
||
81 | { |
||
82 | return [ |
||
83 | 'username' => Yii::t('yii2mod.user', 'Username'), |
||
84 | 'email' => Yii::t('yii2mod.user', 'Email'), |
||
85 | 'status' => Yii::t('yii2mod.user', 'Status'), |
||
86 | 'created_at' => Yii::t('yii2mod.user', 'Registration time'), |
||
87 | 'last_login' => Yii::t('yii2mod.user', 'Last login'), |
||
88 | 'plainPassword' => Yii::t('yii2mod.user', 'Password'), |
||
89 | ]; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * @inheritdoc |
||
94 | */ |
||
95 | public function behaviors() |
||
96 | { |
||
97 | return [ |
||
98 | TimestampBehavior::class, |
||
99 | ]; |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * Create user |
||
104 | * |
||
105 | * @return null|UserModel the saved model or null if saving fails |
||
106 | * |
||
107 | * @throws \Exception |
||
108 | */ |
||
109 | public function create() |
||
110 | { |
||
111 | $transaction = $this->getDb()->beginTransaction(); |
||
112 | |||
113 | try { |
||
114 | $event = $this->getCreateUserEvent($this); |
||
115 | $this->trigger(self::BEFORE_CREATE, $event); |
||
116 | |||
117 | $this->setPassword($this->plainPassword); |
||
118 | $this->generateAuthKey(); |
||
119 | |||
120 | if (!$this->save()) { |
||
121 | $transaction->rollBack(); |
||
122 | |||
123 | return null; |
||
124 | } |
||
125 | |||
126 | $this->trigger(self::AFTER_CREATE, $event); |
||
127 | |||
128 | $transaction->commit(); |
||
129 | |||
130 | return $this; |
||
131 | } catch (\Exception $e) { |
||
132 | $transaction->rollBack(); |
||
133 | Yii::warning($e->getMessage()); |
||
134 | throw $e; |
||
135 | } |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * @inheritdoc |
||
140 | */ |
||
141 | public static function findIdentity($id) |
||
142 | { |
||
143 | return static::findOne($id); |
||
0 ignored issues
–
show
|
|||
144 | } |
||
145 | |||
146 | /** |
||
147 | * @inheritdoc |
||
148 | */ |
||
149 | public static function findIdentityByAccessToken($token, $type = null) |
||
150 | { |
||
151 | throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.'); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Finds user (with active status) by username |
||
156 | * |
||
157 | * @param string $username |
||
158 | * |
||
159 | * @return static|null |
||
160 | */ |
||
161 | public static function findByUsername($username) |
||
162 | { |
||
163 | return static::findOne(['username' => $username, 'status' => UserStatus::ACTIVE]); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Finds user by email |
||
168 | * |
||
169 | * @param $email |
||
170 | * |
||
171 | * @return null|static |
||
172 | */ |
||
173 | public static function findByEmail($email) |
||
174 | { |
||
175 | return static::findOne(['email' => $email]); |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * Finds user by password reset token |
||
180 | * |
||
181 | * @param string $token password reset token |
||
182 | * |
||
183 | * @return static|null |
||
184 | */ |
||
185 | public static function findByPasswordResetToken($token) |
||
186 | { |
||
187 | if (!static::isPasswordResetTokenValid($token)) { |
||
188 | return null; |
||
189 | } |
||
190 | |||
191 | return static::findOne([ |
||
192 | 'password_reset_token' => $token, |
||
193 | 'status' => UserStatus::ACTIVE, |
||
194 | ]); |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Finds out if password reset token is valid |
||
199 | * |
||
200 | * @param string $token password reset token |
||
201 | * |
||
202 | * @return bool |
||
203 | */ |
||
204 | public static function isPasswordResetTokenValid($token) |
||
205 | { |
||
206 | if (empty($token)) { |
||
207 | return false; |
||
208 | } |
||
209 | |||
210 | $timestamp = (int) substr($token, strrpos($token, '_') + 1); |
||
211 | $expire = ArrayHelper::getValue(Yii::$app->params, 'user.passwordResetTokenExpire', 3600); |
||
212 | |||
213 | return $timestamp + $expire >= time(); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * @inheritdoc |
||
218 | */ |
||
219 | public function getId() |
||
220 | { |
||
221 | return $this->getPrimaryKey(); |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * @inheritdoc |
||
226 | */ |
||
227 | public function getAuthKey() |
||
228 | { |
||
229 | return $this->auth_key; |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * @inheritdoc |
||
234 | */ |
||
235 | public function validateAuthKey($authKey) |
||
236 | { |
||
237 | return $this->getAuthKey() === $authKey; |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * Validates password |
||
242 | * |
||
243 | * @param string $password password to validate |
||
244 | * |
||
245 | * @return bool if password provided is valid for current user |
||
246 | */ |
||
247 | public function validatePassword($password) |
||
248 | { |
||
249 | return Yii::$app->getSecurity()->validatePassword($password, $this->password_hash); |
||
250 | } |
||
251 | |||
252 | /** |
||
253 | * Generates password hash from password and sets it to the model |
||
254 | * |
||
255 | * @param string $password |
||
256 | */ |
||
257 | public function setPassword($password) |
||
258 | { |
||
259 | $this->password_hash = Yii::$app->getSecurity()->generatePasswordHash($password); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Generates "remember me" authentication key |
||
264 | */ |
||
265 | public function generateAuthKey() |
||
266 | { |
||
267 | $this->auth_key = Yii::$app->getSecurity()->generateRandomString(); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Generates new password reset token |
||
272 | */ |
||
273 | public function generatePasswordResetToken() |
||
274 | { |
||
275 | $this->password_reset_token = Yii::$app->getSecurity()->generateRandomString() . '_' . time(); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Removes password reset token |
||
280 | */ |
||
281 | public function removePasswordResetToken() |
||
282 | { |
||
283 | $this->password_reset_token = null; |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * @param $lastLogin |
||
288 | */ |
||
289 | public function setLastLogin($lastLogin) |
||
290 | { |
||
291 | $this->last_login = $lastLogin; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Update last login |
||
296 | */ |
||
297 | public function updateLastLogin() |
||
298 | { |
||
299 | $this->updateAttributes(['last_login' => time()]); |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * Resets password. |
||
304 | * |
||
305 | * @param string $password |
||
306 | * |
||
307 | * @return bool |
||
308 | */ |
||
309 | public function resetPassword($password) |
||
310 | { |
||
311 | $this->setPassword($password); |
||
312 | |||
313 | return $this->save(true, ['password_hash']); |
||
314 | } |
||
315 | } |
||
316 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.