From 11fec0345d0baea5bea75f1ab423fcb23e4b9fbd Mon Sep 17 00:00:00 2001 From: lukinovec Date: Mon, 17 Aug 2026 16:52:05 +0200 Subject: [PATCH] Make TenantAssetController not depend on suffixed storage_path() The only thing the controller now depends on is that FilesystemTenancyBootstrapper needs to be enabled (so basically, the same dependency as before, but before this, there was the extra "suffix_storage_path === true" dependency -- not literally, storage_path() just had to be suffixed in tenant context, otherwise, the controller would read from the central storage in tenant context). --- src/Controllers/TenantAssetController.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Controllers/TenantAssetController.php b/src/Controllers/TenantAssetController.php index 243135ed..bd27e7be 100644 --- a/src/Controllers/TenantAssetController.php +++ b/src/Controllers/TenantAssetController.php @@ -9,6 +9,7 @@ use Exception; use Illuminate\Http\Request; use Illuminate\Routing\Controllers\HasMiddleware; use Illuminate\Routing\Controllers\Middleware; +use Stancl\Tenancy\Bootstrappers\FilesystemTenancyBootstrapper; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Throwable; @@ -51,12 +52,27 @@ class TenantAssetController implements HasMiddleware ? (static::$headers)($request) : static::$headers; - return response()->file(storage_path("app/public/$path"), $headers); + return response()->file($this->assetRoot() . "/$path", $headers); } catch (Throwable) { abort(404); } } + /** + * Assets are served from app/public inside the tenant's storage directory. + * + * The directory is resolved using the FilesystemTenancyBootstrapper (rather than storage_path(), + * so that it's tenant-scoped regardless of the suffix_storage_path config). + */ + protected function assetRoot(): string + { + if ($tenant = tenant()) { + return FilesystemTenancyBootstrapper::getBoundTenantStoragePath($tenant) . '/app/public'; + } + + return storage_path('app/public'); + } + /** * Prevent path traversal attacks. This is generally a non-issue on modern * webservers but it's still worth handling on the application level as well. @@ -67,9 +83,9 @@ class TenantAssetController implements HasMiddleware { $this->abortIf($path === null, 'Empty path'); - $allowedRoot = realpath(storage_path('app/public')); + $allowedRoot = realpath($this->assetRoot()); - // `storage_path('app/public')` doesn't exist, so it cannot contain files + // The asset root doesn't exist, so it cannot contain files $this->abortIf($allowedRoot === false, "Storage root doesn't exist"); $attemptedPath = realpath("{$allowedRoot}/{$path}");