mirror of
https://github.com/overleaf/overleaf.git
synced 2025-03-19 01:22:55 +00:00
Merge pull request #3746 from overleaf/jpa-hard-deletion-from-deleted-files
[ProjectDeleter] hard deletion of project deletes deletedFiles entries GitOrigin-RevId: b514c34465d5fdc66b40aae5bcdb8b66975bc350
This commit is contained in:
parent
9c38d41652
commit
23be656aec
3 changed files with 100 additions and 1 deletions
|
@ -354,7 +354,8 @@ async function expireDeletedProject(projectId) {
|
|||
deletedProject.project._id,
|
||||
historyId
|
||||
),
|
||||
FilestoreHandler.promises.deleteProject(deletedProject.project._id)
|
||||
FilestoreHandler.promises.deleteProject(deletedProject.project._id),
|
||||
hardDeleteDeletedFiles(deletedProject.project._id)
|
||||
])
|
||||
|
||||
await DeletedProject.updateOne(
|
||||
|
@ -383,3 +384,22 @@ function filterDuplicateDeletedFilesInPlace(project) {
|
|||
return true
|
||||
})
|
||||
}
|
||||
|
||||
let deletedFilesProjectIdIndexExist
|
||||
async function doesDeletedFilesProjectIdIndexExist() {
|
||||
if (typeof deletedFilesProjectIdIndexExist !== 'boolean') {
|
||||
// Resolve this about once. No need for locking or retry handling.
|
||||
deletedFilesProjectIdIndexExist = await db.deletedFiles.indexExists(
|
||||
'projectId_1'
|
||||
)
|
||||
}
|
||||
return deletedFilesProjectIdIndexExist
|
||||
}
|
||||
|
||||
async function hardDeleteDeletedFiles(projectId) {
|
||||
if (!(await doesDeletedFilesProjectIdIndexExist())) {
|
||||
// Running the deletion command w/o index would kill mongo performance
|
||||
return
|
||||
}
|
||||
return db.deletedFiles.deleteMany({ projectId })
|
||||
}
|
||||
|
|
|
@ -239,6 +239,81 @@ describe('Deleting a project', function() {
|
|||
})
|
||||
})
|
||||
|
||||
describe('when the project has deleted files', function() {
|
||||
beforeEach('get rootFolder id', function(done) {
|
||||
this.user.getProject(this.projectId, (error, project) => {
|
||||
if (error) return done(error)
|
||||
this.rootFolder = project.rootFolder[0]._id
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
let allFileIds
|
||||
beforeEach('reset allFileIds', function() {
|
||||
allFileIds = []
|
||||
})
|
||||
function createAndDeleteFile(name) {
|
||||
let fileId
|
||||
beforeEach(`create file ${name}`, function(done) {
|
||||
this.user.uploadExampleFileInProject(
|
||||
this.projectId,
|
||||
this.rootFolder,
|
||||
name,
|
||||
(error, theFileId) => {
|
||||
fileId = theFileId
|
||||
allFileIds.push(theFileId)
|
||||
done(error)
|
||||
}
|
||||
)
|
||||
})
|
||||
beforeEach(`delete file ${name}`, function(done) {
|
||||
this.user.deleteItemInProject(this.projectId, 'file', fileId, done)
|
||||
})
|
||||
}
|
||||
for (const name of ['a.png', 'another.png']) {
|
||||
createAndDeleteFile(name)
|
||||
}
|
||||
|
||||
it('should have two deleteFiles entries', async function() {
|
||||
const files = await db.deletedFiles
|
||||
.find({}, { sort: { _id: 1 } })
|
||||
.toArray()
|
||||
expect(files).to.have.length(2)
|
||||
expect(files.map(file => file._id.toString())).to.deep.equal(allFileIds)
|
||||
})
|
||||
|
||||
describe('When the deleted project is expired', function() {
|
||||
beforeEach('soft delete the project', function(done) {
|
||||
this.user.deleteProject(this.projectId, done)
|
||||
})
|
||||
beforeEach('hard delete the project', function(done) {
|
||||
request.post(
|
||||
`/internal/project/${this.projectId}/expire-deleted-project`,
|
||||
{
|
||||
auth: {
|
||||
user: settings.apis.web.user,
|
||||
pass: settings.apis.web.pass,
|
||||
sendImmediately: true
|
||||
}
|
||||
},
|
||||
(error, res) => {
|
||||
expect(error).not.to.exist
|
||||
expect(res.statusCode).to.equal(200)
|
||||
|
||||
done()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('should cleanup the deleteFiles', async function() {
|
||||
const files = await db.deletedFiles
|
||||
.find({}, { sort: { _id: 1 } })
|
||||
.toArray()
|
||||
expect(files).to.deep.equal([])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('When the project has docs', function() {
|
||||
beforeEach(function(done) {
|
||||
this.user.getProject(this.projectId, (error, project) => {
|
||||
|
|
|
@ -103,6 +103,10 @@ describe('ProjectDeleter', function() {
|
|||
}
|
||||
|
||||
this.db = {
|
||||
deletedFiles: {
|
||||
indexExists: sinon.stub().resolves(false),
|
||||
deleteMany: sinon.stub()
|
||||
},
|
||||
projects: {
|
||||
insertOne: sinon.stub().resolves()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue