DONE: layout letter with letterhead and footer, notification for newly...
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Auth\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Modules\Auth\Actions\Fortify\PasswordValidationRules;
|
||||
use Modules\Auth\Emails\PasswordResetOtpEmail;
|
||||
use Modules\Auth\Entities\PasswordResetOtp;
|
||||
use Modules\Auth\Entities\User;
|
||||
|
||||
class PasswordResetOtpService
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
public function send(User $user): void
|
||||
{
|
||||
$otp = $this->generateOtp();
|
||||
|
||||
PasswordResetOtp::query()
|
||||
->where('user_id', $user->id)
|
||||
->delete();
|
||||
|
||||
PasswordResetOtp::create([
|
||||
'user_id' => $user->id,
|
||||
'code' => Hash::make($otp),
|
||||
'expires_at' => now()->addMinutes($this->expiryMinutes()),
|
||||
'attempts' => 0,
|
||||
]);
|
||||
|
||||
$user->notify(new PasswordResetOtpEmail($otp));
|
||||
}
|
||||
|
||||
public function reset(User $user, string $otp, array $input): void
|
||||
{
|
||||
validator($input, [
|
||||
'password' => $this->passwordRules(),
|
||||
])->validate();
|
||||
|
||||
$record = PasswordResetOtp::query()
|
||||
->where('user_id', $user->id)
|
||||
->latest()
|
||||
->first();
|
||||
|
||||
if (! $record) {
|
||||
throw ValidationException::withMessages([
|
||||
'otp' => ['Kod OTP tidak dijumpai. Sila minta kod baharu.'],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($record->isExpired()) {
|
||||
$record->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'otp' => ['Kod OTP telah tamat tempoh. Sila minta kod baharu.'],
|
||||
]);
|
||||
}
|
||||
|
||||
if ($record->hasExceededMaxAttempts()) {
|
||||
$record->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'otp' => ['Terlalu banyak percubaan. Sila minta kod baharu.'],
|
||||
]);
|
||||
}
|
||||
|
||||
if (! Hash::check($otp, $record->code)) {
|
||||
$record->increment('attempts');
|
||||
|
||||
if ($record->fresh()->hasExceededMaxAttempts()) {
|
||||
$record->delete();
|
||||
}
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'otp' => ['Kod OTP tidak sah.'],
|
||||
]);
|
||||
}
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
|
||||
$user->tokens()->delete();
|
||||
|
||||
PasswordResetOtp::query()
|
||||
->where('user_id', $user->id)
|
||||
->delete();
|
||||
}
|
||||
|
||||
protected function generateOtp(): string
|
||||
{
|
||||
return str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
protected function expiryMinutes(): int
|
||||
{
|
||||
return (int) config('auth.password_reset.expiry_minutes', 10);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user