mirror of
https://github.com/projectsend/projectsend.git
synced 2026-10-04 05:25:51 +00:00
Merge pull request #1734 from denkfabrik-li/fix/quota-message-inherited-default
ClientStorageUsage::quotaMb() exists because a client's own storage_quota_mb of 0 does not mean "unlimited" -- it means "no quota of their own", and the site default is what is then enforced. Both chunked-upload quota checks enforced the resolved limit through quotaBytes() and then printed the raw column in the rejection, so a client with no quota of their own and a site default of 1 MB was told "This upload would exceed your storage quota of 0 MB." That is every client who was never given a quota, including every self-registered one, and the sentence appears at the one moment somebody is trying to find out what their limit is. Both now print quotaMb(), which is what the check enforced. The API's single-request upload already did exactly this for the same sentence, so the three copies agree. The enforcement itself is untouched -- only the number in the message changes -- and the unlimited case never reaches these branches, because quotaBytes() > 0 guards them. Verified before merging: 16 passed on the trial-merge, 2 failed / 14 passed with app/ reset. The "a client with a quota of their own still sees their own number" test is green either way. The string itself is unchanged, so no locale file needs anything. Reported and fixed by @denkfabrik-li.
This commit is contained in:
@@ -98,7 +98,14 @@ class ChunkedUploadsController extends Controller
|
||||
|
||||
if ($quotaBytes > 0 && $this->storageUsage->usedBytes($user) + (int) $validated['size'] > $quotaBytes) {
|
||||
throw ValidationException::withMessages([
|
||||
'size' => __('This upload would exceed your storage quota of :quota MB.', ['quota' => (string) $user->storage_quota_mb]),
|
||||
'size' => __('This upload would exceed your storage quota of :quota MB.', [
|
||||
// The resolved quota, not the column: a client who
|
||||
// was never given one of their own carries 0 there
|
||||
// and inherits the site default, so printing the
|
||||
// column reads "your storage quota of 0 MB" at the
|
||||
// moment somebody is asking what their limit is.
|
||||
'quota' => (string) $this->storageUsage->quotaMb($user),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -306,7 +313,9 @@ class ChunkedUploadsController extends Controller
|
||||
$session->delete();
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'size' => __('This upload would exceed your storage quota of :quota MB.', ['quota' => (string) $user->storage_quota_mb]),
|
||||
'size' => __('This upload would exceed your storage quota of :quota MB.', [
|
||||
'quota' => (string) $this->storageUsage->quotaMb($user),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +191,58 @@ test('a client with no custom quota is limited by the site default once one is s
|
||||
])->assertJsonValidationErrors('size');
|
||||
});
|
||||
|
||||
test('the rejection names the quota the client is actually held to', function () {
|
||||
// storage_quota_mb of 0 means "no quota of their own", and the site
|
||||
// default is what is then enforced — so the column is the one number
|
||||
// the message must not print.
|
||||
app(Settings::class)->set(Setting::DefaultClientStorageQuotaMb, 1);
|
||||
$client = User::factory()->client()->create(['storage_quota_mb' => 0]);
|
||||
grantUploadPermission($client);
|
||||
makeClientFile($client, 1000 * 1024);
|
||||
$this->actingAs($client);
|
||||
|
||||
$response = $this->postJson('/uploads', [
|
||||
'filename' => 'over-the-default.pdf',
|
||||
'size' => 200 * 1024,
|
||||
'type' => 'application/pdf',
|
||||
])->assertJsonValidationErrors('size');
|
||||
|
||||
expect($response->json('errors.size.0'))->toBe('This upload would exceed your storage quota of 1 MB.');
|
||||
});
|
||||
|
||||
test('the same is true when the real byte count is what pushes them over', function () {
|
||||
// The completion check is a second copy of the same sentence, and had
|
||||
// the same bug.
|
||||
app(Settings::class)->set(Setting::DefaultClientStorageQuotaMb, 1);
|
||||
$client = User::factory()->client()->create(['storage_quota_mb' => 0]);
|
||||
grantUploadPermission($client);
|
||||
makeClientFile($client, 1000 * 1024);
|
||||
$this->actingAs($client);
|
||||
|
||||
$sessionId = createChunkedSession(11, 'lied-about-size.txt');
|
||||
putChunkedPart($sessionId, 1, str_repeat('a', 50 * 1024));
|
||||
|
||||
$response = $this->postJson("/uploads/{$sessionId}/complete")->assertJsonValidationErrors('size');
|
||||
|
||||
expect($response->json('errors.size.0'))->toBe('This upload would exceed your storage quota of 1 MB.');
|
||||
});
|
||||
|
||||
test('a client with a quota of their own still sees their own number', function () {
|
||||
app(Settings::class)->set(Setting::DefaultClientStorageQuotaMb, 250);
|
||||
$client = User::factory()->client()->create(['storage_quota_mb' => 1]);
|
||||
grantUploadPermission($client);
|
||||
makeClientFile($client, 1000 * 1024);
|
||||
$this->actingAs($client);
|
||||
|
||||
$response = $this->postJson('/uploads', [
|
||||
'filename' => 'over-their-own.pdf',
|
||||
'size' => 200 * 1024,
|
||||
'type' => 'application/pdf',
|
||||
])->assertJsonValidationErrors('size');
|
||||
|
||||
expect($response->json('errors.size.0'))->toBe('This upload would exceed your storage quota of 1 MB.');
|
||||
});
|
||||
|
||||
test('a client\'s own custom quota is unaffected by later changes to the site default', function () {
|
||||
app(Settings::class)->set(Setting::DefaultClientStorageQuotaMb, 1);
|
||||
$client = User::factory()->client()->create(['storage_quota_mb' => 500]); // an explicit, much larger override
|
||||
|
||||
Reference in New Issue
Block a user