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

Fix subdomain middleware

This commit is contained in:
Samuel Štancl 2020-08-01 15:07:10 +02:00
parent 94abd732ae
commit d20056b804
2 changed files with 48 additions and 19 deletions

View file

@ -5,15 +5,13 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Middleware;
use Closure;
use Exception;
use Illuminate\Http\Response;
use Illuminate\Support\Str;
use Stancl\Tenancy\Exceptions\NotASubdomainException;
class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
{
/** @var callable|null */
public static $onInvalidSubdomain;
/**
* The index of the subdomain fragment in the hostname
* split by `.`. 0 for first fragment, 1 if you prefix
@ -37,19 +35,27 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
{
$subdomain = $this->makeSubdomain($request->getHost());
// If a non-string, like a Response instance was returned
// from makeSubdomain() - due to NotASubDomainException
// being thrown, we abort by returning the value now.
if (! is_string($subdomain)) {
if (is_object($subdomain) && $subdomain instanceof Exception) {
$onFail = static::$onFail ?? function ($e) {
throw $e;
};
return $onFail($subdomain, $request, $next);
}
// If a Response instance was returned, we return it immediately.
if (is_object($subdomain) && $subdomain instanceof Response) {
return $subdomain;
}
return $this->initializeTenancy(
$request, $next, $subdomain
$request,
$next,
$subdomain
);
}
/** @return string|Response|mixed */
/** @return string|Response|Exception|mixed */
protected function makeSubdomain(string $hostname)
{
$parts = explode('.', $hostname);
@ -58,15 +64,12 @@ class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
$isIpAddress = count(array_filter($parts, 'is_numeric')) === count($parts);
// If we're on localhost or an IP address, then we're not visiting a subdomain.
$isACentralDomain = in_array($hostname, config('tenancy.central_domains'), true);
$notADomain = $isLocalhost || $isIpAddress;
$thirdPartyDomain = ! Str::endsWith($hostname, config('tenancy.central_domains'));
$thirdPartyDomain = !Str::endsWith($hostname, config('tenancy.central_domains'));
if ($notADomain || $thirdPartyDomain) {
$handle = static::$onInvalidSubdomain ?? function ($e) {
throw $e;
};
return $handle(new NotASubdomainException($hostname));
if ($isACentralDomain || $notADomain || $thirdPartyDomain) {
return new NotASubdomainException($hostname);
}
return $parts[static::$subdomainIndex];

View file

@ -17,7 +17,7 @@ class SubdomainTest extends TestCase
parent::setUp();
// Global state cleanup after some tests
InitializeTenancyBySubdomain::$onInvalidSubdomain = null;
InitializeTenancyBySubdomain::$onFail = null;
Route::group([
'middleware' => InitializeTenancyBySubdomain::class,
@ -88,8 +88,12 @@ class SubdomainTest extends TestCase
{
// in this case, we need to return a response instance
// since a string would be treated as the subdomain
InitializeTenancyBySubdomain::$onInvalidSubdomain = function () {
InitializeTenancyBySubdomain::$onFail = function ($e) {
if ($e instanceof NotASubdomainException) {
return response('foo custom invalid subdomain handler');
}
throw $e;
};
$this
@ -120,6 +124,28 @@ class SubdomainTest extends TestCase
->withoutExceptionHandling()
->get('http://foo.localhost/foo/abc/xyz');
}
/** @test */
public function central_domain_is_not_a_subdomain()
{
config(['tenancy.central_domains' => [
'localhost',
]]);
$tenant = SubdomainTenant::create([
'id' => 'acme',
]);
$tenant->domains()->create([
'domain' => 'acme',
]);
$this->expectException(NotASubdomainException::class);
$this
->withoutExceptionHandling()
->get('http://localhost/foo/abc/xyz');
}
}
class SubdomainTenant extends Models\Tenant