Skip to content

Commit

Permalink
feat: add endpoint to check if file size exceeds limit
Browse files Browse the repository at this point in the history
  • Loading branch information
apsantiso committed Feb 28, 2024
1 parent f791c1f commit 5ee6656
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 11 deletions.
34 changes: 26 additions & 8 deletions src/app/middleware/feature-limits.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Request, Response, NextFunction } from 'express';
import { AuthorizedUser } from '../routes/types';
import { MissingValuesForFeatureLimit, NoLimitFoundForUserTierAndLabel } from '../services/errors/FeatureLimitsErrors';
import Logger from '../../lib/logger';

const logger = Logger.getInstance();

type User = AuthorizedUser['user'];
type Middleware = (req: Request & { behalfUser?: User }, res: Response, next: NextFunction) => Promise<void>;
Expand Down Expand Up @@ -27,15 +31,29 @@ const build = (Service: {
return next();
}

const extractedData = extractDataFromRequest(req, dataSources);
const shouldLimitBeEnforced = await Service.FeatureLimits.shouldLimitBeEnforced(
user,
limitLabel,
extractedData,
);
try {
const extractedData = extractDataFromRequest(req, dataSources);
const shouldLimitBeEnforced = await Service.FeatureLimits.shouldLimitBeEnforced(
user,
limitLabel,
extractedData,
);

if (shouldLimitBeEnforced) {
return res.status(402).send('You reached the limit for your tier!');
}
} catch (err) {
if (err instanceof MissingValuesForFeatureLimit) {
return res.status(400).send('You reached the limit for your tier!');
}

if (err instanceof NoLimitFoundForUserTierAndLabel) {
logger.error('[FEATURE_LIMIT]: Error getting user limit, bypassing it userUuid: %s', user.uuid);
next();
}

if (shouldLimitBeEnforced) {
return res.status(402).send('You reached the limit for your tier!');
logger.error('[FEATURE_LIMIT]: Unexpected error ', err);
return res.status(400).send('Internal Server error');
}

next();
Expand Down
43 changes: 41 additions & 2 deletions src/app/routes/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
FolderWithNameAlreadyExistsError
} from '../services/errors/FolderWithNameAlreadyExistsError';
import * as resourceSharingMiddlewareBuilder from '../middleware/resource-sharing.middleware';
import * as featureLimitsMiddlewareBuilder from '../middleware/feature-limits.middleware';
import { build as featureLimitsMiddlewareBuilder, LimitLabels } from '../middleware/feature-limits.middleware';
import {validate } from 'uuid';

type AuthorizedRequest = Request & { user: UserAttributes };
Expand All @@ -31,6 +31,7 @@ interface Services {
Folder: any;
UsersReferrals: any;
Analytics: any;
FeatureLimits: any;
User: any;
Notifications: any;
Share: any;
Expand Down Expand Up @@ -106,6 +107,36 @@ export class StorageController {
}
}

public async checkFileSizeLimit(req: Request, res: Response) {
const { behalfUser } = req as SharedRequest;
const { file } = req.body;
try {
if (!file || file.size === undefined || file.size === null) {
this.logger.error(
`Invalid metadata for file limit check ${behalfUser.email}: ${JSON.stringify(file, null, 2)}`,
);
return res.status(400).json({ error: 'Invalid metadata for limit check' });
}
const shouldLimitBeEnforced = await this.services.FeatureLimits.shouldLimitBeEnforced(
behalfUser,
LimitLabels.MaxFileUploadSize,
{file},
);

if (shouldLimitBeEnforced) {
return res.status(402).send('This file size exceeds the limit for your tier!');
}
return res.status(200).send('File can be upload');
} catch (err) {
this.logger.error(
`[FEATURE_LIMIT] ERROR: ${(err as Error).message}, BODY ${JSON.stringify(file)}, STACK: ${
(err as Error).stack
} USER: ${behalfUser.email}`,
);
res.status(500).send({ error: 'Internal Server Error' });
}
}

public async checkFileExistence(req: Request, res: Response) {
const { behalfUser } = req as SharedRequest;
const { file } = req.body as { file: { name: string; folderId: number; type: string } };
Expand Down Expand Up @@ -812,7 +843,7 @@ export default (router: Router, service: any) => {
const sharedAdapter = sharedMiddlewareBuilder.build(service);
const teamsAdapter = teamsMiddlewareBuilder.build(service);
const resourceSharingAdapter = resourceSharingMiddlewareBuilder.build(service);
const featureLimitsAdapter = featureLimitsMiddlewareBuilder.build(service);
const featureLimitsAdapter = featureLimitsMiddlewareBuilder(service);
const controller = new StorageController(service, Logger);

router.post('/storage/file',
Expand All @@ -822,6 +853,14 @@ export default (router: Router, service: any) => {
featureLimitsAdapter.UploadFile,
controller.createFile.bind(controller)
);

router.post('/storage/file/check-limit',
passportAuth,
sharedAdapter,
resourceSharingAdapter.UploadFile,
controller.checkFileSizeLimit.bind(controller)
);

router.post('/storage/file/exists',
passportAuth,
sharedAdapter,
Expand Down
8 changes: 8 additions & 0 deletions src/app/services/errors/FeatureLimitsErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ export class NoLimitFoundForUserTierAndLabel extends Error {
Object.setPrototypeOf(this, NoLimitFoundForUserTierAndLabel.prototype);
}
}

export class MissingValuesForFeatureLimit extends Error {
constructor(message: string) {
super(message);

Object.setPrototypeOf(this, MissingValuesForFeatureLimit.prototype);
}
}
2 changes: 1 addition & 1 deletion src/app/services/featureLimit.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = (Model, App) => {
case LimitLabels.MaxFileUploadSize:
return isMaxFileSizeLimitSurprassed({ limit, data });
default:
return null;
return false;
}
};

Expand Down

0 comments on commit 5ee6656

Please sign in to comment.