diff --git a/public/openapi/write.yaml b/public/openapi/write.yaml index 6207546cee..b1dabb778b 100644 --- a/public/openapi/write.yaml +++ b/public/openapi/write.yaml @@ -192,6 +192,8 @@ paths: $ref: 'write/flags.yaml' /flags/{flagId}: $ref: 'write/flags/flagId.yaml' + /flags/{flagId}/report: + $ref: 'write/flags/flagId/report.yaml' /flags/{flagId}/notes: $ref: 'write/flags/flagId/notes.yaml' /flags/{flagId}/notes/{datetime}: diff --git a/public/openapi/write/flags/flagId/report.yaml b/public/openapi/write/flags/flagId/report.yaml new file mode 100644 index 0000000000..61944a24df --- /dev/null +++ b/public/openapi/write/flags/flagId/report.yaml @@ -0,0 +1,26 @@ +delete: + tags: + - flags + summary: rescind a flag report + description: This operation rescinds the report made for a given flag. + parameters: + - in: path + name: flagId + schema: + type: number + required: true + description: a valid flag id + example: 2 + responses: + '200': + description: Flag report rescinded + content: + application/json: + schema: + type: object + properties: + status: + $ref: ../../../components/schemas/Status.yaml#/Status + response: + type: object + properties: {} \ No newline at end of file diff --git a/src/api/flags.js b/src/api/flags.js index e4a3ba04e4..ffa56e2782 100644 --- a/src/api/flags.js +++ b/src/api/flags.js @@ -49,6 +49,16 @@ flagsApi.update = async (caller, data) => { flagsApi.delete = async (_, { flagId }) => await flags.purge([flagId]); +flagsApi.rescind = async ({ uid }, { flagId }) => { + const { type, targetId } = await flags.get(flagId); + const exists = await flags.exists(type, targetId, uid); + if (!exists) { + throw new Error('[[error:no-flag]]'); + } + + await flags.rescindReport(type, targetId, uid); +}; + flagsApi.appendNote = async (caller, data) => { const allowed = await user.isPrivileged(caller.uid); if (!allowed) { diff --git a/src/controllers/write/flags.js b/src/controllers/write/flags.js index 1b5df01d2d..4e3ac376a7 100644 --- a/src/controllers/write/flags.js +++ b/src/controllers/write/flags.js @@ -32,6 +32,11 @@ Flags.delete = async (req, res) => { helpers.formatApiResponse(200, res); }; +Flags.rescind = async (req, res) => { + await api.flags.rescind(req, { flagId: req.params.flagId }); + helpers.formatApiResponse(200, res); +}; + Flags.appendNote = async (req, res) => { const { note, datetime } = req.body; const payload = await api.flags.appendNote(req, { diff --git a/src/flags.js b/src/flags.js index fbbf103e5a..7ec1c504c1 100644 --- a/src/flags.js +++ b/src/flags.js @@ -109,7 +109,7 @@ Flags.get = async function (flagId) { Flags.getReports(flagId), ]); if (!base) { - return; + throw new Error('[[error:no-flag]]'); } const flagObj = { state: 'open', diff --git a/src/routes/write/flags.js b/src/routes/write/flags.js index c498421e78..f30232c5b6 100644 --- a/src/routes/write/flags.js +++ b/src/routes/write/flags.js @@ -17,6 +17,8 @@ module.exports = function () { setupApiRoute(router, 'put', '/:flagId', [...middlewares, middleware.assert.flag], controllers.write.flags.update); setupApiRoute(router, 'delete', '/:flagId', [...middlewares, middleware.assert.flag], controllers.write.flags.delete); + setupApiRoute(router, 'delete', '/:flagId/report', middlewares, controllers.write.flags.rescind); + setupApiRoute(router, 'post', '/:flagId/notes', [...middlewares, middleware.assert.flag], controllers.write.flags.appendNote); setupApiRoute(router, 'delete', '/:flagId/notes/:datetime', [...middlewares, middleware.assert.flag], controllers.write.flags.deleteNote); diff --git a/test/flags.js b/test/flags.js index cda71a111f..15dc14533b 100644 --- a/test/flags.js +++ b/test/flags.js @@ -1004,6 +1004,22 @@ describe('Flags', () => { }); }); + describe('.rescind()', () => { + it('should remove a flag\'s report', async () => { + const response = await request({ + method: 'delete', + uri: `${nconf.get('url')}/api/v3/flags/2/report`, + jar, + headers: { + 'x-csrf-token': csrfToken, + }, + resolveWithFullResponse: true, + }); + + assert.strictEqual(response.statusCode, 200); + }); + }); + describe('.appendNote()', () => { it('should append a note to the flag', async () => { const { response } = await request({