mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #2152 from overleaf/as-per-user-trash-backend
Add per-user trash endpoint GitOrigin-RevId: 94a6e3416b047e1f8721159ac0d049e98785e5ce
This commit is contained in:
parent
9a31361795
commit
9cd5af840a
4 changed files with 134 additions and 29 deletions
|
@ -54,6 +54,7 @@ const Features = require('../../infrastructure/Features')
|
|||
const BrandVariationsHandler = require('../BrandVariations/BrandVariationsHandler')
|
||||
const { getUserAffiliations } = require('../Institutions/InstitutionsAPI')
|
||||
const V1Handler = require('../V1/V1Handler')
|
||||
const { Project } = require('../../models/Project')
|
||||
|
||||
module.exports = ProjectController = {
|
||||
_isInPercentageRollout(rolloutName, objectId, percentage) {
|
||||
|
@ -199,6 +200,38 @@ module.exports = ProjectController = {
|
|||
})
|
||||
},
|
||||
|
||||
trashProject(req, res, next) {
|
||||
const projectId = req.params.project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
Project.update(
|
||||
{ _id: projectId },
|
||||
{ $addToSet: { trashed: userId } },
|
||||
error => {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
res.sendStatus(200)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
untrashProject(req, res, next) {
|
||||
const projectId = req.params.project_id
|
||||
const userId = AuthenticationController.getLoggedInUserId(req)
|
||||
|
||||
Project.update(
|
||||
{ _id: projectId },
|
||||
{ $pull: { trashed: userId } },
|
||||
error => {
|
||||
if (error) {
|
||||
return next(error)
|
||||
}
|
||||
res.sendStatus(200)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
cloneProject(req, res, next) {
|
||||
res.setTimeout(5 * 60 * 1000) // allow extra time for the copy to complete
|
||||
metrics.inc('cloned-project')
|
||||
|
|
|
@ -443,6 +443,18 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
|||
CompileController.wordCount
|
||||
)
|
||||
|
||||
webRouter.post(
|
||||
'/project/:project_id/trash',
|
||||
AuthorizationMiddleware.ensureUserCanReadProject,
|
||||
ProjectController.trashProject
|
||||
)
|
||||
|
||||
webRouter.delete(
|
||||
'/project/:project_id/trash',
|
||||
AuthorizationMiddleware.ensureUserCanReadProject,
|
||||
ProjectController.untrashProject
|
||||
)
|
||||
|
||||
webRouter.delete(
|
||||
'/Project/:Project_id',
|
||||
AuthorizationMiddleware.ensureUserCanAdminProject,
|
||||
|
|
|
@ -1,43 +1,102 @@
|
|||
/* eslint-disable
|
||||
handle-callback-err,
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const { expect } = require('chai')
|
||||
const async = require('async')
|
||||
const User = require('./helpers/User')
|
||||
const User = require('./helpers/User').promises
|
||||
const { Project } = require('../../../app/src/models/Project')
|
||||
|
||||
describe('Project CRUD', function() {
|
||||
beforeEach(function(done) {
|
||||
beforeEach(async function() {
|
||||
this.user = new User()
|
||||
return this.user.login(done)
|
||||
await this.user.login()
|
||||
|
||||
this.projectId = await this.user.createProject('example-project')
|
||||
})
|
||||
|
||||
afterEach(async function() {
|
||||
// TODO: This can be removed after migrations are merged
|
||||
await Project.deleteMany({}).exec()
|
||||
})
|
||||
|
||||
describe("when project doesn't exist", function() {
|
||||
it('should return 404', function(done) {
|
||||
return this.user.request.get(
|
||||
'/project/aaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
(err, res, body) => {
|
||||
expect(res.statusCode).to.equal(404)
|
||||
return done()
|
||||
}
|
||||
it('should return 404', async function() {
|
||||
const { response } = await this.user.doRequest(
|
||||
'GET',
|
||||
'/project/aaaaaaaaaaaaaaaaaaaaaaaa'
|
||||
)
|
||||
expect(response.statusCode).to.equal(404)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when project has malformed id', function() {
|
||||
it('should return 404', function(done) {
|
||||
return this.user.request.get('/project/blah', (err, res, body) => {
|
||||
expect(res.statusCode).to.equal(404)
|
||||
return done()
|
||||
})
|
||||
it('should return 404', async function() {
|
||||
const { response } = await this.user.doRequest('GET', '/project/blah')
|
||||
expect(response.statusCode).to.equal(404)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when trashing a project', function() {
|
||||
it('should mark the project as trashed for the user', async function() {
|
||||
const { response } = await this.user.doRequest(
|
||||
'POST',
|
||||
`/project/${this.projectId}/trash`
|
||||
)
|
||||
expect(response.statusCode).to.equal(200)
|
||||
|
||||
const trashedProject = await Project.findById(this.projectId).exec()
|
||||
expectObjectIdArrayEqual(trashedProject.trashed, [this.user._id])
|
||||
})
|
||||
|
||||
it('does nothing if the user has already trashed the project', async function() {
|
||||
// Mark as trashed the first time
|
||||
await this.user.doRequest('POST', `/project/${this.projectId}/trash`)
|
||||
|
||||
// And then a second time
|
||||
await this.user.doRequest('POST', `/project/${this.projectId}/trash`)
|
||||
|
||||
const trashedProject = await Project.findById(this.projectId).exec()
|
||||
expectObjectIdArrayEqual(trashedProject.trashed, [this.user._id])
|
||||
})
|
||||
})
|
||||
|
||||
describe('when untrashing a project', function() {
|
||||
it('should mark the project as untrashed for the user', async function() {
|
||||
await Project.update(
|
||||
{ _id: this.projectId },
|
||||
{ trashed: [this.user._id] }
|
||||
)
|
||||
const { response } = await this.user.doRequest(
|
||||
'DELETE',
|
||||
`/project/${this.projectId}/trash`
|
||||
)
|
||||
expect(response.statusCode).to.equal(200)
|
||||
|
||||
const trashedProject = await Project.findById(this.projectId).exec()
|
||||
expectObjectIdArrayEqual(trashedProject.trashed, [])
|
||||
})
|
||||
|
||||
it('does nothing if the user has already untrashed the project', async function() {
|
||||
await Project.update(
|
||||
{ _id: this.projectId },
|
||||
{ trashed: [this.user._id] }
|
||||
)
|
||||
// Mark as untrashed the first time
|
||||
await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
|
||||
|
||||
// And then a second time
|
||||
await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
|
||||
|
||||
const trashedProject = await Project.findById(this.projectId).exec()
|
||||
expectObjectIdArrayEqual(trashedProject.trashed, [])
|
||||
})
|
||||
|
||||
it('sets trashed to an empty array if not set', async function() {
|
||||
await this.user.doRequest('DELETE', `/project/${this.projectId}/trash`)
|
||||
|
||||
const trashedProject = await Project.findById(this.projectId).exec()
|
||||
expectObjectIdArrayEqual(trashedProject.trashed, [])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function expectObjectIdArrayEqual(objectIdArray, stringArray) {
|
||||
const stringifiedArray = objectIdArray.map(id => id.toString())
|
||||
expect(stringifiedArray).to.deep.equal(stringArray)
|
||||
}
|
||||
|
|
|
@ -171,7 +171,8 @@ describe('ProjectController', function() {
|
|||
'../Institutions/InstitutionsAPI': {
|
||||
getUserAffiliations: this.getUserAffiliations
|
||||
},
|
||||
'../V1/V1Handler': {}
|
||||
'../V1/V1Handler': {},
|
||||
'../../models/Project': {}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue