mirror of
https://github.com/archtechx/tenancy.git
synced 2026-02-06 08:24:03 +00:00
Merge branch 'master' of https://github.com/archtechx/tenancy into add-skip-failing-options-to-migrate
This commit is contained in:
commit
b76ed4ad08
94 changed files with 752 additions and 567 deletions
|
|
@ -107,12 +107,12 @@ function contextIsSwitchedWhenTenancyInitialized()
|
|||
|
||||
class MyBootstrapper implements TenancyBootstrapper
|
||||
{
|
||||
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant)
|
||||
public function bootstrap(\Stancl\Tenancy\Contracts\Tenant $tenant): void
|
||||
{
|
||||
app()->instance('tenancy_initialized_for_tenant', $tenant->getTenantKey());
|
||||
}
|
||||
|
||||
public function revert()
|
||||
public function revert(): void
|
||||
{
|
||||
app()->instance('tenancy_ended', true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ test('batch repository is set to tenant connection and reverted', function () {
|
|||
|
||||
tenancy()->initialize($tenant);
|
||||
expect(getBatchRepositoryConnectionName())->toBe('tenant');
|
||||
|
||||
|
||||
tenancy()->initialize($tenant2);
|
||||
expect(getBatchRepositoryConnectionName())->toBe('tenant');
|
||||
|
||||
tenancy()->end();
|
||||
expect(getBatchRepositoryConnectionName())->toBe('central');
|
||||
})->skip(fn() => version_compare(app()->version(), '8.0', '<'), 'Job batches are only supported in Laravel 8+');
|
||||
});
|
||||
|
||||
function getBatchRepositoryConnectionName()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -332,10 +332,6 @@ function getDiskPrefix(string $disk): string
|
|||
$disk = Storage::disk($disk);
|
||||
$adapter = $disk->getAdapter();
|
||||
|
||||
if (! Str::startsWith(app()->version(), '9.')) {
|
||||
return $adapter->getPathPrefix();
|
||||
}
|
||||
|
||||
$prefixer = (new ReflectionObject($adapter))->getProperty('prefixer');
|
||||
$prefixer->setAccessible(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ use Illuminate\Support\Facades\DB;
|
|||
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||
|
||||
afterEach(function () {
|
||||
DomainTenantResolver::$shouldCache = false;
|
||||
});
|
||||
// todo@v4 test this with other resolvers as well?
|
||||
|
||||
test('tenants can be resolved using the cached resolver', function () {
|
||||
$tenant = Tenant::create();
|
||||
|
|
@ -27,14 +25,14 @@ test('the underlying resolver is not touched when using the cached resolver', fu
|
|||
|
||||
DB::enableQueryLog();
|
||||
|
||||
DomainTenantResolver::$shouldCache = false;
|
||||
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => false]);
|
||||
|
||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||
DB::flushQueryLog();
|
||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||
pest()->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||
|
||||
DomainTenantResolver::$shouldCache = true;
|
||||
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||
|
||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||
DB::flushQueryLog();
|
||||
|
|
@ -50,7 +48,7 @@ test('cache is invalidated when the tenant is updated', function () {
|
|||
|
||||
DB::enableQueryLog();
|
||||
|
||||
DomainTenantResolver::$shouldCache = true;
|
||||
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||
|
||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||
DB::flushQueryLog();
|
||||
|
|
@ -74,7 +72,7 @@ test('cache is invalidated when a tenants domain is changed', function () {
|
|||
|
||||
DB::enableQueryLog();
|
||||
|
||||
DomainTenantResolver::$shouldCache = true;
|
||||
config(['tenancy.identification.resolvers.' . DomainTenantResolver::class . '.cache' => true]);
|
||||
|
||||
expect($tenant->is(app(DomainTenantResolver::class)->resolve('acme')))->toBeTrue();
|
||||
DB::flushQueryLog();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ use Stancl\Tenancy\Tests\Etc\Tenant;
|
|||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use PHPUnit\Framework\ExceptionWrapper;
|
||||
use Stancl\Tenancy\Events\TenancyEnded;
|
||||
use Stancl\Tenancy\Jobs\CreateDatabase;
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
|
|
@ -217,8 +216,9 @@ test('run command with array of tenants works', function () {
|
|||
Artisan::call('tenants:migrate-fresh');
|
||||
|
||||
pest()->artisan("tenants:run --tenants=$tenantId1 --tenants=$tenantId2 'foo foo --b=bar --c=xyz'")
|
||||
->expectsOutput('Tenant: ' . $tenantId1)
|
||||
->expectsOutput('Tenant: ' . $tenantId2);
|
||||
->expectsOutputToContain('Tenant: ' . $tenantId1)
|
||||
->expectsOutputToContain('Tenant: ' . $tenantId2)
|
||||
->assertExitCode(0);
|
||||
});
|
||||
|
||||
test('link command works', function() {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ test('tenant can be identified by domain', function () {
|
|||
|
||||
test('onfail logic can be customized', function () {
|
||||
InitializeTenancyByDomain::$onFail = function () {
|
||||
return 'foo';
|
||||
return response('foo');
|
||||
};
|
||||
|
||||
pest()
|
||||
|
|
|
|||
|
|
@ -7,9 +7,13 @@ namespace Stancl\Tenancy\Tests\Etc;
|
|||
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;
|
||||
use Stancl\Tenancy\Database\Concerns\HasDatabase;
|
||||
use Stancl\Tenancy\Database\Concerns\HasDomains;
|
||||
use Stancl\Tenancy\Database\Concerns\MaintenanceMode;
|
||||
use Stancl\Tenancy\Database\Models;
|
||||
|
||||
/**
|
||||
* @method static static create(array $attributes = [])
|
||||
*/
|
||||
class Tenant extends Models\Tenant implements TenantWithDatabase
|
||||
{
|
||||
use HasDatabase, HasDomains;
|
||||
use HasDatabase, HasDomains, MaintenanceMode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,3 +50,17 @@ test('global cache manager stores data in global cache', function () {
|
|||
expect(cache('def'))->toBe('ghi');
|
||||
});
|
||||
|
||||
test('the global_cache helper supports the same syntax as the cache helper', function () {
|
||||
$tenant = Tenant::create();
|
||||
$tenant->enter();
|
||||
|
||||
expect(cache('foo'))->toBe(null); // tenant cache is empty
|
||||
|
||||
global_cache(['foo' => 'bar']);
|
||||
expect(global_cache('foo'))->toBe('bar');
|
||||
|
||||
global_cache()->set('foo', 'baz');
|
||||
expect(global_cache()->get('foo'))->toBe('baz');
|
||||
|
||||
expect(cache('foo'))->toBe(null); // tenant cache is not affected
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Stancl\Tenancy\Database\Concerns\MaintenanceMode;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Stancl\Tenancy\Middleware\CheckTenantForMaintenanceMode;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||
|
||||
test('tenant can be in maintenance mode', function () {
|
||||
test('tenants can be in maintenance mode', function () {
|
||||
Route::get('/foo', function () {
|
||||
return 'bar';
|
||||
})->middleware([InitializeTenancyByDomain::class, CheckTenantForMaintenanceMode::class]);
|
||||
|
|
@ -19,16 +19,40 @@ test('tenant can be in maintenance mode', function () {
|
|||
'domain' => 'acme.localhost',
|
||||
]);
|
||||
|
||||
pest()->get('http://acme.localhost/foo')
|
||||
->assertSuccessful();
|
||||
|
||||
tenancy()->end(); // flush stored tenant instance
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(200);
|
||||
|
||||
$tenant->putDownForMaintenance();
|
||||
|
||||
pest()->expectException(HttpException::class);
|
||||
pest()->withoutExceptionHandling()
|
||||
->get('http://acme.localhost/foo');
|
||||
tenancy()->end(); // End tenancy before making a request
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(503);
|
||||
|
||||
$tenant->bringUpFromMaintenance();
|
||||
|
||||
tenancy()->end(); // End tenancy before making a request
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(200);
|
||||
});
|
||||
|
||||
test('tenants can be put into maintenance mode using artisan commands', function() {
|
||||
Route::get('/foo', function () {
|
||||
return 'bar';
|
||||
})->middleware([InitializeTenancyByDomain::class, CheckTenantForMaintenanceMode::class]);
|
||||
|
||||
$tenant = MaintenanceTenant::create();
|
||||
$tenant->domains()->create([
|
||||
'domain' => 'acme.localhost',
|
||||
]);
|
||||
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(200);
|
||||
|
||||
Artisan::call('tenants:down');
|
||||
|
||||
tenancy()->end(); // End tenancy before making a request
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(503);
|
||||
|
||||
Artisan::call('tenants:up');
|
||||
|
||||
tenancy()->end(); // End tenancy before making a request
|
||||
pest()->get('http://acme.localhost/foo')->assertStatus(200);
|
||||
});
|
||||
|
||||
class MaintenanceTenant extends Tenant
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ use Stancl\Tenancy\Resolvers\PathTenantResolver;
|
|||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||
|
||||
beforeEach(function () {
|
||||
PathTenantResolver::$tenantParameterName = 'tenant';
|
||||
|
||||
Route::group([
|
||||
'prefix' => '/{tenant}',
|
||||
'middleware' => InitializeTenancyByPath::class,
|
||||
|
|
@ -26,11 +24,6 @@ beforeEach(function () {
|
|||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
// Global state cleanup
|
||||
PathTenantResolver::$tenantParameterName = 'tenant';
|
||||
});
|
||||
|
||||
test('tenant can be identified by path', function () {
|
||||
Tenant::create([
|
||||
'id' => 'acme',
|
||||
|
|
@ -71,7 +64,7 @@ test('exception is thrown when tenant cannot be identified by path', function ()
|
|||
|
||||
test('onfail logic can be customized', function () {
|
||||
InitializeTenancyByPath::$onFail = function () {
|
||||
return 'foo';
|
||||
return response('foo');
|
||||
};
|
||||
|
||||
pest()
|
||||
|
|
@ -101,7 +94,7 @@ test('an exception is thrown when the routes first parameter is not tenant', fun
|
|||
});
|
||||
|
||||
test('tenant parameter name can be customized', function () {
|
||||
PathTenantResolver::$tenantParameterName = 'team';
|
||||
config(['tenancy.identification.resolvers.' . PathTenantResolver::class . '.tenant_parameter_name' => 'team']);
|
||||
|
||||
Route::group([
|
||||
'prefix' => '/{team}',
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ test('header identification works', function () {
|
|||
});
|
||||
|
||||
test('query parameter identification works', function () {
|
||||
InitializeTenancyByRequestData::$header = null;
|
||||
InitializeTenancyByRequestData::$queryParameter = 'tenant';
|
||||
|
||||
$tenant = Tenant::create();
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ use Stancl\Tenancy\Database\Concerns\HasScopedValidationRules;
|
|||
use Stancl\Tenancy\Tests\Etc\Tenant as TestTenant;
|
||||
|
||||
beforeEach(function () {
|
||||
BelongsToTenant::$tenantIdColumn = 'tenant_id';
|
||||
|
||||
Schema::create('posts', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('text');
|
||||
|
|
@ -144,7 +142,7 @@ test('tenant id is not auto added when creating primary resources in central con
|
|||
});
|
||||
|
||||
test('tenant id column name can be customized', function () {
|
||||
BelongsToTenant::$tenantIdColumn = 'team_id';
|
||||
config(['tenancy.single_db.tenant_id_column' => 'team_id']);
|
||||
|
||||
Schema::drop('comments');
|
||||
Schema::drop('posts');
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ test('tenant can be identified by subdomain', function () {
|
|||
|
||||
test('onfail logic can be customized', function () {
|
||||
InitializeTenancyBySubdomain::$onFail = function () {
|
||||
return 'foo';
|
||||
return response('foo');
|
||||
};
|
||||
|
||||
pest()
|
||||
|
|
|
|||
|
|
@ -6,10 +6,8 @@ use Illuminate\Support\Facades\Event;
|
|||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
|
||||
use Stancl\Tenancy\Controllers\TenantAssetsController;
|
||||
use Stancl\Tenancy\Events\TenancyInitialized;
|
||||
use Stancl\Tenancy\Listeners\BootstrapTenancy;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
|
||||
use Stancl\Tenancy\Middleware\InitializeTenancyByRequestData;
|
||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||
|
||||
|
|
@ -21,13 +19,8 @@ beforeEach(function () {
|
|||
Event::listen(TenancyInitialized::class, BootstrapTenancy::class);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
// Cleanup
|
||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomain::class;
|
||||
});
|
||||
|
||||
test('asset can be accessed using the url returned by the tenant asset helper', function () {
|
||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
|
||||
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
|
||||
|
||||
$tenant = Tenant::create();
|
||||
tenancy()->initialize($tenant);
|
||||
|
|
@ -95,7 +88,7 @@ test('asset helper tenancy can be disabled', function () {
|
|||
});
|
||||
|
||||
test('test asset controller returns a 404 when no path is provided', function () {
|
||||
TenantAssetsController::$tenancyMiddleware = InitializeTenancyByRequestData::class;
|
||||
config(['tenancy.identification.default_middleware' => InitializeTenancyByRequestData::class]);
|
||||
|
||||
$tenant = Tenant::create();
|
||||
|
||||
|
|
|
|||
|
|
@ -154,9 +154,7 @@ test('schema manager uses schema to separate tenant dbs', function () {
|
|||
]);
|
||||
tenancy()->initialize($tenant);
|
||||
|
||||
$schemaConfig = version_compare(app()->version(), '9.0', '>=') ?
|
||||
config('database.connections.' . config('database.default') . '.search_path') :
|
||||
config('database.connections.' . config('database.default') . '.schema');
|
||||
$schemaConfig = config('database.connections.' . config('database.default') . '.search_path');
|
||||
|
||||
expect($schemaConfig)->toBe($tenant->database()->getName());
|
||||
expect(config(['database.connections.pgsql.database']))->toBe($originalDatabaseName);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
|||
'--realpath' => true,
|
||||
'--force' => true,
|
||||
],
|
||||
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo0 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
||||
'tenancy.bootstrappers.redis' => RedisTenancyBootstrapper::class, // todo1 change this to []? two tests in TenantDatabaseManagerTest are failing with that
|
||||
'queue.connections.central' => [
|
||||
'driver' => 'sync',
|
||||
'central' => true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue