1 | <?php |
||||
2 | |||||
3 | use DBAL\db_mysql; |
||||
4 | |||||
5 | /** |
||||
6 | * Class auth_local |
||||
7 | */ |
||||
8 | // Расширяет Modules\sn_module, потому что его потомки так же являются модулями |
||||
9 | class auth_local extends auth_abstract { |
||||
10 | public $versionCommitted = '#46a151#'; |
||||
11 | |||||
12 | public $manifest = [ |
||||
13 | 'package' => 'auth', |
||||
14 | 'name' => 'local', |
||||
15 | 'version' => '0a0', |
||||
16 | 'copyright' => 'Project "SuperNova.WS" #46a151# copyright © 2009-2015 Gorlum', |
||||
17 | |||||
18 | self::M_LOAD_ORDER => MODULE_LOAD_ORDER_AUTH_LOCAL, |
||||
19 | |||||
20 | 'config_path' => SN_ROOT_PHYSICAL, |
||||
21 | ]; |
||||
22 | |||||
23 | public $provider_id = ACCOUNT_PROVIDER_LOCAL; |
||||
24 | |||||
25 | /** |
||||
26 | * Флаг входа в игру |
||||
27 | * |
||||
28 | * @var bool |
||||
29 | */ |
||||
30 | protected $is_login = false; |
||||
31 | /** |
||||
32 | * Флаг регистрации |
||||
33 | * |
||||
34 | * @var bool |
||||
35 | */ |
||||
36 | protected $is_register = false; |
||||
37 | /** |
||||
38 | * Флаг запроса кода на сброс пароля |
||||
39 | * |
||||
40 | * @var bool |
||||
41 | */ |
||||
42 | protected $is_password_reset = false; |
||||
43 | /** |
||||
44 | * Флаг запроса на сброс пароля по коду |
||||
45 | * |
||||
46 | * @var bool |
||||
47 | */ |
||||
48 | protected $is_password_reset_confirm = false; |
||||
49 | /** |
||||
50 | * Нужно ли запоминать креденшиался при выходе из браузера |
||||
51 | * |
||||
52 | * @var bool |
||||
53 | */ |
||||
54 | protected $remember_me = 1; |
||||
55 | |||||
56 | /** |
||||
57 | * @var Confirmation |
||||
58 | */ |
||||
59 | protected $confirmation = null; |
||||
60 | |||||
61 | |||||
62 | protected $features = array( |
||||
63 | AUTH_FEATURE_EMAIL_CHANGE => AUTH_FEATURE_EMAIL_CHANGE, |
||||
64 | AUTH_FEATURE_PASSWORD_RESET => AUTH_FEATURE_PASSWORD_RESET, |
||||
65 | AUTH_FEATURE_PASSWORD_CHANGE => AUTH_FEATURE_PASSWORD_CHANGE, |
||||
66 | AUTH_FEATURE_HAS_PASSWORD => AUTH_FEATURE_HAS_PASSWORD, |
||||
67 | ); |
||||
68 | |||||
69 | /** |
||||
70 | * @var string $input_login_unsafe |
||||
71 | */ |
||||
72 | protected $input_login_unsafe = ''; |
||||
73 | protected $input_login_password_raw = ''; |
||||
74 | protected $input_login_password_raw_repeat = ''; |
||||
75 | protected $input_email_unsafe = ''; |
||||
76 | protected $input_language_unsafe = ''; |
||||
77 | protected $input_language_safe = ''; |
||||
78 | |||||
79 | protected $domain = null; |
||||
80 | protected $sn_root_path = SN_ROOT_RELATIVE; |
||||
81 | protected $cookie_name = SN_COOKIE; |
||||
82 | protected $cookie_name_impersonate = SN_COOKIE_I; |
||||
83 | protected $secret_word = ''; |
||||
84 | |||||
85 | /** |
||||
86 | * @param string $filename |
||||
87 | */ |
||||
88 | public function __construct($filename = __FILE__) { |
||||
89 | parent::__construct($filename); |
||||
90 | |||||
91 | $this->prepare(); |
||||
92 | |||||
93 | $this->active = false; |
||||
94 | if (!empty($this->config) && is_array($this->config['db'])) { |
||||
95 | // БД, отличная от стандартной |
||||
96 | $this->db = new db_mysql(); |
||||
97 | |||||
98 | $this->db->sn_db_connect($this->config['db']); |
||||
99 | if ($this->active = $this->db->connected) { |
||||
100 | $this->provider_id = ACCOUNT_PROVIDER_CENTRAL; |
||||
101 | |||||
102 | $this->domain = $this->config['domain']; |
||||
103 | $this->sn_root_path = $this->config['sn_root_path']; |
||||
104 | $this->cookie_name = $this->config['cookie_name']; |
||||
105 | $this->secret_word = $this->config['secretword']; |
||||
106 | // TODO Проверить наличие всех нужных таблиц |
||||
107 | } else { |
||||
108 | unset($this->db); |
||||
109 | } |
||||
110 | } |
||||
111 | |||||
112 | // Fallback to local DB |
||||
113 | if (!$this->active) { |
||||
114 | $this->db = SN::$db; |
||||
115 | |||||
116 | $this->provider_id = ACCOUNT_PROVIDER_LOCAL; |
||||
117 | |||||
118 | $this->domain = null; |
||||
119 | $this->sn_root_path = SN_ROOT_RELATIVE; |
||||
120 | $this->cookie_name = SN_COOKIE; |
||||
121 | $this->secret_word = SN::$sn_secret_word; |
||||
122 | |||||
123 | $this->active = true; |
||||
124 | } |
||||
125 | |||||
126 | $this->cookie_name_impersonate = $this->cookie_name . AUTH_COOKIE_IMPERSONATE_SUFFIX; |
||||
127 | |||||
128 | $this->account = new Account($this->db); |
||||
129 | $this->confirmation = new Confirmation($this->db); |
||||
130 | } |
||||
131 | |||||
132 | /** |
||||
133 | * Попытка залогиниться с использованием метода $method |
||||
134 | * |
||||
135 | * @param string $method_name |
||||
136 | * |
||||
137 | * @version 4.5 |
||||
138 | * |
||||
139 | */ |
||||
140 | public function login() { |
||||
141 | // TODO Проверяем поддерживаемость метода |
||||
142 | // TODO Пытаемся залогиниться |
||||
143 | $this->password_reset_send_code(); |
||||
144 | $this->password_reset_confirm(); |
||||
145 | $this->register(); |
||||
146 | $this->login_username(); |
||||
147 | $this->login_cookie(); |
||||
148 | |||||
149 | // $this->is_impersonating = $this->account_login_status == LOGIN_SUCCESS && !empty($_COOKIE[$this->cookie_name_impersonate]); |
||||
150 | |||||
151 | return $this->account_login_status; |
||||
152 | } |
||||
153 | |||||
154 | public function logout() { |
||||
155 | $this->cookie_clear(); |
||||
156 | } |
||||
157 | |||||
158 | /** |
||||
159 | * Меняет пароль у аккаунта с проверкой старого пароля |
||||
160 | * |
||||
161 | * @param $old_password_unsafe |
||||
162 | * @param $new_password_unsafe |
||||
163 | * @param null $salt_unsafe |
||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||
164 | * |
||||
165 | * @return array|bool|resource |
||||
166 | * @throws Exception |
||||
167 | */ |
||||
168 | public function password_change($old_password_unsafe, $new_password_unsafe, $salt_unsafe = null) { |
||||
169 | $result = parent::password_change($old_password_unsafe, $new_password_unsafe, $salt_unsafe); |
||||
170 | if ($result) { |
||||
171 | $this->cookie_set(); |
||||
172 | } |
||||
173 | |||||
174 | return $result; |
||||
175 | } |
||||
176 | |||||
177 | public function impersonate($account_to_impersonate) { |
||||
178 | $this->cookie_set($account_to_impersonate); |
||||
179 | } |
||||
180 | |||||
181 | /** |
||||
182 | * @param Account $account |
||||
183 | */ |
||||
184 | public function login_with_account($account) { |
||||
185 | $this->account = $account; |
||||
186 | $this->cookie_set(); |
||||
187 | |||||
188 | return $this->login_cookie(); |
||||
189 | } |
||||
190 | |||||
191 | |||||
192 | /** |
||||
193 | * Отсылает письмо с кодом подтверждения для сброса пароля |
||||
194 | * |
||||
195 | * @return int|string |
||||
196 | */ |
||||
197 | protected function password_reset_send_code() { |
||||
198 | global $lang, $config; |
||||
199 | |||||
200 | if (!$this->is_password_reset) { |
||||
201 | return $this->account_login_status; |
||||
202 | } |
||||
203 | |||||
204 | // Проверяем поддержку сброса пароля |
||||
205 | if (!$this->is_feature_supported(AUTH_FEATURE_PASSWORD_RESET)) { |
||||
206 | return $this->account_login_status; |
||||
207 | } |
||||
208 | |||||
209 | try { |
||||
210 | $email_unsafe = $this->input_email_unsafe; |
||||
211 | |||||
212 | unset($this->account); |
||||
213 | $this->account = new Account($this->db); |
||||
214 | |||||
215 | if (!$this->account->db_get_by_email($email_unsafe)) { |
||||
216 | throw new Exception(PASSWORD_RESTORE_ERROR_EMAIL_NOT_EXISTS, ERR_ERROR); |
||||
217 | // return $this->account_login_status; |
||||
218 | } |
||||
219 | |||||
220 | $account_translation = PlayerToAccountTranslate::db_translate_get_users_from_account_list($this->provider_id, $this->account->account_id); // OK 4.5 |
||||
221 | $user_list = db_user_list_by_id(array_keys($account_translation)); |
||||
222 | |||||
223 | // TODO - Проверять уровень доступа аккаунта! |
||||
224 | // Аккаунты с АУТЛЕВЕЛ больше 0 - НЕ СБРАСЫВАЮТ ПАРОЛИ! |
||||
225 | foreach ($user_list as $user_id => $user_data) { |
||||
226 | if ($user_data['authlevel'] > AUTH_LEVEL_REGISTERED) { |
||||
227 | throw new Exception(PASSWORD_RESTORE_ERROR_ADMIN_ACCOUNT, ERR_ERROR); |
||||
228 | } |
||||
229 | } |
||||
230 | |||||
231 | $confirmation = $this->confirmation->db_confirmation_get_latest_by_type_and_email(CONFIRM_PASSWORD_RESET, $email_unsafe); // OK 4.5 |
||||
232 | if (isset($confirmation['create_time']) && SN_TIME_NOW - strtotime($confirmation['create_time']) < PERIOD_MINUTE_10) { |
||||
233 | throw new Exception(PASSWORD_RESTORE_ERROR_TOO_OFTEN, ERR_ERROR); |
||||
234 | } |
||||
235 | |||||
236 | // Удаляем предыдущие записи продтверждения сброса пароля |
||||
237 | !empty($confirmation['id']) or $this->confirmation->db_confirmation_delete_by_type_and_email(CONFIRM_PASSWORD_RESET, $email_unsafe); // OK 4.5 |
||||
238 | |||||
239 | db_mysql::db_transaction_start(); |
||||
240 | $confirm_code_unsafe = $this->confirmation->db_confirmation_get_unique_code_by_type_and_email(CONFIRM_PASSWORD_RESET, $email_unsafe); // OK 4.5 |
||||
241 | db_mysql::db_transaction_commit(); |
||||
242 | |||||
243 | if (!is_email($email_unsafe)) { |
||||
244 | SN::$debug->error("Email is invalid: '{$email_unsafe}'", 'Invalid email for password restoration'); |
||||
245 | } |
||||
246 | |||||
247 | @$result = mymail($email_unsafe, |
||||
248 | sprintf($lang['log_lost_email_title'], $config->game_name), |
||||
249 | sprintf($lang['log_lost_email_code'], SN_ROOT_VIRTUAL . 'login.php', $confirm_code_unsafe, date(FMT_DATE_TIME, SN_TIME_NOW + AUTH_PASSWORD_RESET_CONFIRMATION_EXPIRE), $config->game_name) |
||||
250 | ); |
||||
251 | |||||
252 | $result = $result ? PASSWORD_RESTORE_SUCCESS_CODE_SENT : PASSWORD_RESTORE_ERROR_SENDING; |
||||
253 | } catch (Exception $e) { |
||||
254 | db_mysql::db_transaction_rollback(); |
||||
255 | $result = $e->getMessage(); |
||||
256 | } |
||||
257 | |||||
258 | return $this->account_login_status = $result; |
||||
0 ignored issues
–
show
The property
$account_login_status was declared of type integer , but $result is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
259 | } |
||||
260 | |||||
261 | /** |
||||
262 | * Сброс пароля по введенному коду подтверждения |
||||
263 | * |
||||
264 | * @return int|string |
||||
265 | */ |
||||
266 | protected function password_reset_confirm() { |
||||
267 | global $lang, $config; |
||||
268 | |||||
269 | if (!$this->is_password_reset_confirm) { |
||||
270 | return $this->account_login_status; |
||||
271 | } |
||||
272 | |||||
273 | if ($this->account_login_status != LOGIN_UNDEFINED) { |
||||
274 | return $this->account_login_status; |
||||
275 | } |
||||
276 | |||||
277 | // Проверяем поддержку сброса пароля |
||||
278 | if (!$this->is_feature_supported(AUTH_FEATURE_PASSWORD_RESET)) { |
||||
279 | return $this->account_login_status; |
||||
280 | } |
||||
281 | |||||
282 | try { |
||||
283 | $code_unsafe = sys_get_param_str_unsafe('password_reset_code'); |
||||
284 | if (empty($code_unsafe)) { |
||||
285 | throw new Exception(PASSWORD_RESTORE_ERROR_CODE_EMPTY, ERR_ERROR); |
||||
286 | } |
||||
287 | |||||
288 | db_mysql::db_transaction_start(); |
||||
289 | $confirmation = $this->confirmation->db_confirmation_get_by_type_and_code(CONFIRM_PASSWORD_RESET, $code_unsafe); // OK 4.5 |
||||
290 | |||||
291 | if (empty($confirmation)) { |
||||
292 | throw new Exception(PASSWORD_RESTORE_ERROR_CODE_WRONG, ERR_ERROR); |
||||
293 | } |
||||
294 | |||||
295 | if (SN_TIME_NOW - strtotime($confirmation['create_time']) > AUTH_PASSWORD_RESET_CONFIRMATION_EXPIRE) { |
||||
296 | throw new Exception(PASSWORD_RESTORE_ERROR_CODE_TOO_OLD, ERR_ERROR); |
||||
297 | } |
||||
298 | |||||
299 | unset($this->account); |
||||
300 | $this->account = new Account($this->db); |
||||
301 | |||||
302 | if (!$this->account->db_get_by_email($confirmation['email'])) { |
||||
303 | throw new Exception(PASSWORD_RESTORE_ERROR_CODE_OK_BUT_NO_ACCOUNT_FOR_EMAIL, ERR_ERROR); |
||||
304 | } |
||||
305 | |||||
306 | $new_password_unsafe = $this->make_random_password(); |
||||
307 | $salt_unsafe = $this->password_salt_generate(); |
||||
308 | if (!$this->account->db_set_password($new_password_unsafe, $salt_unsafe)) { |
||||
309 | // Ошибка смены пароля |
||||
310 | throw new Exception(AUTH_ERROR_INTERNAL_PASSWORD_CHANGE_ON_RESTORE, ERR_ERROR); |
||||
311 | } |
||||
312 | |||||
313 | $this->account_login_status = LOGIN_UNDEFINED; |
||||
314 | $this->remember_me = 1; |
||||
315 | $this->cookie_set(); |
||||
316 | $this->login_cookie(); |
||||
317 | |||||
318 | if ($this->account_login_status == LOGIN_SUCCESS) { |
||||
319 | // TODO - НЕ ОБЯЗАТЕЛЬНО ОТПРАВЛЯТЬ ЧЕРЕЗ ЕМЕЙЛ! ЕСЛИ ЭТО ФЕЙСБУЧЕК ИЛИ ВКШЕЧКА - МОЖНО ЧЕРЕЗ ЛС ПИСАТЬ!! |
||||
320 | $message_header = sprintf($lang['log_lost_email_title'], $config->game_name); |
||||
321 | $message = sprintf($lang['log_lost_email_pass'], $config->game_name, $this->account->account_name, $new_password_unsafe); |
||||
322 | @$operation_result = mymail($confirmation['email'], $message_header, htmlspecialchars($message)); |
||||
0 ignored issues
–
show
|
|||||
323 | |||||
324 | $users_translated = PlayerToAccountTranslate::db_translate_get_users_from_account_list($this->provider_id, $this->account->account_id); // OK 4.5 |
||||
325 | if (!empty($users_translated)) { |
||||
326 | // Отправляем в лички письмо о сбросе пароля |
||||
327 | |||||
328 | // ПО ОПРЕДЕЛЕНИЮ в $users_translated только |
||||
329 | // - аккаунты, поддерживающие сброс пароля |
||||
330 | // - список аккаунтов, имеющих тот же емейл, что указан в Подтверждении |
||||
331 | // - игроки, привязанные только к этим аккаунтам |
||||
332 | // Значит им всем сразу скопом можно отправлять сообщения |
||||
333 | $message = sprintf($lang['sys_password_reset_message_body'], $new_password_unsafe); |
||||
334 | $message = HelperString::nl2br($message) . '<br><br>'; |
||||
335 | // msg_send_simple_message($found_provider->data[F_USER_ID], 0, SN_TIME_NOW, MSG_TYPE_ADMIN, $lang['sys_administration'], $lang['sys_login_register_message_title'], $message); |
||||
336 | |||||
337 | foreach ($users_translated as $user_id => $providers_list) { |
||||
338 | msg_send_simple_message($user_id, 0, SN_TIME_NOW, MSG_TYPE_ADMIN, $lang['sys_administration'], $lang['sys_login_register_message_title'], $message); |
||||
339 | } |
||||
340 | } else { |
||||
341 | // Фигня - может быть и пустой, если у нас есть только аккаунт, но нет пользователей |
||||
342 | // throw new Exception(AUTH_PASSWORD_RESET_INSIDE_ERROR_NO_ACCOUNT_FOR_CONFIRMATION, ERR_ERROR); |
||||
343 | } |
||||
344 | } |
||||
345 | |||||
346 | $this->confirmation->db_confirmation_delete_by_type_and_email(CONFIRM_PASSWORD_RESET, $confirmation['email']); // OK 4.5 |
||||
347 | |||||
348 | db_mysql::db_transaction_commit(); |
||||
349 | |||||
350 | sys_redirect('overview.php'); |
||||
351 | } catch (Exception $e) { |
||||
352 | db_mysql::db_transaction_rollback(); |
||||
353 | $this->account_login_status = $e->getMessage(); |
||||
0 ignored issues
–
show
The property
$account_login_status was declared of type integer , but $e->getMessage() is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
354 | } |
||||
355 | |||||
356 | return $this->account_login_status; |
||||
357 | } |
||||
358 | |||||
359 | /** |
||||
360 | * Функция инициализирует данные провайдера - разворачивает куки, берет данные итд |
||||
361 | */ |
||||
362 | protected function prepare() { |
||||
363 | $this->input_login_unsafe = sys_get_param_str_unsafe('username', sys_get_param_str_unsafe('email')); // TODO переделать эту порнографию |
||||
364 | |||||
365 | $this->is_login = sys_get_param('login') ? true : false; |
||||
366 | $this->is_register = sys_get_param('register') ? true : false; |
||||
367 | $this->is_password_reset = sys_get_param('password_reset') ? true : false; |
||||
368 | $this->is_password_reset_confirm = sys_get_param('password_reset_confirm') ? true : false; |
||||
369 | |||||
370 | $this->remember_me = intval(sys_get_param_int('rememberme') || $this->is_register); |
||||
0 ignored issues
–
show
The property
$remember_me was declared of type boolean , but intval(sys_get_param_int... || $this->is_register) is of type integer . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
371 | $this->input_login_password_raw = sys_get_param('password'); |
||||
372 | $this->input_login_password_raw_repeat = sys_get_param('password_repeat'); |
||||
373 | $this->input_email_unsafe = sys_get_param_str_unsafe('email'); |
||||
374 | $this->input_language_unsafe = sys_get_param_str_unsafe('lang', DEFAULT_LANG); |
||||
375 | $this->input_language_safe = sys_get_param_str('lang', DEFAULT_LANG); |
||||
376 | |||||
377 | } |
||||
378 | |||||
379 | /** |
||||
380 | * Пытается зарегестрировать пользователя по введенным данным |
||||
381 | * @return mixed |
||||
382 | * @version 4.5 |
||||
383 | * |
||||
384 | */ |
||||
385 | protected function register() { |
||||
386 | // TODO РЕГИСТРАЦИЯ ВСЕГДА ДОЛЖНА ЛОГИНИТЬ ПОЛЬЗОВАТЕЛЯ! |
||||
387 | $this->flog('Регистрация: начинаем. Провайдер ' . $this->provider_id); |
||||
388 | |||||
389 | if (!$this->is_register) { |
||||
390 | $this->flog('Регистрация: не выставлен флаг регистрации - пропускаем'); |
||||
391 | } else { |
||||
392 | try { |
||||
393 | |||||
394 | $this->register_validate_input(); |
||||
395 | |||||
396 | db_mysql::db_transaction_start(); |
||||
397 | $this->account->db_get_by_name_or_email($this->input_login_unsafe, $this->input_email_unsafe); |
||||
398 | if ($this->account->is_exists) { |
||||
399 | if ($this->account->account_email == $this->input_email_unsafe) { |
||||
400 | throw new Exception(REGISTER_ERROR_EMAIL_EXISTS, ERR_ERROR); |
||||
401 | } else { |
||||
402 | throw new Exception(REGISTER_ERROR_ACCOUNT_NAME_EXISTS, ERR_ERROR); |
||||
403 | } |
||||
404 | } |
||||
405 | |||||
406 | // Проблемы с созданием аккаунта - вызовут эксершн и обработается catch() |
||||
407 | $this->account->db_create( |
||||
408 | $this->input_login_unsafe, |
||||
409 | $this->input_login_password_raw, |
||||
410 | $this->input_email_unsafe, |
||||
411 | $this->input_language_unsafe |
||||
412 | ); |
||||
413 | |||||
414 | // Устанавливать не надо - мы дальше пойдем по workflow |
||||
415 | $this->account_login_status = LOGIN_SUCCESS; |
||||
416 | $this->cookie_set(); |
||||
417 | |||||
418 | // А вот это пока не нужно. Трансляцией аккаунтов в юзеров и созданием новых юзеров для новозашедших аккаунтов занимается Auth |
||||
419 | // $this->register_account(); |
||||
420 | db_mysql::db_transaction_commit(); |
||||
421 | } catch (Exception $e) { |
||||
422 | db_mysql::db_transaction_rollback(); |
||||
423 | $this->account_login_status == LOGIN_UNDEFINED ? $this->account_login_status = $e->getMessage() : false; |
||||
0 ignored issues
–
show
The property
$account_login_status was declared of type integer , but $e->getMessage() is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
424 | } |
||||
425 | } |
||||
426 | |||||
427 | return $this->account_login_status; |
||||
428 | } |
||||
429 | |||||
430 | /** |
||||
431 | * Пытается залогинить пользователя по куке |
||||
432 | * @return int Результат попытки |
||||
433 | * @version 4.5 |
||||
434 | * |
||||
435 | */ |
||||
436 | protected function login_cookie() { |
||||
437 | if ($this->account_login_status != LOGIN_UNDEFINED) { |
||||
438 | return $this->account_login_status; |
||||
439 | } |
||||
440 | |||||
441 | if ($this->account->cookieLogin($rememberMe)) { |
||||
442 | $this->account_login_status = LOGIN_SUCCESS; |
||||
443 | $this->remember_me = intval($rememberMe); |
||||
0 ignored issues
–
show
The property
$remember_me was declared of type boolean , but intval($rememberMe) is of type integer . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
444 | } |
||||
445 | |||||
446 | return $this->account_login_status; |
||||
447 | } |
||||
448 | |||||
449 | /** |
||||
450 | * Пытается залогинить пользователя по имени аккаунта и паролю |
||||
451 | * @return mixed |
||||
452 | * @version 4.5 |
||||
453 | * |
||||
454 | */ |
||||
455 | protected function login_username() { |
||||
456 | // TODO - Логин по старым именам |
||||
457 | try { |
||||
458 | if (!$this->is_login) { |
||||
459 | $this->flog('Логин: не выставлен флаг входа в игру - это не логин'); |
||||
460 | throw new Exception(LOGIN_UNDEFINED, ERR_ERROR); |
||||
461 | } |
||||
462 | |||||
463 | // TODO Пустое имя аккаунта |
||||
464 | if (!$this->input_login_unsafe) { |
||||
465 | throw new Exception(LOGIN_UNDEFINED, ERR_ERROR); |
||||
466 | } |
||||
467 | |||||
468 | $this->login_validate_input(); |
||||
469 | |||||
470 | if (!$this->account->db_get_by_name($this->input_login_unsafe) && !$this->account->db_get_by_email($this->input_login_unsafe)) { |
||||
471 | throw new Exception(LOGIN_ERROR_USERNAME, ERR_ERROR); |
||||
472 | } |
||||
473 | |||||
474 | if (!$this->account->password_check($this->input_login_password_raw)) { |
||||
475 | throw new Exception(LOGIN_ERROR_PASSWORD, ERR_ERROR); |
||||
476 | } |
||||
477 | |||||
478 | $this->cookie_set(); |
||||
479 | $this->account_login_status = LOGIN_SUCCESS; |
||||
480 | } catch (Exception $e) { |
||||
481 | $this->account_login_status == LOGIN_UNDEFINED ? $this->account_login_status = $e->getMessage() : false; |
||||
0 ignored issues
–
show
The property
$account_login_status was declared of type integer , but $e->getMessage() is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||||
482 | } |
||||
483 | |||||
484 | return $this->account_login_status; |
||||
485 | } |
||||
486 | |||||
487 | /** |
||||
488 | * Устанавливает куку аккаунта по данным $this->data[F_ACCOUNT] |
||||
489 | * |
||||
490 | * @param Account|null $account_to_impersonate |
||||
491 | * |
||||
492 | * @return bool |
||||
493 | * @throws Exception |
||||
494 | * |
||||
495 | */ |
||||
496 | // TODO - должен устанавливать куку исходя из пользователя, что бы пользователь мог логинится |
||||
497 | // TODO - или ставить мультикуку - хотя нахуя, спрашивается |
||||
498 | protected function cookie_set($account_to_impersonate = null) { |
||||
499 | $this_account = is_object($account_to_impersonate) ? $account_to_impersonate : $this->account; |
||||
500 | |||||
501 | if (!is_object($this_account) || !$this_account->is_exists) { |
||||
502 | throw new Exception(LOGIN_ERROR_NO_ACCOUNT_FOR_COOKIE_SET, ERR_ERROR); |
||||
503 | } |
||||
504 | |||||
505 | if (is_object($account_to_impersonate) && $account_to_impersonate->is_exists) { |
||||
506 | sn_setcookie($this->cookie_name_impersonate, $_COOKIE[$this->cookie_name], SN_TIME_NOW + PERIOD_YEAR, $this->sn_root_path, $this->domain); |
||||
507 | } |
||||
508 | |||||
509 | $this->flog("cookie_set() - Устанавливаем куку"); |
||||
510 | |||||
511 | return $this_account->cookieSet($this->remember_me, $this->domain); |
||||
512 | } |
||||
513 | |||||
514 | /** |
||||
515 | * Очищает куку аккаунта - совсем или восстанавливая куку текущего имперсонатора |
||||
516 | */ |
||||
517 | protected function cookie_clear() { |
||||
518 | $this->account->cookieClear($this->domain); |
||||
519 | } |
||||
520 | |||||
521 | |||||
522 | // ХЕЛПЕРЫ =========================================================================================================== |
||||
523 | |||||
524 | /** |
||||
525 | * Проверяет введенные данные логина на корректность |
||||
526 | * |
||||
527 | * @throws Exception |
||||
528 | */ |
||||
529 | protected function login_validate_input() { |
||||
530 | // Проверяем, что бы в начале и конце не было пустых символов |
||||
531 | // TODO - при копировании Эксель -> Опера - в конце образуются пустые места. Это не должно быть проблемой! Вынести проверку пароля в регистрацию! |
||||
532 | if ($this->input_login_password_raw != trim($this->input_login_password_raw)) { |
||||
533 | throw new Exception(LOGIN_ERROR_PASSWORD_TRIMMED, ERR_ERROR); |
||||
534 | } |
||||
535 | if (!$this->input_login_password_raw) { |
||||
536 | throw new Exception(LOGIN_ERROR_PASSWORD_EMPTY, ERR_ERROR); |
||||
537 | } |
||||
538 | } |
||||
539 | |||||
540 | /** |
||||
541 | * Проверяет данные для регистрации на корректность |
||||
542 | * |
||||
543 | * @throws Exception |
||||
544 | */ |
||||
545 | protected function register_validate_input() { |
||||
546 | // То, что не подходит для логина - не подходит и для регистрации |
||||
547 | $this->login_validate_input(); |
||||
548 | |||||
549 | // Если нет имени пользователя - NO GO! |
||||
550 | if (!$this->input_login_unsafe) { |
||||
551 | throw new Exception(LOGIN_ERROR_USERNAME_EMPTY, ERR_ERROR); |
||||
552 | } |
||||
553 | // Если логин имеет запрещенные символы - NO GO! |
||||
554 | if (strpbrk($this->input_login_unsafe, LOGIN_REGISTER_CHARACTERS_PROHIBITED)) { |
||||
555 | throw new Exception(LOGIN_ERROR_USERNAME_RESTRICTED_CHARACTERS, ERR_ERROR); |
||||
556 | } |
||||
557 | // Если логин меньше минимальной длины - NO GO! |
||||
558 | if (strlen($this->input_login_unsafe) < LOGIN_LENGTH_MIN) { |
||||
559 | throw new Exception(REGISTER_ERROR_USERNAME_SHORT, ERR_ERROR); |
||||
560 | } |
||||
561 | // Если пароль меньше минимальной длины - NO GO! |
||||
562 | if (strlen($this->input_login_password_raw) < PASSWORD_LENGTH_MIN) { |
||||
563 | throw new Exception(REGISTER_ERROR_PASSWORD_INSECURE, ERR_ERROR); |
||||
564 | } |
||||
565 | // Если пароль имеет пробельные символы в начале или конце - NO GO! |
||||
566 | if ($this->input_login_password_raw != trim($this->input_login_password_raw)) { |
||||
567 | throw new Exception(LOGIN_ERROR_PASSWORD_TRIMMED, ERR_ERROR); |
||||
568 | } |
||||
569 | // Если пароль не совпадает с подтверждением - NO GO! То, что у пароля нет пробельных символов в начале/конце - мы уже проверили выше |
||||
570 | //Если они есть у повтора - значит пароль и повтор не совпадут |
||||
571 | if ($this->input_login_password_raw <> $this->input_login_password_raw_repeat) { |
||||
572 | throw new Exception(REGISTER_ERROR_PASSWORD_DIFFERENT, ERR_ERROR); |
||||
573 | } |
||||
574 | // Если нет емейла - NO GO! |
||||
575 | // TODO - регистрация без емейла |
||||
576 | if (!$this->input_email_unsafe) { |
||||
577 | throw new Exception(REGISTER_ERROR_EMAIL_EMPTY, ERR_ERROR); |
||||
578 | } |
||||
579 | // Если емейл не является емейлом - NO GO! |
||||
580 | if (!is_email($this->input_email_unsafe)) { |
||||
581 | throw new Exception(REGISTER_ERROR_EMAIL_WRONG, ERR_ERROR); |
||||
582 | } |
||||
583 | } |
||||
584 | |||||
585 | |||||
586 | protected function password_encode($password, $salt) { |
||||
587 | return core_auth::password_encode($password, $salt); |
||||
588 | } |
||||
589 | |||||
590 | protected function password_salt_generate() { |
||||
591 | return core_auth::password_salt_generate(); |
||||
592 | } |
||||
593 | |||||
594 | /** |
||||
595 | * Генерирует случайный пароль |
||||
596 | * |
||||
597 | * @return string |
||||
598 | */ |
||||
599 | protected function make_random_password() { |
||||
600 | return core_auth::make_random_password(); |
||||
601 | } |
||||
602 | |||||
603 | protected function flog($message, $die = false) { |
||||
604 | if (!defined('DEBUG_AUTH') || !DEBUG_AUTH) { |
||||
0 ignored issues
–
show
|
|||||
605 | return; |
||||
606 | } |
||||
607 | list($called, $caller) = debug_backtrace(false); |
||||
0 ignored issues
–
show
false of type false is incompatible with the type integer expected by parameter $options of debug_backtrace() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
608 | |||||
609 | $caller_name = |
||||
610 | ((get_called_class()) ? get_called_class() : (!empty($caller['class']) ? $caller['class'] : '')) . |
||||
611 | (!empty($caller['type']) ? $caller['type'] : '') . |
||||
612 | (!empty($caller['function']) ? $caller['function'] : '') . |
||||
613 | (!empty($called['line']) ? ':' . $called['line'] : ''); |
||||
614 | |||||
615 | $_SERVER['SERVER_NAME'] == 'localhost' ? print("<div class='debug'>$message - $caller_name\r\n</div>") : false; |
||||
616 | |||||
617 | SN::log_file("$message - $caller_name"); |
||||
618 | if ($die) { |
||||
619 | $die && die("<div class='negative'>СТОП! Функция {$caller_name} при вызове в " . get_called_class() . " (располагается в " . get_class() . "). СООБЩИТЕ АДМИНИСТРАЦИИ!</div>"); |
||||
0 ignored issues
–
show
|
|||||
620 | } |
||||
621 | } |
||||
622 | |||||
623 | } |
||||
624 |