[4.x] BroadcastingConfigBootstrapper: fix central instances persisting in tenant context#1448
Open
[4.x] BroadcastingConfigBootstrapper: fix central instances persisting in tenant context#1448
Conversation
Test that BroadcastingConfigBootstrapper correctly maps tenant properties to broadcasting config/credentials, and that the credentials don't leak when switching contexts. Also add the `$config` property to `TestingBroadcaster` so that we can access the credentials used by the broadcaster.
…ators Test that TenancyBroadcastManager inherits the custom driver creators from the central BroadcastManager.
…anager's custom creators
…tenant's broadcaster on `bootstrap()`
…ed `Broadcasting\Factory` instance After initializing tenancy, calls like `Broadcast::auth()` use the central `BroadcastManager`. Clearing the facade's resolved `Broadcasting\Factory` instance fixes that problem.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1448 +/- ##
============================================
+ Coverage 86.05% 86.12% +0.06%
- Complexity 1152 1153 +1
============================================
Files 184 184
Lines 3371 3379 +8
============================================
+ Hits 2901 2910 +9
+ Misses 470 469 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Moved binding `Broadcaster` to the bootstrapper.
Test that the bound Broadcaster instance inherits the channels too. Also test that the channels aren't lost when switching context to another tenant.
Tests from BroadcastingTest moved to the appropriate bootstrapper test files. The new tenant credentials test has assertions equal to both the original property -> config mapping test and the config -> credentials test.
Tests now use datasets with all drivers that are in `TenancyBroadcastManager::$tenantBroadcasters` by default plus the custom driver. Also add assertions for updating the tenant properties/config in tenant context.
… order
Previously, credential mappings from `$mapPresets` overrode mappings defined in `$credentialsMap`. If someone used pusher/reverb/ably and wanted to override some of that preset's mappings, e.g. use 'pusher_app_key' instead of 'pusher_key' by specifying 'pusher_app_key' in `$credentialsMap`, the preset's mapping ('pusher_key') would still be used.
Adding 'reverb' to `TenancyBroadcastManager::$tenantBroadcasters` will make these tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Broadcasting auth route problem (
Broadcastfacade always uses centralBroadcastManager)When using
BroadcastingConfigBootstrapperfor broadcasting on private channels with multiple broadcasting apps (= each tenant has its own Pusher/Reverb/... app and credentials), the auth requests sent to the broadcasting server use the central broadcasting credentials. This is because theBroadcastfacade (used inBroadcastController::authenticatelikeBroadcast::auth($request)to authorize the channels and then retrieve the auth key that's then sent to the broadcasting server) keeps using theBroadcastManagerinstance resolved in the central context instead ofTenancyBroadcastManager. This is happening because callingwithBroadcasting()inbootstrap/app.phpresults in callingBroadcast::routes()in the central context.Clearing the facade's resolved
Illuminate\Contracts\Broadcasting\Factoryinstance inBroadcastingConfigBootstrapper::bootstrap()forces the facade to re-resolveFactory(=BroadcastManager) on the next use, so the nextBroadcast::auth()call usesTenantBroadcastManagerin the tenant context, and the credentials from the current config will be used for authentication.TenancyBroadcastManagerdoesn't inherit custom driver creatorsWhen registering a custom driver creator (
app(BroadcastManager::class)->extend('custom-driver', fn($app, $config) => new CustomBroadcaster(...))) in the central context (e.g. inBroadcastServiceProvider/AppServiceProvider, or in our case, in the tests), the creator won't be available in the tenant context. Calling e.g.app(BroadcastManager::class)->driver('custom-driver')in the tenant context (if the creator was registered only in the central context) would throwInvalidArgumentException("Driver [custom-driver] is not supported.").To fix that, register the original (central)
BroadcastManager's custom creators in the newTenancyBroadcastManagerinBroadcastingConfigBootstrapper::bootstrap().Central
Broadcasterinstance bound in tenant contextResolving
Illuminate\Contracts\Broadcasting\Broadcaster::classin the tenant context returns aBroadcasterinstance from the central context. Currently, this doesn't cause any issues, but it could be a problem when using DI/resolvingBroadcaster.Fixed by making
Illuminate\Contracts\Broadcasting\Broadcaster::classresolve to the driver of the currentBroadcastManagerinstance (which isTenancyBroadcastManagerin the tenant context) by usingapp->extend().But there's a catch: updating credentials in the config while in tenant context won't be reflected on the bound Broadcaster instance. To make that work (with direct config updates), we'd have to use
bind()instead ofextend(), but then, we wouldn't be able to resolve the original broadcaster inTenancyBroadcastManager::get()(so that we can pass its channels to the new broadcaster). We'd have to pass the original broadcaster toTenancyBroadcastManager, and for that, we'd have to override the manager's constructor, which doesn't seem worth, since this is a pretty niche use case and simply reinitializing tenancy fixes the problem anyway.So for cases like sending a notification in response to updating tenant's broadcasting credentials in tenant context, it's recommended to reinitialize tenancy after updating the credentials.
Credential map: overriding presets (BroadcastingConfigBootstrapper)
Previously, credential mappings from
$mapPresetsoverrode mappings defined in$credentialsMap. If someone used e.g. Pusher and wanted to override some of that preset's mappings, e.g. use 'pusher_app_key' instead of 'pusher_key' by specifying 'pusher_app_key' in$credentialsMap, the preset's mapping ('pusher_key') would still be used.Fixed that by reversing the
array_merge()order inBroadcastingConfigBootstrapper::__construct().Tests
Deleted the BroadcastingTest file, moved the tests to appropriate bootstrapper test files.
Added tests for mapping tenant properties to broadcaster credentials. Also added tests for the changes mentioned above and improved the existing tests.
To-dos
TenancyBroadcastManager::$tenantBroadcasters(add it everywhere where the prop is modified to make the tests pass)