mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add endpoint to delete a project
Needs acceptance tests
This commit is contained in:
parent
fc80aa3954
commit
47e96a4d94
6 changed files with 82 additions and 0 deletions
|
@ -61,6 +61,11 @@ app.delete(
|
||||||
keyBuilder.userFileKeyMiddleware,
|
keyBuilder.userFileKeyMiddleware,
|
||||||
fileController.deleteFile
|
fileController.deleteFile
|
||||||
)
|
)
|
||||||
|
app.delete(
|
||||||
|
'/project/:project_id',
|
||||||
|
keyBuilder.userProjectKeyMiddleware,
|
||||||
|
fileController.deleteProject
|
||||||
|
)
|
||||||
|
|
||||||
app.head(
|
app.head(
|
||||||
'/template/:template_id/v/:version/:format',
|
'/template/:template_id/v/:version/:format',
|
||||||
|
|
|
@ -13,6 +13,7 @@ module.exports = {
|
||||||
insertFile,
|
insertFile,
|
||||||
copyFile,
|
copyFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
|
deleteProject,
|
||||||
directorySize
|
directorySize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +159,22 @@ function deleteFile(req, res, next) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteProject(req, res, next) {
|
||||||
|
metrics.inc('deleteProject')
|
||||||
|
const { project_id: projectId, bucket } = req
|
||||||
|
|
||||||
|
req.requestLogger.setMessage('getting project size')
|
||||||
|
req.requestLogger.addFields({ projectId, bucket })
|
||||||
|
|
||||||
|
FileHandler.deleteProject(bucket, projectId, function(err) {
|
||||||
|
if (err) {
|
||||||
|
next(err)
|
||||||
|
} else {
|
||||||
|
res.sendStatus(204)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function directorySize(req, res, next) {
|
function directorySize(req, res, next) {
|
||||||
metrics.inc('projectSize')
|
metrics.inc('projectSize')
|
||||||
const { project_id: projectId, bucket } = req
|
const { project_id: projectId, bucket } = req
|
||||||
|
|
|
@ -10,6 +10,7 @@ const { ConversionError, WriteError } = require('./Errors')
|
||||||
module.exports = {
|
module.exports = {
|
||||||
insertFile: callbackify(insertFile),
|
insertFile: callbackify(insertFile),
|
||||||
deleteFile: callbackify(deleteFile),
|
deleteFile: callbackify(deleteFile),
|
||||||
|
deleteProject: callbackify(deleteProject),
|
||||||
getFile: callbackify(getFile),
|
getFile: callbackify(getFile),
|
||||||
getFileSize: callbackify(getFileSize),
|
getFileSize: callbackify(getFileSize),
|
||||||
getDirectorySize: callbackify(getDirectorySize),
|
getDirectorySize: callbackify(getDirectorySize),
|
||||||
|
@ -17,6 +18,7 @@ module.exports = {
|
||||||
getFile,
|
getFile,
|
||||||
insertFile,
|
insertFile,
|
||||||
deleteFile,
|
deleteFile,
|
||||||
|
deleteProject,
|
||||||
getFileSize,
|
getFileSize,
|
||||||
getDirectorySize
|
getDirectorySize
|
||||||
}
|
}
|
||||||
|
@ -48,6 +50,16 @@ async function deleteFile(bucket, key) {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteProject(bucket, key) {
|
||||||
|
if (!key.match(/^[0-9a-f]{24}\//i)) {
|
||||||
|
throw new WriteError({
|
||||||
|
message: 'key does not match validation regex',
|
||||||
|
info: { bucket, key }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await PersistorManager.promises.deleteDirectory(bucket, key)
|
||||||
|
}
|
||||||
|
|
||||||
async function getFile(bucket, key, opts) {
|
async function getFile(bucket, key, opts) {
|
||||||
opts = opts || {}
|
opts = opts || {}
|
||||||
if (!opts.format && !opts.style) {
|
if (!opts.format && !opts.style) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ module.exports = {
|
||||||
getConvertedFolderKey,
|
getConvertedFolderKey,
|
||||||
addCachingToKey,
|
addCachingToKey,
|
||||||
userFileKeyMiddleware,
|
userFileKeyMiddleware,
|
||||||
|
userProjectKeyMiddleware,
|
||||||
publicFileKeyMiddleware,
|
publicFileKeyMiddleware,
|
||||||
publicProjectKeyMiddleware,
|
publicProjectKeyMiddleware,
|
||||||
bucketFileKeyMiddleware,
|
bucketFileKeyMiddleware,
|
||||||
|
@ -37,6 +38,13 @@ function userFileKeyMiddleware(req, res, next) {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function userProjectKeyMiddleware(req, res, next) {
|
||||||
|
const { project_id: projectId } = req.params
|
||||||
|
req.key = `${projectId}/`
|
||||||
|
req.bucket = settings.filestore.stores.user_files
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
function publicFileKeyMiddleware(req, res, next) {
|
function publicFileKeyMiddleware(req, res, next) {
|
||||||
if (settings.filestore.stores.public_files == null) {
|
if (settings.filestore.stores.public_files == null) {
|
||||||
return res.status(501).send('public files not available')
|
return res.status(501).send('public files not available')
|
||||||
|
|
|
@ -40,6 +40,7 @@ describe('FileController', function() {
|
||||||
getFile: sinon.stub().yields(null, fileStream),
|
getFile: sinon.stub().yields(null, fileStream),
|
||||||
getFileSize: sinon.stub().yields(null, fileSize),
|
getFileSize: sinon.stub().yields(null, fileSize),
|
||||||
deleteFile: sinon.stub().yields(),
|
deleteFile: sinon.stub().yields(),
|
||||||
|
deleteProject: sinon.stub().yields(),
|
||||||
insertFile: sinon.stub().yields(),
|
insertFile: sinon.stub().yields(),
|
||||||
getDirectorySize: sinon.stub().yields(null, fileSize)
|
getDirectorySize: sinon.stub().yields(null, fileSize)
|
||||||
}
|
}
|
||||||
|
@ -67,6 +68,7 @@ describe('FileController', function() {
|
||||||
req = {
|
req = {
|
||||||
key: key,
|
key: key,
|
||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
|
project_id: projectId,
|
||||||
query: {},
|
query: {},
|
||||||
params: {
|
params: {
|
||||||
project_id: projectId,
|
project_id: projectId,
|
||||||
|
@ -257,6 +259,23 @@ describe('FileController', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('delete project', function() {
|
||||||
|
it('should tell the file handler', function(done) {
|
||||||
|
res.sendStatus = code => {
|
||||||
|
code.should.equal(204)
|
||||||
|
expect(FileHandler.deleteProject).to.have.been.calledWith(bucket, projectId)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
FileController.deleteProject(req, res, next)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should send a 500 if there was an error', function() {
|
||||||
|
FileHandler.deleteProject.yields(error)
|
||||||
|
FileController.deleteProject(req, res, next)
|
||||||
|
expect(next).to.have.been.calledWith(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('directorySize', function() {
|
describe('directorySize', function() {
|
||||||
it('should return total directory size bytes', function(done) {
|
it('should return total directory size bytes', function(done) {
|
||||||
FileController.directorySize(req, {
|
FileController.directorySize(req, {
|
||||||
|
|
|
@ -27,6 +27,7 @@ describe('FileHandler', function() {
|
||||||
const bucket = 'my_bucket'
|
const bucket = 'my_bucket'
|
||||||
const key = `${ObjectId()}/${ObjectId()}`
|
const key = `${ObjectId()}/${ObjectId()}`
|
||||||
const convertedFolderKey = `${ObjectId()}/${ObjectId()}`
|
const convertedFolderKey = `${ObjectId()}/${ObjectId()}`
|
||||||
|
const projectKey = `${ObjectId()}/`
|
||||||
const sourceStream = 'sourceStream'
|
const sourceStream = 'sourceStream'
|
||||||
const convertedKey = 'convertedKey'
|
const convertedKey = 'convertedKey'
|
||||||
const readStream = {
|
const readStream = {
|
||||||
|
@ -154,6 +155,26 @@ describe('FileHandler', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('deleteProject', function() {
|
||||||
|
it('should tell the filestore manager to delete the folder', function(done) {
|
||||||
|
FileHandler.deleteProject(bucket, projectKey, err => {
|
||||||
|
expect(err).not.to.exist
|
||||||
|
expect(PersistorManager.promises.deleteDirectory).to.have.been.calledWith(
|
||||||
|
bucket,
|
||||||
|
projectKey
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw an error when the key is in the wrong format', function(done) {
|
||||||
|
FileHandler.deleteProject(bucket, 'wombat', err => {
|
||||||
|
expect(err).to.exist
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('getFile', function() {
|
describe('getFile', function() {
|
||||||
it('should return the source stream no format or style are defined', function(done) {
|
it('should return the source stream no format or style are defined', function(done) {
|
||||||
FileHandler.getFile(bucket, key, null, (err, stream) => {
|
FileHandler.getFile(bucket, key, null, (err, stream) => {
|
||||||
|
|
Loading…
Reference in a new issue