Skip to content

Commit 4516d22

Browse files
committed
Allow for admin deletion of challenge tracks and types
#519
1 parent 2e2db18 commit 4516d22

File tree

9 files changed

+243
-4
lines changed

9 files changed

+243
-4
lines changed

app-constants.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ const Topics = {
6464
ChallengeDeleted: 'challenge.notification.delete',
6565
ChallengeTypeCreated: 'test.new.bus.events', // 'challenge.action.type.created',
6666
ChallengeTypeUpdated: 'test.new.bus.events', // 'challenge.action.type.updated',
67+
ChallengeTypeDeleted: 'test.new.bus.events', // 'challenge.action.type.deleted',
68+
ChallengeTrackCreated: 'test.new.bus.events', // 'challenge.action.track.created',
69+
ChallengeTrackUpdated: 'test.new.bus.events', // 'challenge.action.track.updated',
70+
ChallengeTrackDeleted: 'test.new.bus.events', // 'challenge.action.track.deleted',
6771
ChallengePhaseCreated: 'test.new.bus.events', // 'challenge.action.phase.created',
6872
ChallengePhaseUpdated: 'test.new.bus.events', // 'challenge.action.phase.updated',
6973
ChallengePhaseDeleted: 'test.new.bus.events', // 'challenge.action.phase.deleted',

docs/swagger.yaml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,46 @@ paths:
908908
description: Internal Server error
909909
schema:
910910
$ref: "#/definitions/ErrorModel"
911+
delete:
912+
tags:
913+
- ChallengeTypes
914+
description: Delete the challenge type with specified id.
915+
security:
916+
- bearer: []
917+
produces:
918+
- application/json
919+
parameters:
920+
- name: challengeTypeId
921+
in: path
922+
required: true
923+
type: string
924+
format: UUID
925+
description: The id of challengeType to be deleted
926+
responses:
927+
"200":
928+
description: Deleted - The request was successful and the resource is returned.
929+
schema:
930+
$ref: "#/definitions/ChallengeType"
931+
"400":
932+
description: Bad request. Request parameters were invalid.
933+
schema:
934+
$ref: "#/definitions/ErrorModel"
935+
"401":
936+
description: Unauthorized. Fail to authenticate the requester.
937+
schema:
938+
$ref: "#/definitions/ErrorModel"
939+
"403":
940+
description: Forbidden. The requester does not have the correct permission to delete the challenge type.
941+
schema:
942+
$ref: "#/definitions/ErrorModel"
943+
"404":
944+
description: Not Found. Challenge type not found
945+
schema:
946+
$ref: "#/definitions/ErrorModel"
947+
"500":
948+
description: Internal Server Error
949+
schema:
950+
$ref: "#/definitions/ErrorModel"
911951
/challenge-tracks:
912952
get:
913953
tags:
@@ -1143,6 +1183,46 @@ paths:
11431183
description: Internal Server Error
11441184
schema:
11451185
$ref: "#/definitions/ErrorModel"
1186+
delete:
1187+
tags:
1188+
- ChallengeTracks
1189+
description: Delete the challenge track with specified id.
1190+
security:
1191+
- bearer: []
1192+
produces:
1193+
- application/json
1194+
parameters:
1195+
- name: challengeTrackId
1196+
in: path
1197+
required: true
1198+
type: string
1199+
format: UUID
1200+
description: The id of challengeTrack to be deleted.
1201+
responses:
1202+
"200":
1203+
description: Deleted - The request was successful and the resource is returned.
1204+
schema:
1205+
$ref: "#/definitions/ChallengeTrack"
1206+
"400":
1207+
description: Bad request. Request parameters were invalid.
1208+
schema:
1209+
$ref: "#/definitions/ErrorModel"
1210+
"401":
1211+
description: Unauthorized. Fail to authenticate the requester.
1212+
schema:
1213+
$ref: "#/definitions/ErrorModel"
1214+
"403":
1215+
description: Forbidden. The requester does not have the correct permission to delete the challenge track.
1216+
schema:
1217+
$ref: "#/definitions/ErrorModel"
1218+
"404":
1219+
description: Not Found. Challenge track not found
1220+
schema:
1221+
$ref: "#/definitions/ErrorModel"
1222+
"500":
1223+
description: Internal Server Error
1224+
schema:
1225+
$ref: "#/definitions/ErrorModel"
11461226
/challenge-phases:
11471227
get:
11481228
tags:

src/controllers/ChallengeTrackController.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,21 @@ async function partiallyUpdateChallengeTrack (req, res) {
5656
res.send(result)
5757
}
5858

59+
/**
60+
* Delete challenge track
61+
* @param {Object} req the request
62+
* @param {Object} res the response
63+
*/
64+
async function deleteChallengeTrack (req, res) {
65+
const result = await service.deleteChallengeTrack(req.params.challengeTrackId)
66+
res.send(result)
67+
}
68+
5969
module.exports = {
6070
searchChallengeTracks,
6171
createChallengeTrack,
6272
getChallengeTrack,
6373
fullyUpdateChallengeTrack,
64-
partiallyUpdateChallengeTrack
74+
partiallyUpdateChallengeTrack,
75+
deleteChallengeTrack
6576
}

src/controllers/ChallengeTypeController.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,21 @@ async function partiallyUpdateChallengeType (req, res) {
5656
res.send(result)
5757
}
5858

59+
/**
60+
* Delete challenge type
61+
* @param {Object} req the request
62+
* @param {Object} res the response
63+
*/
64+
async function deleteChallengeType (req, res) {
65+
const result = await service.deleteChallengeType(req.params.challengeTypeId)
66+
res.send(result)
67+
}
68+
5969
module.exports = {
6070
searchChallengeTypes,
6171
createChallengeType,
6272
getChallengeType,
6373
fullyUpdateChallengeType,
64-
partiallyUpdateChallengeType
74+
partiallyUpdateChallengeType,
75+
deleteChallengeType
6576
}

src/routes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ module.exports = {
113113
auth: 'jwt',
114114
access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager],
115115
scopes: [UPDATE, ALL]
116+
},
117+
delete: {
118+
controller: 'ChallengeTypeController',
119+
method: 'deleteChallengeType',
120+
auth: 'jwt',
121+
access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager],
122+
scopes: [DELETE, ALL]
116123
}
117124
},
118125
'/challenge-tracks': {
@@ -146,6 +153,13 @@ module.exports = {
146153
auth: 'jwt',
147154
access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager],
148155
scopes: [UPDATE, ALL]
156+
},
157+
delete: {
158+
controller: 'ChallengeTrackController',
159+
method: 'deleteChallengeTrack',
160+
auth: 'jwt',
161+
access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager],
162+
scopes: [DELETE, ALL]
149163
}
150164
},
151165
'/challenge-timelines': {

src/services/ChallengeTrackService.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,32 @@ partiallyUpdateChallengeTrack.schema = {
183183
}).required()
184184
}
185185

186+
/**
187+
* Delete challenge track.
188+
* @param {String} id the challenge track id
189+
* @return {Object} the deleted challenge track
190+
*/
191+
async function deleteChallengeTrack (id) {
192+
const span = await logger.startSpan('ChallengeTrackService.deleteChallengeTrack')
193+
const record = await helper.getById('ChallengeTrack', id)
194+
await record.delete()
195+
// post bus event
196+
await helper.postBusEvent(constants.Topics.ChallengeTrackDeleted, record)
197+
await logger.endSpan(span)
198+
return record
199+
}
200+
201+
deleteChallengeTrack.schema = {
202+
id: Joi.id()
203+
}
204+
186205
module.exports = {
187206
searchChallengeTracks,
188207
createChallengeTrack,
189208
getChallengeTrack,
190209
fullyUpdateChallengeTrack,
191-
partiallyUpdateChallengeTrack
210+
partiallyUpdateChallengeTrack,
211+
deleteChallengeTrack
192212
}
193213

194214
// logger.buildService(module.exports)

src/services/ChallengeTypeService.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,32 @@ partiallyUpdateChallengeType.schema = {
162162
}).required()
163163
}
164164

165+
/**
166+
* Delete challenge type.
167+
* @param {String} id the challenge type id
168+
* @returns {Object} the deleted challenge type
169+
*/
170+
async function deleteChallengeType (id) {
171+
const span = await logger.startSpan('ChallengeTypeService.deleteChallengeType')
172+
const ret = await helper.getById('ChallengeType', id)
173+
await ret.delete()
174+
// post bus event
175+
await helper.postBusEvent(constants.Topics.ChallengeTypeDeleted, ret)
176+
await logger.endSpan(span)
177+
return ret
178+
}
179+
180+
deleteChallengeType.schema = {
181+
id: Joi.id()
182+
}
183+
165184
module.exports = {
166185
searchChallengeTypes,
167186
createChallengeType,
168187
getChallengeType,
169188
fullyUpdateChallengeType,
170-
partiallyUpdateChallengeType
189+
partiallyUpdateChallengeType,
190+
deleteChallengeType
171191
}
172192

