Skip to content

Commit

Permalink
Add configurable maximum size of a single file
Browse files Browse the repository at this point in the history
  • Loading branch information
mzur committed Apr 14, 2022
1 parent c8bf245 commit d28a1bf
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/Http/Controllers/Views/StorageRequestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function create(Request $request)
$user = User::convert($request->user());
$usedQuota = $user->storage_quota_used;
$availableQuota = $user->storage_quota_available;
$maxFilesize = config('user_storage.max_file_size');

$previousRequest = StorageRequest::whereNull('submitted_at')
->where('user_id', $user->id)
Expand All @@ -64,6 +65,7 @@ public function create(Request $request)
'previousRequest' => $previousRequest,
'usedQuota' => $usedQuota,
'availableQuota' => $availableQuota,
'maxFilesize' => $maxFilesize,
]);
}

Expand Down
5 changes: 4 additions & 1 deletion src/Http/Requests/StoreStorageRequestFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ public function rules()
{
$user = User::convert($this->storageRequest->user);

$maxQuota = $user->storage_quota_remaining;
$maxFile = config('user_storage.max_file_size');

// The "max" rule expects kilobyte but the quota is in byte.
$maxKb = intval(round($user->storage_quota_remaining / 1024));
$maxKb = intval(round(min($maxQuota, $maxFile) / 1000));

$mimes = implode(',', array_merge(Image::MIMES, Video::MIMES));

Expand Down
7 changes: 7 additions & 0 deletions src/config/user_storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
*/
'max_pending_requests' => env('USER_STORAGE_MAX_PENDING_REQUESTS', 3),

/*
| Maximum allowed size of a single uploaded file in bytes.
|
| Default: 5 GB
*/
'max_file_size' => env('USER_STORAGE_MAX_FILE_SIZE', 5E+9),

/*
| Allowed maximum combined file size for storage per user (in bytes).
|
Expand Down
2 changes: 1 addition & 1 deletion src/public/assets/scripts/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/public/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/assets/scripts/main.js": "/assets/scripts/main.js?id=f81abff4cf8ef6ae04d46776d5f83b25",
"/assets/scripts/main.js": "/assets/scripts/main.js?id=95755e02993c18b779164b925a9db6e5",
"/assets/styles/main.css": "/assets/styles/main.css?id=16bca02d88eeae2a4e45dba3d77b7757"
}
15 changes: 14 additions & 1 deletion src/resources/assets/js/createContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export default {
storageRequest: null,
usedQuotaBytes: 0,
availableQuotaBytes: 0,
maxFilesizeBytes: 0,
exceedsMaxFilesize: false,
};
},
computed: {
Expand Down Expand Up @@ -75,6 +77,9 @@ export default {
usedQuotaPercent() {
return Math.round(this.usedQuotaBytes / this.availableQuotaBytes * 100);
},
maxFilesize() {
return sizeForHumans(this.maxFilesizeBytes);
},
},
methods: {
handleFilesChosen(event) {
Expand All @@ -85,7 +90,14 @@ export default {
return;
}
let newFiles = event.target.files;
let newFiles = Array.from(event.target.files).filter((file) => {
return file.size <= this.maxFilesizeBytes;
});
if (newFiles.length < event.target.files.length) {
this.exceedsMaxFilesize = true;
}
let files = this.selectedDirectory.files;
let i = 0;
Expand Down Expand Up @@ -333,6 +345,7 @@ export default {
created() {
this.usedQuotaBytes = biigle.$require('user-storage.usedQuota');
this.availableQuotaBytes = biigle.$require('user-storage.availableQuota');
this.maxFilesizeBytes = biigle.$require('user-storage.maxFilesize');
// This remains null if no previous request exists.
this.storageRequest = biigle.$require('user-storage.previousRequest');
if (this.storageRequest && this.storageRequest.files.length > 0) {
Expand Down
12 changes: 10 additions & 2 deletions src/resources/views/create.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
biigle.$declare('user-storage.previousRequest', {!! $previousRequest ?? 'null' !!});
biigle.$declare('user-storage.usedQuota', {!! $usedQuota !!});
biigle.$declare('user-storage.availableQuota', {!! $availableQuota !!});
biigle.$declare('user-storage.maxFilesize', {!! $maxFilesize !!});
</script>
@endpush

Expand Down Expand Up @@ -57,7 +58,7 @@ class="hidden"
v-on:input="handleFilesChosen"
>

<div v-if="!finished" class="create-storage-request-buttons">
<div v-if="!finished" class="create-storage-request-buttons clearfix">
<div v-cloak v-if="loading" class="text-info">
<loader v-bind:active="true"></loader>
Uploaded <span v-text="uploadedSizeForHumans"></span> of <span v-text="totalSizeForHumans"></span>
Expand Down Expand Up @@ -118,7 +119,6 @@ class="btn btn-success"
v-bind:disabled="exceedsMaxSize"
>
<i class="fa fa-upload"></i> Submit
<span v-text="totalSizeForHumans"></span>
</button>
<button
v-else
Expand All @@ -136,9 +136,16 @@ class="btn btn-success"
You have selected more than the <span v-text="availableQuota"></span> of storage available to you.
</p>

<p v-cloak v-if="exceedsMaxFilesize" class="text-danger">
Files larger than the maximum allowed size of <span v-text="maxFilesize"></span> have been ignored.
</p>

<p v-cloak v-if="finished" class="text-success">
The storage request has been submitted. You will be notified when it has been reviewed.
</p>
<p v-cloak v-else v-if="hasFiles" class="text-muted">
Selected files with a total size of <span v-text="totalSizeForHumans"></span>.
</p>

<file-browser
v-cloak
Expand All @@ -150,6 +157,7 @@ class="btn btn-success"
v-on:remove-directory="removeDirectory"
v-on:remove-file="removeFile"
></file-browser>

</div>
</div>
</div>
Expand Down
17 changes: 16 additions & 1 deletion tests/Http/Controllers/Api/StorageRequestFileControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function testStorePrefix()
$this->assertSame(['abc/def/test.jpg'], $request->fresh()->files);
}

public function testStoreTooLarge()
public function testStoreTooLargeQuota()
{
config(['user_storage.pending_disk' => 'test']);
config(['user_storage.user_quota' => 10000]);
Expand All @@ -102,6 +102,21 @@ public function testStoreTooLarge()
->assertStatus(422);
}

public function testStoreTooLargeFile()
{
config(['user_storage.pending_disk' => 'test']);
config(['user_storage.max_file_size' => 10000]);
$disk = Storage::fake('test');

$request = StorageRequest::factory()->create();
$id = $request->id;

$file = new UploadedFile(__DIR__."/../../../files/test.jpg", 'test.jpg', 'image/jpeg', null, true);
$this->be($request->user);
$this->postJson("/api/v1/storage-requests/{$id}/files", ['file' => $file])
->assertStatus(422);
}

public function testStoreMimeType()
{
config(['user_storage.pending_disk' => 'test']);
Expand Down

0 comments on commit d28a1bf

Please sign in to comment.