Merge pull request #2140 from overleaf/as-decorate-archive-manager-errors

Decorate archive manager errors with OError

GitOrigin-RevId: 2795e5aaf172fd3b2b3a396b90b486b4ce5cfa4f
This commit is contained in:
Timothée Alby 2019-09-24 10:45:04 +02:00 committed by sharelatex
parent a23ecc9bf8
commit b43d26b543
5 changed files with 64 additions and 18 deletions

View file

@ -0,0 +1,34 @@
const OError = require('@overleaf/o-error')
class InvalidZipFileError extends OError {
constructor(options) {
super({
message: 'invalid_zip_file',
...options
})
}
}
class EmptyZipFileError extends InvalidZipFileError {
constructor(options) {
super({
message: 'empty_zip_file',
...options
})
}
}
class ZipContentsTooLargeError extends InvalidZipFileError {
constructor(options) {
super({
message: 'zip_contents_too_large',
...options
})
}
}
module.exports = {
InvalidZipFileError,
EmptyZipFileError,
ZipContentsTooLargeError
}

View file

@ -20,7 +20,11 @@ const Path = require('path')
const fse = require('fs-extra')
const yauzl = require('yauzl')
const Settings = require('settings-sharelatex')
const Errors = require('../Errors/Errors')
const {
InvalidZipFileError,
EmptyZipFileError,
ZipContentsTooLargeError
} = require('./ArchiveErrors')
const _ = require('underscore')
const ONE_MEG = 1024 * 1024
@ -35,7 +39,7 @@ const ArchiveManager = {
let totalSizeInBytes = null
return yauzl.open(source, { lazyEntries: true }, function(err, zipfile) {
if (err != null) {
return callback(new Errors.InvalidError('invalid_zip_file'))
return callback(new InvalidZipFileError().withCause(err))
}
if (
@ -61,7 +65,9 @@ const ArchiveManager = {
{ source, totalSizeInBytes },
'error getting bytes of zip'
)
return callback(new Errors.InvalidError('invalid_zip_file'))
return callback(
new InvalidZipFileError({ info: { totalSizeInBytes } })
)
}
const isTooLarge = totalSizeInBytes > ONE_MEG * 300
return callback(null, isTooLarge)
@ -186,7 +192,7 @@ const ArchiveManager = {
if (entryFileCount > 0) {
callback()
} else {
callback(new Errors.InvalidError('empty_zip_file'))
callback(new EmptyZipFileError())
}
})
})
@ -208,7 +214,7 @@ const ArchiveManager = {
}
if (isTooLarge) {
return callback(new Errors.InvalidError('zip_contents_too_large'))
return callback(new ZipContentsTooLargeError())
}
const timer = new metrics.Timer('unzipDirectory')

View file

@ -20,7 +20,7 @@ const FileSystemImportManager = require('./FileSystemImportManager')
const ProjectUploadManager = require('./ProjectUploadManager')
const AuthenticationController = require('../Authentication/AuthenticationController')
const Settings = require('settings-sharelatex')
const Errors = require('../Errors/Errors')
const { InvalidZipFileError } = require('./ArchiveErrors')
const multer = require('multer')
let upload = null
@ -62,7 +62,7 @@ module.exports = ProjectUploadController = {
{ err: error, file_path: path, file_name: name },
'error uploading project'
)
if (error.name != null && error.name === 'InvalidError') {
if (error instanceof InvalidZipFileError) {
return res.status(422).json({
success: false,
error: req.i18n.translate(error.message)

View file

@ -17,7 +17,11 @@ const { expect } = require('chai')
const chai = require('chai')
const should = chai.should()
const modulePath = '../../../../app/src/Features/Uploads/ArchiveManager.js'
const Errors = require('../../../../app/src/Features/Errors/Errors')
const {
InvalidZipFileError,
EmptyZipFileError,
ZipContentsTooLargeError
} = require('../../../../app/src/Features/Uploads/ArchiveErrors')
const SandboxedModule = require('sandboxed-module')
const events = require('events')
@ -136,7 +140,7 @@ describe('ArchiveManager', function() {
it('should return the callback with an error', function() {
return sinon.assert.calledWithExactly(
this.callback,
new Errors.InvalidError('empty_zip_file')
new EmptyZipFileError()
)
})
})
@ -157,7 +161,7 @@ describe('ArchiveManager', function() {
it('should return the callback with an error', function() {
return sinon.assert.calledWithExactly(
this.callback,
new Errors.InvalidError('empty_zip_file')
new EmptyZipFileError()
)
})
})
@ -166,7 +170,7 @@ describe('ArchiveManager', function() {
beforeEach(function(done) {
this.yauzl.open = sinon
.stub()
.callsArgWith(2, new Errors.InvalidError('invalid_zip_file'))
.callsArgWith(2, new InvalidZipFileError())
return this.ArchiveManager.extractZipArchive(
this.source,
this.destination,
@ -180,7 +184,7 @@ describe('ArchiveManager', function() {
it('should return the callback with an error', function() {
return sinon.assert.calledWithExactly(
this.callback,
new Errors.InvalidError('invalid_zip_file')
new InvalidZipFileError()
)
})
@ -207,7 +211,7 @@ describe('ArchiveManager', function() {
it('should return the callback with an error', function() {
return sinon.assert.calledWithExactly(
this.callback,
new Errors.InvalidError('zip_contents_too_large')
new ZipContentsTooLargeError()
)
})

View file

@ -20,7 +20,7 @@ const modulePath =
const SandboxedModule = require('sandboxed-module')
const MockRequest = require('../helpers/MockRequest')
const MockResponse = require('../helpers/MockResponse')
const Errors = require('../../../../app/src/Features/Errors/Errors')
const ArchiveErrors = require('../../../../app/src/Features/Uploads/ArchiveErrors')
describe('ProjectUploadController', function() {
beforeEach(function() {
@ -58,6 +58,7 @@ describe('ProjectUploadController', function() {
'metrics-sharelatex': this.metrics,
'../Authentication/AuthenticationController': this
.AuthenticationController,
'./ArchiveErrors': ArchiveErrors,
fs: (this.fs = {})
}
}))
@ -156,16 +157,17 @@ describe('ProjectUploadController', function() {
.stub()
.callsArgWith(
3,
new Errors.InvalidError('zip_contents_too_large'),
new ArchiveErrors.ZipContentsTooLargeError(),
this.project
)
return this.ProjectUploadController.uploadProject(this.req, this.res)
})
it('should return the reported error to the FileUploader client', function() {
return expect(this.res.body).to.deep.equal(
JSON.stringify({ success: false, error: 'zip_contents_too_large' })
)
expect(JSON.parse(this.res.body)).to.deep.equal({
success: false,
error: 'zip_contents_too_large'
})
})
it("should return an 'unprocessable entity' status code", function() {