Commit e6d602adb39e0ab8962a402881288a927758b036

Authored by Hayk Nazaryan
1 parent 898ae29b23
Exists in master

reset password

Showing 9 changed files with 216 additions and 47 deletions Side-by-side Diff

app/Http/Controllers/MainController.php
... ... @@ -19,6 +19,7 @@ use App\Models\Positions;
19 19 use App\Models\reclame;
20 20 use App\Models\User;
21 21 use Illuminate\Http\Request;
  22 +use Illuminate\Support\Carbon;
22 23 use Illuminate\Support\Facades\Auth;
23 24 use Illuminate\Support\Facades\DB;
24 25 use Illuminate\Support\Facades\Hash;
... ... @@ -26,6 +27,7 @@ use Illuminate\Support\Facades\Mail;
26 27 use Illuminate\Support\Facades\Validator;
27 28 use App\Models\PageContent;
28 29 use App\Enums\MainPageCounters;
  30 +use Illuminate\Support\Str;
29 31  
30 32 class MainController extends Controller
31 33 {
... ... @@ -372,7 +374,8 @@ class MainController extends Controller
372 374 ], 422);
373 375 } else {
374 376 try {
375   - $user = User::query()->where('email', $request->get('email'))->first();
  377 + $email = $request->input('email');
  378 + $user = User::query()->where('email', $email)->first();
376 379 if (!$user) {
377 380 return response()->json([
378 381 'errors' => [
... ... @@ -383,22 +386,37 @@ class MainController extends Controller
383 386 ], 422);
384 387 }
385 388  
386   - $new_password = Tools::generator_id(10);
387   - $hash_password = Hash::make($new_password);
388   -
389   - $user->update([
390   - 'password' => $hash_password,
391   - 'pubpassword' => base64_encode($new_password)
392   - ]);
393   -
394   - Mail::to($user)->send(new MailRepair($new_password));
  389 + $token = Str::random(60);
  390 + DB::table('password_resets')->updateOrInsert(
  391 + [
  392 + 'email' => $email,
  393 + ],
  394 + [
  395 + 'email' => $email,
  396 + 'token' => $token,
  397 + 'created_at' => Carbon::now()
  398 + ]
  399 + );
  400 +
  401 + $link = url('/') . '?' . http_build_query([
  402 + 'token' => $token,
  403 + 'email' => $email,
  404 + ]) . '#reset';
  405 +
  406 + Mail::send('emails.RepairPassword',
  407 + ['link' => $link],
  408 + function($message) use ($email) {
  409 + $message->to($email);
  410 + $message->subject('Repair password');
  411 + }
  412 + );
395 413  
396 414 return response()->json([
397 415 'success' => true
398 416 ], 200);
399 417 } catch (\Exception $exception) {
400 418 return response()->json([
401   - 'success' => true
  419 + 'success' => false
402 420 ], 400);
403 421 }
404 422  
... ... @@ -406,6 +424,62 @@ class MainController extends Controller
406 424  
407 425 }
408 426  
  427 + public function reset_password(Request $request) {
  428 + $rules = [
  429 + 'token' => ['required', 'string', 'max:255'],
  430 + 'email' => ['required', 'email', 'max:255'],
  431 + 'password' => ['required', 'string', 'min:6'],
  432 + 'password_confirmation' => ['required', 'same:password'],
  433 + ];
  434 +
  435 + $messages = [
  436 + 'required' => 'Укажите обязательное поле',
  437 + 'email' => 'Неорректный email',
  438 + 'same' => 'Пароль и подтверждение пароля не совпадают',
  439 + 'min' => [
  440 + 'string' => 'Поле должно быть не менее :min символов',
  441 + ],
  442 + ];
  443 +
  444 + $validator = Validator::make($request->all(), $rules, $messages);
  445 +
  446 + if ($validator->fails()) {
  447 + return response()->json(['ERRORS' => $validator->errors()], 422);
  448 + }
  449 +
  450 + $passwordReset = DB::table('password_resets')
  451 + ->where('email', $request->input('email'))
  452 + ->where('token', $request->input('token'))
  453 + ->first();
  454 +
  455 + if (!$passwordReset) {
  456 + return response()->json([
  457 + 'success' => false,
  458 + 'errors' => [
  459 + 'token' => ['Неверный токен'],
  460 + ],
  461 + ], 400);
  462 + }
  463 +
  464 + if (Carbon::parse($passwordReset->created_at)->addHours(1)->isPast()) {
  465 + return response()->json([
  466 + 'success' => false,
  467 + 'errors' => [
  468 + 'token' => ['Токен устарел'],
  469 + ],
  470 + ], 400);
  471 + }
  472 +
  473 + User::where('email', $request->input('email'))->update([
  474 + 'password' => Hash::make($request->input('password')),
  475 + 'pubpassword' => base64_encode($request->input('password')),
  476 + ]);
  477 +
  478 + DB::table('password_resets')->where('email', $request->input('email'))->delete();
  479 +
  480 + return response()->json(['success' => true], 200);
  481 + }
  482 +
409 483 // Вывод новостей
410 484 public function news(Request $request) {
411 485 $Query = News::query();
resources/views/emails/RepairPassword.blade.php
... ... @@ -12,15 +12,15 @@
12 12 <img src="{{asset('images/emails/20.png')}}" alt="" style="width: 182px; height: 54px; display: block; margin: 0 auto;">
13 13 </a>
14 14 <b style="font-size: 24px; line-height: 32px; display: block; margin: 32px 0;">
15   - Ваш новый пароль.
  15 + Ссылка на воостановление пароля.
16 16 </b>
17 17 <b style="font-size: 24px; line-height: 32px; display: block; margin: 32px 0;">
18   - {{$password}}
  18 + <a href="{{$link}}" target="_blank"
  19 + style="word-wrap: break-word; word-break: break-all; color: #1a55a6; font-size: 16px; line-height: 24px; display: inline-block; text-align: left; max-width: 90%; margin: 0 auto;">
  20 + {{$link}}
  21 + </a>
  22 +
19 23 </b>
20   - <a href="{{ config('app.url') }}" target="_blank"
21   - style="word-wrap: break-word; word-break: break-all; color: #1a55a6; font-size: 16px; line-height: 24px; display: inline-block; text-align: left; max-width: 90%; margin: 0 auto;">
22   - {{ config('app.url') . '#sign' }}
23   - </a>
24 24 <div style="text-align:center;margin-top: 32px;font-size: 0;">
25 25 <a href="https://t.me/rekamore_su" target="_blank"
26 26 style="background: #20A0E1;font-size: 16px;font-weight: 700;margin:0 16px 32px 16px;border-radius: 8px;height: 44px;line-height: 44px;text-decoration: none;color:#fff;display: inline-block;vertical-align: top;padding: 0 32px;">
resources/views/layout/frontend.blade.php
... ... @@ -274,6 +274,7 @@
274 274  
275 275 <!-- Сбросить пароль -->
276 276 @include('modals.reset_password')
  277 + @include('modals.repair_password')
277 278  
278 279 <!-- Регистрация -->
279 280 @include('modals.register')
resources/views/modals/repair_password.blade.php
... ... @@ -0,0 +1,60 @@
  1 +<div id="repair-password" class="modal">
  2 + <div class="modal__body">
  3 + <div class="modal__title left">Сбросить пароль</div>
  4 + <div class="modal__text left">Пожалуйста, введите адрес электронной почты</div>
  5 + <form id="repair-password-form" class="modal__sign" action="{{ route('repair_password') }}">
  6 + <div class="modal__sign-item">
  7 + <input type="text" class="input" name="email" id="email"
  8 + placeholder="Введите свой email для восстановления" required>
  9 + <div id="email-error" class="error-message"></div>
  10 + </div>
  11 +
  12 + <div class="modal__sign-item">
  13 + <button id="repair-password-btn" type="submit" class="button">Отправить</button>
  14 + </div>
  15 + </form>
  16 + <div class="modal__text">
  17 + <span>Вспомнили пароль?</span>
  18 + &nbsp;
  19 + <a data-fancybox data-src="#sign" data-options='{"touch":false,"autoFocus":false}'>Войти</a>
  20 + </div>
  21 + </div>
  22 +</div>
  23 +@include('modals.successful_repair_password_sent')
  24 +<script>
  25 + $(document).on('click', '#repair-password-btn', function (e) {
  26 + e.preventDefault();
  27 + const btnElm = $(this)
  28 + const form = $('#repair-password-form');
  29 + $.ajax({
  30 + url: form.attr('action'),
  31 + method: form.attr('method'),
  32 + data: form.serialize(),
  33 + beforeSend() {
  34 + btnElm.attr('disabled', true)
  35 + },
  36 + success: function (response) {
  37 + btnElm.attr('disabled', false)
  38 + $.fancybox.close(true);
  39 + $.fancybox.open({
  40 + src: '#repair-password-sent',
  41 + type: 'inline',
  42 + opts: {touch: false}
  43 + });
  44 + },
  45 + error: function (jqXHR) {
  46 + btnElm.attr('disabled', false)
  47 + if (jqXHR.status === 422) {
  48 + let errors = jqXHR.responseJSON.errors;
  49 + for (let field in errors) {
  50 + if (errors.hasOwnProperty(field)) {
  51 + $(`#${field}-error`).text(errors[field][0]);
  52 + }
  53 + }
  54 + } else {
  55 + alert('Произошла ошибка. Попробуйте снова.');
  56 + }
  57 + }
  58 + });
  59 + })
  60 +</script>
resources/views/modals/reset_password.blade.php
1   -<div id="reset" class="modal">
  1 +<div id="reset-password" class="modal">
2 2 <div class="modal__body">
3 3 <div class="modal__title left">Сбросить пароль</div>
4   - <div class="modal__text left">Пожалуйста, введите имя пользователя или адрес электронной почты</div>
5   - <form id="reset-password-form" class="modal__sign" action="{{ route('repair_password') }}">
6   - <div class="modal__sign-item">
7   - <input type="text" class="input" name="email" id="email" placeholder="Введите свой email для восстановления" required>
8   - <div id="email-error" class="error-message"></div>
  4 + <div class="modal__text left">Введите новый пароль</div>
  5 + <form id="reset-password-form" class="modal__sign" action="{{ route('reset_password') }}">
  6 + <input type="hidden" name="email" value="{{request()->get('email')}}">
  7 + <input type="hidden" name="token" value="{{request()->get('token')}}">
  8 +
  9 + <div class="modal__reg-item form-group">
  10 + <label class="form-group__label">Пароль *</label>
  11 + <div class="form-group__item">
  12 + <input type="password" name="password" class="input"
  13 + placeholder="**********">
  14 + <button type="button" class="eye">
  15 + <svg class="js-password-show">
  16 + <use xlink:href="{{ asset('images/sprite.svg#eye') }}"></use>
  17 + </svg>
  18 + <svg class="js-password-hide">
  19 + <use xlink:href="{{ asset('images/sprite.svg#eye-2') }}"></use>
  20 + </svg>
  21 + </button>
  22 + <span id="reset_password_error" class="employer_error-message"></span>
  23 + </div>
  24 + </div>
  25 + <div class="modal__reg-item form-group">
  26 + <label class="form-group__label">Подтвердить пароль *</label>
  27 + <div class="form-group__item">
  28 + <input type="password" name="password_confirmation"
  29 + class="input" placeholder="**********">
  30 + <button type="button" class="eye">
  31 + <svg class="js-password-show">
  32 + <use xlink:href="{{ asset('images/sprite.svg#eye') }}"></use>
  33 + </svg>
  34 + <svg class="js-password-hide">
  35 + <use xlink:href="{{ asset('images/sprite.svg#eye-2') }}"></use>
  36 + </svg>
  37 + </button>
  38 + </div>
  39 + <span id="reset_password_confirmation_error" class="employer_error-message"></span>
9 40 </div>
  41 +
10 42 <div class="modal__sign-item">
11   - <button id="reset-password-btn" type="submit" class="button">Получить новый пароль</button>
  43 + <button id="reset-password-btn" type="submit" class="button">Сохранить</button>
12 44 </div>
13 45 </form>
14   - <div class="modal__text">
15   - <span>Вспомнили пароль?</span>
16   - &nbsp;
17   - <a data-fancybox data-src="#sign" data-options='{"touch":false,"autoFocus":false}'>Войти</a>
18   - </div>
19 46 </div>
20 47 </div>
21 48 @include('modals.successful_reset_password')
... ... @@ -35,10 +62,13 @@
35 62 btnElm.attr('disabled', false)
36 63 $.fancybox.close(true);
37 64 $.fancybox.open({
38   - src: '#reset-password-sent',
  65 + src: '#reset-password-success',
39 66 type: 'inline',
40 67 opts: {touch: false}
41 68 });
  69 +
  70 + const url = window.location.origin + window.location.pathname;
  71 + window.history.replaceState({}, document.title, url);
42 72 },
43 73 error: function (jqXHR) {
44 74 btnElm.attr('disabled', false)
... ... @@ -46,7 +76,7 @@
46 76 let errors = jqXHR.responseJSON.errors;
47 77 for (let field in errors) {
48 78 if (errors.hasOwnProperty(field)) {
49   - $(`#${field}-error`).text(errors[field][0]);
  79 + $(`#reset_${field}_error`).text(errors[field][0]);
50 80 }
51 81 }
52 82 } else {
... ... @@ -54,5 +84,15 @@
54 84 }
55 85 }
56 86 });
  87 + }).ready(function () {
  88 + if (window.location.hash === '#reset') {
  89 + $.fancybox.open({
  90 + src: '#reset-password',
  91 + type: 'inline',
  92 + opts: {
  93 + touch: false
  94 + }
  95 + });
  96 + }
57 97 })
58 98 </script>
resources/views/modals/send_login.blade.php
... ... @@ -36,7 +36,7 @@
36 36 </label>
37 37 </div>
38 38 <div>
39   - <a data-fancybox data-src="#reset" data-options='{"touch":false,"autoFocus":false}' class="modal__sign-bottom-link">Забыли пароль?</a>
  39 + <a data-fancybox data-src="#repair-password" data-options='{"touch":false,"autoFocus":false}' class="modal__sign-bottom-link">Забыли пароль?</a>
