clupilot/app/app/Http/Middleware/ResolveCurrentWorkspace.php

84 lines
2.7 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Models\Workspace;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;
/**
* Resolves the active workspace and binds it for the rest of the request.
*
* Resolution order:
* 1. Route param {wsId} (URL-driven, persistent — primary)
* 2. ?workspace=<public_id> query (one-off switch)
* 3. Session 'workspace_id' (sticky between requests)
* 4. authenticated user's current_workspace_id
* 5. authenticated user's first owned workspace
*
* Once resolved:
* - container('currentWorkspace') is bound (used by BelongsToWorkspace).
* - URL::defaults(['wsId' => …]) so every route() call auto-prefixes.
* - session('workspace_id') updated for stickiness across requests.
* - user.current_workspace_id updated when an explicit switch happens.
*/
class ResolveCurrentWorkspace
{
public function handle(Request $request, Closure $next): Response
{
$user = $request->user();
if (! $user) {
return $next($request);
}
$ws = null;
// 1. Route param (e.g. /w/aBcDeF…/dashboard).
if ($wsId = $request->route('wsId')) {
$ws = Workspace::where('public_id', $wsId)->first();
if ($ws) {
$user->forceFill(['current_workspace_id' => $ws->id])->saveQuietly();
$request->session()->put('workspace_id', $ws->id);
}
}
// 2. Query-string explicit switch (?workspace=pubId).
if (! $ws && $pid = $request->query('workspace')) {
$ws = Workspace::where('public_id', $pid)->orWhere('slug', $pid)->first();
if ($ws) {
$request->session()->put('workspace_id', $ws->id);
$user->forceFill(['current_workspace_id' => $ws->id])->saveQuietly();
}
}
// 3. Session sticky.
if (! $ws && $sid = $request->session()->get('workspace_id')) {
$ws = Workspace::find($sid);
}
// 4. User's saved current.
if (! $ws && $user->current_workspace_id) {
$ws = $user->currentWorkspace;
}
// 5. First owned.
if (! $ws) {
$ws = $user->ownedWorkspaces()->first();
if ($ws) {
$user->forceFill(['current_workspace_id' => $ws->id])->saveQuietly();
}
}
if ($ws) {
app()->instance('currentWorkspace', $ws);
$request->session()->put('workspace_id', $ws->id);
// Auto-inject {wsId} into every route() call so links stay scoped.
URL::defaults(['wsId' => $ws->public_id]);
}
return $next($request);
}
}