singleloginsystem/app/Http/Controllers/KekaOutlookController.php
2026-06-12 18:22:10 +05:30

101 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Services\KekaOutlookService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
final class KekaOutlookController extends Controller
{
public function __construct(private KekaOutlookService $kekaOutlook) {}
/**
* GET /keka/connect
*
* If the user already has a stored refresh token, we don't show
* Microsoft's login screen at all — just confirm/refresh silently
* and send them straight back to Keka.
*
* If not connected yet, redirect to Microsoft login (one-time).
*/
public function connect(Request $request): RedirectResponse
{
$user = $request->user();
if ($this->kekaOutlook->isConnected($user)) {
try {
// Ensures token is fresh; throws if refresh token is invalid/revoked.
$this->kekaOutlook->getValidToken($user);
return redirect()->away($this->kekaWebsiteUrl());
} catch (\RuntimeException $e) {
// Refresh failed -> fall through to re-login below.
}
}
return redirect()->away($this->kekaOutlook->getAuthUrl());
}
/**
* GET /keka/callback
*
* Microsoft redirects here after login with ?code=... or ?error=...
*/
public function callback(Request $request): RedirectResponse
{
if ($request->filled('error')) {
return redirect()
->route('dashboard')
->with('error', 'Microsoft login was cancelled or failed: '.$request->get('error_description', $request->get('error')));
}
if (! $this->kekaOutlook->isValidState($request->get('state'))) {
return redirect()
->route('dashboard')
->with('error', 'Invalid login session. Please try connecting again.');
}
$code = $request->get('code');
if (! $code) {
return redirect()
->route('dashboard')
->with('error', 'No authorization code received from Microsoft.');
}
$result = $this->kekaOutlook->handleCallback($request->user(), $code);
if (! $result['success']) {
return redirect()
->route('dashboard')
->with('error', 'Failed to connect: '.($result['message'] ?? 'Unknown error'));
}
return redirect()->away($this->kekaWebsiteUrl());
}
/**
* POST /keka/disconnect
*
* Wipes stored tokens. User must go through Microsoft login again next time.
*/
public function disconnect(Request $request): RedirectResponse
{
$this->kekaOutlook->disconnect($request->user());
return redirect()
->route('dashboard')
->with('success', 'Keka has been disconnected.');
}
/**
* The Keka website URL the user lands on after a successful (silent) connection.
*/
private function kekaWebsiteUrl(): string
{
return (string) config('microsoft.keka_website_url', 'https://app.keka.com');
}
}