| Server IP : 35.80.110.71 / Your IP : 216.73.216.221 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/switchyard/current/app/Http/Controllers/ |
Upload File : |
<?php
namespace App\Http\Controllers;
use App\Models\Workspace;
use App\Services\ClickUp\ClickUpOAuthClient;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use RuntimeException;
class ClickUpOAuthController extends Controller
{
private const CONNECTIONS_URL = '/admin/click-up-connections';
public function __construct(private readonly ClickUpOAuthClient $oauth) {}
public function connect(Request $request): RedirectResponse
{
if (! $this->credsConfigured()) {
return redirect(self::CONNECTIONS_URL)->with(
'error',
'ClickUp OAuth app is not registered yet. See guides/clickup-oauth-app.md (or '
.'~/projects/income-ops/.scratch/plans/switchyard_clickup_oauth_app_registration.md) '
.'for the steps to register the app at app.clickup.com/api and drop CLICKUP_CLIENT_ID + '
.'CLICKUP_CLIENT_SECRET into shared/.env on the server.',
);
}
$workspaceId = $request->user()?->current_workspace_id;
$workspace = $workspaceId ? Workspace::find($workspaceId) : null;
if (! $workspace) {
return redirect(self::CONNECTIONS_URL)->with('error', 'No active workspace. Pick one from Settings → Workspaces.');
}
try {
return redirect()->away($this->oauth->authorizeUrl($workspace));
} catch (RuntimeException $e) {
Log::warning('ClickUp OAuth connect failed', ['error' => $e->getMessage()]);
return redirect(self::CONNECTIONS_URL)->with('error', $e->getMessage());
}
}
public function callback(Request $request): RedirectResponse
{
$error = $request->query('error');
if (is_string($error) && $error !== '') {
Log::warning('ClickUp OAuth callback returned error', ['error' => $error]);
return redirect(self::CONNECTIONS_URL)
->with('error', "ClickUp denied authorization: {$error}");
}
$state = (string) $request->query('state', '');
$code = (string) $request->query('code', '');
if ($state === '' || $code === '') {
return redirect(self::CONNECTIONS_URL)
->with('error', 'ClickUp OAuth callback was missing state or code.');
}
try {
$payload = $this->oauth->consumeState($state);
$accessToken = $this->oauth->exchangeCode($code);
$teams = $this->oauth->fetchAuthorizedTeams($accessToken);
$teamId = $teams['teams'][0]['id'] ?? null;
$this->oauth->persistTokens($payload['workspace_id'], $accessToken, $teamId);
} catch (RuntimeException $e) {
Log::warning('ClickUp OAuth callback failed', ['error' => $e->getMessage()]);
return redirect(self::CONNECTIONS_URL)
->with('error', $e->getMessage());
}
return redirect(self::CONNECTIONS_URL)
->with('success', 'ClickUp connected.');
}
private function credsConfigured(): bool
{
return ! empty(config('switchyard.clickup.client_id'))
&& ! empty(config('switchyard.clickup.client_secret'))
&& ! empty(config('switchyard.clickup.redirect_uri'));
}
}