Switch team invites to email-only flow via identity API.
Deploy Ladill Frontdesk / deploy (push) Successful in 44s

Replace local member UUID invites with platform email invites, SSO post-auth
redirect, and provisioner-backed pending access until accept.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 00:25:09 +00:00
co-authored by Cursor
parent 6bc52d9ef3
commit b68331cdaf
6 changed files with 216 additions and 23 deletions
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\Identity\IdentityTeamClient;
use App\Services\Frontdesk\TeamMemberProvisioner;
use Illuminate\Http\Client\Response as HttpResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -26,12 +28,14 @@ class SsoLoginController extends Controller
*/
private const MAX_SSO_ATTEMPTS = 3;
public function connect(Request $request): RedirectResponse|View
public function connect(Request $request, IdentityTeamClient $identity): RedirectResponse|View
{
$intended = (string) $request->query('redirect', route('frontdesk.dashboard'));
if (Auth::check()) {
return $this->safeRedirect($intended, route('frontdesk.dashboard'));
$redirect = $this->resolveLanding($identity, $request->user(), $intended);
return $this->safeRedirect($redirect, route('frontdesk.dashboard'));
}
if (! $request->boolean('fallback')) {
@@ -39,7 +43,10 @@ class SsoLoginController extends Controller
}
if ($this->attemptSilentRefresh($request, $intended)) {
return $this->safeRedirect($intended, route('frontdesk.dashboard'));
app(TeamMemberProvisioner::class)->sync(Auth::user());
$redirect = $this->resolveLanding($identity, Auth::user(), $intended);
return $this->safeRedirect($redirect, route('frontdesk.dashboard'));
}
$verifier = Str::random(64);
@@ -115,7 +122,9 @@ class SsoLoginController extends Controller
$request->session()->regenerate();
$request->session()->forget('sso.attempts');
return $this->finishCallback($request, $intended, null);
app(TeamMemberProvisioner::class)->sync($user);
return $this->finishCallback($request, $intended, null, app(IdentityTeamClient::class));
}
public function failed(Request $request): View
@@ -241,8 +250,12 @@ class SsoLoginController extends Controller
);
}
private function finishCallback(Request $request, string $intended, ?string $error = null): RedirectResponse
{
private function finishCallback(
Request $request,
string $intended,
?string $error = null,
?IdentityTeamClient $identity = null,
): RedirectResponse {
if ($error) {
$attempts = (int) $request->session()->get('sso.attempts', 0) + 1;
@@ -262,7 +275,21 @@ class SsoLoginController extends Controller
]);
}
return $this->safeRedirect($intended, route('frontdesk.dashboard'));
$user = Auth::user();
$redirect = ($user instanceof User && $identity)
? $this->resolveLanding($identity, $user, $intended)
: $intended;
return $this->safeRedirect($redirect, route('frontdesk.dashboard'));
}
private function resolveLanding(IdentityTeamClient $identity, User $user, string $intended): string
{
try {
return $identity->postAuthRedirect($user->ownerRef(), $intended);
} catch (\Throwable) {
return $intended;
}
}
private function safeReturnUrl(string $url): string