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