mirror of
https://github.com/projectsend/projectsend.git
synced 2026-09-17 00:55:07 +00:00
62c763d04e
Setting::DefaultClientStorageQuotaMb defaults to 0, and 0 means
unlimited. That is the right default for somebody setting up their own
installation and the wrong one for an installation a platform operates
on other people's behalf: an account that arrived without an explicit
quota has no ceiling at all, and it does not have to be an account the
platform created.
So a platform may set a floor in the environment
(PROJECTSEND_PLATFORM_DEFAULT_CLIENT_QUOTA_MB), exactly as it sets the
seat caps, and for the same reason those are not settings: it is the
shape of what was sold rather than a preference the installation's
administrator is expressing. It applies only where the setting says
nothing, so an administrator who chose a number keeps it, and an install
with no platform behind it is unaffected.
ClientStorageUsage::defaultQuotaMb() is where the three sources resolve,
and every screen that presents the answer now reads it there:
- The client create and edit screens. The edit screen mirrors that
resolution client-side to draw the usage bar, so handed the raw
setting on a floored installation it computed an effective quota of
zero, printed "unlimited" and hid the bar entirely -- for a client
whose next upload was about to be rejected for exceeding a limit the
screen said did not exist.
- projectsend:status, which gains clients_can_register and
default_client_storage_quota_mb. Both defaults are the permissive
ones, both are invisible from outside, and a document reporting the
setting while uploads obeyed the floor would say the ceiling was
missing on an installation that has one.
The Client settings form deliberately still reads the raw setting: that
field is read and written back on save, so prefilling it with the floor
would write the platform's number into the setting as the
administrator's own choice, where it would outlive the floor.
101 lines
3.3 KiB
PHP
101 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Modules\Clients;
|
|
|
|
use App\Models\User;
|
|
use App\Modules\Files\Models\File;
|
|
use App\Modules\Platform\Settings\Setting;
|
|
use App\Modules\Platform\Settings\Settings;
|
|
|
|
/**
|
|
* A client's cumulative storage usage against their quota. Usage is a
|
|
* live sum (not a maintained counter) over files the client uploaded
|
|
* themselves — matches how the quota is enforced (portal self-uploads
|
|
* only, see ChunkedUploadsController::store()/complete()).
|
|
*/
|
|
class ClientStorageUsage
|
|
{
|
|
public function __construct(
|
|
private readonly Settings $settings,
|
|
) {}
|
|
|
|
public function usedBytes(User $client): int
|
|
{
|
|
return (int) File::query()->where('uploaded_by', $client->id)->sum('size');
|
|
}
|
|
|
|
/**
|
|
* A client's own storage_quota_mb of 0 means "no custom quota set" —
|
|
* it inherits the installation's default instead of being unlimited,
|
|
* so a default (once set) also protects clients who never got an
|
|
* explicit quota, including self-registered ones.
|
|
*
|
|
* @return int 0 means unlimited.
|
|
*/
|
|
public function quotaMb(User $client): int
|
|
{
|
|
return $client->storage_quota_mb > 0
|
|
? $client->storage_quota_mb
|
|
: $this->defaultQuotaMb();
|
|
}
|
|
|
|
/**
|
|
* What a client with no quota of their own actually gets.
|
|
*
|
|
* Three sources, narrowest first, and the third is why this is a
|
|
* method rather than a `Settings::get()` at the point of use.
|
|
*
|
|
* `Setting::DefaultClientStorageQuotaMb` belongs to whoever runs the
|
|
* installation, and its default is 0 — which means unlimited. That is
|
|
* the right default for somebody setting up their own install, and the
|
|
* wrong one for an installation a platform operates on other people's
|
|
* behalf: there, an account that arrived without an explicit quota has
|
|
* no ceiling at all, which on a shared installation is one account
|
|
* away from unmetered hosting.
|
|
*
|
|
* So a platform may set a floor in the environment, exactly as it sets
|
|
* the seat caps, and for the same reason those are not settings: it is
|
|
* not a preference the installation's administrator is expressing, it
|
|
* is the shape of what was sold. It applies only where the setting says
|
|
* nothing, so an administrator who has chosen a number keeps it, and an
|
|
* install with no platform behind it is unaffected.
|
|
*
|
|
* Unset and zero are the same answer here, on purpose: a platform that
|
|
* wanted no ceiling would not set the variable.
|
|
*
|
|
* @return int 0 means unlimited.
|
|
*/
|
|
public function defaultQuotaMb(): int
|
|
{
|
|
$site = (int) $this->settings->get(Setting::DefaultClientStorageQuotaMb);
|
|
|
|
if ($site > 0) {
|
|
return $site;
|
|
}
|
|
|
|
$floor = config('projectsend.platform.default_client_quota_mb');
|
|
|
|
return is_numeric($floor) ? max(0, (int) $floor) : 0;
|
|
}
|
|
|
|
/**
|
|
* @return int 0 means unlimited.
|
|
*/
|
|
public function quotaBytes(User $client): int
|
|
{
|
|
return $this->quotaMb($client) * 1024 * 1024;
|
|
}
|
|
|
|
/**
|
|
* @return int|null Null means unlimited.
|
|
*/
|
|
public function remainingBytes(User $client): ?int
|
|
{
|
|
$quota = $this->quotaBytes($client);
|
|
|
|
return $quota === 0 ? null : max(0, $quota - $this->usedBytes($client));
|
|
}
|
|
}
|