Files
habitica/website/server/libs/errors.js
Fiz f26d2a59ae add InvalidCredentialsError with language-agnostic code (#15472)
* add InvalidCredentialsError with language-agnostic code and update backend & web logout logic

* error.code in API error responses

Updated the error handler to serialize responseErr.code as the JSON error field, falling back to responseErr.name when no code is set.

* fix(lint): whitespace and missing def

* fix(lint): missed one

* add InvalidCredentialsError case for bad token

Add test verifying that auth middleware throws InvalidCredentialsError with code "invalid_credentials" and correct translated message when the API token is invalid.

* fix(test): user fields implicitly required

---------

Co-authored-by: Kalista Payne <sabrecat@gmail.com>
2025-07-15 09:49:11 -05:00

144 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import common from '../../common'; // eslint-disable-line max-classes-per-file
export const { CustomError } = common.errors;
/**
* @apiDefine NotAuthorized
* @apiError NotAuthorized The client is not authorized to make this request.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 401 Unauthorized
* {
* "error": "NotAuthorized",
* "message": "Not authorized."
* }
*/
export const { NotAuthorized } = common.errors;
/**
* @apiDefine BadRequest
* @apiError BadRequest The request wasn't formatted correctly.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 400 Bad Request
* {
* "error": "BadRequest",
* "message": "Bad request."
* }
*/
export const { BadRequest } = common.errors;
/**
* @apiDefine NotFound
* @apiError NotFound The requested resource was not found.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 404 Not Found
* {
* "error": "NotFound",
* "message": "Not found."
* }
*/
export const { NotFound } = common.errors;
/**
* @apiDefine Forbidden
* @apiError Forbidden The requested resource was not found.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 403 Forbidden
* {
* "error": "Forbidden",
* "message": "Access forbidden."
* }
*/
export const { Forbidden } = common.errors;
/**
* @apiDefine TooManyRequests
* @apiError TooManyRequests The client made too many requests to the API and was rate limited.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 429 TooManyRequests
* {
* "error": "TooManyRequests",
* "message": "Access forbidden."
* }
*/
export const { TooManyRequests } = common.errors;
/**
* @apiDefine RequestTimeout
* @apiError RequestTimeout The request took too long to complete.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 408 RequestTimeout
* {
* "error": "RequestTimeout",
* "message": "Access forbidden."
* }
*/
export const { RequestTimeout } = common.errors;
/**
* @apiDefine NotificationNotFound
* @apiError NotificationNotFound The notification was not found.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 404 Not Found
* {
* "error": "NotificationNotFound",
* "message": "Notification not found."
* }
*/
export class NotificationNotFound extends NotFound {
constructor (language) {
super(common.i18n.t('messageNotificationNotFound', language));
this.name = this.constructor.name;
}
}
/**
* @apiDefine InternalServerError
* @apiError InternalServerError An unexpected error occurred.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 500 Internal Server Error
* {
* "error": "InternalServerError",
* "message": "An unexpected error occurred."
* }
*/
export class InternalServerError extends CustomError {
constructor (customMessage) {
super();
this.name = this.constructor.name;
this.httpCode = 500;
this.message = customMessage || 'An unexpected error occurred.';
}
}
/**
* @apiDefine InvalidCredentials
* @apiError InvalidCredentials The users credentials are no longer valid.
*
* @apiNote
* The 'invalid_credentials' error code is language-agnostic:
* clients should use this code (regardless of locale or translated message)
* to unambiguously trigger a user logout.
*
* @apiErrorExample Error-Response:
* HTTP/1.1 401 Unauthorized
* {
* "error": "invalid_credentials",
* "message": "There is no account that uses those credentials."
* }
*/
export class InvalidCredentialsError extends NotAuthorized {
constructor (message) {
super(message);
this.name = this.constructor.name;
this.code = 'invalid_credentials';
}
}