Просмотр файла app/Controllers/User/UserController.php

Размер файла: 32.47Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace App\Controllers\User;
  6.  
  7. use App\Classes\Validator;
  8. use App\Controllers\BaseController;
  9. use App\Models\BlackList;
  10. use App\Models\ChangeMail;
  11. use App\Models\Flood;
  12. use App\Models\Invite;
  13. use App\Models\Online;
  14. use App\Models\User;
  15. use Exception;
  16. use GuzzleHttp\Exception\GuzzleException;
  17. use Illuminate\Database\Capsule\Manager as DB;
  18. use Illuminate\Http\Request;
  19. use Illuminate\Support\Str;
  20.  
  21. class UserController extends BaseController
  22. {
  23. /**
  24. * User profile
  25. *
  26. * @param string $login
  27. *
  28. * @return string
  29. */
  30. public function index(string $login): string
  31. {
  32. if (! $user = getUserByLogin($login)) {
  33. abort(404, __('validator.user'));
  34. }
  35.  
  36. $invite = Invite::query()->where('invite_user_id', $user->id)->first();
  37. $user->load('lastBan');
  38.  
  39. $adminGroups = User::ADMIN_GROUPS;
  40.  
  41. return view('users/user', compact('user', 'invite', 'adminGroups'));
  42. }
  43.  
  44. /**
  45. * Note
  46. *
  47. * @param string $login
  48. * @param Request $request
  49. * @param Validator $validator
  50. *
  51. * @return string
  52. */
  53. public function note(string $login, Request $request, Validator $validator): string
  54. {
  55. if (! isAdmin()) {
  56. abort(403, __('main.page_only_admins'));
  57. }
  58.  
  59. if (! $user = getUserByLogin($login)) {
  60. abort(404, __('validator.user'));
  61. }
  62.  
  63. if ($request->isMethod('post')) {
  64. $notice = $request->input('notice');
  65.  
  66. $validator->equal($request->input('token'), $_SESSION['token'], ['notice' => __('validator.token')])
  67. ->length($notice, 0, 1000, ['notice' => __('users.note_to_big')]);
  68.  
  69. if ($validator->isValid()) {
  70. $user->note()->updateOrCreate([], [
  71. 'text' => $notice,
  72. 'edit_user_id' => getUser('id'),
  73. 'updated_at' => SITETIME,
  74. ]);
  75.  
  76. setFlash('success', __('users.note_saved_success'));
  77. redirect('/users/' . $user->login);
  78. } else {
  79. setInput($request->all());
  80. setFlash('danger', $validator->getErrors());
  81. }
  82. }
  83.  
  84. return view('users/note', compact('user'));
  85. }
  86.  
  87. /**
  88. * Registration
  89. *
  90. * @param Request $request
  91. * @param Validator $validator
  92. *
  93. * @return string
  94. */
  95. public function register(Request $request, Validator $validator): string
  96. {
  97. if (getUser()) {
  98. abort(403, __('users.already_registered'));
  99. }
  100.  
  101. if (! setting('openreg')) {
  102. abort('default', __('users.registration_suspended'));
  103. }
  104.  
  105. if ($request->isMethod('post')) {
  106. if ($request->has('login') && $request->has('password')) {
  107. $login = $request->input('login');
  108. $password = trim($request->input('password'));
  109. $password2 = trim($request->input('password2'));
  110. $invite = setting('invite') ? $request->input('invite') : '';
  111. $email = strtolower($request->input('email'));
  112. $domain = utfSubstr(strrchr($email, '@'), 1);
  113. $gender = $request->input('gender') === 'male' ? 'male' : 'female';
  114. $level = User::USER;
  115. $activateLink = null;
  116. $activateKey = null;
  117. $invitation = null;
  118.  
  119. $validator->true(captchaVerify(), ['protect' => __('validator.captcha')])
  120. ->regex($login, '|^[a-z0-9\-]+$|i', ['login' => __('validator.login')])
  121. ->regex(utfSubstr($login, 0, 1), '|^[a-z0-9]+$|i', ['login' => __('users.login_begin_requirements')])
  122. ->email($email, ['email' => __('validator.email')])
  123. ->length($invite, 12, 15, ['invite' => __('users.invite_length_requirements')], (bool) setting('invite'))
  124. ->length($login, 3, 20, ['login' => __('users.login_length_requirements')])
  125. ->length($password, 6, 20, ['password' => __('users.password_length_requirements')])
  126. ->equal($password, $password2, ['password2' => __('users.passwords_different')])
  127. ->false(ctype_digit($login), ['login' => __('users.field_characters_requirements')])
  128. ->false(ctype_digit($password), ['password' => __('users.field_characters_requirements')])
  129. ->false(substr_count($login, '-') > 2, ['login' => __('users.login_hyphens_requirements')]);
  130.  
  131. if (! empty($login)) {
  132. // Проверка логина на существование
  133. $checkLogin = User::query()->where('login', $login)->exists();
  134. $validator->false($checkLogin, ['login' => __('users.login_already_exists')]);
  135.  
  136. // Проверка логина в черном списке
  137. $blackLogin = Blacklist::query()
  138. ->where('type', 'login')
  139. ->where('value', strtolower($login))
  140. ->exists();
  141. $validator->false($blackLogin, ['login' => __('users.login_is_blacklisted')]);
  142. }
  143.  
  144. // Проверка email на существование
  145. $checkMail = User::query()->where('email', $email)->exists();
  146. $validator->false($checkMail, ['email' => __('users.email_already_exists')]);
  147.  
  148. // Проверка домена от email в черном списке
  149. $blackDomain = Blacklist::query()
  150. ->where('type', 'domain')
  151. ->where('value', $domain)
  152. ->exists();
  153. $validator->false($blackDomain, ['email' => __('users.domain_is_blacklisted')]);
  154.  
  155. // Проверка email в черном списке
  156. $blackMail = Blacklist::query()
  157. ->where('type', 'email')
  158. ->where('value', $email)
  159. ->exists();
  160. $validator->false($blackMail, ['email' => __('users.email_is_blacklisted')]);
  161.  
  162. // Проверка пригласительного ключа
  163. if (setting('invite')) {
  164. $invitation = Invite::query()
  165. ->select('id')
  166. ->where('hash', $invite)
  167. ->where('used', 0)
  168. ->first();
  169.  
  170. $validator->notEmpty($invitation, ['invite' => __('users.invitation_invalid')]);
  171. }
  172.  
  173. // Регистрация аккаунта
  174. if ($validator->isValid()) {
  175. if (setting('regkeys')) {
  176. $activateKey = Str::random();
  177. $activateLink = siteUrl(true) . '/key?code=' . $activateKey;
  178. $level = User::PENDED;
  179. }
  180.  
  181. /* @var User $user */
  182. $user = User::query()->create([
  183. 'login' => $login,
  184. 'password' => password_hash($password, PASSWORD_BCRYPT),
  185. 'email' => $email,
  186. 'level' => $level,
  187. 'gender' => $gender,
  188. 'themes' => setting('themes'),
  189. 'point' => 0,
  190. 'language' => setting('language'),
  191. 'money' => setting('registermoney'),
  192. 'confirmregkey' => $activateKey,
  193. 'subscribe' => Str::random(32),
  194. 'updated_at' => SITETIME,
  195. 'created_at' => SITETIME,
  196. ]);
  197.  
  198. // Активация пригласительного ключа
  199. if ($invitation && setting('invite')) {
  200. $invitation->update([
  201. 'used' => 1,
  202. 'invite_user_id' => $user->id,
  203. ]);
  204. }
  205.  
  206. // ----- Уведомление в приват ----//
  207. $textNotice = textNotice('register', ['username' => $login]);
  208. $user->sendMessage(null, $textNotice);
  209.  
  210. // --- Уведомление о регистрации на email ---//
  211. $message = 'Добро пожаловать, ' . $login . '<br>Теперь вы зарегистрированный пользователь сайта <a href="' . siteUrl(true) . '">' . setting('title') . '</a> , сохраните ваш логин и пароль в надежном месте, они вам еще пригодятся. <br>Ваши данные для входа на сайт <br><b>Логин: ' . $login . '</b><br><b>Пароль: ' . $password . '</b>';
  212.  
  213. $subject = 'Регистрация на ' . setting('title');
  214. $body = view('mailer.register', compact('subject', 'message', 'activateKey', 'activateLink'));
  215. sendMail($email, $subject, $body);
  216.  
  217. User::auth($login, $password);
  218.  
  219. setFlash('success', __('users.welcome', ['login' => $login]));
  220. redirect('/');
  221. } else {
  222. setInput($request->all());
  223. setFlash('danger', $validator->getErrors());
  224. }
  225. }
  226.  
  227. if ($request->has('token')) {
  228. User::socialAuth($request->input('token'));
  229. }
  230. }
  231.  
  232. return view('users/register');
  233. }
  234.  
  235. /**
  236. * Login
  237. *
  238. * @param Request $request
  239. * @param Validator $validator
  240. * @param Flood $flood
  241. *
  242. * @return string
  243. * @throws GuzzleException
  244. */
  245. public function login(Request $request, Validator $validator, Flood $flood): string
  246. {
  247. if (getUser()) {
  248. setFlash('danger', __('main.already_authorized'));
  249. redirect('/');
  250. }
  251.  
  252. $cooklog = $_COOKIE['login'] ?? '';
  253. $isFlood = $flood->isFlood(1);
  254.  
  255. if ($request->isMethod('post')) {
  256. if ($request->has('login') && $request->has('pass')) {
  257. if ($isFlood) {
  258. $validator->true(captchaVerify(), ['protect' => __('validator.captcha')]);
  259. }
  260.  
  261. if ($validator->isValid()) {
  262. $login = utfLower($request->input('login'));
  263. $pass = trim($request->input('pass'));
  264. $remember = $request->boolean('remember');
  265.  
  266. /** @var User $user */
  267. if ($user = User::auth($login, $pass, $remember)) {
  268. setFlash('success', __('users.welcome', ['login' => $user->getName()]));
  269. redirect($request->input('return') ?? '/');
  270. }
  271.  
  272. $flood->saveState(300);
  273. setInput($request->all());
  274. setFlash('danger', __('users.incorrect_login_or_password'));
  275. } else {
  276. setInput($request->all());
  277. setFlash('danger', $validator->getErrors());
  278. }
  279.  
  280. redirect('/login');
  281. }
  282.  
  283. if ($request->has('token')) {
  284. User::socialAuth($request->input('token'));
  285. }
  286. }
  287.  
  288. return view('users/login', compact('cooklog', 'isFlood'));
  289. }
  290.  
  291. /**
  292. * Exit
  293. *
  294. * @param Request $request
  295. *
  296. * @return void
  297. */
  298. public function logout(Request $request): void
  299. {
  300. if ($request->input('token') === $_SESSION['token']) {
  301. $options = [
  302. 'expires' => strtotime('-1 hour', SITETIME),
  303. 'path' => '/',
  304. 'domain' => siteDomain(siteUrl()),
  305. 'secure' => false,
  306. 'httponly' => true,
  307. 'samesite' => 'Lax',
  308. ];
  309.  
  310. $_SESSION = [];
  311. setcookie('password', '', $options);
  312. setcookie(session_name(), '', strtotime('-1 hour', SITETIME), '/', '');
  313. session_destroy();
  314. } else {
  315. setFlash('danger', __('validator.token'));
  316. }
  317.  
  318. redirect('/');
  319. }
  320.  
  321. /**
  322. * Profile editing
  323. *
  324. * @param Request $request
  325. * @param Validator $validator
  326. *
  327. * @return string
  328. */
  329. public function profile(Request $request, Validator $validator): string
  330. {
  331. if (! $user = getUser()) {
  332. abort(403, __('main.not_authorized'));
  333. }
  334.  
  335. if ($request->isMethod('post')) {
  336. $info = $request->input('info');
  337. $name = $request->input('name');
  338. $country = $request->input('country');
  339. $city = $request->input('city');
  340. $phone = preg_replace('/\D/', '', $request->input('phone'));
  341. $site = $request->input('site');
  342. $birthday = $request->input('birthday');
  343. $gender = $request->input('gender') === 'male' ? 'male' : 'female';
  344.  
  345. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  346. ->url($site, ['site' => __('validator.site')], false)
  347. ->regex($birthday, '#^[0-9]{2}+\.[0-9]{2}+\.[0-9]{4}$#', ['birthday' => __('validator.date')], false)
  348. ->phone($phone, ['phone' => __('validator.phone')], false)
  349. ->length($info, 0, 1000, ['info' => __('users.info_yourself_long')])
  350. ->length($name, 3, 20, ['name' => __('users.name_short_or_long')], false);
  351.  
  352. if ($validator->isValid()) {
  353. $country = utfSubstr($country, 0, 30);
  354. $city = utfSubstr($city, 0, 50);
  355.  
  356. $user->update([
  357. 'name' => $name,
  358. 'gender' => $gender,
  359. 'country' => $country,
  360. 'city' => $city,
  361. 'phone' => $phone,
  362. 'site' => $site,
  363. 'birthday' => $birthday,
  364. 'info' => $info,
  365. ]);
  366.  
  367. setFlash('success', __('users.profile_success_changed'));
  368. redirect('/profile');
  369. } else {
  370. setInput($request->all());
  371. setFlash('danger', $validator->getErrors());
  372. }
  373. }
  374.  
  375. return view('users/profile', compact('user'));
  376. }
  377.  
  378. /**
  379. * Confirmation of registration
  380. *
  381. * @param Request $request
  382. * @param Validator $validator
  383. *
  384. * @return string
  385. */
  386. public function key(Request $request, Validator $validator): string
  387. {
  388. /* @var User $user */
  389. if (! $user = getUser()) {
  390. abort(403, __('main.not_authorized'));
  391. }
  392.  
  393. if (! setting('regkeys')) {
  394. abort('default', __('users.confirm_registration_disabled'));
  395. }
  396.  
  397. if ($user->level !== User::PENDED) {
  398. abort(403, __('users.profile_not_confirmation'));
  399. }
  400.  
  401. /* Повторная отправка */
  402. if ($request->has('email') && $request->isMethod('post')) {
  403. $email = strtolower($request->input('email'));
  404. $domain = utfSubstr(strrchr($email, '@'), 1);
  405.  
  406. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  407. ->true(captchaVerify(), ['protect' => __('validator.captcha')])
  408. ->email($email, ['email' => __('validator.email')]);
  409.  
  410. $regMail = User::query()->where('login', '<>', $user->login)->where('email', $email)->count();
  411. $validator->empty($regMail, ['email' => __('users.email_already_exists')]);
  412.  
  413. $blackMail = BlackList::query()->where('type', 'email')->where('value', $email)->count();
  414. $validator->empty($blackMail, ['email' => __('users.email_is_blacklisted')]);
  415.  
  416. $blackDomain = Blacklist::query()->where('type', 'domain')->where('value', $domain)->count();
  417. $validator->empty($blackDomain, ['email' => __('users.domain_is_blacklisted')]);
  418.  
  419. if ($validator->isValid()) {
  420. $activateKey = Str::random();
  421. $activateLink = siteUrl(true).'/key?code=' . $activateKey;
  422.  
  423. $user->update([
  424. 'email' => $email,
  425. 'confirmregkey' => $activateKey,
  426. ]);
  427.  
  428. /* Уведомление о регистрации на email */
  429. $message = 'Добро пожаловать, ' . $user->getName() . '<br>Теперь вы зарегистрированный пользователь сайта <a href="' . siteUrl(true) . '">' . setting('title') . '</a> , сохраните ваш логин и пароль в надежном месте, они вам еще пригодятся.';
  430.  
  431. $subject = 'Регистрация на ' . setting('title');
  432. $body = view('mailer.register', compact('subject', 'message', 'activateKey', 'activateLink'));
  433.  
  434. sendMail($email, $subject, $body);
  435.  
  436. setFlash('success', __('users.confirm_code_success_sent'));
  437. redirect('/');
  438. } else {
  439. setInput($request->all());
  440. setFlash('danger', $validator->getErrors());
  441. }
  442. }
  443.  
  444. /* Подтверждение кода */
  445. if ($request->has('code')) {
  446. $code = trim($request->input('code'));
  447.  
  448. if ($code === $user->confirmregkey) {
  449. $user->update([
  450. 'confirmregkey' => null,
  451. 'level' => User::USER,
  452. ]);
  453.  
  454. setFlash('success', __('users.account_success_activated'));
  455. redirect('/');
  456. } else {
  457. setFlash('danger', __('users.confirm_code_invalid'));
  458. }
  459. }
  460.  
  461. return view('users/key', compact('user'));
  462. }
  463.  
  464. /**
  465. * Settings
  466. *
  467. * @param Request $request
  468. * @param Validator $validator
  469. *
  470. * @return string
  471. */
  472. public function setting(Request $request, Validator $validator): string
  473. {
  474. if (! $user = getUser()) {
  475. abort(403, __('main.not_authorized'));
  476. }
  477.  
  478. $setting['themes'] = array_map('basename', glob(HOME . '/themes/*', GLOB_ONLYDIR));
  479. $setting['languages'] = array_map('basename', glob(RESOURCES . '/lang/*', GLOB_ONLYDIR));
  480. $setting['timezones'] = range(-12, 12);
  481.  
  482. if ($request->isMethod('post')) {
  483. $themes = $request->input('themes');
  484. $timezone = $request->input('timezone', 0);
  485. $language = $request->input('language');
  486. $notify = $request->input('notify') ? 1 : 0;
  487. $subscribe = $request->input('subscribe') ? Str::random(32) : null;
  488.  
  489. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  490. ->regex($themes, '|^[a-z0-9_\-]+$|i', ['themes' => __('users.theme_invalid')])
  491. ->true(in_array($themes, $setting['themes'], true) || empty($themes), ['themes' => __('users.theme_not_installed')])
  492. ->regex($language, '|^[a-z]+$|', ['language' => __('users.language_invalid')])
  493. ->in($language, $setting['languages'], ['language' => __('users.language_not_installed')])
  494. ->regex($timezone, '|^[\-\+]{0,1}[0-9]{1,2}$|', ['timezone' => __('users.timezone_invalid')]);
  495.  
  496. if ($validator->isValid()) {
  497. $user->update([
  498. 'themes' => $themes,
  499. 'timezone' => $timezone,
  500. 'notify' => $notify,
  501. 'subscribe' => $subscribe,
  502. 'language' => $language,
  503. ]);
  504.  
  505. setFlash('success', __('users.settings_success_changed'));
  506. redirect('/settings');
  507. } else {
  508. setInput($request->all());
  509. setFlash('danger', $validator->getErrors());
  510. }
  511. }
  512.  
  513. return view('users/settings', compact('user', 'setting'));
  514. }
  515.  
  516. /**
  517. * User data
  518. *
  519. * @return string
  520. */
  521. public function account(): string
  522. {
  523. if (! $user = getUser()) {
  524. abort(403, __('main.not_authorized'));
  525. }
  526.  
  527. return view('users/account', compact('user'));
  528. }
  529.  
  530. /**
  531. * Initialize email change
  532. *
  533. * @param Request $request
  534. * @param Validator $validator
  535. *
  536. * @return void
  537. */
  538. public function changeMail(Request $request, Validator $validator): void
  539. {
  540. if (! $user = getUser()) {
  541. abort(403, __('main.not_authorized'));
  542. }
  543.  
  544. $email = strtolower($request->input('email'));
  545. $password = $request->input('password');
  546.  
  547. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  548. ->notEqual($email, $user->email, ['email' => __('users.email_different')])
  549. ->email($email, ['email' => __('validator.email')])
  550. ->true(password_verify($password, $user->password), ['password' => __('users.password_different')]);
  551.  
  552. $regMail = User::query()->where('email', $email)->first();
  553. $validator->empty($regMail, ['email' => __('users.email_already_exists')]);
  554.  
  555. // Проверка email в черном списке
  556. $blackMail = BlackList::query()->where('type', 'email')->where('value', $email)->first();
  557. $validator->empty($blackMail, ['email' => __('users.email_is_blacklisted')]);
  558.  
  559. ChangeMail::query()->where('created_at', '<', SITETIME)->delete();
  560.  
  561. $changeMail = ChangeMail::query()->where('user_id', $user->id)->first();
  562. $validator->empty($changeMail, __('users.confirm_already_sent'));
  563.  
  564. if ($validator->isValid()) {
  565. $genkey = Str::random();
  566.  
  567. $subject = 'Изменение email на '.setting('title');
  568. $message = 'Здравствуйте, ' . $user->getName() . '<br>Вами была произведена операция по изменению адреса электронной почты<br><br>Для того, чтобы изменить email, необходимо подтвердить новый адрес почты<br>Перейдите по данной ссылке:<br><br><a href="' . siteUrl(true) . '/accounts/editmail?key=' . $genkey . '">' . siteUrl(true) . '/accounts/editmail?key=' . $genkey . '</a><br><br>Ссылка будет дейстительной в течение суток до ' . date('j.m.y / H:i', strtotime('+1 day', SITETIME)) . '<br>Для изменения адреса необходимо быть авторизованным на сайте<br>Если это сообщение попало к вам по ошибке или вы не собираетесь менять email, то просто проигнорируйте данное письмо';
  569.  
  570. $body = view('mailer.default', compact('subject', 'message'));
  571. sendMail($email, $subject, $body);
  572.  
  573. changeMail::query()->create([
  574. 'user_id' => $user->id,
  575. 'mail' => $email,
  576. 'hash' => $genkey,
  577. 'created_at' => strtotime('+1 day', SITETIME),
  578. ]);
  579.  
  580. setFlash('success', __('users.confirm_success_sent'));
  581. } else {
  582. setInput($request->all());
  583. setFlash('danger', $validator->getErrors());
  584. }
  585.  
  586. redirect('/accounts');
  587. }
  588.  
  589. /**
  590. * Email change
  591. *
  592. * @param Request $request
  593. * @param Validator $validator
  594. *
  595. * @return void
  596. * @throws Exception
  597. */
  598. public function editMail(Request $request, Validator $validator): void
  599. {
  600. if (! $user = getUser()) {
  601. abort(403, __('main.not_authorized'));
  602. }
  603.  
  604. $key = $request->input('key');
  605.  
  606. ChangeMail::query()->where('created_at', '<', SITETIME)->delete();
  607.  
  608. /** @var ChangeMail $changeMail */
  609. $changeMail = ChangeMail::query()->where('hash', $key)->where('user_id', $user->id)->first();
  610.  
  611. $validator->notEmpty($key, __('users.changed_code_empty'))
  612. ->notEmpty($changeMail, __('users.changed_code_not_found'));
  613.  
  614. if ($changeMail) {
  615. $validator->notEqual($changeMail->mail, $user->mail, __('users.email_different'));
  616.  
  617. $regMail = User::query()->where('email', $changeMail->mail)->count();
  618. $validator->empty($regMail, __('users.email_already_exists'));
  619.  
  620. $blackMail = BlackList::query()->where('type', 'email')->where('value', $changeMail->mail)->count();
  621. $validator->empty($blackMail, __('users.email_is_blacklisted'));
  622. }
  623.  
  624. if ($validator->isValid()) {
  625. $user->update([
  626. 'email' => $changeMail->mail,
  627. ]);
  628.  
  629. $changeMail->delete();
  630.  
  631. setFlash('success', __('users.email_success_changed'));
  632. } else {
  633. setFlash('danger', $validator->getErrors());
  634. }
  635.  
  636. redirect('/accounts');
  637. }
  638.  
  639. /**
  640. * Status change
  641. *
  642. * @param Request $request
  643. * @param Validator $validator
  644. *
  645. * @return void
  646. */
  647. public function editStatus(Request $request, Validator $validator): void
  648. {
  649. if (! $user = getUser()) {
  650. abort(403, __('main.not_authorized'));
  651. }
  652.  
  653. $status = $request->input('status');
  654. $status = ! empty($status) ? $status : null;
  655. $cost = $status ? setting('editstatusmoney') : 0;
  656.  
  657. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  658. ->empty($user->ban, ['status' => __('users.status_changed_not_ban')])
  659. ->notEqual($status, $user->status, ['status' => __('users.status_different')])
  660. ->gte($user->point, setting('editstatuspoint'), ['status' => __('users.status_points')])
  661. ->gte($user->money, $cost, ['status' => __('users.status_moneys')])
  662. ->length($status, 3, 20, ['status' => __('users.status_short_or_long')], false);
  663.  
  664. if ($validator->isValid()) {
  665. $user->update([
  666. 'status' => $status,
  667. 'money' => DB::connection()->raw('money - ' . $cost),
  668. ]);
  669.  
  670. clearCache('status');
  671. setFlash('success', __('users.status_success_changed'));
  672. } else {
  673. setInput($request->all());
  674. setFlash('danger', $validator->getErrors());
  675. }
  676.  
  677. redirect('/accounts');
  678. }
  679.  
  680. /**
  681. * Color change
  682. *
  683. * @param Request $request
  684. * @param Validator $validator
  685. *
  686. * @return void
  687. */
  688. public function editColor(Request $request, Validator $validator): void
  689. {
  690. if (! $user = getUser()) {
  691. abort(403, __('main.not_authorized'));
  692. }
  693.  
  694. $color = $request->input('color');
  695. $color = ! empty($color) ? $color : null;
  696. $cost = $color ? setting('editcolormoney') : 0;
  697.  
  698. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  699. ->notEqual($color, $user->color, ['color' => __('users.color_different')])
  700. ->gte($user->point, setting('editcolorpoint'), ['color' => __('users.color_points')])
  701. ->gte($user->money, $cost, ['color' => __('users.color_moneys')])
  702. ->regex($color, '|^#+[A-f0-9]{6}$|', ['color' => __('validator.color')], false);
  703.  
  704. if ($validator->isValid()) {
  705. $user->update([
  706. 'color' => $color,
  707. 'money' => DB::connection()->raw('money - ' . $cost),
  708. ]);
  709.  
  710. setFlash('success', __('users.color_success_changed'));
  711. } else {
  712. setInput($request->all());
  713. setFlash('danger', $validator->getErrors());
  714. }
  715.  
  716. redirect('/accounts');
  717. }
  718.  
  719. /**
  720. * Password change
  721. *
  722. * @param Request $request
  723. * @param Validator $validator
  724. *
  725. * @return void
  726. */
  727. public function editPassword(Request $request, Validator $validator): void
  728. {
  729. if (! $user = getUser()) {
  730. abort(403, __('main.not_authorized'));
  731. }
  732.  
  733. $newpass = $request->input('newpass');
  734. $newpass2 = $request->input('newpass2');
  735. $oldpass = $request->input('oldpass');
  736.  
  737. $validator->equal($request->input('token'), $_SESSION['token'], __('validator.token'))
  738. ->true(password_verify($oldpass, $user->password), ['oldpass' => __('users.password_different')])
  739. ->length($newpass, 6, 20, ['newpass' => __('users.password_length_requirements')])
  740. ->notEqual($user->login, $newpass, ['newpass' => __('users.login_different')])
  741. ->equal($newpass, $newpass2, ['newpass2' => __('users.passwords_different')]);
  742.  
  743. if (ctype_digit($newpass)) {
  744. $validator->addError(['newpass' => __('users.field_characters_requirements')]);
  745. }
  746.  
  747. if ($validator->isValid()) {
  748. $user->update([
  749. 'password' => password_hash($newpass, PASSWORD_BCRYPT),
  750. ]);
  751.  
  752. $subject = 'Изменение пароля на ' . setting('title');
  753. $message = 'Здравствуйте, ' . $user->getName() . '<br>Вами была произведена операция по изменению пароля<br><br><b>Ваш новый пароль: ' . $newpass . '</b><br>Сохраните его в надежном месте<br><br>Данные инициализации:<br>IP: ' . getIp() . '<br>Браузер: ' . getBrowser() . '<br>Время: ' . date('j.m.y / H:i', SITETIME);
  754.  
  755. $body = view('mailer.default', compact('subject', 'message'));
  756. sendMail($user->email, $subject, $body);
  757.  
  758. unset($_SESSION['id'], $_SESSION['password']);
  759.  
  760. setFlash('success', __('users.password_success_changed'));
  761. redirect('/login');
  762. } else {
  763. setInput($request->all());
  764. setFlash('danger', $validator->getErrors());
  765. redirect('/accounts');
  766. }
  767. }
  768.  
  769. /**
  770. * Key generation
  771. *
  772. * @param Request $request
  773. *
  774. * @return void
  775. */
  776. public function apikey(Request $request): void
  777. {
  778. if (! $user = getUser()) {
  779. abort(403, __('main.not_authorized'));
  780. }
  781.  
  782. if ($request->input('token') === $_SESSION['token']) {
  783. $apiKey = md5($user->login . Str::random());
  784. $message = __('users.token_success_changed');
  785.  
  786. if ($request->input('action') === 'create') {
  787. $message = __('users.token_success_created');
  788. }
  789.  
  790. if ($request->input('action') === 'delete') {
  791. $apiKey = '';
  792. $message = __('users.token_success_deleted');
  793. }
  794.  
  795. $user->update([
  796. 'apikey' => $apiKey
  797. ]);
  798.  
  799. setFlash('success', $message);
  800. } else {
  801. setFlash('danger', __('validator.token'));
  802. }
  803.  
  804. redirect('/accounts');
  805. }
  806.  
  807. /**
  808. * Проверка доступности логина
  809. *
  810. * @param Request $request
  811. * @param Validator $validator
  812. *
  813. * @return string
  814. * @throws Exception
  815. */
  816. public function checkLogin(Request $request, Validator $validator): string
  817. {
  818. $login = $request->input('login');
  819.  
  820. $validator
  821. ->true($request->ajax(), __('validator.not_ajax'))
  822. ->regex($login, '|^[a-z0-9\-]+$|i', __('validator.login'))
  823. ->regex(utfSubstr($login, 0, 1), '|^[a-z0-9]+$|i', __('users.login_begin_requirements'))
  824. ->length($login, 3, 20, __('users.login_length_requirements'))
  825. ->false(ctype_digit($login), __('users.field_characters_requirements'))
  826. ->false(substr_count($login, '-') > 2, __('users.login_hyphens_requirements'));
  827.  
  828. if ($validator->isValid()) {
  829. $existLogin = User::query()
  830. ->where('login', $login)
  831. ->exists();
  832.  
  833. $blackLogin = Blacklist::query()
  834. ->where('type', 'login')
  835. ->where('value', strtolower($login))
  836. ->exists();
  837.  
  838. $validator
  839. ->false($existLogin, __('users.login_already_exists'))
  840. ->false($blackLogin, __('users.login_is_blacklisted'));
  841. }
  842.  
  843. if ($validator->isValid()) {
  844. return json_encode(['status' => 'success']);
  845. }
  846.  
  847. return json_encode(['status' => 'error', 'message' => current($validator->getErrors())]);
  848. }
  849. }