Skip to content

Commit b23e56b

Browse files
#175 - Allow users to delete their own submission
1 parent 267ff96 commit b23e56b

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

src/controllers/SubmissionController.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ function * patchSubmission (req, res) {
9494
* @param res the http response
9595
*/
9696
function * deleteSubmission (req, res) {
97-
yield SubmissionService.deleteSubmission(req.params.submissionId, req.span)
97+
yield SubmissionService.deleteSubmission(req.authUser, req.params.submissionId, req.span)
9898

9999
logResultOnSpan(req.span, httpStatus.NO_CONTENT)
100100

src/routes/SubmissionRoutes.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ module.exports = {
4545
controller: 'SubmissionController',
4646
method: 'deleteSubmission',
4747
auth: 'jwt',
48-
access: ['Administrator'],
48+
access: ['Administrator', 'Topcoder User', 'Copilot'],
4949
scopes: ['delete:submission', 'all:submission']
5050
}
5151
},

src/services/SubmissionService.js

+48-4
Original file line numberDiff line numberDiff line change
@@ -589,17 +589,60 @@ patchSubmission.schema = {
589589
* @param {Object} span the Span object
590590
* @return {Promise}
591591
*/
592-
function * deleteSubmission (submissionId, span) {
592+
function * deleteSubmission (authUser, submissionId, span) {
593593
const deleteSubmissionSpan = tracer.startChildSpans('SubmissionService.deleteSubmission', span)
594594
deleteSubmissionSpan.setTag('submissionId', submissionId)
595595

596596
try {
597-
const exist = yield _getSubmission(submissionId, deleteSubmissionSpan)
598-
if (!exist) {
597+
const submissionRecord = yield _getSubmission(submissionId, deleteSubmissionSpan)
598+
if (!submissionRecord) {
599599
throw new errors.HttpStatusError(404, `Submission with ID = ${submissionId} is not found`)
600600
}
601601

602-
// Filter used to delete the record
602+
if (_.intersection(authUser.roles, ['Administrator', 'administrator']).length === 0 && !authUser.scopes) {
603+
// If not administrator, verify that the submission is owned by the user
604+
if (submissionRecord.memberId !== authUser.userId) {
605+
throw new errors.HttpStatusError(403, 'You cannot access other member\'s submission')
606+
}
607+
608+
// Now verify that the Submission phase for the challenge is still active
609+
// If not, non admin user cannot delete the submission
610+
const activeSubmissionPhaseId = yield helper.getSubmissionPhaseId(submissionRecord.challengeId, deleteSubmissionSpan)
611+
612+
if (!activeSubmissionPhaseId) {
613+
throw new errors.HttpStatusError(403, 'You cannot delete the submission because submission phase is not active')
614+
}
615+
}
616+
617+
// All checks passed - proceed to delete
618+
// First, delete reviews and review summations for the submission
619+
if (submissionRecord.review) {
620+
const reviewService = require('./ReviewService')
621+
for (let i = 0; i < submissionRecord.review.length; i++) {
622+
const review = submissionRecord.review[i]
623+
yield reviewService.deleteReview(review.id, deleteSubmissionSpan)
624+
}
625+
}
626+
627+
if (submissionRecord.reviewSummation) {
628+
const reviewSummationService = require('./ReviewSummationService')
629+
for (let i = 0; i < submissionRecord.reviewSummation.length; i++) {
630+
const reviewSummation = submissionRecord.reviewSummation[i]
631+
yield reviewSummationService.deleteReviewSummation(reviewSummation.id, deleteSubmissionSpan)
632+
}
633+
}
634+
635+
// Importing at the beginning of this service causes a circular dependency. Hence, dynamically invoking it
636+
const artifactService = require('./ArtifactService')
637+
638+
// Next delete the artifacts for the submission
639+
const submissionArtifacts = yield artifactService.listArtifacts(submissionRecord.id, deleteSubmissionSpan)
640+
641+
for (let i = 0; i < submissionArtifacts.artifacts.length; i++) {
642+
yield artifactService.deleteArtifact(submissionRecord.id, submissionArtifacts.artifacts[i], deleteSubmissionSpan)
643+
}
644+
645+
// Finally delete the submission itself
603646
const filter = {
604647
TableName: table,
605648
Key: {
@@ -630,6 +673,7 @@ function * deleteSubmission (submissionId, span) {
630673
}
631674

632675
deleteSubmission.schema = {
676+
authUser: joi.object().required(),
633677
submissionId: joi.string().guid().required()
634678
}
635679

test/unit/SubmissionService.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,10 @@ describe('Submission Service tests', () => {
519519
})
520520
})
521521

522-
it('Deleting submission with user token should throw 403', (done) => {
522+
it('Deleting submission with copilot token should throw 403', (done) => {
523523
chai.request(app)
524524
.delete(`${config.API_VERSION}/submissions/${testSubmission.Item.id}`)
525-
.set('Authorization', `Bearer ${config.USER_TOKEN}`)
525+
.set('Authorization', `Bearer ${config.COPILOT_TOKEN}`)
526526
.end((err, res) => {
527527
res.should.have.status(403)
528528
res.body.message.should.be.eql('You are not allowed to perform this action!')

0 commit comments

Comments
 (0)