change file limitation logic
This commit is contained in:
@@ -37,6 +37,10 @@ BROADCAST_CONNECTION=log
|
|||||||
FILESYSTEM_DISK=local
|
FILESYSTEM_DISK=local
|
||||||
QUEUE_CONNECTION=database
|
QUEUE_CONNECTION=database
|
||||||
|
|
||||||
|
CHAT_ATTACHMENT_MAX_FILES=5
|
||||||
|
CHAT_ATTACHMENT_MAX_FILE_SIZE_KB=2097152
|
||||||
|
CHAT_LIVEWIRE_MAX_UPLOAD_TIME=60
|
||||||
|
|
||||||
CACHE_STORE=database
|
CACHE_STORE=database
|
||||||
# CACHE_PREFIX=
|
# CACHE_PREFIX=
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use Illuminate\Contracts\View\View;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Support\Number;
|
||||||
use Livewire\Attributes\Locked;
|
use Livewire\Attributes\Locked;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||||
@@ -41,16 +42,19 @@ class MessageComposer extends Component
|
|||||||
{
|
{
|
||||||
$this->body = trim($this->body);
|
$this->body = trim($this->body);
|
||||||
$hasAttachments = $this->hasAttachments();
|
$hasAttachments = $this->hasAttachments();
|
||||||
|
$maxAttachmentFiles = $this->maxAttachmentFiles();
|
||||||
|
$maxAttachmentFileSizeKilobytes = $this->maxAttachmentFileSizeKilobytes();
|
||||||
|
$maxAttachmentFileSizeLabel = $this->maxAttachmentFileSizeLabel();
|
||||||
|
|
||||||
$validated = $this->validate([
|
$validated = $this->validate([
|
||||||
'body' => [$hasAttachments ? 'nullable' : 'required', 'string', 'max:4000'],
|
'body' => [$hasAttachments ? 'nullable' : 'required', 'string', 'max:4000'],
|
||||||
'attachments' => ['array', 'max:5'],
|
'attachments' => ['array', 'max:'.$maxAttachmentFiles],
|
||||||
'attachments.*' => ['file', 'max:10240'],
|
'attachments.*' => ['file', 'max:'.$maxAttachmentFileSizeKilobytes],
|
||||||
], [
|
], [
|
||||||
'body.required' => __('Write a message or attach a file before sending.'),
|
'body.required' => __('Write a message or attach a file before sending.'),
|
||||||
'attachments.max' => __('Attach up to :max files at a time.'),
|
'attachments.max' => __('Attach up to :max files at a time.', ['max' => $maxAttachmentFiles]),
|
||||||
'attachments.*.file' => __('Each attachment must be a valid file.'),
|
'attachments.*.file' => __('Each attachment must be a valid file.'),
|
||||||
'attachments.*.max' => __('Each attachment must be 10 MB or smaller.'),
|
'attachments.*.max' => __('Each attachment must be :size or smaller.', ['size' => $maxAttachmentFileSizeLabel]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$conversation = $this->conversation();
|
$conversation = $this->conversation();
|
||||||
@@ -172,6 +176,14 @@ class MessageComposer extends Component
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function attachmentLimitSummary(): string
|
||||||
|
{
|
||||||
|
return __('Up to :count files, :size each', [
|
||||||
|
'count' => $this->maxAttachmentFiles(),
|
||||||
|
'size' => $this->maxAttachmentFileSizeLabel(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
private function conversation(): Conversation
|
private function conversation(): Conversation
|
||||||
{
|
{
|
||||||
$conversation = Conversation::query()
|
$conversation = Conversation::query()
|
||||||
@@ -190,6 +202,21 @@ class MessageComposer extends Component
|
|||||||
->isNotEmpty();
|
->isNotEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function maxAttachmentFiles(): int
|
||||||
|
{
|
||||||
|
return (int) config('chat.attachments.max_files', 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function maxAttachmentFileSizeKilobytes(): int
|
||||||
|
{
|
||||||
|
return (int) config('chat.attachments.max_file_size_kilobytes', 2 * 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function maxAttachmentFileSizeLabel(): string
|
||||||
|
{
|
||||||
|
return Number::fileSize($this->maxAttachmentFileSizeKilobytes() * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
private function emojiForCode(string $code): ?string
|
private function emojiForCode(string $code): ?string
|
||||||
{
|
{
|
||||||
$code = strtoupper($code);
|
$code = strtoupper($code);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
//
|
$this->configureFileUploads();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,4 +47,14 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function configureFileUploads(): void
|
||||||
|
{
|
||||||
|
$maxFileSizeKilobytes = (int) config('chat.attachments.max_file_size_kilobytes');
|
||||||
|
|
||||||
|
config([
|
||||||
|
'livewire.temporary_file_upload.rules' => ['required', 'file', 'max:'.$maxFileSizeKilobytes],
|
||||||
|
'livewire.temporary_file_upload.max_upload_time' => (int) config('chat.attachments.livewire_max_upload_time'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
config/chat.php
Normal file
9
config/chat.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'attachments' => [
|
||||||
|
'max_files' => (int) env('CHAT_ATTACHMENT_MAX_FILES', 5),
|
||||||
|
'max_file_size_kilobytes' => (int) env('CHAT_ATTACHMENT_MAX_FILE_SIZE_KB', 2 * 1024 * 1024),
|
||||||
|
'livewire_max_upload_time' => (int) env('CHAT_LIVEWIRE_MAX_UPLOAD_TIME', 60),
|
||||||
|
],
|
||||||
|
];
|
||||||
4
public/.user.ini
Normal file
4
public/.user.ini
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
upload_max_filesize=2048M
|
||||||
|
post_max_size=2050M
|
||||||
|
max_input_time=3600
|
||||||
|
max_execution_time=3600
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<div class="flex items-start justify-between gap-3">
|
<div class="flex items-start justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<div class="text-sm font-medium text-zinc-900 dark:text-zinc-100">{{ __('Attachments') }}</div>
|
<div class="text-sm font-medium text-zinc-900 dark:text-zinc-100">{{ __('Attachments') }}</div>
|
||||||
<div class="mt-0.5 text-xs text-zinc-500 dark:text-zinc-400">{{ __('Up to 5 files, 10 MB each') }}</div>
|
<div class="mt-0.5 text-xs text-zinc-500 dark:text-zinc-400">{{ $this->attachmentLimitSummary() }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<flux:button
|
<flux:button
|
||||||
|
|||||||
@@ -180,6 +180,42 @@ test('participants can send file messages', function () {
|
|||||||
Storage::disk('local')->assertExists($message->attachmentPath());
|
Storage::disk('local')->assertExists($message->attachmentPath());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('chat file uploads are configured for two gigabyte attachments', function () {
|
||||||
|
expect(config('chat.attachments.max_file_size_kilobytes'))->toBe(2 * 1024 * 1024)
|
||||||
|
->and(config('livewire.temporary_file_upload.rules'))->toContain('max:2097152')
|
||||||
|
->and(config('livewire.temporary_file_upload.max_upload_time'))->toBe(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('participants can send files larger than the previous ten megabyte limit', function () {
|
||||||
|
Storage::fake('local');
|
||||||
|
|
||||||
|
$user = User::factory()->create();
|
||||||
|
$conversation = Conversation::factory()
|
||||||
|
->direct()
|
||||||
|
->for($user, 'creator')
|
||||||
|
->create();
|
||||||
|
|
||||||
|
ConversationParticipant::factory()->for($conversation)->for($user)->create();
|
||||||
|
|
||||||
|
$this->actingAs($user);
|
||||||
|
|
||||||
|
Livewire::test(MessageComposer::class, ['conversationId' => $conversation->id])
|
||||||
|
->set('attachments', [
|
||||||
|
UploadedFile::fake()->create('large-export.zip', 13 * 1024, 'application/zip'),
|
||||||
|
])
|
||||||
|
->call('sendMessage')
|
||||||
|
->assertHasNoErrors();
|
||||||
|
|
||||||
|
$message = Message::query()
|
||||||
|
->where('conversation_id', $conversation->id)
|
||||||
|
->where('user_id', $user->id)
|
||||||
|
->where('type', Message::TypeFile)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
expect($message)->not->toBeNull();
|
||||||
|
expect($message->attachmentName())->toBe('large-export.zip');
|
||||||
|
});
|
||||||
|
|
||||||
test('file metadata is captured before temporary uploads are moved', function () {
|
test('file metadata is captured before temporary uploads are moved', function () {
|
||||||
Storage::fake('local');
|
Storage::fake('local');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user