173193
// logger.buildService(module.exports)

test/e2e/challenge.type.api.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,4 +665,46 @@ describe('challenge type API E2E tests', () => {
665665
should.equal(response.body.message, '"legacyId" must be a number')
666666
})
667667
})
668+
669+
describe('remove challenge type API tests', () => {
670+
it('remove challenge type - forbidden', async () => {
671+
const response = await chai.request(app)
672+
.delete(`${basePath}/${id}`)
673+
.set('Authorization', `Bearer ${config.USER_TOKEN}`)
674+
should.equal(response.status, 403)
675+
should.equal(response.body.message, 'You are not allowed to perform this action!')
676+
})
677+
678+
it('remove challenge type successfully', async () => {
679+
const response = await chai.request(app)
680+
.delete(`${basePath}/${id}`)
681+
.set('Authorization', `Bearer ${config.ADMIN_TOKEN}`)
682+
should.equal(response.status, 200)
683+
should.equal(response.body.id, id)
684+
})
685+
686+
it('remove challenge type - not found 1', async () => {
687+
const response = await chai.request(app)
688+
.delete(`${basePath}/${id}`)
689+
.set('Authorization', `Bearer ${config.ADMIN_TOKEN}`)
690+
should.equal(response.status, 404)
691+
should.equal(response.body.message, `ChallengeType with id: ${id} doesn't exist`)
692+
})
693+
694+
it('remove challenge type - not found 2', async () => {
695+
const response = await chai.request(app)
696+
.delete(`${basePath}/${notFoundId}`)
697+
.set('Authorization', `Bearer ${config.ADMIN_TOKEN}`)
698+
should.equal(response.status, 404)
699+
should.equal(response.body.message, `ChallengeType with id: ${notFoundId} doesn't exist`)
700+
})
701+
702+
it('remove challenge type - invalid id', async () => {
703+
const response = await chai.request(app)
704+
.delete(`${basePath}/invalid`)
705+
.set('Authorization', `Bearer ${config.ADMIN_TOKEN}`)
706+
should.equal(response.status, 400)
707+
should.equal(response.body.message, '"challengeTypeId" must be a valid GUID')
708+
})
709+
})
668710
})

test/unit/ChallengeTypeService.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,4 +630,41 @@ describe('challenge type service unit tests', () => {
630630
throw new Error('should not reach here')
631631
})
632632
})
633+
634+
describe('remove challenge type tests', () => {
635+
it('remove challenge type successfully', async () => {
636+
const result = await service.deleteChallengeType(id2)
637+
should.equal(result.id, id2)
638+
})
639+
640+
it('remove challenge type - not found 1', async () => {
641+
try {
642+
await service.deleteChallengeType(notFoundId)
643+
} catch (e) {
644+
should.equal(e.message, `ChallengeType with id: ${notFoundId} doesn't exist`)
645+
return
646+
}
647+
throw new Error('should not reach here')
648+
})
649+
650+
it('remove challenge type - not found 2', async () => {
651+
try {
652+
await service.deleteChallengeType(id2)
653+
} catch (e) {
654+
should.equal(e.message, `ChallengeType with id: ${id2} doesn't exist`)
655+
return
656+
}
657+
throw new Error('should not reach here')
658+
})
659+
660+
it('remove challenge type - invalid id', async () => {
661+
try {
662+
await service.deleteChallengeType('invalid')
663+
} catch (e) {
664+
should.equal(e.message.indexOf('"challengeType" must be a valid GUID') >= 0, true)
665+
return
666+
}
667+
throw new Error('should not reach here')
668+
})
669+
})
633670
})

0 commit comments

Comments
 (0)