Files
fotospiel-app/app/Http/Controllers/TenantAdminFacebookController.php
Codex Agent 73728f6baf
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled
Add Facebook social login
2026-01-23 20:19:15 +01:00

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 TenantAdminFacebookController 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('facebook')
->scopes(['email'])
->fields(['name', 'email', 'first_name', 'last_name'])
->redirect();
}
public function callback(Request $request): RedirectResponse
{
try {
$facebookUser = Socialite::driver('facebook')->user();
} catch (Throwable $exception) {
Log::warning('Tenant admin Facebook sign-in failed', [
'message' => $exception->getMessage(),
]);
return $this->sendBackWithError($request, 'facebook_failed', 'Unable to complete Facebook sign-in.');
}
$email = $facebookUser->getEmail();
if (! $email) {
return $this->sendBackWithError($request, 'facebook_failed', 'Facebook 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, 'facebook_no_match', 'No tenant admin account is linked to this Facebook address.');
}
$user->forceFill([
'name' => $facebookUser->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;
}
}