id === (int) $id; }); // Laravel broadcast notifications channel (used by UnreadIndicator for BroadcastNotificationCreated) Broadcast::channel('users.{id}', function ($user, $id) { return (int) $user->id === (int) $id; }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], ]); // Test private broadcast: $toUserId is provided in web.php route Broadcast::channel('change-lang.{toUserId}', function ($user, $toUserId) { return (int) $user->id == (int) $toUserId; }); Broadcast::channel('switch-profile.{userId}', function ($user, $userId) { // The switch-profile channel is always subscribed using the web user's ID // (from SwitchProfile component's getListeners method using Auth::guard('web')->id()) // We need to authorize against the web user, not the active profile $webUser = Auth::guard('web')->user(); if (!$webUser) { return false; } return (int) $webUser->id === (int) $userId; }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], ]); // Override WireChat conversation channel Broadcast::channel('conversation.{conversationId}', function ($user, $conversationId) { $activeGuard = session('active_guard'); $actor = null; // If no active_guard is set, default to 'web' guard if (!$activeGuard) { $activeGuard = 'web'; } if ($activeGuard && in_array($activeGuard, ['admin', 'bank', 'organization', 'web'])) { $actor = Auth::guard($activeGuard)->user(); } $conversation = Conversation::find($conversationId); if ($actor && $conversation && $actor->belongsToConversation($conversation)) { return true; } return false; }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], 'middleware' => ['auth.any:admin,bank,organization,web'], ]); // Override WireChat participant channel Broadcast::channel('participant.{encodedType}.{id}', function ($user, $encodedType, $id) { $activeGuard = session('active_guard'); if (!$activeGuard) { $activeGuard = 'web'; } $actor = null; if (in_array($activeGuard, ['admin', 'bank', 'organization', 'web'])) { $actor = Auth::guard($activeGuard)->user(); } $morphType = MorphClassResolver::decode($encodedType); // Allow active profile to subscribe to its own channel if ($actor && $actor->id == $id && $actor->getMorphClass() == $morphType) { return true; } // Also allow the web user to subscribe to channels for profiles they manage // (needed for SwitchProfileUnreadIndicator to track non-active profiles) $webUser = Auth::guard('web')->user(); if (!$webUser) { return false; } if ($morphType === 'App\Models\Organization') { return $webUser->organizations()->where('organizations.id', $id)->exists(); } if ($morphType === 'App\Models\Bank') { return $webUser->banksManaged()->where('banks.id', $id)->exists(); } if ($morphType === 'App\Models\Admin') { return $webUser->admins()->where('admins.id', $id)->exists(); } if ($morphType === 'App\Models\User') { return $webUser->id == $id; } return false; }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], 'middleware' => ['auth.any:admin,bank,organization,web'], ]); // Presence Channel Authorization // Any authenticated user (on any guard) may join any presence-*-users channel // so they can receive online status updates for profiles of other guard types. Broadcast::channel('presence-{guard}-users', function ($user, $guard) { $activeGuard = session('active_guard', 'web'); if (auth($activeGuard)->check()) { $activeUser = auth($activeGuard)->user(); return [ 'id' => $activeUser->id, 'name' => $activeUser->name, 'avatar' => $activeUser->avatar ?? null, 'guard' => $activeGuard, 'joined_at' => now(), ]; } return false; }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], ]); //Private channel for presence updates Broadcast::channel('presence-updates-{guard}', function ($user, $guard) { $activeGuard = session('active_guard', 'web'); return auth($activeGuard)->check(); }, [ 'guards' => ['admin', 'bank', 'organization', 'web'], ]); // Private channel for forced logout Broadcast::channel('user.logout.{userId}', function ($user, $userId) { return (int) $user->id === (int) $userId; }); // Broadcast::channel('redirect-channel', function ($user) { // return !is_null($user); // });