diff --git a/platforms/file-manager/api/src/controllers/FileController.ts b/platforms/file-manager/api/src/controllers/FileController.ts index 77868ed1b..f4a08d1eb 100644 --- a/platforms/file-manager/api/src/controllers/FileController.ts +++ b/platforms/file-manager/api/src/controllers/FileController.ts @@ -7,12 +7,10 @@ import os from "os"; import { FileService } from "../services/FileService"; const upload = multer({ - limits: { fileSize: 1024 * 1024 * 1024 }, // 1GB limit storage: multer.memoryStorage(), }); const uploadMultiple = multer({ - limits: { fileSize: 1024 * 1024 * 1024 }, // 1GB limit storage: multer.memoryStorage(), }); @@ -43,19 +41,19 @@ export class FileController { .json({ error: "Authentication required" }); } - // Check file size limit (1GB) - const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB in bytes - if (req.file.size > MAX_FILE_SIZE) { + // Check user's storage quota + const { used, limit } = + await this.fileService.getUserStorageUsage(req.user.id); + + // Check individual file size against user's limit + if (req.file.size > limit) { return res.status(413).json({ - error: "File size exceeds 1GB limit", - maxSize: MAX_FILE_SIZE, + error: `File size exceeds ${Math.round(limit / (1024 * 1024 * 1024))}GB limit`, + maxSize: limit, fileSize: req.file.size, }); } - // Check user's storage quota (1GB total) - const { used, limit } = - await this.fileService.getUserStorageUsage(req.user.id); if (used + req.file.size > limit) { return res.status(413).json({ error: "Storage quota exceeded", @@ -124,7 +122,6 @@ export class FileController { .json({ error: "Authentication required" }); } - const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB in bytes const { used, limit } = await this.fileService.getUserStorageUsage(req.user.id); @@ -169,10 +166,10 @@ export class FileController { for (const file of files) { try { // Check file size limit - if (file.size > MAX_FILE_SIZE) { + if (file.size > limit) { errors.push({ fileName: file.originalname, - error: "File size exceeds 1GB limit", + error: `File size exceeds ${Math.round(limit / (1024 * 1024 * 1024))}GB limit`, fileSize: file.size, }); continue; diff --git a/platforms/file-manager/api/src/database/entities/User.ts b/platforms/file-manager/api/src/database/entities/User.ts index 2eb71a6d8..61b8508c7 100644 --- a/platforms/file-manager/api/src/database/entities/User.ts +++ b/platforms/file-manager/api/src/database/entities/User.ts @@ -43,5 +43,8 @@ export class User { @Column({ default: false }) isArchived!: boolean; + + @Column({ type: "int", default: 1 }) + size!: number; } diff --git a/platforms/file-manager/api/src/database/migrations/1773609001333-AddUserSize.ts b/platforms/file-manager/api/src/database/migrations/1773609001333-AddUserSize.ts new file mode 100644 index 000000000..223241ef1 --- /dev/null +++ b/platforms/file-manager/api/src/database/migrations/1773609001333-AddUserSize.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddUserSize1773609001333 implements MigrationInterface { + name = 'AddUserSize1773609001333' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "users" ADD "size" integer NOT NULL DEFAULT 1`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "size"`); + } + +} diff --git a/platforms/file-manager/api/src/services/FileService.ts b/platforms/file-manager/api/src/services/FileService.ts index 8ba0e4018..59db7de6a 100644 --- a/platforms/file-manager/api/src/services/FileService.ts +++ b/platforms/file-manager/api/src/services/FileService.ts @@ -4,6 +4,7 @@ import { Folder } from "../database/entities/Folder"; import { FileAccess } from "../database/entities/FileAccess"; import { FolderAccess } from "../database/entities/FolderAccess"; import { SignatureContainer } from "../database/entities/SignatureContainer"; +import { User } from "../database/entities/User"; import { In, IsNull, Not } from "typeorm"; import crypto from "crypto"; import { Readable } from "stream"; @@ -16,6 +17,7 @@ export class FileService { private fileAccessRepository = AppDataSource.getRepository(FileAccess); private folderRepository = AppDataSource.getRepository(Folder); private signatureRepository = AppDataSource.getRepository(SignatureContainer); + private userRepository = AppDataSource.getRepository(User); async calculateMD5(buffer: Buffer): Promise { return crypto.createHash('md5').update(buffer).digest('hex'); @@ -355,7 +357,13 @@ export class FileService { const folderSize = folderCount * FOLDER_SIZE; const used = fileSize + folderSize; - const limit = 1073741824; // 1GB in bytes + + const user = await this.userRepository.findOne({ + where: { id: userId }, + select: ["size"], + }); + const sizeInGB = user?.size ?? 1; + const limit = sizeInGB * 1024 * 1024 * 1024; return { used, limit, fileCount, folderCount }; } diff --git a/platforms/file-manager/client/src/routes/(protected)/files/+page.svelte b/platforms/file-manager/client/src/routes/(protected)/files/+page.svelte index 531cc73d8..0e91f9168 100644 --- a/platforms/file-manager/client/src/routes/(protected)/files/+page.svelte +++ b/platforms/file-manager/client/src/routes/(protected)/files/+page.svelte @@ -230,21 +230,7 @@ async function handleFileUpload(filesToUpload: globalThis.File[]) { if (filesToUpload.length === 0) return; - // Client-side validation - const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB - const validFiles: globalThis.File[] = []; - - for (const file of filesToUpload) { - if (file.size > MAX_FILE_SIZE) { - toast.error( - `File "${file.name}" exceeds 1GB limit. Your file is ${(file.size / 1024 / 1024).toFixed(2)}MB`, - ); - } else { - validFiles.push(file); - } - } - - if (validFiles.length === 0) return; + const validFiles = filesToUpload; isUploading = true; uploadProgress = {}; @@ -308,7 +294,7 @@ ); } else { toast.error( - `File "${file.name}" size exceeds 1GB limit`, + `File "${file.name}" exceeds the size limit`, ); } } else { diff --git a/platforms/file-manager/client/src/routes/(protected)/storage/+page.svelte b/platforms/file-manager/client/src/routes/(protected)/storage/+page.svelte index 3068b9a29..c7a99ef9f 100644 --- a/platforms/file-manager/client/src/routes/(protected)/storage/+page.svelte +++ b/platforms/file-manager/client/src/routes/(protected)/storage/+page.svelte @@ -209,8 +209,8 @@

Storage Information

    -
  • • Maximum file size: 5 MB per file
  • -
  • • Total storage quota: 1 GB
  • +
  • • Maximum file size: {formatBytes(limit)} per file
  • +
  • • Total storage quota: {formatBytes(limit)}
  • • Each folder counts as 4 KB
  • • Deleted files are permanently removed and cannot be recovered