112 lines
3.7 KiB
PHP
112 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Socialite\Facades\Socialite;
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
use Throwable;
|
|
|
|
class TenantAdminGoogleController extends Controller
|
|
{
|
|
public function redirect(Request $request): RedirectResponse
|
|
{
|
|
$returnTo = $request->query('return_to');
|
|
if (is_string($returnTo) && $returnTo !== '') {
|
|
$request->session()->put('tenant_oauth_return_to', $returnTo);
|
|
}
|
|
|
|
return Socialite::driver('google')
|
|
->scopes(['openid', 'profile', 'email'])
|
|
->with(['prompt' => 'select_account'])
|
|
->redirect();
|
|
}
|
|
|
|
public function callback(Request $request)
|
|
{
|
|
try {
|
|
$googleUser = Socialite::driver('google')->user();
|
|
} catch (Throwable $exception) {
|
|
Log::warning('Tenant admin Google sign-in failed', [
|
|
'message' => $exception->getMessage(),
|
|
]);
|
|
|
|
return $this->sendBackWithError($request, 'google_failed', 'Unable to complete Google sign-in.');
|
|
}
|
|
|
|
$email = $googleUser->getEmail();
|
|
if (! $email) {
|
|
return $this->sendBackWithError($request, 'google_failed', 'Google account did not provide an email address.');
|
|
}
|
|
|
|
/** @var User|null $user */
|
|
$user = User::query()->where('email', $email)->first();
|
|
|
|
if (! $user || ! in_array($user->role, ['tenant_admin', 'super_admin', 'superadmin'], true)) {
|
|
return $this->sendBackWithError($request, 'google_no_match', 'No tenant admin account is linked to this Google address.');
|
|
}
|
|
|
|
$user->forceFill([
|
|
'name' => $googleUser->getName() ?: $user->name,
|
|
'email_verified_at' => $user->email_verified_at ?? now(),
|
|
])->save();
|
|
|
|
Auth::login($user, true);
|
|
$request->session()->regenerate();
|
|
$request->session()->forget('url.intended');
|
|
|
|
$returnTo = $request->session()->pull('tenant_oauth_return_to');
|
|
if (is_string($returnTo)) {
|
|
$decoded = $this->decodeReturnTo($returnTo, $request);
|
|
if ($decoded) {
|
|
return redirect()->to($decoded);
|
|
}
|
|
}
|
|
|
|
$fallback = $request->session()->pull('tenant_admin.return_to');
|
|
if (is_string($fallback) && str_starts_with($fallback, '/event-admin')) {
|
|
return redirect()->to($fallback);
|
|
}
|
|
|
|
return redirect()->to('/event-admin/dashboard');
|
|
}
|
|
|
|
private function sendBackWithError(Request $request, string $code, string $message): RedirectResponse
|
|
{
|
|
$query = [
|
|
'error' => $code,
|
|
'error_description' => $message,
|
|
];
|
|
|
|
if ($request->session()->has('tenant_oauth_return_to')) {
|
|
$query['return_to'] = $request->session()->get('tenant_oauth_return_to');
|
|
}
|
|
|
|
return redirect()->route('tenant.admin.login', $query);
|
|
}
|
|
|
|
private function decodeReturnTo(string $encoded, Request $request): ?string
|
|
{
|
|
$padded = str_pad($encoded, strlen($encoded) + ((4 - (strlen($encoded) % 4)) % 4), '=');
|
|
$normalized = strtr($padded, '-_', '+/');
|
|
$decoded = base64_decode($normalized);
|
|
|
|
if (! is_string($decoded) || $decoded === '') {
|
|
return null;
|
|
}
|
|
|
|
$targetHost = parse_url($decoded, PHP_URL_HOST);
|
|
$appHost = parse_url($request->getSchemeAndHttpHost(), PHP_URL_HOST);
|
|
|
|
if ($targetHost && $appHost && ! Str::endsWith($targetHost, $appHost)) {
|
|
return null;
|
|
}
|
|
|
|
return $decoded;
|
|
}
|
|
}
|