TenancyServiceProvider.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Providers;
  4. use App\Http\Middleware\GetTenancyByUsername;
  5. use App\Jobs\InitTenantData;
  6. use Illuminate\Support\Facades\Event;
  7. use Illuminate\Support\Facades\Route;
  8. use Illuminate\Support\ServiceProvider;
  9. use Stancl\JobPipeline\JobPipeline;
  10. use Stancl\Tenancy\Events;
  11. use Stancl\Tenancy\Jobs;
  12. use Stancl\Tenancy\Listeners;
  13. use Stancl\Tenancy\Middleware;
  14. class TenancyServiceProvider extends ServiceProvider
  15. {
  16. // By default, no namespace is used to support the callable array syntax.
  17. public static string $controllerNamespace = '';
  18. public function events()
  19. {
  20. return [
  21. // Tenant events
  22. Events\CreatingTenant::class => [],
  23. Events\TenantCreated::class => [
  24. JobPipeline::make([
  25. Jobs\CreateDatabase::class,
  26. Jobs\MigrateDatabase::class,
  27. Jobs\SeedDatabase::class,
  28. // Your own jobs to prepare the tenant.
  29. // Provision API keys, create S3 buckets, anything you want!
  30. ])->send(function (Events\TenantCreated $event) {
  31. return $event->tenant;
  32. })->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
  33. ],
  34. Events\SavingTenant::class => [],
  35. Events\TenantSaved::class => [],
  36. Events\UpdatingTenant::class => [],
  37. Events\TenantUpdated::class => [],
  38. Events\DeletingTenant::class => [],
  39. Events\TenantDeleted::class => [
  40. JobPipeline::make([
  41. Jobs\DeleteDatabase::class,
  42. ])->send(function (Events\TenantDeleted $event) {
  43. return $event->tenant;
  44. })->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
  45. ],
  46. // Domain events
  47. Events\CreatingDomain::class => [],
  48. Events\DomainCreated::class => [],
  49. Events\SavingDomain::class => [],
  50. Events\DomainSaved::class => [],
  51. Events\UpdatingDomain::class => [],
  52. Events\DomainUpdated::class => [],
  53. Events\DeletingDomain::class => [],
  54. Events\DomainDeleted::class => [],
  55. // Database events
  56. Events\DatabaseCreated::class => [],
  57. Events\DatabaseMigrated::class => [],
  58. Events\SeedingDatabase::class => [
  59. JobPipeline::make([
  60. InitTenantData::class,
  61. ])->send(function (Events\SeedingDatabase $event) {
  62. return $event->tenant;
  63. })->shouldBeQueued(false)
  64. ],
  65. Events\DatabaseSeeded::class => [],
  66. Events\DatabaseRolledBack::class => [],
  67. Events\DatabaseDeleted::class => [],
  68. // Tenancy events
  69. Events\InitializingTenancy::class => [],
  70. Events\TenancyInitialized::class => [
  71. Listeners\BootstrapTenancy::class,
  72. ],
  73. Events\EndingTenancy::class => [],
  74. Events\TenancyEnded::class => [
  75. Listeners\RevertToCentralContext::class,
  76. ],
  77. Events\BootstrappingTenancy::class => [],
  78. Events\TenancyBootstrapped::class => [],
  79. Events\RevertingToCentralContext::class => [],
  80. Events\RevertedToCentralContext::class => [],
  81. // Resource syncing
  82. Events\SyncedResourceSaved::class => [
  83. Listeners\UpdateSyncedResource::class,
  84. ],
  85. // Fired only when a synced resource is changed in a different DB than the origin DB (to avoid infinite loops)
  86. Events\SyncedResourceChangedInForeignDatabase::class => [],
  87. ];
  88. }
  89. public function register()
  90. {
  91. //
  92. }
  93. public function boot()
  94. {
  95. $this->bootEvents();
  96. $this->mapRoutes();
  97. $this->makeTenancyMiddlewareHighestPriority();
  98. }
  99. protected function bootEvents()
  100. {
  101. foreach ($this->events() as $event => $listeners) {
  102. foreach ($listeners as $listener) {
  103. if ($listener instanceof JobPipeline) {
  104. $listener = $listener->toListener();
  105. }
  106. Event::listen($event, $listener);
  107. }
  108. }
  109. }
  110. protected function mapRoutes()
  111. {
  112. $this->app->booted(function () {
  113. if (file_exists(base_path('routes/tenant.php'))) {
  114. Route::namespace(static::$controllerNamespace)
  115. ->group(base_path('routes/tenant.php'));
  116. }
  117. });
  118. }
  119. protected function makeTenancyMiddlewareHighestPriority()
  120. {
  121. $tenancyMiddleware = [
  122. GetTenancyByUsername::class,
  123. // Even higher priority than the initialization middleware
  124. Middleware\PreventAccessFromCentralDomains::class,
  125. Middleware\InitializeTenancyByDomain::class,
  126. Middleware\InitializeTenancyBySubdomain::class,
  127. Middleware\InitializeTenancyByDomainOrSubdomain::class,
  128. Middleware\InitializeTenancyByPath::class,
  129. Middleware\InitializeTenancyByRequestData::class,
  130. ];
  131. foreach (array_reverse($tenancyMiddleware) as $middleware) {
  132. $this->app[\Illuminate\Contracts\Http\Kernel::class]->prependToMiddlewarePriority($middleware);
  133. }
  134. }
  135. }