mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 18:44:03 +00:00
Finish path identification - configurability & exception handling
This commit is contained in:
parent
cb2bd018aa
commit
494d274798
4 changed files with 83 additions and 5 deletions
16
src/Exceptions/RouteIsMissingTenantParameterException.php
Normal file
16
src/Exceptions/RouteIsMissingTenantParameterException.php
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Stancl\Tenancy\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
||||||
|
|
||||||
|
class RouteIsMissingTenantParameterException extends Exception
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$parameter = PathTenantResolver::$tenantParameterName;
|
||||||
|
|
||||||
|
parent::__construct("The route's first argument is not the tenant id (configured paramter name: $parameter).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ namespace Stancl\Tenancy\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Route;
|
use Illuminate\Routing\Route;
|
||||||
|
use Stancl\Tenancy\Exceptions\RouteIsMissingTenantParameterException;
|
||||||
use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
||||||
use Stancl\Tenancy\Tenancy;
|
use Stancl\Tenancy\Tenancy;
|
||||||
|
|
||||||
|
|
@ -27,15 +28,16 @@ class InitializeTenancyByPath extends IdentificationMiddleware
|
||||||
/** @var Route $route */
|
/** @var Route $route */
|
||||||
$route = $request->route();
|
$route = $request->route();
|
||||||
|
|
||||||
// todo test the behavior described by the comment
|
|
||||||
// Only initialize tenancy if tenant is the first parameter
|
// Only initialize tenancy if tenant is the first parameter
|
||||||
// We don't want to initialize tenancy if the tenant is
|
// We don't want to initialize tenancy if the tenant is
|
||||||
// simply injected into some route controller action.
|
// simply injected into some route controller action.
|
||||||
if ($route->parameterNames()[0] === 'tenant') {
|
if ($route->parameterNames()[0] === PathTenantResolver::$tenantParameterName) {
|
||||||
return $this->initializeTenancy(
|
return $this->initializeTenancy(
|
||||||
$request, $next, $route
|
$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);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,15 @@ use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException;
|
||||||
|
|
||||||
class PathTenantResolver implements TenantResolver
|
class PathTenantResolver implements TenantResolver
|
||||||
{
|
{
|
||||||
|
public static $tenantParameterName = 'tenant';
|
||||||
|
|
||||||
public function resolve(...$args): Tenant
|
public function resolve(...$args): Tenant
|
||||||
{
|
{
|
||||||
/** @var Route $route */
|
/** @var Route $route */
|
||||||
$route = $args[0];
|
$route = $args[0];
|
||||||
|
|
||||||
if ($id = $route->parameter('tenant')) {
|
if ($id = $route->parameter(static::$tenantParameterName)) {
|
||||||
$route->forgetParameter('tenant');
|
$route->forgetParameter(static::$tenantParameterName);
|
||||||
|
|
||||||
if ($tenant = config('tenancy.tenant_model')::find($id)) {
|
if ($tenant = config('tenancy.tenant_model')::find($id)) {
|
||||||
return $tenant;
|
return $tenant;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@ namespace Stancl\Tenancy\Tests\v3;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Stancl\Tenancy\Database\Models\Tenant;
|
use Stancl\Tenancy\Database\Models\Tenant;
|
||||||
|
use Stancl\Tenancy\Exceptions\RouteIsMissingTenantParameterException;
|
||||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException;
|
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByPathException;
|
||||||
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
|
use Stancl\Tenancy\Middleware\InitializeTenancyByPath;
|
||||||
|
use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
||||||
use Stancl\Tenancy\Tests\TestCase;
|
use Stancl\Tenancy\Tests\TestCase;
|
||||||
|
|
||||||
class PathIdentificationTest extends TestCase
|
class PathIdentificationTest extends TestCase
|
||||||
|
|
@ -14,6 +16,8 @@ class PathIdentificationTest extends TestCase
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
|
PathTenantResolver::$tenantParameterName = 'tenant';
|
||||||
|
|
||||||
Route::group([
|
Route::group([
|
||||||
'prefix' => '/{tenant}',
|
'prefix' => '/{tenant}',
|
||||||
'middleware' => InitializeTenancyByPath::class,
|
'middleware' => InitializeTenancyByPath::class,
|
||||||
|
|
@ -79,4 +83,58 @@ class PathIdentificationTest extends TestCase
|
||||||
->get('/acme/foo/abc/xyz')
|
->get('/acme/foo/abc/xyz')
|
||||||
->assertContent('foo');
|
->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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue