validate([ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email', 'max:255', 'unique:earn_members,email'], 'password' => ['required', 'confirmed', Password::defaults()], 'terms_accepted' => ['accepted'], 'privacy_notice_acknowledged' => ['accepted'], ], [ 'terms_accepted.accepted' => __('earn_legal.validation.terms_accepted'), 'privacy_notice_acknowledged.accepted' => __('earn_legal.validation.privacy_notice_acknowledged'), ]); $member = DB::transaction(function () use ($data, $request): EarnMember { $member = EarnMember::query()->create([ 'name' => trim($data['name']), 'email' => Str::lower($data['email']), 'password' => $data['password'], 'status' => EarnMemberStatus::Pending, ]); $context = ['accepted_at' => now(), 'ip_address' => $request->ip(), 'user_agent' => Str::limit((string) $request->userAgent(), 1000, '')]; $member->legalAcceptances()->create($context + ['document_type' => EarnLegalDocumentType::Terms, 'document_version' => config('earn.legal.terms.version')]); $member->legalAcceptances()->create($context + ['document_type' => EarnLegalDocumentType::PrivacyNotice, 'document_version' => config('earn.legal.privacy.version')]); return $member; }); event(new Registered($member)); Auth::guard('earn')->login($member); $request->session()->regenerate(); return redirect()->route('earn.verification.notice'); } public function login(Request $request): RedirectResponse { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required', 'string'], ]); $key = 'earn-login:'.Str::transliterate(Str::lower($credentials['email']).'|'.$request->ip()); if (RateLimiter::tooManyAttempts($key, 5)) { throw ValidationException::withMessages(['email' => __('ui.errors.throttle')]); } if (! Auth::guard('earn')->attempt($credentials, $request->boolean('remember'))) { RateLimiter::hit($key, 60); throw ValidationException::withMessages(['email' => __('ui.errors.credentials')]); } $member = Auth::guard('earn')->user(); if (! $member->canUseApi()) { Auth::guard('earn')->logout(); RateLimiter::hit($key, 60); throw ValidationException::withMessages(['email' => __('earn_portal.account_unavailable')]); } RateLimiter::clear($key); $request->session()->regenerate(); $member->forceFill(['last_login_at' => now(), 'last_login_ip' => $request->ip()])->saveQuietly(); return redirect()->intended(route('earn.dashboard')); } public function logout(Request $request): RedirectResponse { Auth::guard('earn')->logout(); $request->session()->regenerate(); $request->session()->regenerateToken(); return redirect()->route('earn.login'); } }