Skip to content

Commit a324b76

Browse files
authored
feat: per user limit (#922)
* feat: per user limit * fix: limit issues at other parts
1 parent 54df1dc commit a324b76

6 files changed

Lines changed: 40 additions & 32 deletions

File tree

platforms/file-manager/api/src/controllers/FileController.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ import os from "os";
77
import { FileService } from "../services/FileService";
88

99
const upload = multer({
10-
limits: { fileSize: 1024 * 1024 * 1024 }, // 1GB limit
1110
storage: multer.memoryStorage(),
1211
});
1312

1413
const uploadMultiple = multer({
15-
limits: { fileSize: 1024 * 1024 * 1024 }, // 1GB limit
1614
storage: multer.memoryStorage(),
1715
});
1816

@@ -43,19 +41,19 @@ export class FileController {
4341
.json({ error: "Authentication required" });
4442
}
4543

46-
// Check file size limit (1GB)
47-
const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB in bytes
48-
if (req.file.size > MAX_FILE_SIZE) {
44+
// Check user's storage quota
45+
const { used, limit } =
46+
await this.fileService.getUserStorageUsage(req.user.id);
47+
48+
// Check individual file size against user's limit
49+
if (req.file.size > limit) {
4950
return res.status(413).json({
50-
error: "File size exceeds 1GB limit",
51-
maxSize: MAX_FILE_SIZE,
51+
error: `File size exceeds ${Math.round(limit / (1024 * 1024 * 1024))}GB limit`,
52+
maxSize: limit,
5253
fileSize: req.file.size,
5354
});
5455
}
5556

56-
// Check user's storage quota (1GB total)
57-
const { used, limit } =
58-
await this.fileService.getUserStorageUsage(req.user.id);
5957
if (used + req.file.size > limit) {
6058
return res.status(413).json({
6159
error: "Storage quota exceeded",
@@ -124,7 +122,6 @@ export class FileController {
124122
.json({ error: "Authentication required" });
125123
}
126124

127-
const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB in bytes
128125
const { used, limit } =
129126
await this.fileService.getUserStorageUsage(req.user.id);
130127

@@ -169,10 +166,10 @@ export class FileController {
169166
for (const file of files) {
170167
try {
171168
// Check file size limit
172-
if (file.size > MAX_FILE_SIZE) {
169+
if (file.size > limit) {
173170
errors.push({
174171
fileName: file.originalname,
175-
error: "File size exceeds 1GB limit",
172+
error: `File size exceeds ${Math.round(limit / (1024 * 1024 * 1024))}GB limit`,
176173
fileSize: file.size,
177174
});
178175
continue;

platforms/file-manager/api/src/database/entities/User.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@ export class User {
4343

4444
@Column({ default: false })
4545
isArchived!: boolean;
46+
47+
@Column({ type: "int", default: 1 })
48+
size!: number;
4649
}
4750

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { MigrationInterface, QueryRunner } from "typeorm";
2+
3+
export class AddUserSize1773609001333 implements MigrationInterface {
4+
name = 'AddUserSize1773609001333'
5+
6+
public async up(queryRunner: QueryRunner): Promise<void> {
7+
await queryRunner.query(`ALTER TABLE "users" ADD "size" integer NOT NULL DEFAULT 1`);
8+
}
9+
10+
public async down(queryRunner: QueryRunner): Promise<void> {
11+
await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "size"`);
12+
}
13+
14+
}

platforms/file-manager/api/src/services/FileService.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Folder } from "../database/entities/Folder";
44
import { FileAccess } from "../database/entities/FileAccess";
55
import { FolderAccess } from "../database/entities/FolderAccess";
66
import { SignatureContainer } from "../database/entities/SignatureContainer";
7+
import { User } from "../database/entities/User";
78
import { In, IsNull, Not } from "typeorm";
89
import crypto from "crypto";
910
import { Readable } from "stream";
@@ -16,6 +17,7 @@ export class FileService {
1617
private fileAccessRepository = AppDataSource.getRepository(FileAccess);
1718
private folderRepository = AppDataSource.getRepository(Folder);
1819
private signatureRepository = AppDataSource.getRepository(SignatureContainer);
20+
private userRepository = AppDataSource.getRepository(User);
1921

2022
async calculateMD5(buffer: Buffer): Promise<string> {
2123
return crypto.createHash('md5').update(buffer).digest('hex');
@@ -355,7 +357,13 @@ export class FileService {
355357
const folderSize = folderCount * FOLDER_SIZE;
356358

357359
const used = fileSize + folderSize;
358-
const limit = 1073741824; // 1GB in bytes
360+
361+
const user = await this.userRepository.findOne({
362+
where: { id: userId },
363+
select: ["size"],
364+
});
365+
const sizeInGB = user?.size ?? 1;
366+
const limit = sizeInGB * 1024 * 1024 * 1024;
359367

360368
return { used, limit, fileCount, folderCount };
361369
}

platforms/file-manager/client/src/routes/(protected)/files/+page.svelte

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -230,21 +230,7 @@
230230
async function handleFileUpload(filesToUpload: globalThis.File[]) {
231231
if (filesToUpload.length === 0) return;
232232
233-
// Client-side validation
234-
const MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1GB
235-
const validFiles: globalThis.File[] = [];
236-
237-
for (const file of filesToUpload) {
238-
if (file.size > MAX_FILE_SIZE) {
239-
toast.error(
240-
`File "${file.name}" exceeds 1GB limit. Your file is ${(file.size / 1024 / 1024).toFixed(2)}MB`,
241-
);
242-
} else {
243-
validFiles.push(file);
244-
}
245-
}
246-
247-
if (validFiles.length === 0) return;
233+
const validFiles = filesToUpload;
248234
249235
isUploading = true;
250236
uploadProgress = {};
@@ -308,7 +294,7 @@
308294
);
309295
} else {
310296
toast.error(
311-
`File "${file.name}" size exceeds 1GB limit`,
297+
`File "${file.name}" exceeds the size limit`,
312298
);
313299
}
314300
} else {

platforms/file-manager/client/src/routes/(protected)/storage/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@
209209
<div class="flex-1">
210210
<h4 class="text-sm font-semibold text-blue-900 mb-1">Storage Information</h4>
211211
<ul class="text-sm text-blue-700 space-y-1">
212-
<li>• Maximum file size: 5 MB per file</li>
213-
<li>• Total storage quota: 1 GB</li>
212+
<li>• Maximum file size: {formatBytes(limit)} per file</li>
213+
<li>• Total storage quota: {formatBytes(limit)}</li>
214214
<li>• Each folder counts as 4 KB</li>
215215
<li>• Deleted files are permanently removed and cannot be recovered</li>
216216
</ul>

0 commit comments

Comments
 (0)