feat: internationalize API error messages

v1.18.x
Julian Lam 4 years ago
parent a54a3ee1ca
commit 7036c3751e

@ -230,5 +230,16 @@
"topic-event-unrecognized": "Topic event '%1' unrecognized", "topic-event-unrecognized": "Topic event '%1' unrecognized",
"cant-set-child-as-parent": "Can't set child as parent category", "cant-set-child-as-parent": "Can't set child as parent category",
"cant-set-self-as-parent": "Can't set self as parent category" "cant-set-self-as-parent": "Can't set self as parent category",
"api.master-token-no-uid": "A master token was received without a corresponding `_uid` in the request body",
"api.400": "Something was wrong with the request payload you passed in.",
"api.401": "A valid login session was not found. Please log in and try again.",
"api.403": "You are not authorised to make this call",
"api.404": "Invalid API call",
"api.426": "HTTPS is required for requests to the write api, please re-send your request via HTTPS",
"api.429": "You have made too many requests, please try again later",
"api.500": "An unexpected error was encountered while attempting to service your request.",
"api.501": "The route you are trying to call is not implemented yet, please try again tomorrow",
"api.503": "The route you are trying to call is not currently available due to a server configuration"
} }

@ -3,6 +3,7 @@
const nconf = require('nconf'); const nconf = require('nconf');
const winston = require('winston'); const winston = require('winston');
const validator = require('validator'); const validator = require('validator');
const translator = require('../translator');
const plugins = require('../plugins'); const plugins = require('../plugins');
const middleware = require('../middleware'); const middleware = require('../middleware');
const middlewareHelpers = require('../middleware/helpers'); const middlewareHelpers = require('../middleware/helpers');
@ -57,7 +58,12 @@ exports.handleErrors = function handleErrors(err, req, res, next) { // eslint-di
const path = String(req.path || ''); const path = String(req.path || '');
if (path.startsWith(`${nconf.get('relative_path')}/api/v3`)) { if (path.startsWith(`${nconf.get('relative_path')}/api/v3`)) {
return helpers.formatApiResponse(err.message.startsWith('[[') ? 400 : 500, res, err); let status = 500;
if (err.message.startsWith('[[')) {
status = 400;
err.message = await translator.translate(err.message);
}
return helpers.formatApiResponse(status, res, err);
} }
winston.error(`${req.path}\n${err.stack}`); winston.error(`${req.path}\n${err.stack}`);

@ -6,6 +6,7 @@ const validator = require('validator');
const querystring = require('querystring'); const querystring = require('querystring');
const _ = require('lodash'); const _ = require('lodash');
const translator = require('../translator');
const user = require('../user'); const user = require('../user');
const privileges = require('../privileges'); const privileges = require('../privileges');
const categories = require('../categories'); const categories = require('../categories');
@ -456,7 +457,7 @@ helpers.formatApiResponse = async (statusCode, res, payload) => {
break; break;
} }
const returnPayload = helpers.generateError(statusCode, message); const returnPayload = await helpers.generateError(statusCode, message);
returnPayload.response = response; returnPayload.response = response;
if (global.env === 'development') { if (global.env === 'development') {
@ -467,7 +468,8 @@ helpers.formatApiResponse = async (statusCode, res, payload) => {
res.status(statusCode).json(returnPayload); res.status(statusCode).json(returnPayload);
} else if (!payload) { } else if (!payload) {
// Non-2xx statusCode, generate predefined error // Non-2xx statusCode, generate predefined error
res.status(statusCode).json(helpers.generateError(statusCode)); const returnPayload = await helpers.generateError(statusCode);
res.status(statusCode).json(returnPayload);
} }
}; };
@ -490,60 +492,50 @@ async function generateBannedResponse(res) {
return response; return response;
} }
helpers.generateError = (statusCode, message) => { helpers.generateError = async (statusCode, message) => {
const payload = { const payload = {
status: { status: {
code: 'internal-server-error', code: 'internal-server-error',
message: 'An unexpected error was encountered while attempting to service your request.', message: message || await translator.translate(`[[error:api.${statusCode}]]`),
}, },
response: {}, response: {},
}; };
// Need to turn all these into translation strings
switch (statusCode) { switch (statusCode) {
case 400: case 400:
payload.status.code = 'bad-request'; payload.status.code = 'bad-request';
payload.status.message = message || 'Something was wrong with the request payload you passed in.';
break; break;
case 401: case 401:
payload.status.code = 'not-authorised'; payload.status.code = 'not-authorised';
payload.status.message = message || 'A valid login session was not found. Please log in and try again.';
break; break;
case 403: case 403:
payload.status.code = 'forbidden'; payload.status.code = 'forbidden';
payload.status.message = message || 'You are not authorised to make this call';
break; break;
case 404: case 404:
payload.status.code = 'not-found'; payload.status.code = 'not-found';
payload.status.message = message || 'Invalid API call';
break; break;
case 426: case 426:
payload.status.code = 'upgrade-required'; payload.status.code = 'upgrade-required';
payload.status.message = message || 'HTTPS is required for requests to the write api, please re-send your request via HTTPS';
break; break;
case 429: case 429:
payload.status.code = 'too-many-requests'; payload.status.code = 'too-many-requests';
payload.status.message = message || 'You have made too many requests, please try again later';
break; break;
case 500: case 500:
payload.status.code = 'internal-server-error'; payload.status.code = 'internal-server-error';
payload.status.message = message || payload.status.message;
break; break;
case 501: case 501:
payload.status.code = 'not-implemented'; payload.status.code = 'not-implemented';
payload.status.message = message || 'The route you are trying to call is not implemented yet, please try again tomorrow';
break; break;
case 503: case 503:
payload.status.code = 'service-unavailable'; payload.status.code = 'service-unavailable';
payload.status.message = message || 'The route you are trying to call is not currently available due to a server configuration';
break; break;
} }

@ -65,7 +65,7 @@ module.exports = function (middleware) {
return true; return true;
} }
throw new Error('[[errors:api.master-token-no-uid]]'); throw new Error('[[error:api.master-token-no-uid]]');
} else { } else {
winston.warn('[api/authenticate] Unable to find user after verifying token'); winston.warn('[api/authenticate] Unable to find user after verifying token');
return true; return true;

Loading…
Cancel
Save