mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(connector,phrases): cloud sms/email connectors error message (#3699)
This commit is contained in:
parent
8a07ef9fbd
commit
3e5b8dd796
23 changed files with 99 additions and 35 deletions
|
@ -74,7 +74,10 @@ const sendMessage =
|
|||
|
||||
assert(
|
||||
typeof rawBody === 'string',
|
||||
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
|
||||
new ConnectorError(
|
||||
ConnectorErrorCodes.InvalidResponse,
|
||||
`Invalid response raw body type: ${typeof rawBody}`
|
||||
)
|
||||
);
|
||||
|
||||
errorHandler(rawBody);
|
||||
|
|
|
@ -41,7 +41,10 @@ const sendMessage =
|
|||
|
||||
assert(
|
||||
template,
|
||||
new ConnectorError(ConnectorErrorCodes.TemplateNotFound, `Cannot find template!`)
|
||||
new ConnectorError(
|
||||
ConnectorErrorCodes.TemplateNotFound,
|
||||
`Cannot find template for type: ${type}`
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -56,37 +59,49 @@ const sendMessage =
|
|||
accessKeySecret
|
||||
);
|
||||
|
||||
const { body: rawBody } = httpResponse;
|
||||
const { Code, Message, ...rest } = parseResponseString(httpResponse.body);
|
||||
|
||||
const { Code, Message, ...rest } = parseResponseString(rawBody);
|
||||
assert(
|
||||
Code === 'OK',
|
||||
new ConnectorError(
|
||||
/**
|
||||
* See https://help.aliyun.com/document_detail/101347.html for more details.
|
||||
* Some errors (like rate limit) can be addressed by end users.
|
||||
*/
|
||||
Code === 'isv.BUSINESS_LIMIT_CONTROL'
|
||||
? ConnectorErrorCodes.RateLimitExceeded
|
||||
: ConnectorErrorCodes.General,
|
||||
{
|
||||
errorDescription: Message,
|
||||
Code,
|
||||
...rest,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
if (Code !== 'OK') {
|
||||
return { Code, Message, ...rest };
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof HTTPError) {
|
||||
const {
|
||||
response: { body: rawBody },
|
||||
} = error;
|
||||
|
||||
assert(
|
||||
typeof rawBody === 'string',
|
||||
new ConnectorError(
|
||||
ConnectorErrorCodes.InvalidResponse,
|
||||
`Invalid response raw body type: ${typeof rawBody}`
|
||||
)
|
||||
);
|
||||
|
||||
const { Message, ...rest } = parseResponseString(rawBody);
|
||||
throw new ConnectorError(ConnectorErrorCodes.General, {
|
||||
errorDescription: Message,
|
||||
Code,
|
||||
...rest,
|
||||
});
|
||||
}
|
||||
|
||||
return httpResponse;
|
||||
} catch (error: unknown) {
|
||||
if (!(error instanceof HTTPError)) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const {
|
||||
response: { body: rawBody },
|
||||
} = error;
|
||||
|
||||
assert(typeof rawBody === 'string', new ConnectorError(ConnectorErrorCodes.InvalidResponse));
|
||||
|
||||
const { Code, Message, ...rest } = parseResponseString(rawBody);
|
||||
|
||||
throw new ConnectorError(ConnectorErrorCodes.General, {
|
||||
errorDescription: Message,
|
||||
Code,
|
||||
...rest,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { assert } from '@silverhand/essentials';
|
||||
|
||||
import type { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2';
|
||||
import type { SESv2Client, SendEmailCommand, SendEmailCommandOutput } from '@aws-sdk/client-sesv2';
|
||||
import { SESv2ServiceException } from '@aws-sdk/client-sesv2';
|
||||
import type {
|
||||
CreateConnector,
|
||||
|
@ -42,18 +42,19 @@ const sendMessage =
|
|||
const command: SendEmailCommand = makeCommand(config, emailContent, to);
|
||||
|
||||
try {
|
||||
const response = await client.send(command);
|
||||
const response: SendEmailCommandOutput = await client.send(command);
|
||||
|
||||
if (response.$metadata.httpStatusCode !== 200) {
|
||||
throw new ConnectorError(ConnectorErrorCodes.InvalidResponse, { response });
|
||||
}
|
||||
assert(
|
||||
response.$metadata.httpStatusCode === 200,
|
||||
new ConnectorError(ConnectorErrorCodes.InvalidResponse, response)
|
||||
);
|
||||
|
||||
return response.MessageId;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof SESv2ServiceException) {
|
||||
const { message } = error;
|
||||
throw new ConnectorError(ConnectorErrorCodes.InvalidResponse, message);
|
||||
throw new ConnectorError(ConnectorErrorCodes.InvalidResponse, error.message);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -75,9 +75,13 @@ const sendMessage =
|
|||
const {
|
||||
response: { body: rawBody },
|
||||
} = error;
|
||||
|
||||
assert(
|
||||
typeof rawBody === 'string',
|
||||
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
|
||||
new ConnectorError(
|
||||
ConnectorErrorCodes.InvalidResponse,
|
||||
`Invalid response raw body type: ${typeof rawBody}`
|
||||
)
|
||||
);
|
||||
|
||||
throw new ConnectorError(ConnectorErrorCodes.General, rawBody);
|
||||
|
|
|
@ -60,7 +60,10 @@ const sendMessage =
|
|||
} = error;
|
||||
assert(
|
||||
typeof rawBody === 'string',
|
||||
new ConnectorError(ConnectorErrorCodes.InvalidResponse)
|
||||
new ConnectorError(
|
||||
ConnectorErrorCodes.InvalidResponse,
|
||||
`Invalid response raw body type: ${typeof rawBody}`
|
||||
)
|
||||
);
|
||||
|
||||
throw new ConnectorError(ConnectorErrorCodes.General, rawBody);
|
||||
|
|
|
@ -187,6 +187,24 @@ describe('koaConnectorErrorHandler middleware', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('Rate Limit Exceeded', async () => {
|
||||
const message = 'Mock Rate Limit Exceeded';
|
||||
const error = new ConnectorError(ConnectorErrorCodes.RateLimitExceeded, message);
|
||||
next.mockImplementationOnce(() => {
|
||||
throw error;
|
||||
});
|
||||
|
||||
await expect(koaConnectorErrorHandler()(ctx, next)).rejects.toMatchError(
|
||||
new RequestError(
|
||||
{
|
||||
code: 'connector.rate_limit_exceeded',
|
||||
status: 429,
|
||||
},
|
||||
{ message }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('General connector errors with string type messages', async () => {
|
||||
const message = 'Mock General connector errors';
|
||||
const error = new ConnectorError(ConnectorErrorCodes.General, message);
|
||||
|
|
|
@ -52,6 +52,10 @@ export default function koaConnectorErrorHandler<StateT, ContextT>(): Middleware
|
|||
throw new RequestError({ code: `connector.${code}`, status: 501 }, data);
|
||||
}
|
||||
|
||||
case ConnectorErrorCodes.RateLimitExceeded: {
|
||||
throw new RequestError({ code: `connector.${code}`, status: 429 }, data);
|
||||
}
|
||||
|
||||
default: {
|
||||
throw new RequestError(
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ const connector = {
|
|||
invalid_response: 'Die Antwort des Connectors ist ungültig.',
|
||||
template_not_found:
|
||||
'Die richtige Vorlage in der Connector-Konfiguration konnte nicht gefunden werden.',
|
||||
rate_limit_exceeded: 'Auslöser-Rate-Limit. Bitte versuchen Sie es später erneut.',
|
||||
not_implemented: '{{method}}: wurde noch nicht implementiert.',
|
||||
social_invalid_access_token: 'Der Access Token des Connectors ist ungültig.',
|
||||
invalid_auth_code: 'Der Authentifizierungscode des Connectors ist ungültig.',
|
||||
|
@ -38,5 +39,4 @@ const connector = {
|
|||
cannot_overwrite_metadata_for_non_standard_connector:
|
||||
"Die 'Metadaten' dieses Connectors können nicht überschrieben werden.",
|
||||
};
|
||||
|
||||
export default connector;
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
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.',
|
||||
rate_limit_exceeded: 'Trigger rate limit. Please try again later.',
|
||||
not_implemented: '{{method}}: has not been implemented yet.',
|
||||
social_invalid_access_token: "The connector's access token is invalid.",
|
||||
invalid_auth_code: "The connector's auth code is invalid.",
|
||||
|
|
|
@ -11,6 +11,7 @@ const connector = {
|
|||
invalid_response: 'La respuesta del conector es inválida.',
|
||||
template_not_found:
|
||||
'No se puede encontrar la plantilla correcta en la configuración del conector.',
|
||||
rate_limit_exceeded: 'Límite de frecuencia activado. Por favor, inténtalo de nuevo más tarde.',
|
||||
not_implemented: '{{method}}: aún no se ha implementado.',
|
||||
social_invalid_access_token: 'El token de acceso del conector es inválido.',
|
||||
invalid_auth_code: 'El código de autenticación del conector es inválido.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: "La configuration du connecteur n'est pas valide.",
|
||||
invalid_response: "La réponse du connecteur n'est pas valide.",
|
||||
template_not_found: 'Impossible de trouver le bon modèle dans la configuration du connecteur.',
|
||||
rate_limit_exceeded: 'Limite de taux déclenchée. Veuillez réessayer plus tard.',
|
||||
not_implemented: "{{method}} : n'a pas encore été mis en œuvre.",
|
||||
social_invalid_access_token: "Le jeton d'accès du connecteur n'est pas valide.",
|
||||
invalid_auth_code: "Le code d'authentification du connecteur n'est pas valide.",
|
||||
|
|
|
@ -11,6 +11,7 @@ const connector = {
|
|||
invalid_response: 'La risposta del connettore non è valida.',
|
||||
template_not_found:
|
||||
'Impossibile trovare il modello corretto nella configurazione del connettore.',
|
||||
rate_limit_exceeded: 'Limite di frequenza attivata. Riprova più tardi.',
|
||||
not_implemented: '{{method}}: non è stato ancora implementato.',
|
||||
social_invalid_access_token: 'Il token di accesso del connettore non è valido.',
|
||||
invalid_auth_code: 'Il codice di autenticazione del connettore non è valido.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: 'コネクタの設定が無効です。',
|
||||
invalid_response: 'コネクタのレスポンスが無効です。',
|
||||
template_not_found: 'コネクタ構成から正しいテンプレートを見つけることができませんでした。',
|
||||
rate_limit_exceeded: 'トリガーレート制限。後でもう一度お試しください。',
|
||||
not_implemented: '{{method}}:まだ実装されていません。',
|
||||
social_invalid_access_token: 'コネクタのアクセストークンが無効です。',
|
||||
invalid_auth_code: 'コネクタの認証コードが無効です。',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: '연동 설정이 유효하지 않아요.',
|
||||
invalid_response: '연동 응답이 유효하지 않아요.',
|
||||
template_not_found: '연동 예제 설정을 찾을 수 없어요.',
|
||||
rate_limit_exceeded: '트리거 주기 제한. 나중에 다시 시도하세요.',
|
||||
not_implemented: '{{method}}은 아직 구현되지 않았어요.',
|
||||
social_invalid_access_token: '연동 서비스의 Access 토큰이 유효하지 않아요.',
|
||||
invalid_auth_code: '연동 서비스의 Auth 코드가 유효하지 않아요.',
|
||||
|
|
|
@ -11,6 +11,7 @@ const connector = {
|
|||
invalid_config: 'Konfiguracja łącznika jest nieprawidłowa.',
|
||||
invalid_response: 'Odpowiedź łącznika jest nieprawidłowa.',
|
||||
template_not_found: 'Nie można znaleźć poprawnego szablonu w konfiguracji łącznika.',
|
||||
rate_limit_exceeded: 'Ograniczenie szybkości wywołań. Spróbuj ponownie później.',
|
||||
not_implemented: '{{method}}: jeszcze nie zaimplementowano.',
|
||||
social_invalid_access_token: 'Token dostępu łącznika jest nieprawidłowy.',
|
||||
invalid_auth_code: 'Kod autoryzacji łącznika jest nieprawidłowy.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: 'A configuração do conector é inválida.',
|
||||
invalid_response: 'A resposta do conector é inválida.',
|
||||
template_not_found: 'Não foi possível encontrar o modelo correto na configuração do conector.',
|
||||
rate_limit_exceeded: 'Limite de taxa de acionamento. Tente novamente mais tarde.',
|
||||
not_implemented: '{{method}}: ainda não foi implementado.',
|
||||
social_invalid_access_token: 'O token de acesso do conector é inválido.',
|
||||
invalid_auth_code: 'O código de autenticação do conector é inválido.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: 'A configuração do conector é inválida.',
|
||||
invalid_response: 'A resposta do conector é inválida.',
|
||||
template_not_found: 'Não foi possível encontrar o modelo correto na configuração do conector.',
|
||||
rate_limit_exceeded: 'Limite de taxa de ativação. Por favor, tente novamente mais tarde.',
|
||||
not_implemented: '{{method}}: ainda não foi implementado.',
|
||||
social_invalid_access_token: 'O token de acesso do conector é inválido.',
|
||||
invalid_auth_code: 'O código de autenticação do conector é inválido.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: 'Конфигурация коннектора недействительна.',
|
||||
invalid_response: 'Ответ коннектора недействителен.',
|
||||
template_not_found: 'Невозможно найти правильный шаблон в конфигурации коннектора.',
|
||||
rate_limit_exceeded: 'Превышен лимит запросов. Пожалуйста, попробуйте позже.',
|
||||
not_implemented: '{{method}}: еще не реализован.',
|
||||
social_invalid_access_token: 'Токен доступа коннектора недействителен.',
|
||||
invalid_auth_code: 'Код аутентификации коннектора недействителен.',
|
||||
|
@ -34,4 +35,5 @@ const connector = {
|
|||
cannot_overwrite_metadata_for_non_standard_connector:
|
||||
'Метаданные этого коннектора не могут быть перезаписаны.',
|
||||
};
|
||||
|
||||
export default connector;
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: 'Bağlayıcının ayarları geçersiz.',
|
||||
invalid_response: 'Bağlayıcının yanıtı geçersiz.',
|
||||
template_not_found: 'Bağlayıcı yapılandırmasında doğru şablon bulunamıyor.',
|
||||
rate_limit_exceeded: 'Tetikleyici oran sınırına ulaşıldı. Lütfen daha sonra tekrar deneyin.',
|
||||
not_implemented: '{{method}}: henüz uygulanmadı.',
|
||||
social_invalid_access_token: 'Bağlayıcının erişim tokenı geçersiz.',
|
||||
invalid_auth_code: 'Bağlayıcının yetki kodu geçersiz.',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: '连接器配置错误',
|
||||
invalid_response: '连接器错误响应',
|
||||
template_not_found: '无法从连接器配置中找到对应的模板',
|
||||
rate_limit_exceeded: '触发速率限制。请稍后再试。',
|
||||
not_implemented: '方法 {{method}} 尚未实现',
|
||||
social_invalid_access_token: '当前连接器的 access_token 无效',
|
||||
invalid_auth_code: '当前连接器的授权码无效',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: '連接器配置錯誤',
|
||||
invalid_response: '連接器錯誤響應',
|
||||
template_not_found: '無法從連接器配置中找到對應的模板',
|
||||
rate_limit_exceeded: '觸發速率限制。請稍後再試。',
|
||||
not_implemented: '方法 {{method}} 尚未實現',
|
||||
social_invalid_access_token: '當前連接器的 access_token 無效',
|
||||
invalid_auth_code: '當前連接器的授權碼無效',
|
||||
|
|
|
@ -10,6 +10,7 @@ const connector = {
|
|||
invalid_config: '連接器配置錯誤',
|
||||
invalid_response: '連接器錯誤響應',
|
||||
template_not_found: '無法從連接器配置中找到對應的模板',
|
||||
rate_limit_exceeded: '觸發速率限制。請稍後再試。',
|
||||
not_implemented: '方法 {{method}} 尚未實現',
|
||||
social_invalid_access_token: '當前連接器的 access_token 無效',
|
||||
invalid_auth_code: '當前連接器的授權碼無效',
|
||||
|
|
|
@ -49,6 +49,7 @@ export enum ConnectorErrorCodes {
|
|||
InvalidConfig = 'invalid_config',
|
||||
InvalidResponse = 'invalid_response',
|
||||
TemplateNotFound = 'template_not_found',
|
||||
RateLimitExceeded = 'rate_limit_exceeded',
|
||||
NotImplemented = 'not_implemented',
|
||||
SocialAuthCodeInvalid = 'social_auth_code_invalid',
|
||||
SocialAccessTokenInvalid = 'social_invalid_access_token',
|
||||
|
|
Loading…
Reference in a new issue