resolveAmministratore(); if (! $amministratore instanceof Amministratore) { abort(403, 'Amministratore non disponibile per questa sessione.'); } $google = Arr::get($amministratore->impostazioni ?? [], 'google', []); $clientId = (string) ($google['client_id'] ?? config('services.google.client_id')); $clientSecret = (string) ($google['client_secret'] ?? config('services.google.client_secret')); $redirectUri = (string) ($google['redirect_uri'] ?? config('services.google.redirect')); if ($clientId === '' || $clientSecret === '' || $redirectUri === '') { return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('error', 'Configura Client ID, Client Secret e Redirect URI in Scheda amministratore.'); } $state = bin2hex(random_bytes(20)); session()->put('google_oauth_state', $state); $query = http_build_query([ 'client_id' => $clientId, 'redirect_uri' => $redirectUri, 'response_type' => 'code', 'scope' => implode(' ', self::GOOGLE_SCOPES), 'access_type' => 'offline', 'prompt' => 'consent', 'include_granted_scopes' => 'true', 'state' => $state, ]); return redirect()->away('https://accounts.google.com/o/oauth2/v2/auth?' . $query); } public function callback(): RedirectResponse { $amministratore = $this->resolveAmministratore(); if (! $amministratore instanceof Amministratore) { abort(403, 'Amministratore non disponibile per questa sessione.'); } $google = Arr::get($amministratore->impostazioni ?? [], 'google', []); $clientId = (string) ($google['client_id'] ?? config('services.google.client_id')); $clientSecret = (string) ($google['client_secret'] ?? config('services.google.client_secret')); $redirectUri = (string) ($google['redirect_uri'] ?? config('services.google.redirect')); try { $incomingState = (string) request()->query('state', ''); $sessionState = (string) session()->pull('google_oauth_state', ''); if ($incomingState === '' || $sessionState === '' || ! hash_equals($sessionState, $incomingState)) { return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('error', 'Stato OAuth non valido. Riprova il collegamento Google.'); } $code = (string) request()->query('code', ''); if ($code === '') { return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('error', 'Google non ha restituito il codice di autorizzazione.'); } $tokenResponse = Http::asForm()->post('https://oauth2.googleapis.com/token', [ 'client_id' => $clientId, 'client_secret' => $clientSecret, 'redirect_uri' => $redirectUri, 'grant_type' => 'authorization_code', 'code' => $code, ]); if (! $tokenResponse->successful()) { $message = (string) (Arr::get($tokenResponse->json(), 'error_description') ?: Arr::get($tokenResponse->json(), 'error.message') ?: 'token_exchange_failed'); return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('error', 'Errore scambio token Google: ' . $message); } $payload = $tokenResponse->json(); $accessToken = (string) Arr::get($payload, 'access_token', ''); $refreshToken = (string) Arr::get($payload, 'refresh_token', ''); $expiresIn = (int) Arr::get($payload, 'expires_in', 3600); $profileResponse = Http::withToken($accessToken) ->acceptJson() ->get('https://openidconnect.googleapis.com/v1/userinfo'); $profile = $profileResponse->successful() ? $profileResponse->json() : []; $googleUserId = (string) Arr::get($profile, 'sub', ''); $email = (string) Arr::get($profile, 'email', ''); $name = (string) Arr::get($profile, 'name', ''); $impostazioni = $amministratore->impostazioni ?? []; $impostazioni['google'] = array_merge($google, [ 'oauth' => [ 'connected' => true, 'email' => $email, 'name' => $name, 'google_user_id' => $googleUserId, 'access_token' => $accessToken, 'refresh_token' => $refreshToken, 'expires_in' => $expiresIn, 'connected_at' => now()->toDateTimeString(), ], ]); $amministratore->impostazioni = $impostazioni; $amministratore->save(); return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('status', 'Account Google collegato con successo.'); } catch (Throwable $e) { Log::error('Google OAuth callback failed', [ 'admin_id' => $amministratore->id, 'error' => $e->getMessage(), ]); return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('error', 'Errore durante il collegamento Google: ' . $e->getMessage()); } } public function disconnect(): RedirectResponse { $amministratore = $this->resolveAmministratore(); if (! $amministratore instanceof Amministratore) { abort(403, 'Amministratore non disponibile per questa sessione.'); } $impostazioni = $amministratore->impostazioni ?? []; $google = Arr::get($impostazioni, 'google', []); $google['oauth'] = [ 'connected' => false, 'disconnected_at' => now()->toDateTimeString(), ]; $impostazioni['google'] = $google; $amministratore->impostazioni = $impostazioni; $amministratore->save(); return redirect('/admin-filament/impostazioni/scheda-amministratore') ->with('status', 'Collegamento Google rimosso.'); } private function resolveAmministratore(): ?Amministratore { $user = Auth::user(); if (! $user instanceof User) { return null; } $amministratore = $user->amministratore; if (! $amministratore instanceof Amministratore && $user->hasAnyRole(['super-admin', 'admin'])) { $stabile = StabileContext::getActiveStabile($user); if ($stabile instanceof Stabile && $stabile->amministratore instanceof Amministratore) { $amministratore = $stabile->amministratore; } } return $amministratore instanceof Amministratore ? $amministratore : null; } }