Files
moonwell-web/app/Http/Controllers/Auth/AccountAccessController.php
T

142 lines
5.9 KiB
PHP

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\AccountEmailRequest;
use App\Http\Requests\ResetAccountPasswordRequest;
use App\Models\User;
use App\Services\AccountEmailService;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Auth\Events\Verified;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;
use Throwable;
class AccountAccessController extends Controller
{
public function forgot(Request $request): Response
{
return $this->page($request, 'forgot');
}
public function sendResetLink(AccountEmailRequest $request): RedirectResponse
{
try {
Password::broker('web_users')->sendResetLink($request->safe()->only('email'));
} catch (Throwable $exception) {
report($exception);
return back()->with('error', __('Не удалось отправить письмо. Попробуй ещё раз через минуту.'))->onlyInput('email');
}
return back()->with('status', __('Если аккаунт с такой почтой существует, письмо со ссылкой для восстановления придёт в течение нескольких минут. Проверь также папку «Спам».'))->onlyInput('email');
}
public function reset(Request $request, string $token): Response
{
return $this->page($request, 'reset', ['token' => $token]);
}
public function updatePassword(ResetAccountPasswordRequest $request): RedirectResponse
{
// Keep token validation, password update and token consumption atomic.
$status = DB::transaction(function () use ($request): string {
User::where('email', $request->string('email')->toString())->lockForUpdate()->first();
return Password::broker('web_users')->reset(
$request->safe()->only(['email', 'password', 'password_confirmation', 'token']),
function (User $user, string $password): void {
$user->forceFill(['password' => $password, 'remember_token' => Str::random(60)])->save();
event(new PasswordReset($user));
},
);
});
if ($status !== Password::PASSWORD_RESET) {
return back()->withErrors(['token' => __('Ссылка недействительна или срок её действия истёк. Запроси новое письмо.')])->onlyInput('email');
}
return redirect()->route('login')->with('status', __('Пароль обновлён. Войди в аккаунт с новым паролем.'));
}
public function notice(Request $request): Response
{
return $this->page($request, 'verification');
}
public function resend(AccountEmailRequest $request, AccountEmailService $emails): RedirectResponse
{
$user = User::whereRaw('LOWER(email) = ?', [$request->string('email')->toString()])->first();
if ($user !== null) {
$emails->sendVerification($user);
}
return back()->with('status', __('Если этот email ожидает подтверждения, мы отправим письмо. Повторный запрос доступен через минуту. Проверь также папку «Спам».'))->onlyInput('email');
}
public function verify(Request $request, string $id, string $hash): Response
{
if (! $request->hasValidSignature()) {
return $this->page($request, 'invalid');
}
$user = User::find($id);
if ($user === null || ! hash_equals(sha1($user->getEmailForVerification()), $hash)) {
return $this->page($request, 'invalid');
}
if (! $user->hasVerifiedEmail() && $user->markEmailAsVerified()) {
event(new Verified($user));
}
return $this->page($request, 'verified');
}
private function page(Request $request, string $mode, array $extra = []): Response
{
$email = $mode === 'reset'
? $request->query('email', '')
: $request->old('email', $mode === 'verification' ? $request->session()->get('verification_email', '') : '');
return Inertia::render('Auth/AccountAccess', [
'site' => [
'name' => config('moonwell.realm.server_name'),
'tagline' => config('moonwell.realm.tagline'),
],
'auth' => [
'authenticated' => $request->user() !== null,
'username' => $request->user()?->username,
'access_label' => $request->user()?->accessLabel(),
'is_admin' => $request->user()?->canAccessAdminPanel() ?? false,
],
'urls' => [
'home' => route('landing.index'),
'login' => route('login'),
'cabinet' => route('cabinet.index'),
'logout' => route('logout'),
'forgot' => route('password.request'),
'send_reset' => route('password.email'),
'reset' => route('password.update'),
'verification' => route('verification.notice'),
'resend' => route('verification.send'),
'offer' => config('moonwell.legal.offer_published') ? route('legal.offer') : null,
'privacy' => config('moonwell.legal.privacy_published') ? route('legal.privacy') : null,
'rules' => config('moonwell.legal.rules_published') ? route('legal.rules') : null,
],
'flash' => [
'status' => $request->session()->get('status'),
'error' => $request->session()->get('error'),
],
'mode' => $mode,
'email' => is_string($email) ? $email : '',
...$extra,
]);
}
}