Created
August 12, 2024 12:29
-
-
Save akrez/62b09416ce3886713092296c86e7c5cb to your computer and use it in GitHub Desktop.
Reset Password Request in LARAVEL 11 with Mobile ( or SMS or Phone or anything else except Email )
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Auth; | |
use App\Http\Controllers\Controller; | |
use App\Rules\IranMobileRule; | |
use Illuminate\Http\JsonResponse; | |
use Illuminate\Http\Request; | |
use Illuminate\Support\Facades\Password; | |
use Illuminate\Validation\ValidationException; | |
class ForgotPasswordController extends Controller | |
{ | |
/** | |
* Display the form to request a password reset link. | |
* | |
* @return \Illuminate\View\View | |
*/ | |
public function showLinkRequestForm() | |
{ | |
return view('auth.passwords.mobile'); | |
} | |
/** | |
* Send a reset link to the given user. | |
* | |
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse | |
*/ | |
public function sendResetLinkEmail(Request $request) | |
{ | |
$this->validateMobile($request); | |
// We will send the password reset link to this user. Once we have attempted | |
// to send the link, we will examine the response then see the message we | |
// need to show to the user. Finally, we'll send out a proper response. | |
$response = $this->broker()->sendResetLink( | |
$this->credentials($request) | |
); | |
return $response == Password::RESET_LINK_SENT | |
? $this->sendResetLinkResponse($request, $response) | |
: $this->sendResetLinkFailedResponse($request, $response); | |
} | |
/** | |
* Validate the mobile for the given request. | |
* | |
* @return void | |
*/ | |
protected function validateMobile(Request $request) | |
{ | |
$request->validate(['mobile' => ['required', new IranMobileRule]]); | |
} | |
/** | |
* Get the needed authentication credentials from the request. | |
* | |
* @return array | |
*/ | |
protected function credentials(Request $request) | |
{ | |
return $request->only('mobile'); | |
} | |
/** | |
* Get the response for a successful password reset link. | |
* | |
* @param string $response | |
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse | |
*/ | |
protected function sendResetLinkResponse(Request $request, $response) | |
{ | |
return $request->wantsJson() | |
? new JsonResponse(['message' => trans($response)], 200) | |
: back()->with('status', trans($response)); | |
} | |
/** | |
* Get the response for a failed password reset link. | |
* | |
* @param string $response | |
* @return \Illuminate\Http\RedirectResponse | |
* | |
* @throws \Illuminate\Validation\ValidationException | |
*/ | |
protected function sendResetLinkFailedResponse(Request $request, $response) | |
{ | |
if ($request->wantsJson()) { | |
throw ValidationException::withMessages([ | |
'mobile' => [trans($response)], | |
]); | |
} | |
return back() | |
->withInput($request->only('mobile')) | |
->withErrors(['mobile' => trans($response)]); | |
} | |
/** | |
* Get the broker to be used during password reset. | |
* | |
* @return \Illuminate\Contracts\Auth\PasswordBroker | |
*/ | |
public function broker() | |
{ | |
return Password::broker(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Auth; | |
use Illuminate\Auth\Passwords\DatabaseTokenRepository; | |
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; | |
use Illuminate\Support\Carbon; | |
use Illuminate\Support\Str; | |
class MobileDatabaseTokenRepository extends DatabaseTokenRepository | |
{ | |
/** | |
* Create a new token record. | |
* | |
* @return string | |
*/ | |
public function create(CanResetPasswordContract $user) | |
{ | |
$mobile = $user->getEmailForPasswordReset(); | |
$this->deleteExisting($user); | |
// We will create a new, random token for the user so that we can e-mail them | |
// a safe link to the password reset form. Then we will insert a record in | |
// the database so that we can verify the token within the actual reset. | |
$token = $this->createNewToken(); | |
$this->getTable()->insert($this->getPayload($mobile, $token)); | |
return $token; | |
} | |
/** | |
* Delete all existing reset tokens from the database. | |
* | |
* @return int | |
*/ | |
protected function deleteExisting(CanResetPasswordContract $user) | |
{ | |
return $this->getTable()->where('mobile', $user->getEmailForPasswordReset())->delete(); | |
} | |
/** | |
* Build the record payload for the table. | |
* | |
* @param string $mobile | |
* @param string $token | |
* @return array | |
*/ | |
protected function getPayload($mobile, #[\SensitiveParameter] $token) | |
{ | |
return ['mobile' => $mobile, 'token' => $this->hasher->make($token), 'created_at' => new Carbon]; | |
} | |
/** | |
* Determine if a token record exists and is valid. | |
* | |
* @param string $token | |
* @return bool | |
*/ | |
public function exists(CanResetPasswordContract $user, #[\SensitiveParameter] $token) | |
{ | |
$record = (array) $this->getTable()->where( | |
'mobile', $user->getEmailForPasswordReset() | |
)->first(); | |
return $record && | |
! $this->tokenExpired($record['created_at']) && | |
$this->hasher->check($token, $record['token']); | |
} | |
/** | |
* Determine if the given user recently created a password reset token. | |
* | |
* @return bool | |
*/ | |
public function recentlyCreatedToken(CanResetPasswordContract $user) | |
{ | |
$record = (array) $this->getTable()->where( | |
'mobile', $user->getEmailForPasswordReset() | |
)->first(); | |
return $record && $this->tokenRecentlyCreated($record['created_at']); | |
} | |
/** | |
* Create a new token for the user. | |
* | |
* @return string | |
*/ | |
public function createNewToken() | |
{ | |
return hash_hmac('sha256', Str::random(6), $this->hashKey); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Auth; | |
use Illuminate\Auth\Passwords\PasswordBroker; | |
class MobilePasswordBroker extends PasswordBroker {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Auth; | |
use Illuminate\Auth\Passwords\PasswordBrokerManager; | |
use InvalidArgumentException; | |
/** | |
* @mixin \Illuminate\Contracts\Auth\PasswordBroker | |
*/ | |
class MobilePasswordBrokerManager extends PasswordBrokerManager | |
{ | |
/** | |
* Resolve the given broker. | |
* | |
* @param string $name | |
* @return \Illuminate\Contracts\Auth\PasswordBroker | |
* | |
* @throws \InvalidArgumentException | |
*/ | |
protected function resolve($name) | |
{ | |
$config = $this->getConfig($name); | |
if (is_null($config)) { | |
throw new InvalidArgumentException("Password resetter [{$name}] is not defined."); | |
} | |
// The password broker uses a token repository to validate tokens and send user | |
// password e-mails, as well as validating that password reset process as an | |
// aggregate service of sorts providing a convenient interface for resets. | |
return new MobilePasswordBroker( | |
$this->createTokenRepository($config), | |
$this->app['auth']->createUserProvider($config['provider'] ?? null), | |
$this->app['events'] ?? null, | |
); | |
} | |
/** | |
* Create a token repository instance based on the given configuration. | |
* | |
* @return \Illuminate\Auth\Passwords\TokenRepositoryInterface | |
*/ | |
protected function createTokenRepository(array $config) | |
{ | |
$key = $this->app['config']['app.key']; | |
if (str_starts_with($key, 'base64:')) { | |
$key = base64_decode(substr($key, 7)); | |
} | |
$connection = $config['connection'] ?? null; | |
return new MobileDatabaseTokenRepository( | |
$this->app['db']->connection($connection), | |
$this->app['hash'], | |
$config['table'], | |
$key, | |
$config['expire'], | |
$config['throttle'] ?? 0 | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use App\Auth\MobilePasswordBrokerManager; | |
use Illuminate\Auth\Passwords\PasswordResetServiceProvider as PasswordResetServiceProviderBase; | |
class PasswordResetServiceProvider extends PasswordResetServiceProviderBase | |
{ | |
protected function registerPasswordBroker() | |
{ | |
$this->app->singleton('auth.password', function ($app) { | |
return new MobilePasswordBrokerManager($app); | |
}); | |
$this->app->bind('auth.password.broker', function ($app) { | |
return $app->make('auth.password')->broker(); | |
}); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
#bootstrap/providers.php | |
return [ | |
App\Providers\AppServiceProvider::class, | |
App\Providers\PasswordResetServiceProvider::class, | |
]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@extends('layouts.auth') | |
@section('content') | |
@if (session('status')) | |
<div class="p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400" | |
role="alert"> | |
{{ session('status') }} | |
</div> | |
@endif | |
<form class="w-full space-y-3" method="POST" action="{{ route('password.email') }}"> | |
@csrf | |
<div class="grid sm:grid-cols-1 gap-4"> | |
@include('auth._form', ['names' => ['mobile']]) | |
</div> | |
@include('components.SubmitButton', ['content' => __('Send Password Reset Link')]) | |
</form> | |
@endsection |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models; | |
// use Illuminate\Contracts\Auth\MustVerifyEmail; | |
use App\Enums\User\GenderEnum; | |
use App\Enums\User\RoleEnum; | |
use Illuminate\Database\Eloquent\Factories\HasFactory; | |
use Illuminate\Foundation\Auth\User as Authenticatable; | |
use Illuminate\Notifications\Notifiable; | |
use Laravel\Passport\HasApiTokens; | |
class User extends Authenticatable | |
{ | |
use HasApiTokens, HasFactory, Notifiable; | |
// ... | |
/** | |
* Get the e-mail address where password reset links are sent. | |
* | |
* @return string | |
*/ | |
public function getEmailForPasswordReset() | |
{ | |
return $this->mobile; | |
} | |
/** | |
* Send the password reset notification. | |
* | |
* @param string $token | |
* @return void | |
*/ | |
public function sendPasswordResetNotification(#[\SensitiveParameter] $token) | |
{ | |
info($token); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment