0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

feat(core): align connector error handler middleware with ConnectorErrorCodes (#1063)

* feat(core): align connector error handler middleware with ConnectorErrorCodes

* feat(phrases,core): fix locale error descriptions
This commit is contained in:
Darcy Ye 2022-06-10 10:25:28 +08:00 committed by GitHub
parent 36dda2bdbb
commit 1b8190addf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 213 additions and 12 deletions

View file

@ -9,7 +9,7 @@ import mount from 'koa-mount';
import envSet, { MountedApps } from '@/env-set';
import koaCheckDemoApp from '@/middleware/koa-check-demo-app';
import koaConnectorErrorHandler from '@/middleware/koa-connector-error-handle';
import koaConnectorErrorHandler from '@/middleware/koa-connector-error-handler';
import koaErrorHandler from '@/middleware/koa-error-handler';
import koaI18next from '@/middleware/koa-i18next';
import koaLog from '@/middleware/koa-log';

View file

@ -0,0 +1,169 @@
import { ConnectorError, ConnectorErrorCodes } from '@logto/connector-types';
import RequestError from '@/errors/RequestError';
import { createContextWithRouteParameters } from '@/utils/test-utils';
import koaConnectorErrorHandler from './koa-connector-error-handler';
describe('koaConnectorErrorHandler middleware', () => {
const next = jest.fn();
const ctx = createContextWithRouteParameters();
it('should throw no errors if no errors are caught', async () => {
await expect(koaConnectorErrorHandler()(ctx, next)).resolves.not.toThrow();
});
it('should throw original error if error type is not ConnectorError', async () => {
const error = new Error('err');
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(error);
});
it('Insufficient Request Parameters', async () => {
const message = 'Mock Insufficient Request Parameters';
const error = new ConnectorError(ConnectorErrorCodes.InsufficientRequestParameters, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.insufficient_request_parameters',
status: 400,
},
{ message }
)
);
});
it('Invalid Config', async () => {
const message = 'Mock Invalid Config';
const error = new ConnectorError(ConnectorErrorCodes.InvalidConfig, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.invalid_config',
status: 400,
},
{ message }
)
);
});
it('Invalid Response', async () => {
const message = 'Mock Invalid Response';
const error = new ConnectorError(ConnectorErrorCodes.InvalidResponse, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.invalid_response',
status: 400,
},
{ message }
)
);
});
it('Template Not Found', async () => {
const message = 'Mock Template Not Found';
const error = new ConnectorError(ConnectorErrorCodes.TemplateNotFound, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.template_not_found',
status: 500,
},
{ message }
)
);
});
it('Social Auth Code Invalid', async () => {
const message = 'Mock Social Auth Code Invalid';
const error = new ConnectorError(ConnectorErrorCodes.SocialAuthCodeInvalid, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.oauth_code_invalid',
status: 401,
},
{ message }
)
);
});
it('Social Access Token Invalid', async () => {
const message = 'Mock Social Access Token Invalid';
const error = new ConnectorError(ConnectorErrorCodes.SocialAccessTokenInvalid, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.invalid_access_token',
status: 401,
},
{ message }
)
);
});
it('Social Id Token Invalid', async () => {
const message = 'Mock Social Id Token Invalid';
const error = new ConnectorError(ConnectorErrorCodes.SocialIdTokenInvalid, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.invalid_id_token',
status: 401,
},
{ message }
)
);
});
it('General connector errors', async () => {
const message = 'Mock General connector errors';
const error = new ConnectorError(ConnectorErrorCodes.General, message);
next.mockImplementationOnce(() => {
throw error;
});
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
new RequestError(
{
code: 'connector.general',
status: 500,
},
{ message }
)
);
});
});

View file

@ -18,6 +18,14 @@ export default function koaConnectorErrorHandler<StateT, ContextT>(): Middleware
const data = { message };
switch (code) {
case ConnectorErrorCodes.InsufficientRequestParameters:
throw new RequestError(
{
code: 'connector.insufficient_request_parameters',
status: 400,
},
data
);
case ConnectorErrorCodes.InvalidConfig:
throw new RequestError(
{
@ -26,11 +34,19 @@ export default function koaConnectorErrorHandler<StateT, ContextT>(): Middleware
},
data
);
case ConnectorErrorCodes.SocialAccessTokenInvalid:
case ConnectorErrorCodes.InvalidResponse:
throw new RequestError(
{
code: 'connector.access_token_invalid',
status: 401,
code: 'connector.invalid_response',
status: 400,
},
data
);
case ConnectorErrorCodes.TemplateNotFound:
throw new RequestError(
{
code: 'connector.template_not_found',
status: 500,
},
data
);
@ -42,11 +58,19 @@ export default function koaConnectorErrorHandler<StateT, ContextT>(): Middleware
},
data
);
case ConnectorErrorCodes.TemplateNotFound:
case ConnectorErrorCodes.SocialAccessTokenInvalid:
throw new RequestError(
{
code: 'connector.template_not_found',
status: 500,
code: 'connector.invalid_access_token',
status: 401,
},
data
);
case ConnectorErrorCodes.SocialIdTokenInvalid:
throw new RequestError(
{
code: 'connector.invalid_id_token',
status: 401,
},
data
);

View file

@ -9,11 +9,11 @@ describe('koaOIDCErrorHandler middleware', () => {
const next = jest.fn();
const ctx = createContextWithRouteParameters();
it('should throw no errors if no errors are catched', async () => {
it('should throw no errors if no errors are caught', async () => {
await expect(koaOIDCErrorHandler()(ctx, next)).resolves.not.toThrow();
});
it('should throw original error if error type is no OIDCProviderError', async () => {
it('should throw original error if error type is not OIDCProviderError', async () => {
const error = new Error('err');
next.mockImplementationOnce(() => {

View file

@ -11,7 +11,7 @@ describe('koaSlonikErrorHandler middleware', () => {
const next = jest.fn();
const ctx = createContextWithRouteParameters();
it('should throw no errors if no errors are catched', async () => {
it('should throw no errors if no errors are caught', async () => {
await expect(koaSlonikErrorHandler()(ctx, next)).resolves.not.toThrow();
});

View file

@ -639,9 +639,13 @@ const errors = {
general: 'An unexpected error occurred in connector.',
not_found: 'Cannot find any available connector for type: {{type}}.',
not_enabled: 'The connector is not enabled.',
insufficient_request_parameters: 'The request might miss some input parameters.',
invalid_config: "The connector's config is invalid.",
invalid_response: "The connector's response is invalid.",
template_not_found: 'Unable to find correct template in connector config.',
access_token_invalid: "Connector's access token is invalid.",
invalid_access_token: "The connector's access token is invalid.",
invalid_auth_code: "The connector's auth code is invalid.",
invalid_id_token: "The connector's id token is invalid.",
oauth_code_invalid: 'Unable to get access token, please check authorization code.',
more_than_one_sms: 'The number of SMS connectors is larger then 1.',
more_than_one_email: 'The number of Email connectors is larger then 1.',

View file

@ -621,9 +621,13 @@ const errors = {
general: '连接器发生未知错误。',
not_found: '找不到可用的 {{type}} 类型的连接器。',
not_enabled: '连接器尚未启用。',
insufficient_request_parameters: '请求参数缺失。',
invalid_config: '连接器配置错误。',
invalid_response: '连接器错误响应。',
template_not_found: '无法从连接器配置中找到对应的模板。',
access_token_invalid: '当前连接器的 access_token 无效。',
invalid_access_token: '当前连接器的 access_token 无效。',
invalid_auth_code: '当前连接器的授权码无效。',
invalid_id_token: '当前连接器的 id_token 无效。',
oauth_code_invalid: '无法获取 access_token请检查授权 code 是否有效。',
more_than_one_sms: '同时存在超过 1 个短信连接器。',
more_than_one_email: '同时存在超过 1 个邮件连接器。',