40 40 </div>
41 41 </div>
42 42 </div>
... ... @@ -51,16 +51,3 @@
51 51 </div>
52 52 </div>
53 53 </div>
54   -<script>
55   - $(document).ready(function () {
56   - if (window.location.hash === '#sign') {
57   - $.fancybox.open({
58   - src: '#sign',
59   - type: 'inline',
60   - opts: {
61   - touch: false
62   - }
63   - });
64   - }
65   - });
66   -</script>
resources/views/modals/successful_repair_password_sent.blade.php
... ... @@ -0,0 +1,6 @@
  1 +<div id="repair-password-sent" class="modal modal_bg" style="display: none;">
  2 + <div class="modal__body">
  3 + <div class="modal__title">Успешно!</div>
  4 + <div class="modal__text">На вашу электронную почту отправлено ссылка на воостановление пароля.</div>
  5 + </div>
  6 +</div>
resources/views/modals/successful_reset_password.blade.php
1   -<div id="reset-password-sent" class="modal modal_bg" style="display: none;">
  1 +<div id="reset-password-success" class="modal modal_bg" style="display: none;">
2 2 <div class="modal__body">
3 3 <div class="modal__title">Успешно!</div>
4   - <div class="modal__text">На вашу электронную почту отправлено новый пароль.</div>
  4 + <div class="modal__text">Ваш пароль успешно воостановлена.</div>
5 5 </div>
6 6 </div>
... ... @@ -446,6 +446,7 @@ Route::post(&#39;register_employer&#39;, [EmployerController::class, &#39;register_employer&#39;
446 446  
447 447 //восстановление пароля
448 448 Route::get('repair-password', [MainController::class, 'repair_password'])->name('repair_password');
  449 +Route::get('reset-password', [MainController::class, 'reset_password'])->name('reset_password');
449 450 // Звезда сообщения
450 451 Route::post('stars-answer', [WorkerController::class, 'stars_answer'])->name('stars_answer');
451 452