mirror of
https://github.com/archtechx/tenancy.git
synced 2026-09-20 12:34:03 +00:00
Throw an exception in TenantAssetController if the disk is not tenant-aware
Instead of just saying that the publicDisk *should* be listed in tenancy.filesystem.disks, enforce that -- if the disk isn't tenant-aware, throw an exception. Also update comments accordingly. E.g. since scoped disks don't have to have a single "parent disk" (the parent can also be a scoped disk and have another parent, and so on), use "base disk".
This commit is contained in:
parent
041b023a95
commit
e0e696f83e
1 changed files with 36 additions and 9 deletions
|
|
@ -47,10 +47,10 @@ class TenantAssetController implements HasMiddleware
|
|||
* When null, the assets are served from app/public inside the tenant's storage directory.
|
||||
*
|
||||
* The disk has to be local, since the assets are read from the filesystem. Disks using the
|
||||
* 'scoped' driver are supported as long as their parent disk uses the 'local' driver.
|
||||
* 'scoped' driver are supported as long as the disk they're based on uses the 'local' driver.
|
||||
*
|
||||
* It should also be listed in tenancy.filesystem.disks -- for scoped disks, it's the parent
|
||||
* disk that has to be listed there (since a scoped disk inherits the parent's root).
|
||||
* The disk also has to be listed in tenancy.filesystem.disks -- for scoped disks, it's the
|
||||
* disk they're based on that has to be listed there (since a scoped disk inherits its root).
|
||||
* FilesystemTenancyBootstrapper only scopes the roots of disks listed there, so
|
||||
* without that every tenant would be served the same (central) directory.
|
||||
*/
|
||||
|
|
@ -87,8 +87,8 @@ class TenantAssetController implements HasMiddleware
|
|||
|
||||
/**
|
||||
* Directory the assets are served from -- the root of the $publicDisk, or app/public
|
||||
* inside the tenant's storage directory when no disk is configured. With no current
|
||||
* tenant (e.g. on a universal route), the central storage directory is used.
|
||||
* inside the tenant's storage directory when no disk is configured. With no disk and
|
||||
* no current tenant (e.g. on a universal route), the central app/public is used.
|
||||
*
|
||||
* The tenant's storage directory is resolved using the FilesystemTenancyBootstrapper (rather
|
||||
* than storage_path(), so that it's tenant-scoped regardless of the suffix_storage_path config).
|
||||
|
|
@ -99,13 +99,20 @@ class TenantAssetController implements HasMiddleware
|
|||
$disk = Storage::disk(static::$publicDisk);
|
||||
|
||||
if (! $disk instanceof LocalFilesystemAdapter) {
|
||||
// The root has to be read from the resolved disk rather than from the disk's config,
|
||||
// since the config root isn't the full root path of every local disk. Disks using the
|
||||
// 'scoped' driver have no root in their config -- they inherit their parent disk's root --
|
||||
// and a 'prefix' is part of the root path as well.
|
||||
throw new Exception('Disk [' . static::$publicDisk . '] is not a local disk. Only local disks can be used for serving assets.');
|
||||
}
|
||||
|
||||
$baseDiskName = $this->baseDiskName(static::$publicDisk);
|
||||
|
||||
if (! in_array($baseDiskName, config('tenancy.filesystem.disks'), true)) {
|
||||
// FilesystemTenancyBootstrapper only scopes the roots of disks listed in tenancy.filesystem.disks.
|
||||
// Without that, the root stays central and every tenant would be served the same directory.
|
||||
throw new Exception("Disk [$baseDiskName] is not tenant-aware. Add it to the tenancy.filesystem.disks config to make its root tenant-specific.");
|
||||
}
|
||||
|
||||
// The root is read from the resolved disk rather than from the disk's config, since the
|
||||
// config root isn't the full root path of every local disk. Disks using the 'scoped' driver
|
||||
// have no root in their config, and a 'prefix' is part of the root path as well.
|
||||
return rtrim($disk->path(''), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +123,26 @@ class TenantAssetController implements HasMiddleware
|
|||
return storage_path('app/public');
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the disk whose root the passed disk uses.
|
||||
*
|
||||
* Disks using the 'scoped' driver have no root of their own -- they inherit the root of their parent disk,
|
||||
* which can be scoped as well, so the final/base parent is what has to be tenant-aware.
|
||||
*/
|
||||
protected function baseDiskName(string $disk): string
|
||||
{
|
||||
while (config("filesystems.disks.$disk.driver") === 'scoped') {
|
||||
if (! is_string($parent = config("filesystems.disks.$disk.disk"))) {
|
||||
// Laravel allows configuring the parent inline as an array, in which case it has no name
|
||||
throw new Exception("Disk [$disk] has its parent disk configured inline. Use a named parent disk listed in tenancy.filesystem.disks.");
|
||||
}
|
||||
|
||||
$disk = $parent;
|
||||
}
|
||||
|
||||
return $disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue