diff --git a/core/server/api/canary/labels.js b/core/server/api/canary/labels.js index b550eeb0de..837fc8ea88 100644 --- a/core/server/api/canary/labels.js +++ b/core/server/api/canary/labels.js @@ -76,8 +76,16 @@ module.exports = { } }, permissions: true, - query(frame) { - return models.Label.add(frame.data.labels[0], frame.options); + async query(frame) { + try { + return await models.Label.add(frame.data.labels[0], frame.options); + } catch (error) { + if (error.code && error.message.toLowerCase().indexOf('unique') !== -1) { + throw new errors.ValidationError({message: i18n.t('errors.api.labels.labelAlreadyExists')}); + } + + throw error; + } } }, diff --git a/core/server/translations/en.json b/core/server/translations/en.json index 93bbbf7499..33ad91fdc7 100644 --- a/core/server/translations/en.json +++ b/core/server/translations/en.json @@ -373,7 +373,8 @@ "tagNotFound": "Tag not found." }, "labels": { - "labelNotFound": "Label not found." + "labelNotFound": "Label not found.", + "labelAlreadyExists": "Label already exists" }, "themes": { "noPermissionToBrowseThemes": "You do not have permission to browse themes.", diff --git a/test/regression/api/canary/admin/labels_spec.js b/test/regression/api/canary/admin/labels_spec.js new file mode 100644 index 0000000000..d604072ec6 --- /dev/null +++ b/test/regression/api/canary/admin/labels_spec.js @@ -0,0 +1,70 @@ +const path = require('path'); +const should = require('should'); +const supertest = require('supertest'); +const sinon = require('sinon'); +const testUtils = require('../../../../utils'); +const localUtils = require('./utils'); +const config = require('../../../../../core/shared/config'); + +const ghost = testUtils.startGhost; + +let request; + +describe('Labels API', function () { + after(function () { + sinon.restore(); + }); + + before(function () { + return ghost() + .then(function () { + request = supertest.agent(config.get('url')); + }) + .then(function () { + return localUtils.doAuth(request); + }); + }); + + it('Errors when adding label with the same name', function () { + const label = { + name: 'test' + }; + + return request + .post(localUtils.API.getApiQuery(`labels/`)) + .send({labels: [label]}) + .set('Origin', config.get('url')) + .expect('Content-Type', /json/) + .expect('Cache-Control', testUtils.cacheRules.private) + .expect(201) + .then((res) => { + should.not.exist(res.headers['x-cache-invalidate']); + const jsonResponse = res.body; + should.exist(jsonResponse); + should.exist(jsonResponse.labels); + jsonResponse.labels.should.have.length(1); + + jsonResponse.labels[0].name.should.equal(label.name); + jsonResponse.labels[0].slug.should.equal(label.name); + }) + .then(() => { + return request + .post(localUtils.API.getApiQuery(`labels/`)) + .send({labels: [label]}) + .set('Origin', config.get('url')) + .expect('Content-Type', /json/) + .expect('Cache-Control', testUtils.cacheRules.private) + .expect(422); + }) + .then((res) => { + should.not.exist(res.headers['x-cache-invalidate']); + const jsonResponse = res.body; + should.exist(jsonResponse); + should.exist(jsonResponse.errors); + jsonResponse.errors.should.have.length(1); + + jsonResponse.errors[0].type.should.equal('ValidationError'); + jsonResponse.errors[0].context.should.equal('Label already exists'); + }); + }); +});