Skip to content

Commit 514bffc

Browse files
authored
Merge branch 'master' into stop-impersonating
2 parents 3e20576 + da7eb94 commit 514bffc

16 files changed

Lines changed: 260 additions & 31 deletions

assets/TenancyServiceProvider.stub.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ public function events()
5353
])->send(function (Events\TenantCreated $event) {
5454
return $event->tenant;
5555
})->shouldBeQueued(false),
56-
57-
// Listeners\CreateTenantStorage::class,
5856
],
5957
Events\SavingTenant::class => [],
6058
Events\TenantSaved::class => [],
@@ -63,12 +61,11 @@ public function events()
6361
Events\DeletingTenant::class => [
6462
JobPipeline::make([
6563
Jobs\DeleteDomains::class,
64+
// Jobs\DeleteTenantStorage::class,
6665
// Jobs\RemoveStorageSymlinks::class,
6766
])->send(function (Events\DeletingTenant $event) {
6867
return $event->tenant;
6968
})->shouldBeQueued(false),
70-
71-
// Listeners\DeleteTenantStorage::class,
7269
],
7370
Events\TenantDeleted::class => [
7471
JobPipeline::make([

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ services:
8080
mssql:
8181
image: mcr.microsoft.com/mssql/server:2022-latest
8282
environment:
83-
- ACCEPT_EULA=Y
84-
- SA_PASSWORD=P@ssword # must be the same as TENANCY_TEST_SQLSRV_PASSWORD
83+
ACCEPT_EULA: "Y"
84+
SA_PASSWORD: "P@ssword" # must be the same as TENANCY_TEST_SQLSRV_PASSWORD
8585
healthcheck: # https://github.com/Microsoft/mssql-docker/issues/133#issuecomment-1995615432
8686
test: timeout 2 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/1433'
8787
interval: 10s

src/Database/Concerns/PendingScope.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class PendingScope implements Scope
1414
/**
1515
* Apply the scope to a given Eloquent query builder.
1616
*
17-
* @param Builder<Model> $builder
17+
* @param Builder<covariant Model> $builder
1818
*
1919
* @return void
2020
*/
@@ -58,8 +58,10 @@ protected function addWithoutPending(Builder $builder): void
5858
{
5959
$builder->macro('withoutPending', function (Builder $builder) {
6060
$builder->withoutGlobalScope(static::class)
61-
->whereNull($builder->getModel()->getColumnForQuery('pending_since'))
62-
->orWhereNull($builder->getModel()->getDataColumn());
61+
->where(function (Builder $query) {
62+
$query->whereNull($query->getModel()->getColumnForQuery('pending_since'))
63+
->orWhereNull($query->getModel()->getDataColumn());
64+
});
6365

6466
return $builder;
6567
});

src/Database/ParentModelScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class ParentModelScope implements Scope
1313
{
1414
/**
15-
* @param Builder<Model> $builder
15+
* @param Builder<covariant Model> $builder
1616
*/
1717
public function apply(Builder $builder, Model $model): void
1818
{

src/Database/TenantScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class TenantScope implements Scope
1414
{
1515
/**
16-
* @param Builder<Model> $builder
16+
* @param Builder<covariant Model> $builder
1717
*/
1818
public function apply(Builder $builder, Model $model)
1919
{

src/Jobs/DeleteDatabase.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,34 @@ public function __construct(
2222
protected TenantWithDatabase&Model $tenant,
2323
) {}
2424

25+
/** Skip database deletion if the create_database internal attribute is false. */
26+
public static bool $skipWhenCreateDatabaseIsFalse = true;
27+
28+
/** Ignore exceptions thrown during database deletion and continue execution. */
29+
public static bool $ignoreFailures = false;
30+
2531
public function handle(): void
2632
{
33+
if (static::$skipWhenCreateDatabaseIsFalse && $this->tenant->getInternal('create_database') === false) {
34+
// If database creation was skipped, we presume deletion should also be skipped.
35+
// To avoid this skip, either unset the `create_database` attribute (or make it true), or
36+
// set the $skipWhenCreateDatabaseIsFalse static property to false.
37+
return;
38+
}
39+
2740
event(new DeletingDatabase($this->tenant));
2841

29-
$this->tenant->database()->manager()->deleteDatabase($this->tenant);
42+
$deleted = false;
43+
44+
try {
45+
$this->tenant->database()->manager()->deleteDatabase($this->tenant);
46+
$deleted = true;
47+
} catch (\Throwable $e) {
48+
if (! static::$ignoreFailures) {
49+
throw $e;
50+
}
51+
}
3052

31-
event(new DatabaseDeleted($this->tenant));
53+
if ($deleted) event(new DatabaseDeleted($this->tenant));
3254
}
3355
}

src/Jobs/DeleteTenantStorage.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Stancl\Tenancy\Jobs;
6+
7+
use Illuminate\Bus\Queueable;
8+
use Illuminate\Contracts\Queue\ShouldQueue;
9+
use Illuminate\Foundation\Bus\Dispatchable;
10+
use Illuminate\Queue\InteractsWithQueue;
11+
use Illuminate\Queue\SerializesModels;
12+
use Illuminate\Support\Facades\File;
13+
use Stancl\Tenancy\Contracts\Tenant;
14+
15+
class DeleteTenantStorage implements ShouldQueue
16+
{
17+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
18+
19+
public function __construct(
20+
public Tenant $tenant,
21+
) {}
22+
23+
public function handle(): void
24+
{
25+
if (config('tenancy.filesystem.suffix_storage_path') === false) {
26+
// Skip storage deletion if path suffixing is disabled
27+
return;
28+
}
29+
30+
$centralStoragePath = tenancy()->central(fn () => storage_path());
31+
$tenantStoragePath = tenancy()->run($this->tenant, fn () => storage_path());
32+
33+
if ($tenantStoragePath === $centralStoragePath) {
34+
// Check again to ensure the tenant storage path is distinct from the central storage path
35+
// to avoid any accidental central storage path deletion
36+
return;
37+
}
38+
39+
if (is_dir($tenantStoragePath)) {
40+
File::deleteDirectory($tenantStoragePath);
41+
}
42+
}
43+
}

src/Listeners/CreateTenantStorage.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
use Stancl\Tenancy\Events\Contracts\TenantEvent;
88

99
/**
10-
* Can be used to manually create framework directories in the tenant storage when storage_path() is scoped.
11-
*
12-
* Useful when using real-time facades which use the framework/cache directory.
13-
*
14-
* Generally not needed anymore as the directory is also created by the FilesystemTenancyBootstrapper.
10+
* @deprecated FilesystemTenancyBootstrapper creates the path automatically when suffix_storage_path is enabled.
1511
*/
1612
class CreateTenantStorage
1713
{

src/Listeners/DeleteTenantStorage.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,29 @@
77
use Illuminate\Support\Facades\File;
88
use Stancl\Tenancy\Events\Contracts\TenantEvent;
99

10+
/**
11+
* @deprecated Use Stancl\Tenancy\Jobs\DeleteTenantStorage in a job pipeline instead.
12+
*/
1013
class DeleteTenantStorage
1114
{
1215
public function handle(TenantEvent $event): void
1316
{
14-
$path = tenancy()->run($event->tenant, fn () => storage_path());
17+
if (config('tenancy.filesystem.suffix_storage_path') === false) {
18+
// Skip storage deletion if path suffixing is disabled
19+
return;
20+
}
21+
22+
$centralStoragePath = tenancy()->central(fn () => storage_path());
23+
$tenantStoragePath = tenancy()->run($event->tenant, fn () => storage_path());
24+
25+
if ($tenantStoragePath === $centralStoragePath) {
26+
// Check again to ensure the tenant storage path is distinct from the central storage path
27+
// to avoid any accidental central storage path deletion
28+
return;
29+
}
1530

16-
if (is_dir($path)) {
17-
File::deleteDirectory($path);
31+
if (is_dir($tenantStoragePath)) {
32+
File::deleteDirectory($tenantStoragePath);
1833
}
1934
}
2035
}

src/Middleware/PreventAccessFromUnwantedDomains.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ public function handle(Request $request, Closure $next): mixed
3131
{
3232
$route = tenancy()->getRoute($request);
3333

34-
if ($this->shouldBeSkipped($route) || tenancy()->routeIsUniversal($route)) {
34+
if ($this->shouldBeSkipped($route)) {
3535
return $next($request);
3636
}
3737

38+
// If the route is universal, neither of these checks will pass and the logic will
39+
// fall through to the $next($request) call at the end.
3840
if ($this->accessingTenantRouteFromCentralDomain($request, $route) || $this->accessingCentralRouteFromTenantDomain($request, $route)) {
3941
$abortRequest = static::$abortRequest ?? function () {
4042
abort(404);

0 commit comments

Comments
 (0)