feat: configurable upload file size limits via .env (#695)
* feat: make upload file size limits configurable via .env Add UPLOAD_MAX_*_MB environment variables for documents, images, videos, exercise assignment files, AI assistant documents, landing page images, and media thumbnails. API presign routes validate file size server-side; dashboard UI reads the same limits from layout data. * chore: wire upload limit env vars through Docker compose and docs Pass UPLOAD_MAX_*_MB from the root .env into api and dashboard containers in both compose files, document them in .env.example and self-hosting guides. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * docs: cross-link upload limits in README, Railway, Coolify, and Cloudflare guides Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix: address PR review feedback on upload limits - Restore 5 MB default for thumbnail uploads (edit-asset-dialog regression) - Add getResolvedUploadLimits() fallback for Storybook/tests - Cache core getUploadLimits() like the dashboard helper - Document presign fileSize as advisory; allow zero-byte fileSize in schema - Only send fileSize to presign when greater than zero * docs: remove upload limits from Cloudflare setup guide ---------
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
import { snackbar } from '$features/ui/snackbar/store';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { uploadImage } from '$lib/utils/services/upload';
|
||||
import { getResolvedUploadLimits } from '$lib/utils/config/upload-limits-context';
|
||||
|
||||
interface Props {
|
||||
open?: boolean;
|
||||
@@ -22,7 +23,8 @@
|
||||
|
||||
type AssetStatusValue = 'active' | 'archived';
|
||||
|
||||
const THUMBNAIL_MAX_SIZE = 5 * FileDropZone.MEGABYTE;
|
||||
const uploadLimits = getResolvedUploadLimits();
|
||||
const thumbnailMaxSize = uploadLimits.thumbnailBytes;
|
||||
|
||||
let { open = $bindable(false), asset = null, isSaving = false, onSave = async () => {} }: Props = $props();
|
||||
|
||||
@@ -126,7 +128,7 @@
|
||||
accept={FileDropZone.ACCEPT_IMAGE}
|
||||
maxFiles={1}
|
||||
fileCount={0}
|
||||
maxFileSize={THUMBNAIL_MAX_SIZE}
|
||||
maxFileSize={thumbnailMaxSize}
|
||||
onUpload={handleThumbnailFilesUpload}
|
||||
onFileRejected={handleThumbnailRejected}
|
||||
>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { uploadImage } from '$lib/utils/services/upload';
|
||||
import { classroomio } from '$lib/utils/services/api';
|
||||
import { getResolvedUploadLimits } from '$lib/utils/config/upload-limits-context';
|
||||
|
||||
function buildHlsUrl(asset: OrganizationAsset): string | null {
|
||||
if (!asset.hlsManifestKey) return null;
|
||||
@@ -32,7 +33,8 @@
|
||||
onThumbnailSaved?: (asset: OrganizationAsset) => void;
|
||||
}
|
||||
|
||||
const THUMBNAIL_MAX_SIZE = 1 * FileDropZone.MEGABYTE;
|
||||
const uploadLimits = getResolvedUploadLimits();
|
||||
const thumbnailMaxSize = uploadLimits.thumbnailBytes;
|
||||
const REGEN_POLL_INTERVAL_MS = 2000;
|
||||
const REGEN_POLL_TIMEOUT_MS = 60_000;
|
||||
const SLOT_KEYS = ['start', 'middle', 'end'] as const;
|
||||
@@ -289,7 +291,7 @@
|
||||
accept={FileDropZone.ACCEPT_IMAGE}
|
||||
maxFiles={1}
|
||||
fileCount={0}
|
||||
maxFileSize={THUMBNAIL_MAX_SIZE}
|
||||
maxFileSize={thumbnailMaxSize}
|
||||
onUpload={handleCustomUpload}
|
||||
onFileRejected={handleUploadRejected}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user