0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

refactor(connector): fix bugs

This commit is contained in:
Darcy Ye 2022-08-18 18:55:26 +08:00
parent b076ba4bc9
commit c4af31c195
No known key found for this signature in database
GPG key ID: B46F4C07EDEFC610
13 changed files with 111 additions and 77 deletions

View file

@ -60,7 +60,11 @@ describe('sendMessage()', () => {
});
it('should call singleSendMail() and replace code in content', async () => {
await aliyunDmMethods.sendMessage('to@email.com', 'SignIn', { code: '1234' });
await aliyunDmMethods.sendMessage({
to: 'to@email.com',
type: 'SignIn',
payload: { code: '1234' },
});
expect(singleSendMail).toHaveBeenCalledWith(
expect.objectContaining({
HtmlBody: 'Your code is 1234, 1234 is your code',
@ -71,7 +75,11 @@ describe('sendMessage()', () => {
it('throws if template is missing', async () => {
await expect(
aliyunDmMethods.sendMessage('to@email.com', 'Register', { code: '1234' })
aliyunDmMethods.sendMessage({
to: 'to@email.com',
type: 'Register',
payload: { code: '1234' },
})
).rejects.toThrow();
});
});

View file

@ -3,7 +3,7 @@ import {
ConnectorErrorCodes,
EmailConnector,
GetConnectorConfig,
SendMessageByFunction,
SendMessageFunction,
ValidateConfig,
} from '@logto/connector-schemas';
import { assert } from '@silverhand/essentials';
@ -34,12 +34,11 @@ export default class AliyunDmConnector extends EmailConnector<AliyunDmConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<AliyunDmConfig> = async (
config,
address,
type,
data
protected readonly sendMessageBy: SendMessageFunction<AliyunDmConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { accessKeyId, accessKeySecret, accountName, fromAlias, templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -58,12 +57,12 @@ export default class AliyunDmConnector extends EmailConnector<AliyunDmConfig> {
AccountName: accountName,
ReplyToAddress: 'false',
AddressType: '1',
ToAddress: address,
ToAddress: to,
FromAlias: fromAlias,
Subject: template.subject,
HtmlBody:
typeof data.code === 'string'
? template.content.replace(/{{code}}/g, data.code)
typeof payload.code === 'string'
? template.content.replace(/{{code}}/g, payload.code)
: template.content,
},
accessKeySecret

View file

@ -55,7 +55,11 @@ describe('sendMessage()', () => {
});
it('should call singleSendMail() and replace code in content', async () => {
await aliyunSmsMethods.sendMessage(phoneTest, 'SignIn', { code: codeTest });
await aliyunSmsMethods.sendMessage({
to: phoneTest,
type: 'SignIn',
payload: { code: codeTest },
});
expect(sendSms).toHaveBeenCalledWith(
expect.objectContaining({
AccessKeyId: mockedConnectorConfig.accessKeyId,
@ -70,7 +74,7 @@ describe('sendMessage()', () => {
it('throws if template is missing', async () => {
await expect(
aliyunSmsMethods.sendMessage(phoneTest, 'Register', { code: codeTest })
aliyunSmsMethods.sendMessage({ to: phoneTest, type: 'Register', payload: { code: codeTest } })
).rejects.toThrow();
});
});

View file

@ -3,7 +3,7 @@ import {
ConnectorErrorCodes,
GetConnectorConfig,
SmsConnector,
SendMessageByFunction,
SendMessageFunction,
ValidateConfig,
} from '@logto/connector-schemas';
import { assert } from '@silverhand/essentials';
@ -28,12 +28,11 @@ export default class AliyunSmsConnector extends SmsConnector<AliyunSmsConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<AliyunSmsConfig> = async (
config,
phone,
type,
data
protected readonly sendMessageBy: SendMessageFunction<AliyunSmsConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { accessKeyId, accessKeySecret, signName, templates } = config;
const template = templates.find(({ usageType }) => usageType === type);
@ -46,10 +45,10 @@ export default class AliyunSmsConnector extends SmsConnector<AliyunSmsConfig> {
const httpResponse = await sendSms(
{
AccessKeyId: accessKeyId,
PhoneNumbers: phone,
PhoneNumbers: to,
SignName: signName,
TemplateCode: template.templateCode,
TemplateParam: JSON.stringify(data),
TemplateParam: JSON.stringify(payload),
},
accessKeySecret
);

View file

@ -6,7 +6,7 @@ import {
ConnectorErrorCodes,
EmailConnector,
GetConnectorConfig,
SendMessageByFunction,
SendMessageFunction,
ValidateConfig,
} from '@logto/connector-schemas';
import { assert } from '@silverhand/essentials';
@ -30,12 +30,11 @@ export default class MockMailConnector extends EmailConnector<MockMailConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<MockMailConfig> = async (
config,
address,
type,
data
protected readonly sendMessageBy: SendMessageFunction<MockMailConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -49,9 +48,9 @@ export default class MockMailConnector extends EmailConnector<MockMailConfig> {
await fs.writeFile(
path.join('/tmp', 'logto_mock_passcode_record.txt'),
JSON.stringify({ address, code: data.code, type }) + '\n'
JSON.stringify({ to, code: payload.code, type }) + '\n'
);
return { address, data };
return { to, payload };
};
}

View file

@ -4,7 +4,7 @@ import path from 'path';
import {
ConnectorError,
ConnectorErrorCodes,
SendMessageByFunction,
SendMessageFunction,
SmsConnector,
GetConnectorConfig,
ValidateConfig,
@ -30,12 +30,11 @@ export default class MockSmsConnector extends SmsConnector<MockSmsConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<MockSmsConfig> = async (
config,
phone,
type,
data
protected readonly sendMessageBy: SendMessageFunction<MockSmsConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -49,9 +48,9 @@ export default class MockSmsConnector extends SmsConnector<MockSmsConfig> {
await fs.writeFile(
path.join('/tmp', 'logto_mock_passcode_record.txt'),
JSON.stringify({ phone, code: data.code, type }) + '\n'
JSON.stringify({ to, code: payload.code, type }) + '\n'
);
return { phone, data };
return { to, payload };
};
}

View file

@ -1,7 +1,7 @@
import {
ConnectorError,
ConnectorErrorCodes,
SendMessageByFunction,
SendMessageFunction,
EmailConnector,
GetConnectorConfig,
ValidateConfig,
@ -35,12 +35,11 @@ export default class SendGridMailConnector extends EmailConnector<SendGridMailCo
}
};
protected readonly sendMessageBy: SendMessageByFunction<SendGridMailConfig> = async (
config,
address,
type,
data
protected readonly sendMessageBy: SendMessageFunction<SendGridMailConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { apiKey, fromEmail, fromName, templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -52,7 +51,7 @@ export default class SendGridMailConnector extends EmailConnector<SendGridMailCo
)
);
const toEmailData: EmailData[] = [{ email: address }];
const toEmailData: EmailData[] = [{ email: to }];
const fromEmailData: EmailData = fromName
? { email: fromEmail, name: fromName }
: { email: fromEmail };
@ -60,8 +59,8 @@ export default class SendGridMailConnector extends EmailConnector<SendGridMailCo
const content: Content = {
type: template.type,
value:
typeof data.code === 'string'
? template.content.replace(/{{code}}/g, data.code)
typeof payload.code === 'string'
? template.content.replace(/{{code}}/g, payload.code)
: template.content,
};
const { subject } = template;

View file

@ -1,7 +1,7 @@
import {
ConnectorError,
ConnectorErrorCodes,
SendMessageByFunction,
SendMessageFunction,
EmailConnector,
GetConnectorConfig,
ValidateConfig,
@ -29,12 +29,11 @@ export default class SmtpConnector extends EmailConnector<SmtpConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<SmtpConfig> = async (
config,
address,
type,
data
protected readonly sendMessageBy: SendMessageFunction<SmtpConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { host, port, username, password, fromEmail, replyTo, templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -63,14 +62,14 @@ export default class SmtpConnector extends EmailConnector<SmtpConfig> {
const transporter = nodemailer.createTransport(configOptions);
const contentsObject = this.parseContents(
typeof data.code === 'string'
? template.content.replace(/{{code}}/g, data.code)
typeof payload.code === 'string'
? template.content.replace(/{{code}}/g, payload.code)
: template.content,
template.contentType
);
const mailOptions = {
to: address,
to,
from: fromEmail,
replyTo,
subject: template.subject,

View file

@ -1,7 +1,7 @@
import {
ConnectorError,
ConnectorErrorCodes,
SendMessageByFunction,
SendMessageFunction,
SmsConnector,
GetConnectorConfig,
ValidateConfig,
@ -28,12 +28,11 @@ export default class TwilioSmsConnector extends SmsConnector<TwilioSmsConfig> {
}
};
protected readonly sendMessageBy: SendMessageByFunction<TwilioSmsConfig> = async (
config,
phone,
type,
data
protected readonly sendMessageBy: SendMessageFunction<TwilioSmsConfig> = async (
{ to, type, payload },
config
) => {
assert(config, new ConnectorError(ConnectorErrorCodes.InvalidConfig));
const { accountSID, authToken, fromMessagingServiceSID, templates } = config;
const template = templates.find((template) => template.usageType === type);
@ -46,11 +45,11 @@ export default class TwilioSmsConnector extends SmsConnector<TwilioSmsConfig> {
);
const parameters: PublicParameters = {
To: phone,
To: to,
MessagingServiceSid: fromMessagingServiceSID,
Body:
typeof data.code === 'string'
? template.content.replace(/{{code}}/g, data.code)
typeof payload.code === 'string'
? template.content.replace(/{{code}}/g, payload.code)
: template.content,
};

View file

@ -217,8 +217,12 @@ describe('sendPasscode', () => {
createdAt: Date.now(),
};
await sendPasscode(passcode);
expect(sendMessage).toHaveBeenCalledWith(passcode.phone, passcode.type, {
code: passcode.code,
expect(sendMessage).toHaveBeenCalledWith({
to: passcode.phone,
type: passcode.type,
payload: {
code: passcode.code,
},
});
});
});

View file

@ -68,8 +68,12 @@ export const sendPasscode = async (passcode: Passcode) => {
const { connector, metadata, sendMessage } = connectorInstance;
const response = await sendMessage(emailOrPhone, passcode.type, {
code: passcode.code,
const response = await sendMessage({
to: emailOrPhone,
type: passcode.type,
payload: {
code: passcode.code,
},
});
return { connector, metadata, response };

View file

@ -122,9 +122,16 @@ describe('connector route', () => {
.post('/connectors/id/test')
.send({ phone: '12345678901', config: { test: 123 } });
expect(sendMessageSpy).toHaveBeenCalledTimes(1);
expect(sendMessageSpy).toHaveBeenCalledWith({ test: 123 }, '12345678901', 'Test', {
code: '123456',
});
expect(sendMessageSpy).toHaveBeenCalledWith(
{
to: '12345678901',
type: 'Test',
payload: {
code: '123456',
},
},
{ test: 123 }
);
expect(response).toHaveProperty('statusCode', 204);
});
@ -144,9 +151,16 @@ describe('connector route', () => {
.post('/connectors/id/test')
.send({ email: 'test@email.com', config: { test: 123 } });
expect(sendMessageSpy).toHaveBeenCalledTimes(1);
expect(sendMessageSpy).toHaveBeenCalledWith({ test: 123 }, 'test@email.com', 'Test', {
code: 'email-test',
});
expect(sendMessageSpy).toHaveBeenCalledWith(
{
to: 'test@email.com',
type: 'Test',
payload: {
code: 'email-test',
},
},
{ test: 123 }
);
expect(response).toHaveProperty('statusCode', 204);
});

View file

@ -212,9 +212,16 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
})
);
await sendTestMessage(config, subject, 'Test', {
code: phone ? '123456' : 'email-test',
});
await sendTestMessage(
{
to: subject,
type: 'Test',
payload: {
code: phone ? '123456' : 'email-test',
},
},
config
);
ctx.status = 204;