1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 21:54:03 +00:00

[2.1.0] Initialize tenancy before executing controller constructors (#169)

* Update message about migrations in Install

* wip

* Apply fixes from StyleCI

* string instead of array

* Fix globalUrl binding

* Simplify if condition in TenantRouteServiceProvider

* Apply fixes from StyleCI

* Improve PreventAccessFromTenantDomains - look into middleware subgroups

* Fix typo

* gatherMiddleware() instead of middleware()

* Fix tests

* Apply fixes from StyleCI

* Update install command

* Apply fixes from StyleCI

* Add the PreventAccess MW to tenant routes by default
This commit is contained in:
Samuel Štancl 2019-10-15 20:23:56 +02:00 committed by GitHub
parent 7143bce5f9
commit cbd3850a8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 66 additions and 22 deletions

View file

@ -47,6 +47,9 @@ class Install extends Command
$newKernel = str_replace("'web' => [", "'web' => [ $newKernel = str_replace("'web' => [", "'web' => [
\Stancl\Tenancy\Middleware\PreventAccessFromTenantDomains::class,", $newKernel); \Stancl\Tenancy\Middleware\PreventAccessFromTenantDomains::class,", $newKernel);
$newKernel = str_replace("'api' => [", "'api' => [
\Stancl\Tenancy\Middleware\PreventAccessFromTenantDomains::class,", $newKernel);
file_put_contents(app_path('Http/Kernel.php'), $newKernel); file_put_contents(app_path('Http/Kernel.php'), $newKernel);
$this->info('✔️ Set middleware priority'); $this->info('✔️ Set middleware priority');
@ -59,9 +62,9 @@ class Install extends Command
| Tenant Routes | Tenant Routes
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here is where you can register tenant routes for your application. These | Here you can register the tenant routes for your application.
| routes are loaded by the TenantRouteServiceProvider within a group | These routes are loaded by the TenantRouteServiceProvider
| which contains the \"InitializeTenancy\" middleware. Good luck! | with the tenancy and web middleware groups. Good luck!
| |
*/ */
@ -73,8 +76,8 @@ Route::get('/app', function () {
$this->info('✔️ Created routes/tenant.php'); $this->info('✔️ Created routes/tenant.php');
$this->line(''); $this->line('');
$this->line("This package lets you store data about tenants either in Redis or in a relational database like MySQL. If you're going to use the database storage, you need to create a tenants table."); $this->line('This package lets you store data about tenants either in Redis or in a relational database like MySQL. To store data about tenants in a relational database, you need a few database tables.');
if ($this->confirm('Do you want to publish the default database migrations?', true)) { if ($this->confirm('Do you wish to publish the migrations that create these tables?', true)) {
$this->callSilent('vendor:publish', [ $this->callSilent('vendor:publish', [
'--provider' => 'Stancl\Tenancy\TenancyServiceProvider', '--provider' => 'Stancl\Tenancy\TenancyServiceProvider',
'--tag' => 'migrations', '--tag' => 'migrations',

View file

@ -28,11 +28,17 @@ class InitializeTenancy
*/ */
public function handle($request, Closure $next) public function handle($request, Closure $next)
{ {
if (tenancy()->initialized) {
return $next($request);
}
if (! in_array($request->getHost(), config('tenancy.exempt_domains', []), true)) {
try { try {
tenancy()->init($request->getHost()); tenancy()->init($request->getHost());
} catch (TenantCouldNotBeIdentifiedException $e) { } catch (TenantCouldNotBeIdentifiedException $e) {
($this->onFail)($e); ($this->onFail)($e);
} }
}
return $next($request); return $next($request);
} }

View file

@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Middleware; namespace Stancl\Tenancy\Middleware;
use Closure; use Closure;
use Illuminate\Routing\Route;
use Illuminate\Support\Facades\Route as Router;
/** /**
* Prevent access from tenant domains to central routes and vice versa. * Prevent access from tenant domains to central routes and vice versa.
@ -25,7 +27,7 @@ class PreventAccessFromTenantDomains
$isExemptDomain = in_array($request->getHost(), config('tenancy.exempt_domains')); $isExemptDomain = in_array($request->getHost(), config('tenancy.exempt_domains'));
$isTenantDomain = ! $isExemptDomain; $isTenantDomain = ! $isExemptDomain;
$isTenantRoute = in_array('tenancy', $request->route()->middleware()); $isTenantRoute = $this->isTenantRoute($request->route());
if ($isTenantDomain && ! $isTenantRoute) { // accessing web routes from tenant domains if ($isTenantDomain && ! $isTenantRoute) { // accessing web routes from tenant domains
return redirect(config('tenancy.home_url')); return redirect(config('tenancy.home_url'));
@ -37,4 +39,22 @@ class PreventAccessFromTenantDomains
return $next($request); return $next($request);
} }
public function isTenantRoute(Route $route): bool
{
if (in_array('tenancy', $route->middleware(), true)) {
return true;
}
// Loop one level deep and check if the route's middleware
// groups have a `tenancy` middleware group inside them
$middlewareGroups = Router::getMiddlewareGroups();
foreach ($route->gatherMiddleware() as $middleware) {
if (isset($middlewareGroups[$middleware]) && in_array('tenancy', $middlewareGroups[$middleware], true)) {
return true;
}
}
return false;
}
} }

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Stancl\Tenancy; namespace Stancl\Tenancy;
use Illuminate\Cache\CacheManager; use Illuminate\Cache\CacheManager;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Stancl\Tenancy\TenancyBootstrappers\FilesystemTenancyBootstrapper; use Stancl\Tenancy\TenancyBootstrappers\FilesystemTenancyBootstrapper;
@ -77,15 +78,27 @@ class TenancyServiceProvider extends ServiceProvider
__DIR__ . '/../assets/migrations/' => database_path('migrations'), __DIR__ . '/../assets/migrations/' => database_path('migrations'),
], 'migrations'); ], 'migrations');
$this->loadRoutesFrom(__DIR__ . '/routes.php'); $this->app->make(Kernel::class)->prependMiddleware(Middleware\InitializeTenancy::class);
/*
* Since tenancy is initialized in the global middleware stack, this
* middleware group acts mostly as a 'flag' for the PreventAccess
* middleware to decide whether the request should be aborted.
*/
Route::middlewareGroup('tenancy', [ Route::middlewareGroup('tenancy', [
\Stancl\Tenancy\Middleware\InitializeTenancy::class, /* Prevent access from tenant domains to central routes and vice versa. */
Middleware\PreventAccessFromTenantDomains::class,
]); ]);
$this->loadRoutesFrom(__DIR__ . '/routes.php');
$this->app->singleton('globalUrl', function ($app) { $this->app->singleton('globalUrl', function ($app) {
if ($app->bound(FilesystemTenancyBootstrapper::class)) {
$instance = clone $app['url']; $instance = clone $app['url'];
$instance->setAssetRoot($app[FilesystemTenancyBootstrapper::class]->originalPaths['asset_url']); $instance->setAssetRoot($app[FilesystemTenancyBootstrapper::class]->originalPaths['asset_url']);
} else {
$instance = $app['url'];
}
return $instance; return $instance;
}); });

View file

@ -11,8 +11,7 @@ class TenantRouteServiceProvider extends RouteServiceProvider
{ {
public function map() public function map()
{ {
if (! in_array(request()->getHost(), $this->app['config']['tenancy.exempt_domains'] ?? []) if (file_exists(base_path('routes/tenant.php'))) {
&& file_exists(base_path('routes/tenant.php'))) {
Route::middleware(['web', 'tenancy']) Route::middleware(['web', 'tenancy'])
->namespace($this->app['config']['tenancy.tenant_route_namespace'] ?? 'App\Http\Controllers') ->namespace($this->app['config']['tenancy.tenant_route_namespace'] ?? 'App\Http\Controllers')
->group(base_path('routes/tenant.php')); ->group(base_path('routes/tenant.php'));

View file

@ -2,6 +2,8 @@
declare(strict_types=1); declare(strict_types=1);
Route::get('/tenancy/assets/{path}', 'Stancl\Tenancy\Controllers\TenantAssetsController@asset') Route::middleware(['tenancy'])->group(function () {
Route::get('/tenancy/assets/{path}', 'Stancl\Tenancy\Controllers\TenantAssetsController@asset')
->where('path', '(.*)') ->where('path', '(.*)')
->name('stancl.tenancy.asset'); ->name('stancl.tenancy.asset');
});

View file

@ -130,7 +130,7 @@ class CommandsTest extends TestCase
file_put_contents(app_path('Http/Kernel.php'), file_get_contents(__DIR__ . '/Etc/defaultHttpKernel.stub')); file_put_contents(app_path('Http/Kernel.php'), file_get_contents(__DIR__ . '/Etc/defaultHttpKernel.stub'));
$this->artisan('tenancy:install') $this->artisan('tenancy:install')
->expectsQuestion('Do you want to publish the default database migrations?', 'yes'); ->expectsQuestion('Do you wish to publish the migrations that create these tables?', 'yes');
$this->assertFileExists(base_path('routes/tenant.php')); $this->assertFileExists(base_path('routes/tenant.php'));
$this->assertFileExists(base_path('config/tenancy.php')); $this->assertFileExists(base_path('config/tenancy.php'));
$this->assertFileExists(database_path('migrations/2019_09_15_000010_create_tenants_table.php')); $this->assertFileExists(database_path('migrations/2019_09_15_000010_create_tenants_table.php'));

View file

@ -39,6 +39,7 @@ class Kernel extends HttpKernel
], ],
'api' => [ 'api' => [
\Stancl\Tenancy\Middleware\PreventAccessFromTenantDomains::class,
'throttle:60,1', 'throttle:60,1',
'bindings', 'bindings',
], ],