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

[4.x] Storage::url() support (modified #689) (#909)

* This adds support for tenancy aware  Storage::url() method

* Trigger CI build

* Fixed Link command for Laravel v6, added StorageLink Events, more StorageLink tests, added RemoveStorageSymlinks Job, added Storage Jobs to TenancyServiceProvider stub, renamed misleading config example.

* Fix typo

* Fix code style (php-cs-fixer)

* Update config comments

* Format code in Link command, make writing more concise

* Change "symLinks" to "symlinks"

* Refactor Link command

* Fix test name typo

* Test fetching files using the public URL

* Extract Link command logic into actions

* Fix code style (php-cs-fixer)

* Check if closure is null in CreateStorageSymlinksAction

* Stop using command terminology in CreateStorageSymlinksAction

* Separate the Storage::url() test cases

* Update url_override comments

* Remove afterLink closures, add types, move actions, add usage explanation to the symlink trait

* Fix code style (php-cs-fixer)

* Update public storage URL test

* Fix issue with using str()

* Improve url_override comment, add todos

* add todo comment

* fix docblock style

* Add link command tests back

* Add types to $tenants in the action handle() methods

* Fix typo, update variable name formatting

* Add tests for the symlink actions

* Change possibleTenantSymlinks not to prefix the paths twice while tenancy is initialized

* Fix code style (php-cs-fixer)

* Stop testing storage directory existence in symlink test

* Don't specify full namespace for Tenant model annotation

* Don't specify full namespace in ActionTest

* Remove "change to DI" todo

* Remove possibleTenantSymlinks return annotation

* Remove symlink-related jobs, instantiate and use actions

* Revert "Remove symlink-related jobs, instantiate and use actions"

This reverts commit 547440c887.

* Add a comment line about the possible tenant symlinks

* Correct storagePath and publicPath variables

* Revert "Correct storagePath and publicPath variables"

This reverts commit e3aa8e2086.

* add a todo

Co-authored-by: Martin Vlcek <martin@dontfreakout.eu>
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
This commit is contained in:
Samuel Štancl 2022-09-28 05:09:45 +02:00 committed by GitHub
parent b78320b882
commit 7bacc50b27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 622 additions and 14 deletions

View file

@ -14,16 +14,19 @@ use Illuminate\Support\Facades\Storage;
use Stancl\Tenancy\Events\TenancyEnded;
use Stancl\Tenancy\Jobs\CreateDatabase;
use Stancl\Tenancy\Events\TenantCreated;
use Stancl\Tenancy\Events\TenantDeleted;
use Stancl\Tenancy\Events\DeletingTenant;
use Illuminate\Filesystem\FilesystemAdapter;
use Stancl\Tenancy\Events\TenancyInitialized;
use Stancl\Tenancy\Jobs\CreateStorageSymlinks;
use Stancl\Tenancy\Jobs\RemoveStorageSymlinks;
use Stancl\Tenancy\Listeners\BootstrapTenancy;
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
use Stancl\Tenancy\Listeners\RevertToCentralContext;
use Stancl\Tenancy\Bootstrappers\CacheTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\RedisTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper;
use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper;
use Stancl\Tenancy\Events\DeletingTenant;
use Stancl\Tenancy\Listeners\DeleteTenantStorage;
beforeEach(function () {
$this->mockConsoleOutput = false;
@ -192,8 +195,121 @@ test('tenant storage can get deleted after the tenant when DeletingTenant listen
'tenancy.bootstrappers' => [
FilesystemTenancyBootstrapper::class,
],
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
]);
$tenant1 = Tenant::create();
$tenant2 = Tenant::create();
$tenant1StorageUrl = 'http://localhost/public-' . $tenant1->getKey().'/';
$tenant2StorageUrl = 'http://localhost/public-' . $tenant2->getKey().'/';
tenancy()->initialize($tenant1);
$this->assertEquals(
$tenant1StorageUrl,
Storage::disk('public')->url('')
);
Storage::disk('public')->put($tenant1FileName = 'tenant1.txt', 'text');
$this->assertEquals(
$tenant1StorageUrl . $tenant1FileName,
Storage::disk('public')->url($tenant1FileName)
);
tenancy()->initialize($tenant2);
$this->assertEquals(
$tenant2StorageUrl,
Storage::disk('public')->url('')
);
Storage::disk('public')->put($tenant2FileName = 'tenant2.txt', 'text');
$this->assertEquals(
$tenant2StorageUrl . $tenant2FileName,
Storage::disk('public')->url($tenant2FileName)
);
});
test('files can get fetched using the storage url', function() {
config([
'tenancy.bootstrappers' => [
FilesystemTenancyBootstrapper::class,
],
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
]);
$tenant1 = Tenant::create();
$tenant2 = Tenant::create();
pest()->artisan('tenants:link');
// First tenant
tenancy()->initialize($tenant1);
Storage::disk('public')->put($tenantFileName = 'tenant1.txt', $tenantKey = $tenant1->getTenantKey());
$url = Storage::disk('public')->url($tenantFileName);
$tenantDiskName = Str::of(config('tenancy.filesystem.url_override.public'))->replace('%tenant_id%', $tenantKey);
$hostname = Str::of($url)->before($tenantDiskName);
$parsedUrl = Str::of($url)->after($hostname);
expect(file_get_contents(public_path($parsedUrl)))->toBe($tenantKey);
// Second tenant
tenancy()->initialize($tenant2);
Storage::disk('public')->put($tenantFileName = 'tenant2.txt', $tenantKey = $tenant2->getTenantKey());
$url = Storage::disk('public')->url($tenantFileName);
$tenantDiskName = Str::of(config('tenancy.filesystem.url_override.public'))->replace('%tenant_id%', $tenantKey);
$hostname = Str::of($url)->before($tenantDiskName);
$parsedUrl = Str::of($url)->after($hostname);
expect(file_get_contents(public_path($parsedUrl)))->toBe($tenantKey);
});
test('create and delete storage symlinks jobs work', function() {
Event::listen(
TenantCreated::class,
JobPipeline::make([CreateStorageSymlinks::class])->send(function (TenantCreated $event) {
return $event->tenant;
})->toListener()
);
Event::listen(
TenantDeleted::class,
JobPipeline::make([RemoveStorageSymlinks::class])->send(function (TenantDeleted $event) {
return $event->tenant;
})->toListener()
);
config([
'tenancy.bootstrappers' => [
FilesystemTenancyBootstrapper::class,
],
'tenancy.filesystem.suffix_base' => 'tenant-',
'tenancy.filesystem.root_override.public' => '%storage_path%/app/public/',
'tenancy.filesystem.url_override.public' => 'public-%tenant_id%'
]);
/** @var Tenant $tenant */
$tenant = Tenant::create();
tenancy()->initialize($tenant);
$tenantKey = $tenant->getTenantKey();
$this->assertDirectoryExists(storage_path("app/public"));
$this->assertEquals(storage_path("app/public/"), readlink(public_path("public-$tenantKey")));
$tenant->delete();
$this->assertDirectoryDoesNotExist(public_path("public-$tenantKey"));
});
test('local storage public urls are generated correctly', function() {
Event::listen(DeletingTenant::class, DeleteTenantStorage::class);
tenancy()->initialize(Tenant::create());
@ -220,14 +336,14 @@ function getDiskPrefix(string $disk): string
return $adapter->getPathPrefix();
}
$prefixer = (new ReflectionObject($adapter))->getProperty('prefixer');
$prefixer->setAccessible(true);
$prefixer = (new ReflectionObject($adapter))->getProperty('prefixer');
$prefixer->setAccessible(true);
// reflection -> instance
$prefixer = $prefixer->getValue($adapter);
// reflection -> instance
$prefixer = $prefixer->getValue($adapter);
$prefix = (new ReflectionProperty($prefixer, 'prefix'));
$prefix->setAccessible(true);
$prefix = (new ReflectionProperty($prefixer, 'prefix'));
$prefix->setAccessible(true);
return $prefix->getValue($prefixer);
return $prefix->getValue($prefixer);
}