nicer package layout, also in checkout step 1, fixed missing registration language strings, registration error handling, email verification redirect, email verification error handling and messaging,

This commit is contained in:
Codex Agent
2025-11-19 20:21:54 +01:00
parent 91d3e61b0e
commit 8d2075bdd2
24 changed files with 1000 additions and 363 deletions

View File

@@ -15,8 +15,18 @@ class EmailVerificationPromptController extends Controller
*/
public function __invoke(Request $request): Response|RedirectResponse
{
return $request->user()->hasVerifiedEmail()
? redirect()->intended(route('dashboard', absolute: false))
: Inertia::render('auth/verify-email', ['status' => $request->session()->get('status')]);
if ($request->user()->hasVerifiedEmail()) {
$redirectToCheckout = $request->session()->pull('checkout.verify_redirect');
if ($redirectToCheckout) {
$separator = str_contains($redirectToCheckout, '?') ? '&' : '?';
return redirect()->to($redirectToCheckout.$separator.'verified=1');
}
return redirect()->intended(route('dashboard', absolute: false));
}
return Inertia::render('auth/verify-email', ['status' => $request->session()->get('status')]);
}
}

View File

@@ -13,12 +13,61 @@ class VerifyEmailController extends Controller
*/
public function __invoke(EmailVerificationRequest $request): RedirectResponse
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
if (! $request->user()->hasVerifiedEmail()) {
$request->fulfill();
}
$request->fulfill();
return $this->redirectAfterVerification($request);
}
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
protected function redirectAfterVerification(EmailVerificationRequest $request): RedirectResponse
{
$redirectToCheckout = $request->session()->pull('checkout.verify_redirect');
if (! $redirectToCheckout && $request->user()->pending_purchase) {
$packageId = $request->session()->pull('checkout.pending_package_id');
if (! $packageId) {
$packageId = optional($request->user()->tenant)
?->packages()
->latest('tenant_packages.created_at')
->value('packages.id');
}
if ($packageId) {
$redirectToCheckout = route('checkout.show', ['package' => $packageId]);
}
}
$this->flashVerificationSuccess($request, (bool) $redirectToCheckout);
if ($redirectToCheckout) {
$request->session()->forget('checkout.pending_package_id');
$separator = str_contains($redirectToCheckout, '?') ? '&' : '?';
return redirect()->to($redirectToCheckout.$separator.'verified=1');
}
$fallbackLogin = route('marketing.login');
$separator = str_contains($fallbackLogin, '?') ? '&' : '?';
return redirect()->intended($fallbackLogin.$separator.'verified=1');
}
private function flashVerificationSuccess(EmailVerificationRequest $request, bool $forCheckout): void
{
$message = $forCheckout
? __('auth.verification.checkout_success_message')
: __('auth.verification.success_message');
$request->session()->flash('verification', [
'status' => 'success',
'title' => __('auth.verification.success_title'),
'message' => $message,
]);
if (! $forCheckout) {
$request->session()->flash('status', __('auth.verification.success_message'));
}
}
}

View File

@@ -76,7 +76,7 @@ class CheckoutController extends Controller
$package = Package::findOrFail($request->package_id);
$validated = $validator->validated();
DB::transaction(function () use ($request, $package, $validated) {
$user = DB::transaction(function () use ($request, $package, $validated) {
// User erstellen
$user = User::create([
@@ -138,10 +138,28 @@ class CheckoutController extends Controller
Mail::to($user)
->locale($user->preferred_locale ?? app()->getLocale())
->queue(new Welcome($user));
return $user;
});
Auth::login($user);
$request->session()->put('checkout.pending_package_id', $package->id);
$redirectUrl = route('checkout.show', ['package' => $package->id]);
$request->session()->put('checkout.verify_redirect', $redirectUrl);
$request->session()->put('url.intended', $redirectUrl);
return response()->json([
'success' => true,
'message' => 'Registrierung erfolgreich. Bitte überprüfen Sie Ihre E-Mail zur Verifizierung.',
'redirect' => $redirectUrl,
'user' => [
'id' => $user->id,
'email' => $user->email,
'name' => $user->name ?? trim($user->first_name.' '.$user->last_name),
'pending_purchase' => $user->pending_purchase ?? true,
'email_verified_at' => $user->email_verified_at,
],
'pending_purchase' => $user->pending_purchase ?? true,
]);
}

View File

@@ -48,13 +48,13 @@ class Kernel extends HttpKernel
];
/**
* The application's route middleware.
* The application's middleware aliases.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,

View File

@@ -69,6 +69,9 @@ class HandleInertiaRequests extends Middleware
'profile' => __('profile'),
'dashboard' => __('dashboard'),
],
'flash' => [
'verification' => fn () => $request->session()->get('verification'),
],
];
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class NormalizeSignedUrlParameters
{
public function handle(Request $request, Closure $next)
{
$queryString = $request->server->get('QUERY_STRING');
if (is_string($queryString) && str_contains($queryString, '&amp;')) {
$normalized = str_replace('&amp;', '&', $queryString);
if ($normalized !== $queryString) {
$request->server->set('QUERY_STRING', $normalized);
parse_str($normalized, $params);
if (is_array($params) && ! empty($params)) {
$request->query->replace(array_merge($request->query->all(), $params));
}
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Routing\Exceptions\InvalidSignatureException;
use Illuminate\Routing\Middleware\ValidateSignature as BaseValidateSignature;
class ValidateSignature extends BaseValidateSignature
{
public function handle($request, Closure $next, ...$args)
{
try {
return parent::handle($request, $next, ...$args);
} catch (InvalidSignatureException $exception) {
if ($request->expectsJson()) {
throw $exception;
}
if ($request->routeIs('verification.verify')) {
$request->session()->flash('verification', [
'status' => 'error',
'title' => __('auth.verification.expired_title'),
'message' => __('auth.verification.expired_message'),
]);
return redirect()->route('verification.notice');
}
throw $exception;
}
}
}