mirror of
https://github.com/archtechx/tenancy.git
synced 2026-08-06 05:34:04 +00:00
Copy the broadcaster auth state directly
Instead of re-registering the central channels on the tenant broadcaster one by one, copy the properties directly. Also the authenticated user callback wasn't copied before, so user authentication (/broadcasting/user-auth) that worked in central context would 403 in tenant context if the callback was registered in central context.
This commit is contained in:
parent
50afc49d2b
commit
fe7468ab72
1 changed files with 28 additions and 18 deletions
|
|
@ -91,27 +91,11 @@ class BroadcastingConfigBootstrapper implements TenancyBootstrapper
|
|||
// contract gets the same tenant broadcaster that the manager uses, instead of the stale central one.
|
||||
// The closure runs immediately (the extended singleton is already resolved), and it's also what makes
|
||||
// channel auth work in tenant context -- the broadcaster resolved here gets cached as the tenant
|
||||
// manager's default driver and receives the central channel auth closures (see below).
|
||||
// manager's default driver and receives the central broadcaster's auth state (see copyAuthState()).
|
||||
$this->app->extend(BroadcasterContract::class, function (BroadcasterContract $centralBroadcaster) {
|
||||
$tenantBroadcaster = $this->app->make(BroadcastManager::class)->connection();
|
||||
|
||||
// The newly resolved broadcaster doesn't have any channel auth closures registered, so the
|
||||
// closures registered in central context (e.g. in routes/channels.php) have to be passed to it
|
||||
// manually, otherwise, Broadcast::auth() would throw a 403 for those channels.
|
||||
// Since Laravel only ever uses the default broadcaster's channel auth closures for broadcasting auth,
|
||||
// we only have to pass the channel closures to the default broadcaster.
|
||||
//
|
||||
// The channel() and getChannels() methods aren't part of the Broadcaster contract -- they come
|
||||
// from the abstract Broadcaster class, so the closures can only be copied between broadcasters extending it
|
||||
// (which all of Laravel's default broadcasters, e.g. PusherBroadcaster, do).
|
||||
if ($centralBroadcaster instanceof Broadcaster && $tenantBroadcaster instanceof Broadcaster) {
|
||||
// invade() because the channel options can't be retrieved through any of the broadcaster's public methods
|
||||
$channelOptions = invade($centralBroadcaster)->channelOptions;
|
||||
|
||||
foreach ($centralBroadcaster->getChannels() as $channel => $callback) {
|
||||
$tenantBroadcaster->channel($channel, $callback, $channelOptions[$channel] ?? []);
|
||||
}
|
||||
}
|
||||
$this->copyAuthState($centralBroadcaster, $tenantBroadcaster);
|
||||
|
||||
return $tenantBroadcaster;
|
||||
});
|
||||
|
|
@ -122,6 +106,32 @@ class BroadcastingConfigBootstrapper implements TenancyBootstrapper
|
|||
Broadcast::clearResolvedInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the auth state (the channel auth closures, their options, and the authenticated user
|
||||
* callback) from one broadcaster to another. A freshly resolved broadcaster has no auth state,
|
||||
* so without the copying, channel auth and user auth would stop working (403) in tenant context.
|
||||
*
|
||||
* The auth state is stored on the abstract Broadcaster class, not in the Broadcaster
|
||||
* contract, and it's stored in protected properties. Because of that, we have
|
||||
* to check that both broadcasters are instances of the abstract Broadcaster class and
|
||||
* use invade() to access the protected properties (for the $channels property, there
|
||||
* is a public accessor -- getChannels() -- but since invade is already used here,
|
||||
* we access the property directly for consistency).
|
||||
*/
|
||||
protected function copyAuthState(BroadcasterContract $from, BroadcasterContract $to): void
|
||||
{
|
||||
if (! $from instanceof Broadcaster || ! $to instanceof Broadcaster) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fromState = invade($from);
|
||||
$toState = invade($to);
|
||||
|
||||
$toState->channels = $fromState->channels;
|
||||
$toState->channelOptions = $fromState->channelOptions;
|
||||
$toState->authenticatedUserCallback = $fromState->authenticatedUserCallback;
|
||||
}
|
||||
|
||||
public function revert(): void
|
||||
{
|
||||
// Revert the bound BroadcastManager and Broadcaster singletons back to their original state
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue