diff --git a/test/api/v3/integration/coupons/GET-coupons.test.js b/test/api/v3/integration/coupons/GET-coupons.test.js
index fd61ac1a98..2e31669c70 100644
--- a/test/api/v3/integration/coupons/GET-coupons.test.js
+++ b/test/api/v3/integration/coupons/GET-coupons.test.js
@@ -2,7 +2,7 @@ import {
generateUser,
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
-import apiMessages from '../../../../../website/server/libs/apiMessages';
+import apiError from '../../../../../website/server/libs/apiError';
describe('GET /coupons/', () => {
let user;
@@ -19,7 +19,7 @@ describe('GET /coupons/', () => {
await expect(user.get('/coupons')).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
- message: apiMessages('noSudoAccess'),
+ message: apiError('noSudoAccess'),
});
});
diff --git a/test/api/v3/integration/coupons/POST-coupons_generate_event.test.js b/test/api/v3/integration/coupons/POST-coupons_generate_event.test.js
index 12730c8296..6b533b76d6 100644
--- a/test/api/v3/integration/coupons/POST-coupons_generate_event.test.js
+++ b/test/api/v3/integration/coupons/POST-coupons_generate_event.test.js
@@ -4,7 +4,7 @@ import {
resetHabiticaDB,
} from '../../../../helpers/api-v3-integration.helper';
import couponCode from 'coupon-code';
-import apiMessages from '../../../../../website/server/libs/apiMessages';
+import apiError from '../../../../../website/server/libs/apiError';
describe('POST /coupons/generate/:event', () => {
let user;
@@ -26,7 +26,7 @@ describe('POST /coupons/generate/:event', () => {
await expect(user.post('/coupons/generate/aaa')).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
- message: apiMessages('noSudoAccess'),
+ message: apiError('noSudoAccess'),
});
});
diff --git a/test/api/v3/integration/groups/GET-groups.test.js b/test/api/v3/integration/groups/GET-groups.test.js
index c0feea5851..9b41fcb53a 100644
--- a/test/api/v3/integration/groups/GET-groups.test.js
+++ b/test/api/v3/integration/groups/GET-groups.test.js
@@ -7,7 +7,7 @@ import {
import {
TAVERN_ID,
} from '../../../../../website/server/models/group';
-import apiMessages from '../../../../../website/server/libs/apiMessages';
+import apiError from '../../../../../website/server/libs/apiError';
describe('GET /groups', () => {
let user;
@@ -167,7 +167,7 @@ describe('GET /groups', () => {
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: apiMessages('guildsOnlyPaginate'),
+ message: apiError('guildsOnlyPaginate'),
});
});
diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js
index bae6423be0..38500d72c1 100644
--- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js
+++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_checkout_success.test.js
@@ -1,8 +1,8 @@
import {
generateUser,
- translate as t,
} from '../../../../../helpers/api-integration/v3';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
+import apiError from '../../../../../../website/server/libs/apiError';
describe('payments : paypal #checkoutSuccess', () => {
let endpoint = '/paypal/checkout/success';
@@ -17,7 +17,7 @@ describe('payments : paypal #checkoutSuccess', () => {
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('missingPaymentId'),
+ message: apiError('missingPaymentId'),
});
});
@@ -26,7 +26,7 @@ describe('payments : paypal #checkoutSuccess', () => {
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('missingCustomerId'),
+ message: apiError('missingCustomerId'),
});
});
diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js
index 3146eb0c5d..e967388bfe 100644
--- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js
+++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe.test.js
@@ -1,9 +1,9 @@
import {
generateUser,
- translate as t,
} from '../../../../../helpers/api-integration/v3';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import shared from '../../../../../../website/common';
+import apiError from '../../../../../../website/server/libs/apiError';
describe('payments : paypal #subscribe', () => {
let endpoint = '/paypal/subscribe';
@@ -17,7 +17,7 @@ describe('payments : paypal #subscribe', () => {
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('missingSubKey'),
+ message: apiError('missingSubKey'),
});
});
diff --git a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js
index bace51302a..b01ccfcd99 100644
--- a/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js
+++ b/test/api/v3/integration/payments/paypal/GET-payments_paypal_subscribe_success.test.js
@@ -1,7 +1,7 @@
import {
generateUser,
- translate as t,
} from '../../../../../helpers/api-integration/v3';
+import apiError from '../../../../../../website/server/libs/apiError';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
describe('payments : paypal #subscribeSuccess', () => {
@@ -16,7 +16,7 @@ describe('payments : paypal #subscribeSuccess', () => {
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('missingPaypalBlock'),
+ message: apiError('missingPaypalBlock'),
});
});
diff --git a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js
index 852057f338..011039f675 100644
--- a/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js
+++ b/test/api/v3/integration/quests/POST-groups_groupId_quests_invite.test.js
@@ -6,6 +6,7 @@ import {
import { v4 as generateUUID } from 'uuid';
import { quests as questScrolls } from '../../../../../website/common/script/content';
import { model as Chat } from '../../../../../website/server/models/chat';
+import apiError from '../../../../../website/server/libs/apiError';
describe('POST /groups/:groupId/quests/invite/:questKey', () => {
let questingGroup;
@@ -69,7 +70,7 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => {
await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${FAKE_QUEST}`)).to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('questNotFound', {key: FAKE_QUEST}),
+ message: apiError('questNotFound', {key: FAKE_QUEST}),
});
});
diff --git a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
index 595b779e07..f95f8c030d 100644
--- a/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
+++ b/test/api/v3/integration/user/POST-user_class_cast_spellId.test.js
@@ -9,6 +9,7 @@ import {
import { v4 as generateUUID } from 'uuid';
import { find } from 'lodash';
+import apiError from '../../../../../website/server/libs/apiError';
describe('POST /user/class/cast/:spellId', () => {
let user;
@@ -24,7 +25,7 @@ describe('POST /user/class/cast/:spellId', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('spellNotFound', {spellId}),
+ message: apiError('spellNotFound', {spellId}),
});
});
@@ -34,7 +35,7 @@ describe('POST /user/class/cast/:spellId', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('spellNotFound', {spellId}),
+ message: apiError('spellNotFound', {spellId}),
});
});
diff --git a/test/api/v3/integration/user/buy/POST-user_buy.test.js b/test/api/v3/integration/user/buy/POST-user_buy.test.js
index 37670d115b..fddd08802a 100644
--- a/test/api/v3/integration/user/buy/POST-user_buy.test.js
+++ b/test/api/v3/integration/user/buy/POST-user_buy.test.js
@@ -5,6 +5,7 @@ import {
translate as t,
} from '../../../../../helpers/api-integration/v3';
import shared from '../../../../../../website/common/script';
+import apiError from '../../../../../../website/server/libs/apiError';
let content = shared.content;
@@ -24,7 +25,7 @@ describe('POST /user/buy/:key', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('itemNotFound', {key: 'notExisting'}),
+ message: apiError('itemNotFound', {key: 'notExisting'}),
});
});
diff --git a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js
index d3992ed1fe..2b44edf022 100644
--- a/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js
+++ b/test/api/v3/integration/user/buy/POST-user_buy_gear.test.js
@@ -2,8 +2,8 @@
import {
generateUser,
- translate as t,
} from '../../../../../helpers/api-integration/v3';
+import apiError from '../../../../../../website/server/libs/apiError';
describe('POST /user/buy-gear/:key', () => {
let user;
@@ -21,7 +21,7 @@ describe('POST /user/buy-gear/:key', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('itemNotFound', {key: 'notExisting'}),
+ message: apiError('itemNotFound', {key: 'notExisting'}),
});
});
diff --git a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js
index f539a29a5a..0bc9b40d3d 100644
--- a/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js
+++ b/test/api/v3/integration/user/buy/POST-user_buy_quest.test.js
@@ -3,6 +3,7 @@ import {
translate as t,
} from '../../../../../helpers/api-integration/v3';
import shared from '../../../../../../website/common/script';
+import apiError from '../../../../../../website/server/libs/apiError';
let content = shared.content;
@@ -20,7 +21,7 @@ describe('POST /user/buy-quest/:key', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('questNotFound', {key: 'notExisting'}),
+ message: apiError('questNotFound', {key: 'notExisting'}),
});
});
diff --git a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js
index f6c16febee..20a73fb173 100644
--- a/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js
+++ b/test/api/v3/integration/user/buy/POST-user_buy_special_spell.test.js
@@ -3,6 +3,7 @@ import {
translate as t,
} from '../../../../../helpers/api-integration/v3';
import shared from '../../../../../../website/common/script';
+import apiError from '../../../../../../website/server/libs/apiError';
let content = shared.content;
@@ -20,7 +21,7 @@ describe('POST /user/buy-special-spell/:key', () => {
.to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
- message: t('spellNotFound', {spellId: 'notExisting'}),
+ message: apiError('spellNotFound', {spellId: 'notExisting'}),
});
});
diff --git a/test/api/v3/integration/user/stats/POST-user_allocate.test.js b/test/api/v3/integration/user/stats/POST-user_allocate.test.js
index 6487641c79..bf10e722de 100644
--- a/test/api/v3/integration/user/stats/POST-user_allocate.test.js
+++ b/test/api/v3/integration/user/stats/POST-user_allocate.test.js
@@ -2,6 +2,7 @@ import {
generateUser,
translate as t,
} from '../../../../../helpers/api-integration/v3';
+import apiError from '../../../../../../website/server/libs/apiError';
describe('POST /user/allocate', () => {
let user;
@@ -17,7 +18,7 @@ describe('POST /user/allocate', () => {
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('invalidAttribute', {attr: 'invalid'}),
+ message: apiError('invalidAttribute', {attr: 'invalid'}),
});
});
diff --git a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js
index 1c654e1705..cbed7e56af 100644
--- a/test/api/v3/integration/webhook/POST-user_add_webhook.test.js
+++ b/test/api/v3/integration/webhook/POST-user_add_webhook.test.js
@@ -3,6 +3,7 @@ import {
translate as t,
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID } from 'uuid';
+import apiError from '../../../../../website/server/libs/apiError';
describe('POST /user/webhook', () => {
let user, body;
@@ -205,7 +206,7 @@ describe('POST /user/webhook', () => {
await expect(user.post('/user/webhook', body)).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('groupIdRequired'),
+ message: apiError('groupIdRequired'),
});
});
diff --git a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js
index e388b8610b..abebc4aff3 100644
--- a/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js
+++ b/test/api/v3/integration/webhook/PUT-user_update_webhook.test.js
@@ -3,6 +3,7 @@ import {
translate as t,
} from '../../../../helpers/api-integration/v3';
import { v4 as generateUUID} from 'uuid';
+import apiError from '../../../../../website/server/libs/apiError';
describe('PUT /user/webhook/:id', () => {
let user, webhookToUpdate;
@@ -127,7 +128,7 @@ describe('PUT /user/webhook/:id', () => {
await expect(user.put(`/user/webhook/${webhookToUpdate.id}`, {type, options})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
- message: t('groupIdRequired'),
+ message: apiError('groupIdRequired'),
});
});
});
diff --git a/test/api/v3/unit/libs/apiMessages.js b/test/api/v3/unit/libs/apiError.js
similarity index 73%
rename from test/api/v3/unit/libs/apiMessages.js
rename to test/api/v3/unit/libs/apiError.js
index 3d2ac2fad1..014374a68a 100644
--- a/test/api/v3/unit/libs/apiMessages.js
+++ b/test/api/v3/unit/libs/apiError.js
@@ -1,19 +1,19 @@
-import apiMessages from '../../../../../website/server/libs/apiMessages';
+import apiError from '../../../../../website/server/libs/apiError';
describe('API Messages', () => {
const message = 'Only public guilds support pagination.';
it('returns an API message', () => {
- expect(apiMessages('guildsOnlyPaginate')).to.equal(message);
+ expect(apiError('guildsOnlyPaginate')).to.equal(message);
});
it('throws if the API message does not exist', () => {
- expect(() => apiMessages('iDoNotExist')).to.throw;
+ expect(() => apiError('iDoNotExist')).to.throw;
});
it('clones the passed variables', () => {
let vars = {a: 1};
sandbox.stub(_, 'clone').returns({});
- apiMessages('guildsOnlyPaginate', vars);
+ apiError('guildsOnlyPaginate', vars);
expect(_.clone).to.have.been.calledOnce;
expect(_.clone).to.have.been.calledWith(vars);
});
@@ -22,7 +22,7 @@ describe('API Messages', () => {
let vars = {a: 1};
let stub = sinon.stub().returns('string');
sandbox.stub(_, 'template').returns(stub);
- apiMessages('guildsOnlyPaginate', vars);
+ apiError('guildsOnlyPaginate', vars);
expect(_.template).to.have.been.calledOnce;
expect(_.template).to.have.been.calledWith(message);
expect(stub).to.have.been.calledOnce;
diff --git a/test/api/v3/unit/middlewares/ensureAccessRight.test.js b/test/api/v3/unit/middlewares/ensureAccessRight.test.js
index 0adee75fd4..6406dd3c9b 100644
--- a/test/api/v3/unit/middlewares/ensureAccessRight.test.js
+++ b/test/api/v3/unit/middlewares/ensureAccessRight.test.js
@@ -7,7 +7,7 @@ import {
import i18n from '../../../../../website/common/script/i18n';
import { ensureAdmin, ensureSudo } from '../../../../../website/server/middlewares/ensureAccessRight';
import { NotAuthorized } from '../../../../../website/server/libs/errors';
-import apiMessages from '../../../../../website/server/libs/apiMessages';
+import apiError from '../../../../../website/server/libs/apiError';
describe('ensure access middlewares', () => {
let res, req, next;
@@ -46,7 +46,7 @@ describe('ensure access middlewares', () => {
ensureSudo(req, res, next);
const calledWith = next.getCall(0).args;
- expect(calledWith[0].message).to.equal(apiMessages('noSudoAccess'));
+ expect(calledWith[0].message).to.equal(apiError('noSudoAccess'));
expect(calledWith[0] instanceof NotAuthorized).to.equal(true);
});
diff --git a/test/api/v3/unit/models/webhook.test.js b/test/api/v3/unit/models/webhook.test.js
index 1917330a9f..b3cb23c44e 100644
--- a/test/api/v3/unit/models/webhook.test.js
+++ b/test/api/v3/unit/models/webhook.test.js
@@ -1,6 +1,7 @@
import { model as Webhook } from '../../../../../website/server/models/webhook';
import { BadRequest } from '../../../../../website/server/libs/errors';
import { v4 as generateUUID } from 'uuid';
+import apiError from '../../../../../website/server/libs/apiError';
describe('Webhook Model', () => {
context('Instance Methods', () => {
@@ -287,8 +288,8 @@ describe('Webhook Model', () => {
wh.formatOptions(res);
} catch (err) {
expect(err).to.be.an.instanceOf(BadRequest);
- expect(res.t).to.be.calledOnce;
- expect(res.t).to.be.calledWith('groupIdRequired');
+
+ expect(err.message).to.eql(apiError('groupIdRequired'));
done();
}
});
diff --git a/test/common/ops/buy/buy.js b/test/common/ops/buy/buy.js
index ab72d1f2b7..975edacbde 100644
--- a/test/common/ops/buy/buy.js
+++ b/test/common/ops/buy/buy.js
@@ -8,6 +8,7 @@ import {
} from '../../../../website/common/script/libs/errors';
import i18n from '../../../../website/common/script/i18n';
import content from '../../../../website/common/script/content/index';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.buy', () => {
let user;
@@ -40,7 +41,7 @@ describe('shared.ops.buy', () => {
buy(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingKeyParam'));
+ expect(err.message).to.equal(errorMessage('missingKeyParam'));
done();
}
});
diff --git a/test/common/ops/buy/buyMarketGear.js b/test/common/ops/buy/buyMarketGear.js
index 48ce22ea1d..397297dd67 100644
--- a/test/common/ops/buy/buyMarketGear.js
+++ b/test/common/ops/buy/buyMarketGear.js
@@ -10,6 +10,7 @@ import {
BadRequest, NotAuthorized, NotFound,
} from '../../../../website/common/script/libs/errors';
import i18n from '../../../../website/common/script/i18n';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
function buyGear (user, req, analytics) {
let buyOp = new BuyMarketGearOperation(user, req, analytics);
@@ -190,7 +191,7 @@ describe('shared.ops.buyMarketGear', () => {
buyGear(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingKeyParam'));
+ expect(err.message).to.equal(errorMessage('missingKeyParam'));
done();
}
});
@@ -202,7 +203,7 @@ describe('shared.ops.buyMarketGear', () => {
buyGear(user, {params});
} catch (err) {
expect(err).to.be.an.instanceof(NotFound);
- expect(err.message).to.equal(i18n.t('itemNotFound', params));
+ expect(err.message).to.equal(errorMessage('itemNotFound', params));
done();
}
});
diff --git a/test/common/ops/buy/buyMysterySet.js b/test/common/ops/buy/buyMysterySet.js
index 5334d3e671..dca60d7489 100644
--- a/test/common/ops/buy/buyMysterySet.js
+++ b/test/common/ops/buy/buyMysterySet.js
@@ -10,6 +10,7 @@ import {
NotFound,
} from '../../../../website/common/script/libs/errors';
import i18n from '../../../../website/common/script/i18n';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.buyMysterySet', () => {
let user;
@@ -70,7 +71,7 @@ describe('shared.ops.buyMysterySet', () => {
buyMysterySet(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingKeyParam'));
+ expect(err.message).to.equal(errorMessage('missingKeyParam'));
done();
}
});
diff --git a/test/common/ops/buy/buyQuest.js b/test/common/ops/buy/buyQuest.js
index 390b65ee01..4994e38af2 100644
--- a/test/common/ops/buy/buyQuest.js
+++ b/test/common/ops/buy/buyQuest.js
@@ -8,6 +8,7 @@ import {
NotFound,
} from '../../../../website/common/script/libs/errors';
import i18n from '../../../../website/common/script/i18n';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.buyQuest', () => {
let user;
@@ -106,7 +107,7 @@ describe('shared.ops.buyQuest', () => {
});
} catch (err) {
expect(err).to.be.an.instanceof(NotFound);
- expect(err.message).to.equal(i18n.t('questNotFound', {key: 'snarfblatter'}));
+ expect(err.message).to.equal(errorMessage('questNotFound', {key: 'snarfblatter'}));
expect(user.items.quests).to.eql({});
expect(user.stats.gp).to.equal(9999);
done();
@@ -151,7 +152,7 @@ describe('shared.ops.buyQuest', () => {
buyQuest(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingKeyParam'));
+ expect(err.message).to.equal(errorMessage('missingKeyParam'));
done();
}
});
diff --git a/test/common/ops/buy/buySpecialSpell.js b/test/common/ops/buy/buySpecialSpell.js
index 97aade05ae..bd4b0cf22c 100644
--- a/test/common/ops/buy/buySpecialSpell.js
+++ b/test/common/ops/buy/buySpecialSpell.js
@@ -9,6 +9,7 @@ import {
generateUser,
} from '../../../helpers/common.helper';
import content from '../../../../website/common/script/content/index';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.buySpecialSpell', () => {
let user;
@@ -28,7 +29,7 @@ describe('shared.ops.buySpecialSpell', () => {
buySpecialSpell(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingKeyParam'));
+ expect(err.message).to.equal(errorMessage('missingKeyParam'));
done();
}
});
@@ -42,7 +43,7 @@ describe('shared.ops.buySpecialSpell', () => {
});
} catch (err) {
expect(err).to.be.an.instanceof(NotFound);
- expect(err.message).to.equal(i18n.t('spellNotFound', {spellId: 'notExisting'}));
+ expect(err.message).to.equal(errorMessage('spellNotFound', {spellId: 'notExisting'}));
done();
}
});
diff --git a/test/common/ops/buy/hourglassPurchase.js b/test/common/ops/buy/hourglassPurchase.js
index 3684f7d416..d1631fb277 100644
--- a/test/common/ops/buy/hourglassPurchase.js
+++ b/test/common/ops/buy/hourglassPurchase.js
@@ -8,6 +8,7 @@ import content from '../../../../website/common/script/content/index';
import {
generateUser,
} from '../../../helpers/common.helper';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('common.ops.hourglassPurchase', () => {
let user;
@@ -28,7 +29,7 @@ describe('common.ops.hourglassPurchase', () => {
hourglassPurchase(user, {params: {}});
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.eql(i18n.t('missingKeyParam'));
+ expect(err.message).to.eql(errorMessage('missingKeyParam'));
done();
}
});
@@ -38,7 +39,7 @@ describe('common.ops.hourglassPurchase', () => {
hourglassPurchase(user, {params: {key: 'Base'}});
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.eql(i18n.t('missingTypeParam'));
+ expect(err.message).to.eql(errorMessage('missingTypeParam'));
done();
}
});
diff --git a/test/common/ops/feed.js b/test/common/ops/feed.js
index 91c6a9cee9..4aabd119df 100644
--- a/test/common/ops/feed.js
+++ b/test/common/ops/feed.js
@@ -9,6 +9,7 @@ import i18n from '../../../website/common/script/i18n';
import {
generateUser,
} from '../../helpers/common.helper';
+import errorMessage from '../../../website/common/script/libs/errorMessage';
describe('shared.ops.feed', () => {
let user;
@@ -23,7 +24,7 @@ describe('shared.ops.feed', () => {
feed(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingPetFoodFeed'));
+ expect(err.message).to.equal(errorMessage('missingPetFoodFeed'));
done();
}
});
@@ -33,7 +34,7 @@ describe('shared.ops.feed', () => {
feed(user, {params: {pet: 'invalid', food: 'food'}});
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('invalidPetName'));
+ expect(err.message).to.equal(errorMessage('invalidPetName'));
done();
}
});
@@ -43,7 +44,7 @@ describe('shared.ops.feed', () => {
feed(user, {params: {pet: 'Wolf-Red', food: 'invalid food name'}});
} catch (err) {
expect(err).to.be.an.instanceof(NotFound);
- expect(err.message).to.equal(i18n.t('messageFoodNotFound'));
+ expect(err.message).to.equal(errorMessage('invalidFoodName'));
done();
}
});
diff --git a/test/common/ops/hatch.js b/test/common/ops/hatch.js
index fc6c7875f9..9c1039f29b 100644
--- a/test/common/ops/hatch.js
+++ b/test/common/ops/hatch.js
@@ -8,6 +8,7 @@ import i18n from '../../../website/common/script/i18n';
import {
generateUser,
} from '../../helpers/common.helper';
+import errorMessage from '../../../website/common/script/libs/errorMessage';
describe('shared.ops.hatch', () => {
let user;
@@ -24,7 +25,7 @@ describe('shared.ops.hatch', () => {
hatch(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('missingEggHatchingPotionHatch'));
+ expect(err.message).to.equal(errorMessage('missingEggHatchingPotion'));
expect(user.items.pets).to.be.empty;
}
});
diff --git a/test/common/ops/stats/allocate.js b/test/common/ops/stats/allocate.js
index 1eaa14f88d..40f43d3bf2 100644
--- a/test/common/ops/stats/allocate.js
+++ b/test/common/ops/stats/allocate.js
@@ -7,6 +7,7 @@ import i18n from '../../../../website/common/script/i18n';
import {
generateUser,
} from '../../../helpers/common.helper';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.allocate', () => {
let user;
@@ -22,7 +23,7 @@ describe('shared.ops.allocate', () => {
});
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'notValid'}));
+ expect(err.message).to.equal(errorMessage('invalidAttribute', {attr: 'notValid'}));
done();
}
});
diff --git a/test/common/ops/stats/allocateBulk.js b/test/common/ops/stats/allocateBulk.js
index e91de8cf9e..2dbeca5a37 100644
--- a/test/common/ops/stats/allocateBulk.js
+++ b/test/common/ops/stats/allocateBulk.js
@@ -7,6 +7,7 @@ import i18n from '../../../../website/common/script/i18n';
import {
generateUser,
} from '../../../helpers/common.helper';
+import errorMessage from '../../../../website/common/script/libs/errorMessage';
describe('shared.ops.allocateBulk', () => {
let user;
@@ -27,7 +28,7 @@ describe('shared.ops.allocateBulk', () => {
});
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('invalidAttribute', {attr: 'invalid'}));
+ expect(err.message).to.equal(errorMessage('invalidAttribute', {attr: 'invalid'}));
done();
}
});
@@ -37,7 +38,7 @@ describe('shared.ops.allocateBulk', () => {
allocateBulk(user);
} catch (err) {
expect(err).to.be.an.instanceof(BadRequest);
- expect(err.message).to.equal(i18n.t('statsObjectRequired'));
+ expect(err.message).to.equal(errorMessage('statsObjectRequired'));
done();
}
});
diff --git a/website/common/errors/apiErrorMessages.js b/website/common/errors/apiErrorMessages.js
new file mode 100644
index 0000000000..4857be3d58
--- /dev/null
+++ b/website/common/errors/apiErrorMessages.js
@@ -0,0 +1,25 @@
+// When this file grows, it can be split into multiple ones.
+module.exports = {
+ taskIdRequired: 'req.params.taskId must contain a task id.',
+ keepOrRemove: 'req.query.keep must be either "keep" or "remove".',
+ keepOrRemoveAll: 'req.query.keep must be either "keep-all" or "remove-all".',
+
+ queryPageInteger: 'req.query.page must be an integer greater than or equal to 0.',
+
+ missingTypeKeyEquip: '"key" and "type" are required parameters.',
+
+ guildsOnlyPaginate: 'Only public guilds support pagination.',
+ guildsPaginateBooleanString: 'req.query.paginate must be a boolean string.',
+ groupIdRequired: 'req.params.groupId must contain a groupId.',
+ groupRemainOrLeaveChallenges: 'req.query.keep must be either "remain-in-challenges" or "leave-challenges"',
+ managerIdRequired: 'req.body.managerId must contain a user ID.',
+ noSudoAccess: 'You don\'t have sudo access.',
+
+ eventRequired: '"req.params.event" is required.',
+ countRequired: '"req.query.count" is required.',
+
+ missingPaymentId: 'Missing "req.query.paymentId"',
+ missingCustomerId: 'Missing "req.query.customerId"',
+ missingPaypalBlock: 'Missing "req.session.paypalBlock"',
+ missingSubKey: 'Missing "req.query.sub"',
+};
diff --git a/website/common/errors/commonErrorMessages.js b/website/common/errors/commonErrorMessages.js
new file mode 100644
index 0000000000..dc754b6e36
--- /dev/null
+++ b/website/common/errors/commonErrorMessages.js
@@ -0,0 +1,18 @@
+// When this file grows, it can be split into multiple ones.
+module.exports = {
+ invalidAttribute: '"<%= attr %>" is not a valid Stat.',
+
+ statsObjectRequired: '"stats" update is required',
+
+ missingTypeParam: '"req.params.type" is required.',
+ missingKeyParam: '"req.params.key" is required.',
+ itemNotFound: 'Item "<%= key %>" not found.',
+ questNotFound: 'Quest "<%= key %>" not found.',
+ spellNotFound: 'Skill "<%= spellId %>" not found.',
+ invalidTypeEquip: '"type" must be one of "equipped", "pet", "mount", "costume"',
+ missingPetFoodFeed: '"pet" and "food" are required parameters.',
+ missingEggHatchingPotion: '"egg" and "hatchingPotion" are required parameters.',
+
+ invalidPetName: 'Invalid pet name supplied.',
+ invalidFoodName: 'Invalid food name supplied.',
+};
diff --git a/website/common/locales/en/character.json b/website/common/locales/en/character.json
index 162fa6e701..7bfe47d255 100644
--- a/website/common/locales/en/character.json
+++ b/website/common/locales/en/character.json
@@ -201,7 +201,6 @@
"showQuickAllocation": "Show Stat Allocation",
"hideQuickAllocation": "Hide Stat Allocation",
"quickAllocationLevelPopover": "Each level earns you one Point to assign to a Stat of your choice. You can do so manually, or let the game decide for you using one of the Automatic Allocation options found in User Icon > Stats.",
- "invalidAttribute": "\"<%= attr %>\" is not a valid Stat.",
"notEnoughAttrPoints": "You don't have enough Stat Points.",
"style": "Style",
"facialhair": "Facial",
@@ -224,6 +223,5 @@
"allocated": "Allocated",
"buffs": "Buffs",
"pointsAvailable": "Points Available",
- "pts": "pts",
- "statsObjectRequired": "Stats update is required"
+ "pts": "pts"
}
diff --git a/website/common/locales/en/contrib.json b/website/common/locales/en/contrib.json
index 4977277a27..87b27f5d9a 100644
--- a/website/common/locales/en/contrib.json
+++ b/website/common/locales/en/contrib.json
@@ -49,7 +49,6 @@
"UUID": "User ID",
"loadUser": "Load User",
"noAdminAccess": "You don't have admin access.",
- "pageMustBeNumber": "req.query.page must be a number",
"userNotFound": "User not found.",
"invalidUUID": "UUID must be valid",
"title": "Title",
diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json
index 706934318d..42f77bbc20 100644
--- a/website/common/locales/en/groups.json
+++ b/website/common/locales/en/groups.json
@@ -210,7 +210,6 @@
"partyOnName": "Party On",
"partyUpText": "Joined a Party with another person! Have fun battling monsters and supporting each other.",
"partyOnText": "Joined a Party with at least four people! Enjoy your increased accountability as you unite with your friends to vanquish your foes!",
- "groupIdRequired": "\"groupId\" must be a valid UUID",
"groupNotFound": "Group not found or you don't have access.",
"groupTypesRequired": "You must supply a valid \"type\" query string.",
"questLeaderCannotLeaveGroup": "You cannot leave your Party when you have started a quest. Abort the quest first.",
@@ -220,8 +219,6 @@
"memberCannotRemoveYourself": "You cannot remove yourself!",
"groupMemberNotFound": "User not found among group's members",
"mustBeGroupMember": "Must be member of the group.",
- "keepOrRemoveAll": "req.query.keep must be either \"keep-all\" or \"remove-all\"",
- "keepOrRemove": "req.query.keep must be either \"keep\" or \"remove\"",
"canOnlyInviteEmailUuid": "Can only invite using uuids or emails.",
"inviteMissingEmail": "Missing email address in invite.",
"inviteMissingUuid": "Missing user id in invite",
@@ -328,7 +325,6 @@
"cantDeleteAssignedGroupTasks": "Can't delete group tasks that are assigned to you.",
"confirmGuildPlanCreation": "Create this group?",
"onlyGroupLeaderCanInviteToGroupPlan": "Only the group leader can invite users to a group with a subscription.",
- "remainOrLeaveChallenges": "req.query.keep must be either 'remain-in-challenges' or 'leave-challenges'",
"paymentDetails": "Payment Details",
"aboutToJoinCancelledGroupPlan": "You are about to join a group with a canceled plan. You will NOT receive a free subscription.",
"cannotChangeLeaderWithActiveGroupPlan": "You can not change the leader while the group has an active plan.",
diff --git a/website/common/locales/en/npc.json b/website/common/locales/en/npc.json
index 0fdb31496d..49b4a6b456 100644
--- a/website/common/locales/en/npc.json
+++ b/website/common/locales/en/npc.json
@@ -82,14 +82,7 @@
"ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...",
"featuredQuests": "Featured Quests!",
- "missingKeyParam": "\"req.params.key\" is required.",
- "itemNotFound": "Item \"<%= key %>\" not found.",
"cannotBuyItem": "You can't buy this item.",
- "missingTypeKeyEquip": "\"key\" and \"type\" are required parameters.",
- "missingPetFoodFeed": "\"pet\" and \"food\" are required parameters.",
- "invalidPetName": "Invalid pet name supplied.",
- "missingEggHatchingPotionHatch": "\"egg\" and \"hatchingPotion\" are required parameters.",
- "invalidTypeEquip": "\"type\" must be one of 'equipped', 'pet', 'mount', 'costume'.",
"mustPurchaseToSet": "Must purchase <%= val %> to set it on <%= key %>.",
"typeRequired": "Type is required",
"positiveAmountRequired": "Positive amount is required",
diff --git a/website/common/locales/en/quests.json b/website/common/locales/en/quests.json
index 0bfac41b6c..5c09433384 100644
--- a/website/common/locales/en/quests.json
+++ b/website/common/locales/en/quests.json
@@ -96,7 +96,6 @@
"questInvitationDoesNotExist": "No quest invitation has been sent out yet.",
"questInviteNotFound": "No quest invitation found.",
"guildQuestsNotSupported": "Guilds cannot be invited on quests.",
- "questNotFound": "Quest \"<%= key %>\" not found.",
"questNotOwned": "You don't own that quest scroll.",
"questNotGoldPurchasable": "Quest \"<%= key %>\" is not a Gold-purchasable quest.",
"questLevelTooHigh": "You must be level <%= level %> to begin this quest.",
diff --git a/website/common/locales/en/spells.json b/website/common/locales/en/spells.json
index 773e3301ba..d67816a19a 100644
--- a/website/common/locales/en/spells.json
+++ b/website/common/locales/en/spells.json
@@ -72,7 +72,6 @@
"spellSpecialSandText": "Sand",
"spellSpecialSandNotes": "Reverse the spell that made you a sea star.",
- "spellNotFound": "Skill \"<%= spellId %>\" not found.",
"partyNotFound": "Party not found",
"targetIdUUID": "\"targetId\" must be a valid User ID.",
"challengeTasksNoCast": "Casting a skill on challenge tasks is not allowed.",
diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json
index a216d3dd6b..aa7f063043 100644
--- a/website/common/locales/en/subscriber.json
+++ b/website/common/locales/en/subscriber.json
@@ -178,12 +178,6 @@
"invalidCoupon": "Invalid coupon code.",
"couponUsed": "Coupon code already used.",
"couponCodeRequired": "The coupon code is required.",
- "eventRequired": "\"req.params.event\" is required.",
- "countRequired": "\"req.query.count\" is required.",
- "missingPaymentId": "Missing req.query.paymentId",
- "missingCustomerId": "Missing req.query.customerId",
- "missingPaypalBlock": "Missing req.session.paypalBlock",
- "missingSubKey": "Missing req.query.sub",
"paypalCanceled": "Your subscription has been canceled",
"earnGemsMonthly": "Earn up to **<%= cap %> Gems** per month",
"receiveMysticHourglass": "Receive a Mystic Hourglass!",
diff --git a/website/common/locales/en/tasks.json b/website/common/locales/en/tasks.json
index 9990119356..afaba0032a 100644
--- a/website/common/locales/en/tasks.json
+++ b/website/common/locales/en/tasks.json
@@ -145,7 +145,6 @@
"rewardHelp3": "Special equipment will appear here during World Events.",
"rewardHelp4": "Don't be afraid to set custom Rewards! Check out some samples here.",
"clickForHelp": "Click for help",
- "taskIdRequired": "\"taskId\" must be a valid UUID.",
"taskAliasAlreadyUsed": "Task alias already used on another task.",
"taskNotFound": "Task not found.",
"invalidTaskType": "Task type must be one of \"habit\", \"daily\", \"todo\", \"reward\".",
diff --git a/website/common/script/libs/errorMessage.js b/website/common/script/libs/errorMessage.js
new file mode 100644
index 0000000000..d083e6cdfa
--- /dev/null
+++ b/website/common/script/libs/errorMessage.js
@@ -0,0 +1,16 @@
+// errorMessage(key) will be called by all common-ops , which is also imported to the website
+
+import _clone from 'lodash/clone';
+import _template from 'lodash/template';
+
+import messages from '../../errors/commonErrorMessages';
+
+export default function (msgKey, vars = {}) {
+ let message = messages[msgKey];
+ if (!message) throw new Error(`Error processing the common message "${msgKey}".`);
+
+ let clonedVars = vars ? _clone(vars) : {};
+
+ // TODO cache the result of template() ? More memory usage, faster output
+ return _template(message)(clonedVars);
+}
diff --git a/website/common/script/ops/buy/buy.js b/website/common/script/ops/buy/buy.js
index f0ec31e5f2..e3cb62bdca 100644
--- a/website/common/script/ops/buy/buy.js
+++ b/website/common/script/ops/buy/buy.js
@@ -1,4 +1,3 @@
-import i18n from '../../i18n';
import get from 'lodash/get';
import {
BadRequest,
@@ -11,6 +10,7 @@ import {BuyQuestWithGoldOperation} from './buyQuest';
import buySpecialSpell from './buySpecialSpell';
import purchaseOp from './purchase';
import hourglassPurchase from './hourglassPurchase';
+import errorMessage from '../../libs/errorMessage';
import {BuyGemOperation} from './buyGem';
// @TODO: remove the req option style. Dependency on express structure is an anti-pattern
@@ -20,7 +20,7 @@ import {BuyGemOperation} from './buyGem';
module.exports = function buy (user, req = {}, analytics) {
let key = get(req, 'params.key');
- if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
// @TODO: Slowly remove the need for key and use type instead
// This should evenutally be the 'factory' function with vendor classes
diff --git a/website/common/script/ops/buy/buyMarketGear.js b/website/common/script/ops/buy/buyMarketGear.js
index 06fe881e48..13408b18bb 100644
--- a/website/common/script/ops/buy/buyMarketGear.js
+++ b/website/common/script/ops/buy/buyMarketGear.js
@@ -13,6 +13,7 @@ import ultimateGear from '../../fns/ultimateGear';
import {removePinnedGearAddPossibleNewOnes} from '../pinnedGearUtils';
import { AbstractGoldItemOperation } from './abstractBuyOperation';
+import errorMessage from '../../libs/errorMessage';
export class BuyMarketGearOperation extends AbstractGoldItemOperation {
constructor (user, req, analytics) {
@@ -25,9 +26,10 @@ export class BuyMarketGearOperation extends AbstractGoldItemOperation {
extractAndValidateParams (user, req) {
let key = this.key = get(req, 'params.key');
- if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
+
let item = content.gear.flat[key];
- if (!item) throw new NotFound(this.i18n('itemNotFound', {key}));
+ if (!item) throw new NotFound(errorMessage('itemNotFound', {key}));
this.canUserPurchase(user, item);
diff --git a/website/common/script/ops/buy/buyMysterySet.js b/website/common/script/ops/buy/buyMysterySet.js
index 3a8b17a011..7e0bf0c83a 100644
--- a/website/common/script/ops/buy/buyMysterySet.js
+++ b/website/common/script/ops/buy/buyMysterySet.js
@@ -7,10 +7,11 @@ import {
NotAuthorized,
NotFound,
} from '../../libs/errors';
+import errorMessage from '../../libs/errorMessage';
module.exports = function buyMysterySet (user, req = {}, analytics) {
let key = get(req, 'params.key');
- if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
if (!(user.purchased.plan.consecutive.trinkets > 0)) {
throw new NotAuthorized(i18n.t('notEnoughHourglasses', req.language));
diff --git a/website/common/script/ops/buy/buyQuest.js b/website/common/script/ops/buy/buyQuest.js
index e30513347b..b7e9f783b9 100644
--- a/website/common/script/ops/buy/buyQuest.js
+++ b/website/common/script/ops/buy/buyQuest.js
@@ -7,6 +7,7 @@ import content from '../../content/index';
import get from 'lodash/get';
import {AbstractGoldItemOperation} from './abstractBuyOperation';
+import errorMessage from '../../libs/errorMessage';
export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
constructor (user, req, analytics) {
@@ -30,7 +31,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
extractAndValidateParams (user, req) {
let key = this.key = get(req, 'params.key');
- if (!key) throw new BadRequest(this.i18n('missingKeyParam'));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
if (key === 'lostMasterclasser1' && !this.userAbleToStartMasterClasser(user)) {
throw new NotAuthorized(this.i18n('questUnlockLostMasterclasser'));
@@ -38,7 +39,7 @@ export class BuyQuestWithGoldOperation extends AbstractGoldItemOperation {
let item = content.quests[key];
- if (!item) throw new NotFound(this.i18n('questNotFound', {key}));
+ if (!item) throw new NotFound(errorMessage('questNotFound', {key}));
if (!(item.category === 'gold' && item.goldValue)) {
throw new NotAuthorized(this.i18n('questNotGoldPurchasable', {key}));
diff --git a/website/common/script/ops/buy/buySpecialSpell.js b/website/common/script/ops/buy/buySpecialSpell.js
index d6a8492c81..d63638acfd 100644
--- a/website/common/script/ops/buy/buySpecialSpell.js
+++ b/website/common/script/ops/buy/buySpecialSpell.js
@@ -8,15 +8,16 @@ import {
NotAuthorized,
NotFound,
} from '../../libs/errors';
+import errorMessage from '../../libs/errorMessage';
module.exports = function buySpecialSpell (user, req = {}, analytics) {
let key = get(req, 'params.key');
let quantity = req.quantity || 1;
- if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
let item = content.special[key];
- if (!item) throw new NotFound(i18n.t('spellNotFound', {spellId: key}, req.language));
+ if (!item) throw new NotFound(errorMessage('spellNotFound', {spellId: key}));
if (user.stats.gp < item.value * quantity) {
throw new NotAuthorized(i18n.t('messageNotEnoughGold', req.language));
diff --git a/website/common/script/ops/buy/hourglassPurchase.js b/website/common/script/ops/buy/hourglassPurchase.js
index d9afc4b440..5354ee20bd 100644
--- a/website/common/script/ops/buy/hourglassPurchase.js
+++ b/website/common/script/ops/buy/hourglassPurchase.js
@@ -7,13 +7,14 @@ import {
BadRequest,
NotAuthorized,
} from '../../libs/errors';
+import errorMessage from '../../libs/errorMessage';
module.exports = function purchaseHourglass (user, req = {}, analytics) {
let key = get(req, 'params.key');
- if (!key) throw new BadRequest(i18n.t('missingKeyParam', req.language));
+ if (!key) throw new BadRequest(errorMessage('missingKeyParam'));
let type = get(req, 'params.type');
- if (!type) throw new BadRequest(i18n.t('missingTypeParam', req.language));
+ if (!type) throw new BadRequest(errorMessage('missingTypeParam'));
if (!content.timeTravelStable[type]) {
throw new NotAuthorized(i18n.t('typeNotAllowedHourglass', {allowedTypes: keys(content.timeTravelStable).toString()}, req.language));
diff --git a/website/common/script/ops/equip.js b/website/common/script/ops/equip.js
index 02f13e935c..679a5aa4a2 100644
--- a/website/common/script/ops/equip.js
+++ b/website/common/script/ops/equip.js
@@ -6,6 +6,7 @@ import {
BadRequest,
} from '../libs/errors';
import get from 'lodash/get';
+import errorMessage from '../libs/errorMessage';
module.exports = function equip (user, req = {}) {
// Being type a parameter followed by another parameter
@@ -13,9 +14,9 @@ module.exports = function equip (user, req = {}) {
let type = get(req, 'params.type', 'equipped');
let key = get(req, 'params.key');
- if (!key || !type) throw new BadRequest(i18n.t('missingTypeKeyEquip', req.language));
+ if (!key || !type) throw new BadRequest(errorMessage('missingTypeKeyEquip'));
if (['mount', 'pet', 'costume', 'equipped'].indexOf(type) === -1) {
- throw new BadRequest(i18n.t('invalidTypeEquip', req.language));
+ throw new BadRequest(errorMessage('invalidTypeEquip'));
}
let message;
diff --git a/website/common/script/ops/feed.js b/website/common/script/ops/feed.js
index cbe0e347f9..9e4582b71b 100644
--- a/website/common/script/ops/feed.js
+++ b/website/common/script/ops/feed.js
@@ -6,6 +6,7 @@ import {
NotAuthorized,
NotFound,
} from '../libs/errors';
+import errorMessage from '../libs/errorMessage';
function evolve (user, pet, req) {
user.items.pets[pet.key] = -1;
@@ -24,17 +25,17 @@ module.exports = function feed (user, req = {}) {
let pet = get(req, 'params.pet');
let foodK = get(req, 'params.food');
- if (!pet || !foodK) throw new BadRequest(i18n.t('missingPetFoodFeed', req.language));
+ if (!pet || !foodK) throw new BadRequest(errorMessage('missingPetFoodFeed'));
pet = content.petInfo[pet];
if (!pet) {
- throw new BadRequest(i18n.t('invalidPetName', req.language));
+ throw new BadRequest(errorMessage('invalidPetName'));
}
let food = content.food[foodK];
if (!food) {
- throw new NotFound(i18n.t('messageFoodNotFound', req.language));
+ throw new NotFound(errorMessage('invalidFoodName', req.language));
}
let userPets = user.items.pets;
diff --git a/website/common/script/ops/hatch.js b/website/common/script/ops/hatch.js
index 15129e03f0..eacb1c0e49 100644
--- a/website/common/script/ops/hatch.js
+++ b/website/common/script/ops/hatch.js
@@ -6,13 +6,14 @@ import {
NotAuthorized,
NotFound,
} from '../libs/errors';
+import errorMessage from '../libs/errorMessage';
module.exports = function hatch (user, req = {}) {
let egg = get(req, 'params.egg');
let hatchingPotion = get(req, 'params.hatchingPotion');
if (!(egg && hatchingPotion)) {
- throw new BadRequest(i18n.t('missingEggHatchingPotionHatch', req.language));
+ throw new BadRequest(errorMessage('missingEggHatchingPotion'));
}
if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) {
diff --git a/website/common/script/ops/stats/allocate.js b/website/common/script/ops/stats/allocate.js
index 70b5944c92..d65b2e05cb 100644
--- a/website/common/script/ops/stats/allocate.js
+++ b/website/common/script/ops/stats/allocate.js
@@ -7,12 +7,13 @@ import {
NotAuthorized,
} from '../../libs/errors';
import i18n from '../../i18n';
+import errorMessage from '../../libs/errorMessage';
module.exports = function allocate (user, req = {}) {
let stat = get(req, 'query.stat', 'str');
if (ATTRIBUTES.indexOf(stat) === -1) {
- throw new BadRequest(i18n.t('invalidAttribute', {attr: stat}, req.language));
+ throw new BadRequest(errorMessage('invalidAttribute', {attr: stat}));
}
if (user.stats.points > 0) {
diff --git a/website/common/script/ops/stats/allocateBulk.js b/website/common/script/ops/stats/allocateBulk.js
index f44800a813..7a68972d03 100644
--- a/website/common/script/ops/stats/allocateBulk.js
+++ b/website/common/script/ops/stats/allocateBulk.js
@@ -7,17 +7,18 @@ import {
NotAuthorized,
} from '../../libs/errors';
import i18n from '../../i18n';
+import errorMessage from '../../libs/errorMessage';
module.exports = function allocateBulk (user, req = {}) {
const stats = get(req, 'body.stats');
- if (!stats) throw new BadRequest(i18n.t('statsObjectRequired', req.language));
+ if (!stats) throw new BadRequest(errorMessage('statsObjectRequired'));
const statKeys = Object.keys(stats);
const invalidStats = statKeys.filter(statKey => {
return ATTRIBUTES.indexOf(statKey) === -1;
});
if (invalidStats.length > 0) {
- throw new BadRequest(i18n.t('invalidAttribute', {attr: invalidStats.join(',')}, req.language));
+ throw new BadRequest(errorMessage('invalidAttribute', {attr: invalidStats.join(',')}));
}
if (user.stats.points <= 0) {
diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js
index 46f39b022e..3ad57642b9 100644
--- a/website/server/controllers/api-v3/challenges.js
+++ b/website/server/controllers/api-v3/challenges.js
@@ -27,6 +27,7 @@ import {
createChallenge,
cleanUpTask,
} from '../../libs/challenges';
+import apiError from '../../libs/apiError';
let api = {};
@@ -189,7 +190,7 @@ api.createChallenge = {
async handler (req, res) {
let user = res.locals.user;
- req.checkBody('group', res.t('groupIdRequired')).notEmpty();
+ req.checkBody('group', apiError('groupIdRequired')).notEmpty();
const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -454,7 +455,7 @@ api.getGroupChallenges = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/chat.js b/website/server/controllers/api-v3/chat.js
index d3381e9184..34a3868efe 100644
--- a/website/server/controllers/api-v3/chat.js
+++ b/website/server/controllers/api-v3/chat.js
@@ -18,6 +18,7 @@ import bannedWords from '../../libs/bannedWords';
import guildsAllowingBannedWords from '../../libs/guildsAllowingBannedWords';
import { getMatchesByWordArray } from '../../libs/stringUtils';
import bannedSlurs from '../../libs/bannedSlurs';
+import apiError from '../../libs/apiError';
const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => {
return { email, canSend: true };
@@ -67,7 +68,7 @@ api.getChat = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -110,7 +111,7 @@ api.postChat = {
let groupId = req.params.groupId;
let chatUpdated;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
req.sanitize('message').trim();
req.checkBody('message', res.t('messageGroupChatBlankMessage')).notEmpty();
@@ -232,7 +233,7 @@ api.likeChat = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
req.checkParams('chatId', res.t('chatIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
@@ -323,7 +324,7 @@ api.clearChatFlags = {
let groupId = req.params.groupId;
let chatId = req.params.chatId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
req.checkParams('chatId', res.t('chatIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
@@ -394,7 +395,7 @@ api.seenChat = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -463,7 +464,7 @@ api.deleteChat = {
let groupId = req.params.groupId;
let chatId = req.params.chatId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
req.checkParams('chatId', res.t('chatIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
diff --git a/website/server/controllers/api-v3/coupon.js b/website/server/controllers/api-v3/coupon.js
index bec35182b4..f18644306e 100644
--- a/website/server/controllers/api-v3/coupon.js
+++ b/website/server/controllers/api-v3/coupon.js
@@ -7,6 +7,7 @@ import { ensureSudo } from '../../middlewares/ensureAccessRight';
import { model as Coupon } from '../../models/coupon';
import _ from 'lodash';
import couponCode from 'coupon-code';
+import apiError from '../../libs/apiError';
let api = {};
@@ -71,8 +72,8 @@ api.generateCoupons = {
userFieldsToExclude: ['inbox'],
}), ensureSudo],
async handler (req, res) {
- req.checkParams('event', res.t('eventRequired')).notEmpty();
- req.checkQuery('count', res.t('countRequired')).notEmpty().isNumeric();
+ req.checkParams('event', apiError('eventRequired')).notEmpty();
+ req.checkQuery('count', apiError('countRequired')).notEmpty().isNumeric();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js
index 2a97fb6de2..7e88d487b1 100644
--- a/website/server/controllers/api-v3/groups.js
+++ b/website/server/controllers/api-v3/groups.js
@@ -25,7 +25,7 @@ import payments from '../../libs/payments/payments';
import stripePayments from '../../libs/payments/stripe';
import amzLib from '../../libs/payments/amazon';
import shared from '../../../common';
-import apiMessages from '../../libs/apiMessages';
+import apiError from '../../libs/apiError';
const MAX_EMAIL_INVITES_BY_USER = 200;
const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS:TECH_ASSISTANCE_EMAIL');
@@ -279,7 +279,7 @@ api.createGroupPlan = {
*
* @apiError (400) {BadRequest} groupTypesRequired Group types are required
* @apiError (400) {BadRequest} guildsPaginateBooleanString Paginate query parameter must be a boolean (true or false)
- * @apiError (400) {BadRequest} guildsPageInteger Page query parameter must be a positive integer
+ * @apiError (400) {BadRequest} queryPageInteger Page query parameter must be a positive integer
* @apiError (400) {BadRequest} guildsOnlyPaginate Only public guilds support pagination
*
* @apiSuccess {Object[]} data An array of the requested groups (See /website/server/models/group.js)
@@ -301,8 +301,8 @@ api.getGroups = {
req.checkQuery('type', res.t('groupTypesRequired')).notEmpty();
// pagination options, can only be used with public guilds
- req.checkQuery('paginate').optional().isIn(['true', 'false'], apiMessages('guildsPaginateBooleanString'));
- req.checkQuery('page').optional().isInt({min: 0}, apiMessages('guildsPageInteger'));
+ req.checkQuery('paginate').optional().isIn(['true', 'false'], apiError('guildsPaginateBooleanString'));
+ req.checkQuery('page').optional().isInt({min: 0}, apiError('queryPageInteger'));
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -311,7 +311,7 @@ api.getGroups = {
let paginate = req.query.paginate === 'true' ? true : false;
if (paginate && !_.includes(types, 'publicGuilds')) {
- throw new BadRequest(apiMessages('guildsOnlyPaginate'));
+ throw new BadRequest(apiError('guildsOnlyPaginate'));
}
let groupFields = basicGroupFields.concat(' description memberCount balance');
@@ -389,7 +389,7 @@ api.getGroup = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -449,7 +449,7 @@ api.updateGroup = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -515,7 +515,7 @@ api.joinGroup = {
let user = res.locals.user;
let inviter;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -687,7 +687,7 @@ api.rejectGroupInvite = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -763,10 +763,10 @@ api.leaveGroup = {
})],
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
// When removing the user from challenges, should we keep the tasks?
- req.checkQuery('keep', res.t('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']);
- req.checkBody('keepChallenges', res.t('remainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']);
+ req.checkQuery('keep', apiError('keepOrRemoveAll')).optional().isIn(['keep-all', 'remove-all']);
+ req.checkBody('keepChallenges', apiError('groupRemainOrLeaveChallenges')).optional().isIn(['remain-in-challenges', 'leave-challenges']);
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -853,7 +853,7 @@ api.removeGroupMember = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
req.checkParams('memberId', res.t('userIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
@@ -1175,7 +1175,7 @@ api.inviteToGroup = {
if (user.flags.chatRevoked) throw new NotAuthorized(res.t('cannotInviteWhenMuted'));
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
if (user.invitesSent >= MAX_EMAIL_INVITES_BY_USER) throw new NotAuthorized(res.t('inviteLimitReached', { techAssistanceEmail: TECH_ASSISTANCE_EMAIL }));
@@ -1239,8 +1239,8 @@ api.addGroupManager = {
let user = res.locals.user;
let managerId = req.body.managerId;
- req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
- req.checkBody('managerId', apiMessages('managerIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
+ req.checkBody('managerId', apiError('managerIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -1290,8 +1290,8 @@ api.removeGroupManager = {
let user = res.locals.user;
let managerId = req.body.managerId;
- req.checkParams('groupId', apiMessages('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
- req.checkBody('managerId', apiMessages('managerIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty(); // .isUUID(); can't be used because it would block 'habitrpg' or 'party'
+ req.checkBody('managerId', apiError('managerIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/hall.js b/website/server/controllers/api-v3/hall.js
index f713ac8568..6abfb65d47 100644
--- a/website/server/controllers/api-v3/hall.js
+++ b/website/server/controllers/api-v3/hall.js
@@ -5,6 +5,7 @@ import {
NotFound,
} from '../../libs/errors';
import _ from 'lodash';
+import apiError from '../../libs/apiError';
let api = {};
@@ -64,7 +65,7 @@ api.getPatrons = {
userFieldsToExclude: ['inbox'],
})],
async handler (req, res) {
- req.checkQuery('page', res.t('pageMustBeNumber')).optional().isNumeric();
+ req.checkQuery('page').optional().isInt({min: 0}, apiError('queryPageInteger'));
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/quests.js b/website/server/controllers/api-v3/quests.js
index b08585e892..0abf6c67c5 100644
--- a/website/server/controllers/api-v3/quests.js
+++ b/website/server/controllers/api-v3/quests.js
@@ -17,6 +17,7 @@ import {
} from '../../libs/email';
import common from '../../../common';
import { sendNotification as sendPushNotification } from '../../libs/pushNotifications';
+import apiError from '../../libs/apiError';
const questScrolls = common.content.quests;
@@ -62,7 +63,7 @@ api.inviteToQuest = {
let questKey = req.params.questKey;
let quest = questScrolls[questKey];
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -71,7 +72,7 @@ api.inviteToQuest = {
if (!group) throw new NotFound(res.t('groupNotFound'));
if (group.type !== 'party') throw new NotAuthorized(res.t('guildQuestsNotSupported'));
- if (!quest) throw new NotFound(res.t('questNotFound', { key: questKey }));
+ if (!quest) throw new NotFound(apiError('questNotFound', { key: questKey }));
if (!user.items.quests[questKey]) throw new NotAuthorized(res.t('questNotOwned'));
if (user.stats.lvl < quest.lvl) throw new NotAuthorized(res.t('questLevelTooHigh', { level: quest.lvl }));
if (group.quest.key) throw new NotAuthorized(res.t('questAlreadyUnderway'));
@@ -176,7 +177,7 @@ api.acceptQuest = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -237,7 +238,7 @@ api.rejectQuest = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -302,7 +303,7 @@ api.forceStart = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -366,7 +367,7 @@ api.cancelQuest = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -420,7 +421,7 @@ api.abortQuest = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -481,7 +482,7 @@ api.leaveQuest = {
let user = res.locals.user;
let groupId = req.params.groupId;
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js
index e00b082512..92f28d7145 100644
--- a/website/server/controllers/api-v3/tasks.js
+++ b/website/server/controllers/api-v3/tasks.js
@@ -23,6 +23,7 @@ import common from '../../../common';
import _ from 'lodash';
import logger from '../../libs/logger';
import moment from 'moment';
+import apiError from '../../libs/apiError';
const MAX_SCORE_NOTES_LENGTH = 256;
@@ -430,7 +431,7 @@ api.updateTask = {
let user = res.locals.user;
let challenge;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -710,7 +711,7 @@ api.moveTask = {
url: '/tasks/:taskId/move/to/:position',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric();
let validationErrors = req.validationErrors();
@@ -783,7 +784,7 @@ api.addChecklistItem = {
let challenge;
let group;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -841,7 +842,7 @@ api.scoreCheckListItem = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
@@ -897,7 +898,7 @@ api.updateChecklistItem = {
let challenge;
let group;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
@@ -962,7 +963,7 @@ api.removeChecklistItem = {
let challenge;
let group;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('itemId', res.t('itemIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
@@ -1023,7 +1024,7 @@ api.addTagToTask = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
let userTags = user.tags.map(tag => tag.id);
req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID().isIn(userTags);
@@ -1072,7 +1073,7 @@ api.removeTagFromTask = {
async handler (req, res) {
let user = res.locals.user;
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
@@ -1116,7 +1117,7 @@ api.unlinkAllTasks = {
middlewares: [authWithHeaders()],
async handler (req, res) {
req.checkParams('challengeId', res.t('challengeIdRequired')).notEmpty().isUUID();
- req.checkQuery('keep', res.t('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']);
+ req.checkQuery('keep', apiError('keepOrRemoveAll')).notEmpty().isIn(['keep-all', 'remove-all']);
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
@@ -1182,8 +1183,8 @@ api.unlinkOneTask = {
url: '/tasks/unlink-one/:taskId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID();
- req.checkQuery('keep', res.t('keepOrRemove')).notEmpty().isIn(['keep', 'remove']);
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty().isUUID();
+ req.checkQuery('keep', apiError('keepOrRemove')).notEmpty().isIn(['keep', 'remove']);
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js
index 5065ebc0c8..9a920b5b3e 100644
--- a/website/server/controllers/api-v3/tasks/groups.js
+++ b/website/server/controllers/api-v3/tasks/groups.js
@@ -12,6 +12,7 @@ import {
getTasks,
moveTask,
} from '../../../libs/taskManager';
+import apiError from '../../../libs/apiError';
let requiredGroupFields = '_id leader tasksOrder name';
let types = Tasks.tasksTypes.map(type => `${type}s`);
@@ -40,7 +41,7 @@ api.createGroupTasks = {
url: '/tasks/group/:groupId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty().isUUID();
let reqValidationErrors = req.validationErrors();
if (reqValidationErrors) throw reqValidationErrors;
@@ -84,7 +85,7 @@ api.getGroupTasks = {
url: '/tasks/group/:groupId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty().isUUID();
req.checkQuery('type', res.t('invalidTasksType')).optional().isIn(types);
let validationErrors = req.validationErrors();
@@ -117,7 +118,7 @@ api.groupMoveTask = {
url: '/group-tasks/:taskId/move/to/:position',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty();
req.checkParams('position', res.t('positionRequired')).notEmpty().isNumeric();
let reqValidationErrors = req.validationErrors();
@@ -168,7 +169,7 @@ api.assignTask = {
url: '/tasks/:taskId/assign/:assignedUserId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty().isUUID();
req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID();
let reqValidationErrors = req.validationErrors();
@@ -228,7 +229,7 @@ api.unassignTask = {
url: '/tasks/:taskId/unassign/:assignedUserId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty().isUUID();
req.checkParams('assignedUserId', res.t('userIdRequired')).notEmpty().isUUID();
let reqValidationErrors = req.validationErrors();
@@ -278,7 +279,7 @@ api.approveTask = {
url: '/tasks/:taskId/approve/:userId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty().isUUID();
req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID();
let reqValidationErrors = req.validationErrors();
@@ -374,7 +375,7 @@ api.taskNeedsWork = {
url: '/tasks/:taskId/needs-work/:userId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('taskId', res.t('taskIdRequired')).notEmpty().isUUID();
+ req.checkParams('taskId', apiError('taskIdRequired')).notEmpty().isUUID();
req.checkParams('userId', res.t('userIdRequired')).notEmpty().isUUID();
let reqValidationErrors = req.validationErrors();
@@ -471,7 +472,7 @@ api.getGroupApprovals = {
url: '/approvals/group/:groupId',
middlewares: [authWithHeaders()],
async handler (req, res) {
- req.checkParams('groupId', res.t('groupIdRequired')).notEmpty().isUUID();
+ req.checkParams('groupId', apiError('groupIdRequired')).notEmpty().isUUID();
let validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
diff --git a/website/server/controllers/api-v3/user/spells.js b/website/server/controllers/api-v3/user/spells.js
index 33d2eee575..3a8e6a56d9 100644
--- a/website/server/controllers/api-v3/user/spells.js
+++ b/website/server/controllers/api-v3/user/spells.js
@@ -14,6 +14,7 @@ import {
castPartySpell,
castUserSpell,
} from '../../../libs/spells';
+import apiError from '../../../libs/apiError';
const partyMembersFields = 'profile.name stats achievements items.special';
@@ -85,7 +86,7 @@ api.castSpell = {
let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class;
let spell = common.content.spells[klass][spellId];
- if (!spell) throw new NotFound(res.t('spellNotFound', {spellId}));
+ if (!spell) throw new NotFound(apiError('spellNotFound', {spellId}));
if (spell.mana > user.stats.mp) throw new NotAuthorized(res.t('notEnoughMana'));
if (spell.value > user.stats.gp && !spell.previousPurchase) throw new NotAuthorized(res.t('messageNotEnoughGold'));
if (spell.lvl > user.stats.lvl) throw new NotAuthorized(res.t('spellLevelTooHigh', {level: spell.lvl}));
diff --git a/website/server/controllers/top-level/payments/paypal.js b/website/server/controllers/top-level/payments/paypal.js
index 36b7b7a189..cb3f9a00af 100644
--- a/website/server/controllers/top-level/payments/paypal.js
+++ b/website/server/controllers/top-level/payments/paypal.js
@@ -8,8 +8,7 @@ import {
import {
BadRequest,
} from '../../../libs/errors';
-
-const i18n = shared.i18n;
+import apiError from '../../../libs/apiError';
let api = {};
@@ -54,8 +53,8 @@ api.checkoutSuccess = {
let gift = req.session.gift ? JSON.parse(req.session.gift) : undefined;
delete req.session.gift;
- if (!paymentId) throw new BadRequest(i18n.t('missingPaymentId'));
- if (!customerId) throw new BadRequest(i18n.t('missingCustomerId'));
+ if (!paymentId) throw new BadRequest(apiError('missingPaymentId'));
+ if (!customerId) throw new BadRequest(apiError('missingCustomerId'));
await paypalPayments.checkoutSuccess({user, gift, paymentId, customerId});
@@ -78,7 +77,7 @@ api.subscribe = {
url: '/paypal/subscribe',
middlewares: [authWithUrl],
async handler (req, res) {
- if (!req.query.sub) throw new BadRequest(i18n.t('missingSubKey'));
+ if (!req.query.sub) throw new BadRequest(apiError('missingSubKey'));
let sub = shared.content.subscriptionBlocks[req.query.sub];
let coupon = req.query.coupon;
@@ -109,7 +108,7 @@ api.subscribeSuccess = {
async handler (req, res) {
let user = res.locals.user;
- if (!req.session.paypalBlock) throw new BadRequest(i18n.t('missingPaypalBlock'));
+ if (!req.session.paypalBlock) throw new BadRequest(apiError('missingPaypalBlock'));
let block = shared.content.subscriptionBlocks[req.session.paypalBlock];
let groupId = req.session.groupId;
diff --git a/website/server/libs/apiError.js b/website/server/libs/apiError.js
new file mode 100644
index 0000000000..ac0066636a
--- /dev/null
+++ b/website/server/libs/apiError.js
@@ -0,0 +1,18 @@
+// apiError(key) will be called by all controllers / api tests
+// it includes the api- and commonErrors, since common-ops are used in the api too
+
+import _ from 'lodash';
+
+import commonErrors from '../../common/errors/commonErrorMessages';
+import apiErrors from '../../common/errors/apiErrorMessages';
+
+export default function (msgKey, vars = {}) {
+ let message = apiErrors[msgKey];
+ if (!message) message = commonErrors[msgKey];
+ if (!message) throw new Error(`Error processing the API message "${msgKey}".`);
+
+ let clonedVars = vars ? _.clone(vars) : {};
+
+ // TODO cache the result of template() ? More memory usage, faster output
+ return _.template(message)(clonedVars);
+}
diff --git a/website/server/libs/apiMessages.js b/website/server/libs/apiMessages.js
deleted file mode 100644
index f368228dbb..0000000000
--- a/website/server/libs/apiMessages.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// A map of messages used by the API that don't need to be translated and
-// so are not placed into /common/locales
-
-import _ from 'lodash';
-
-// When this file grows, it can be split into multiple ones.
-const messages = {
- guildsOnlyPaginate: 'Only public guilds support pagination.',
- guildsPaginateBooleanString: 'req.query.paginate must be a boolean string.',
- guildsPageInteger: 'req.query.page must be an integer greater than or equal to 0.',
- groupIdRequired: 'req.params.groupId must contain a groupId.',
- managerIdRequired: 'req.body.managerId must contain a user ID.',
- noSudoAccess: 'You don\'t have sudo access',
-};
-
-export default function (msgKey, vars = {}) {
- let message = messages[msgKey];
- if (!message) throw new Error(`Error processing the API message "${msgKey}".`);
-
- let clonedVars = vars ? _.clone(vars) : {};
-
- // TODO cache the result of template() ? More memory usage, faster output
- return _.template(message)(clonedVars);
-}
diff --git a/website/server/libs/chatReporting/groupChatReporter.js b/website/server/libs/chatReporting/groupChatReporter.js
index ef39eb951d..c344607418 100644
--- a/website/server/libs/chatReporting/groupChatReporter.js
+++ b/website/server/libs/chatReporting/groupChatReporter.js
@@ -9,6 +9,7 @@ import { getGroupUrl, sendTxn } from '../email';
import slack from '../slack';
import { model as Group } from '../../models/group';
import { model as Chat } from '../../models/chat';
+import apiError from '../apiError';
const COMMUNITY_MANAGER_EMAIL = nconf.get('EMAILS:COMMUNITY_MANAGER_EMAIL');
const FLAG_REPORT_EMAILS = nconf.get('FLAG_REPORT_EMAIL').split(',').map((email) => {
@@ -24,7 +25,7 @@ export default class GroupChatReporter extends ChatReporter {
}
async validate () {
- this.req.checkParams('groupId', this.res.t('groupIdRequired')).notEmpty();
+ this.req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
this.req.checkParams('chatId', this.res.t('chatIdRequired')).notEmpty();
let validationErrors = this.req.validationErrors();
diff --git a/website/server/middlewares/ensureAccessRight.js b/website/server/middlewares/ensureAccessRight.js
index e6debdc066..4e38f04c5b 100644
--- a/website/server/middlewares/ensureAccessRight.js
+++ b/website/server/middlewares/ensureAccessRight.js
@@ -1,7 +1,7 @@
import {
NotAuthorized,
} from '../libs/errors';
-import apiMessages from '../libs/apiMessages';
+import apiError from '../libs/apiError';
export function ensureAdmin (req, res, next) {
let user = res.locals.user;
@@ -17,7 +17,7 @@ export function ensureSudo (req, res, next) {
let user = res.locals.user;
if (!user.contributor.sudo) {
- return next(new NotAuthorized(apiMessages('noSudoAccess')));
+ return next(new NotAuthorized(apiError('noSudoAccess')));
}
next();
diff --git a/website/server/models/webhook.js b/website/server/models/webhook.js
index b1ed0a94d3..09dd6dd15c 100644
--- a/website/server/models/webhook.js
+++ b/website/server/models/webhook.js
@@ -6,6 +6,7 @@ import {v4 as uuid} from 'uuid';
import _ from 'lodash';
import { BadRequest } from '../libs/errors';
import nconf from 'nconf';
+import apiError from '../libs/apiError';
const IS_PRODUCTION = nconf.get('IS_PROD');
const Schema = mongoose.Schema;
@@ -95,7 +96,7 @@ schema.methods.formatOptions = function formatOptions (res) {
this.options = _.pick(this.options, 'groupId');
if (!validator.isUUID(String(this.options.groupId))) {
- throw new BadRequest(res.t('groupIdRequired'));
+ throw new BadRequest(apiError('groupIdRequired'));
}
} else if (this.type === 'userActivity') {
_.defaults(this.options, USER_ACTIVITY_DEFAULT_OPTIONS);