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

feat(core): validate connector config before enabling (#478)

* feat(core): validate connector config before enabling

* feat(core): remove code redundancy
This commit is contained in:
Darcy Ye 2022-03-31 18:02:35 +08:00 committed by GitHub
parent 4c18734530
commit 004fe65d5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 10 deletions

View file

@ -182,7 +182,7 @@ describe('connector route', () => {
expect(response).toHaveProperty('statusCode', 400);
});
it('enables one of the social connectors', async () => {
it('enables one of the social connectors (with valid config)', async () => {
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
connector: {
@ -199,6 +199,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
validateConfig: jest.fn(),
};
});
const response = await connectorRequest
@ -223,6 +224,34 @@ describe('connector route', () => {
expect(response).toHaveProperty('statusCode', 200);
});
it('enables one of the social connectors (with invalid config)', async () => {
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
connector: {
id: 'connector_0',
enabled: true,
config: {},
createdAt: 1_234_567_890_123,
},
metadata: {
id: 'connector_0',
type: ConnectorType.Social,
name: {},
logo: './logo.png',
description: {},
readme: 'README.md',
},
validateConfig: async () => {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig);
},
};
});
const response = await connectorRequest
.patch('/connectors/connector_0/enabled')
.send({ enabled: true });
expect(response).toHaveProperty('statusCode', 500);
});
it('disables one of the social connectors', async () => {
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
@ -264,7 +293,7 @@ describe('connector route', () => {
expect(response).toHaveProperty('statusCode', 200);
});
it('enables one of the email/sms connectors', async () => {
it('enables one of the email/sms connectors (with valid config)', async () => {
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstanceList);
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
@ -282,6 +311,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
validateConfig: jest.fn(),
};
});
const response = await connectorRequest
@ -321,6 +351,35 @@ describe('connector route', () => {
expect(response).toHaveProperty('statusCode', 200);
});
it('enables one of the email/sms connectors (with invalid config)', async () => {
getConnectorInstancesPlaceHolder.mockResolvedValueOnce(mockConnectorInstanceList);
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
connector: {
id: 'connector_1',
enabled: true,
config: {},
createdAt: 1_234_567_890_234,
},
metadata: {
id: 'connector_1',
type: ConnectorType.SMS,
name: {},
logo: './logo.png',
description: {},
readme: 'README.md',
},
validateConfig: async () => {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig);
},
};
});
const response = await connectorRequest
.patch('/connectors/connector_1/enabled')
.send({ enabled: true });
expect(response).toHaveProperty('statusCode', 500);
});
it('disables one of the email/sms connectors', async () => {
getConnectorInstanceByIdPlaceHolder.mockImplementationOnce(async (_id: string) => {
return {
@ -417,7 +476,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
validateConfig: async (_config) => {
validateConfig: async () => {
throw new ConnectorError(ConnectorErrorCodes.InvalidConfig);
},
};
@ -445,8 +504,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
validateConfig: async (_config) => {},
validateConfig: jest.fn(),
};
});
const response = await connectorRequest
@ -493,8 +551,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
validateConfig: async (_config: any) => {},
validateConfig: jest.fn(),
sendMessage: async (
address: string,
type: keyof EmailMessageTypes,
@ -538,8 +595,7 @@ describe('connector route', () => {
description: {},
readme: 'README.md',
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
validateConfig: async (_config: any) => {},
validateConfig: jest.fn(),
sendMessage: async (
address: string,
type: keyof EmailMessageTypes,

View file

@ -73,7 +73,15 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
params: { id },
body: { enabled },
} = ctx.guard;
const { metadata } = await getConnectorInstanceById(id);
const {
connector: { config },
metadata,
validateConfig,
} = await getConnectorInstanceById(id);
if (enabled) {
await validateConfig(config);
}
// Only allow one enabled connector for SMS and Email.
// disable other connectors before enable this one.