feat: add whole JSON size validation and check for storage usage
This commit is contained in:
parent
fefbf15f5e
commit
2b1e35e55f
5 changed files with 72 additions and 2 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import Utils from './Utils'
|
||||||
import aws from 'aws-sdk'
|
import aws from 'aws-sdk'
|
||||||
import multer from 'multer'
|
import multer from 'multer'
|
||||||
import multerS3 from 'multer-s3'
|
import multerS3 from 'multer-s3'
|
||||||
|
@ -79,4 +80,30 @@ export default class MediaService {
|
||||||
static getMediaBaseUrl() {
|
static getMediaBaseUrl() {
|
||||||
return process.env.S3_BASE_URL == null ? '___BUCKET_BASE_URL_NOT_FOUND_ENV_VAR_ISSUE___' : process.env.S3_BASE_URL
|
return process.env.S3_BASE_URL == null ? '___BUCKET_BASE_URL_NOT_FOUND_ENV_VAR_ISSUE___' : process.env.S3_BASE_URL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getSizeLimit(): number {
|
||||||
|
//return 1073741824 for 1 GB
|
||||||
|
return 1000000000
|
||||||
|
}
|
||||||
|
|
||||||
|
// will return the sum of all the medias size used by the proposedVersion of the organization
|
||||||
|
static computeSize(version: any) {
|
||||||
|
// if (!Utils.isUsable(org, 'proposedVersion')) {
|
||||||
|
// return 0
|
||||||
|
// }
|
||||||
|
// let version: any = org.proposedVersion
|
||||||
|
let size: number = 0
|
||||||
|
if (Utils.isUsable(version, 'thumbnail.size')) {
|
||||||
|
size += version.thumbnail.size
|
||||||
|
}
|
||||||
|
if (Utils.isUsable(version, 'cover.size')) {
|
||||||
|
size += version.cover.size
|
||||||
|
}
|
||||||
|
if (Utils.isUsable(version, 'gallery') && Array.isArray(version.gallery)) {
|
||||||
|
version.gallery.forEach((media: any) => {
|
||||||
|
size += media.size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -91,6 +91,7 @@ let main = async () => {
|
||||||
app.use('/delegate', express.Router()
|
app.use('/delegate', express.Router()
|
||||||
.use(DelegateAuthMiddleware.handle)
|
.use(DelegateAuthMiddleware.handle)
|
||||||
.get('/', DelegateController.get)
|
.get('/', DelegateController.get)
|
||||||
|
.get('/size', DelegateController.getCurrentSize)
|
||||||
//.post('/test', DelegateController.test)
|
//.post('/test', DelegateController.test)
|
||||||
.put('/', DelegateController.update)
|
.put('/', DelegateController.update)
|
||||||
.post('/submit', DelegateController.submit)
|
.post('/submit', DelegateController.submit)
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default class AdminOrganizationController {
|
||||||
_note: 'Invalid import data or csv'
|
_note: 'Invalid import data or csv'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let promises = parsed.data.map(d => {
|
let promises = parsed.data.map((d: any) => {
|
||||||
return AdminOrganizationController.storeUniversal(
|
return AdminOrganizationController.storeUniversal(
|
||||||
d[0],
|
d[0],
|
||||||
d[1].replace(' ', ''),
|
d[1].replace(' ', ''),
|
||||||
|
|
|
@ -21,6 +21,17 @@ export default class DelegateController {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getCurrentSize(req: express.Request, res: express.Response) {
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
size: MediaService.computeSize(res.locals.organization.proposedVersion),
|
||||||
|
max: MediaService.getSizeLimit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// static test(req: express.Request, res: express.Response) {
|
// static test(req: express.Request, res: express.Response) {
|
||||||
// res.json({ success: true, body: req.body, organization: res.locals.organization })
|
// res.json({ success: true, body: req.body, organization: res.locals.organization })
|
||||||
// }
|
// }
|
||||||
|
@ -103,6 +114,14 @@ export default class DelegateController {
|
||||||
proposedVersion.pricing = []
|
proposedVersion.pricing = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// just before updating the whole organization, we want to check the size of the proposedVersion JSON String, just in case it is too large
|
||||||
|
if (JSON.stringify(proposedVersion).length > 10000) {
|
||||||
|
return res.status(413).json({
|
||||||
|
success: false,
|
||||||
|
errors: [{ code: 'too-large', message: 'The proposedVersion object that you are trying to update is too long, we cannot handle it' }]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
Organization.updateOne({ _id: organization._id }, {
|
Organization.updateOne({ _id: organization._id }, {
|
||||||
proposedVersion,
|
proposedVersion,
|
||||||
updatedAt: new Date()
|
updatedAt: new Date()
|
||||||
|
@ -173,8 +192,29 @@ export default class DelegateController {
|
||||||
}).catch(err => res.status(400).json({ success: false, errors: err.errors !== undefined ? err.errors : err }))
|
}).catch(err => res.status(400).json({ success: false, errors: err.errors !== undefined ? err.errors : err }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static verifySize(req: express.Request, res: express.Response, next: any) {
|
||||||
|
// before starting the upload process, we want to make sure that this organization is not exeeding the size limit for all the file
|
||||||
|
let currentSize = MediaService.computeSize(res.locals.organization.proposedVersion)
|
||||||
|
if (currentSize >= MediaService.getSizeLimit()) {
|
||||||
|
return res
|
||||||
|
.status(413)
|
||||||
|
.json({
|
||||||
|
success: false,
|
||||||
|
errors: [
|
||||||
|
{ code: 'quota-exeeded', message: 'We cannot accept this file because you already reached the maximum storage capacity for this organization' }
|
||||||
|
],
|
||||||
|
data: {
|
||||||
|
currentSize,
|
||||||
|
maxSize: MediaService.getSizeLimit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
static uploadThumbnail(): express.RequestHandler[] {
|
static uploadThumbnail(): express.RequestHandler[] {
|
||||||
return [
|
return [
|
||||||
|
DelegateController.verifySize,
|
||||||
MediaService.multer('thumbnail'),
|
MediaService.multer('thumbnail'),
|
||||||
(req: express.Request, res: express.Response) => {
|
(req: express.Request, res: express.Response) => {
|
||||||
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
||||||
|
@ -202,6 +242,7 @@ export default class DelegateController {
|
||||||
|
|
||||||
static uploadCover(): express.RequestHandler[] {
|
static uploadCover(): express.RequestHandler[] {
|
||||||
return [
|
return [
|
||||||
|
DelegateController.verifySize,
|
||||||
MediaService.multer('cover'),
|
MediaService.multer('cover'),
|
||||||
(req: express.Request, res: express.Response) => {
|
(req: express.Request, res: express.Response) => {
|
||||||
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
||||||
|
@ -226,6 +267,7 @@ export default class DelegateController {
|
||||||
|
|
||||||
static uploadMedias(): express.RequestHandler[] {
|
static uploadMedias(): express.RequestHandler[] {
|
||||||
return [
|
return [
|
||||||
|
DelegateController.verifySize,
|
||||||
MediaService.multer('media', true),
|
MediaService.multer('media', true),
|
||||||
(req: express.Request, res: express.Response) => {
|
(req: express.Request, res: express.Response) => {
|
||||||
let proposedVersion: any = res.locals.organization.proposedVersion
|
let proposedVersion: any = res.locals.organization.proposedVersion
|
||||||
|
|
|
@ -32,7 +32,7 @@ const email = {
|
||||||
lowercase: true,
|
lowercase: true,
|
||||||
unique: true,
|
unique: true,
|
||||||
validate: {
|
validate: {
|
||||||
validator: function(v) {
|
validator: function(v: string) {
|
||||||
return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v);
|
return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v);
|
||||||
},
|
},
|
||||||
message: "Invalid email"
|
message: "Invalid email"
|
||||||
|
|
Loading…
Reference in a new issue