From 494d2747984a1e0079f2ab7d376b9a092e7ddf5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Sun, 10 May 2020 20:16:08 +0200 Subject: [PATCH] Finish path identification - configurability & exception handling --- ...RouteIsMissingTenantParameterException.php | 16 +++++ src/Middleware/InitializeTenancyByPath.php | 8 ++- src/Resolvers/PathTenantResolver.php | 6 +- tests/v3/PathIdentificationTest.php | 58 +++++++++++++++++++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/Exceptions/RouteIsMissingTenantParameterException.php diff --git a/src/Exceptions/RouteIsMissingTenantParameterException.php b/src/Exceptions/RouteIsMissingTenantParameterException.php new file mode 100644 index 00000000..01d52136 --- /dev/null +++ b/src/Exceptions/RouteIsMissingTenantParameterException.php @@ -0,0 +1,16 @@ +route(); - // todo test the behavior described by the comment // Only initialize tenancy if tenant is the first parameter // We don't want to initialize tenancy if the tenant is // simply injected into some route controller action. - if ($route->parameterNames()[0] === 'tenant') { + if ($route->parameterNames()[0] === PathTenantResolver::$tenantParameterName) { return $this->initializeTenancy( $request, $next, $route ); - } // todo else case should probably throw exception about malformed route? or do we just leave that as the developer's responsibility? + } else { + throw new RouteIsMissingTenantParameterException; + } return $next($request); } diff --git a/src/Resolvers/PathTenantResolver.php b/src/Resolvers/PathTenantResolver.php index cfd68a71..4a7c4187 100644 --- a/src/Resolvers/PathTenantResolver.php +++ b/src/Resolvers/PathTenantResolver.php @@ -9,13 +9,15 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException; class PathTenantResolver implements TenantResolver { + public static $tenantParameterName = 'tenant'; + public function resolve(...$args): Tenant { /** @var Route $route */ $route = $args[0]; - if ($id = $route->parameter('tenant')) { - $route->forgetParameter('tenant'); + if ($id = $route->parameter(static::$tenantParameterName)) { + $route->forgetParameter(static::$tenantParameterName); if ($tenant = config('tenancy.tenant_model')::find($id)) { return $tenant; diff --git a/tests/v3/PathIdentificationTest.php b/tests/v3/PathIdentificationTest.php index 1190ce36..587059fe 100644 --- a/tests/v3/PathIdentificationTest.php +++ b/tests/v3/PathIdentificationTest.php @@ -4,8 +4,10 @@ namespace Stancl\Tenancy\Tests\v3; use Illuminate\Support\Facades\Route; use Stancl\Tenancy\Database\Models\Tenant; +use Stancl\Tenancy\Exceptions\RouteIsMissingTenantParameterException; use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException; use Stancl\Tenancy\Middleware\InitializeTenancyByPath; +use Stancl\Tenancy\Resolvers\PathTenantResolver; use Stancl\Tenancy\Tests\TestCase; class PathIdentificationTest extends TestCase @@ -14,6 +16,8 @@ class PathIdentificationTest extends TestCase { parent::setUp(); + PathTenantResolver::$tenantParameterName = 'tenant'; + Route::group([ 'prefix' => '/{tenant}', 'middleware' => InitializeTenancyByPath::class, @@ -79,4 +83,58 @@ class PathIdentificationTest extends TestCase ->get('/acme/foo/abc/xyz') ->assertContent('foo'); } + + /** @test */ + public function an_exception_is_thrown_when_the_routes_first_parameter_is_not_tenant() + { + Route::group([ + // 'prefix' => '/{tenant}', -- intentionally commented + 'middleware' => InitializeTenancyByPath::class, + ], function () { + Route::get('/bar/{a}/{b}', function ($a, $b) { + return "$a + $b"; + }); + }); + + Tenant::create([ + 'id' => 'acme', + ]); + + $this->expectException(RouteIsMissingTenantParameterException::class); + + $this + ->withoutExceptionHandling() + ->get('/bar/foo/bar'); + } + + + /** @test */ + public function tenant_parameter_name_can_be_customized() + { + PathTenantResolver::$tenantParameterName = 'team'; + + Route::group([ + 'prefix' => '/{team}', + 'middleware' => InitializeTenancyByPath::class, + ], function () { + Route::get('/bar/{a}/{b}', function ($a, $b) { + return "$a + $b"; + }); + }); + + Tenant::create([ + 'id' => 'acme', + ]); + + $this + ->get('/acme/bar/abc/xyz') + ->assertContent('abc + xyz'); + + // Parameter for resolver is changed, so the /{tenant}/foo route will no longer work. + $this->expectException(RouteIsMissingTenantParameterException::class); + + $this + ->withoutExceptionHandling() + ->get('/acme/foo/abc/xyz'); + } }