0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat: update available social targets after connector deletion (#2524)

This commit is contained in:
Darcy Ye 2022-11-28 12:17:35 +08:00 committed by GitHub
parent 1d64ded7eb
commit efd404e9aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 2 deletions

View file

@ -10,6 +10,7 @@ import { expectSqlAssert } from '#src/utils/test-utils.js';
import {
findAllConnectors,
findConnectorById,
countConnectorByConnectorId,
deleteConnectorById,
insertConnector,
@ -47,6 +48,28 @@ describe('connector queries', () => {
await expect(findAllConnectors()).resolves.toEqual([rowData]);
});
it('findConnectorById', async () => {
const row = {
...mockConnector,
config: JSON.stringify(mockConnector.config),
metadata: JSON.stringify(mockConnector.metadata),
};
const expectSql = sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
where ${fields.id}=$1
`;
mockQuery.mockImplementationOnce(async (sql, values) => {
expectSqlAssert(sql, expectSql.sql);
expect(values).toEqual([mockConnector.id]);
return createMockQueryResult([row]);
});
await expect(findConnectorById(mockConnector.id)).resolves.toEqual(row);
});
it('countConnectorsByConnectorId', async () => {
const rowData = { id: 'foo', connectorId: 'bar' };

View file

@ -19,6 +19,13 @@ export const findAllConnectors = async () =>
`)
);
export const findConnectorById = async (id: string) =>
envSet.pool.one<Connector>(sql`
select ${sql.join(Object.values(fields), sql`,`)}
from ${table}
where ${fields.id}=${id}
`);
export const countConnectorByConnectorId = async (connectorId: string) =>
envSet.pool.one<{ count: number }>(sql`
select count(*)

View file

@ -16,7 +16,12 @@ import {
import { defaultConnectorMethods } from '#src/connectors/consts.js';
import type { ConnectorFactory, LogtoConnector } from '#src/connectors/types.js';
import RequestError from '#src/errors/RequestError/index.js';
import { countConnectorByConnectorId, deleteConnectorById } from '#src/queries/connector.js';
import { removeUnavailableSocialConnectorTargets } from '#src/lib/sign-in-experience/index.js';
import {
findConnectorById,
countConnectorByConnectorId,
deleteConnectorById,
} from '#src/queries/connector.js';
import assertThat from '#src/utils/assert-that.js';
import { createRequester } from '#src/utils/test-utils.js';
@ -29,7 +34,12 @@ const getLogtoConnectorsPlaceHolder = jest.fn() as jest.MockedFunction<
() => Promise<LogtoConnector[]>
>;
jest.mock('#src/lib/sign-in-experience/index.js', () => ({
removeUnavailableSocialConnectorTargets: jest.fn(),
}));
jest.mock('#src/queries/connector.js', () => ({
findConnectorById: jest.fn(),
countConnectorByConnectorId: jest.fn(),
deleteConnectorById: jest.fn(),
insertConnector: jest.fn(async (body: unknown) => body),
@ -300,13 +310,44 @@ describe('connector route', () => {
});
describe('DELETE /connectors/:id', () => {
beforeEach(() => {
jest.resetAllMocks();
});
afterEach(() => {
jest.clearAllMocks();
});
it('delete connector instance', async () => {
it('delete connector instance and remove unavailable social connector targets', async () => {
(findConnectorById as jest.Mock).mockResolvedValueOnce(mockConnector);
loadConnectorFactoriesPlaceHolder.mockResolvedValueOnce([mockConnectorFactory]);
await connectorRequest.delete('/connectors/id').send({});
expect(deleteConnectorById).toHaveBeenCalledTimes(1);
expect(removeUnavailableSocialConnectorTargets).toHaveBeenCalledTimes(1);
});
it('delete connector instance (connector factory is not social type)', async () => {
(findConnectorById as jest.Mock).mockResolvedValueOnce(mockConnector);
loadConnectorFactoriesPlaceHolder.mockResolvedValueOnce([
{ ...mockConnectorFactory, type: ConnectorType.Sms },
]);
await connectorRequest.delete('/connectors/id').send({});
expect(deleteConnectorById).toHaveBeenCalledTimes(1);
expect(removeUnavailableSocialConnectorTargets).toHaveBeenCalledTimes(0);
});
it('delete connector instance (connector factory is not found)', async () => {
(findConnectorById as jest.Mock).mockResolvedValueOnce(mockConnector);
loadConnectorFactoriesPlaceHolder.mockResolvedValueOnce([]);
await connectorRequest.delete('/connectors/id').send({});
expect(deleteConnectorById).toHaveBeenCalledTimes(1);
expect(removeUnavailableSocialConnectorTargets).toHaveBeenCalledTimes(0);
});
it('throws when connector not exists with `id`', async () => {
// eslint-disable-next-line unicorn/no-useless-undefined
(findConnectorById as jest.Mock).mockResolvedValueOnce(undefined);
const response = await connectorRequest.delete('/connectors/id').send({});
expect(response).toHaveProperty('statusCode', 500);
});
});
});

View file

@ -15,6 +15,7 @@ import RequestError from '#src/errors/RequestError/index.js';
import { removeUnavailableSocialConnectorTargets } from '#src/lib/sign-in-experience/index.js';
import koaGuard from '#src/middleware/koa-guard.js';
import {
findConnectorById,
countConnectorByConnectorId,
deleteConnectorById,
insertConnector,
@ -291,8 +292,18 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
params: { id },
} = ctx.guard;
const { connectorId } = await findConnectorById(id);
const connectorFactories = await loadConnectorFactories();
const connectorFactory = connectorFactories.find(
({ metadata }) => metadata.id === connectorId
);
await deleteConnectorById(id);
if (connectorFactory?.type === ConnectorType.Social) {
await removeUnavailableSocialConnectorTargets();
}
ctx.status = 204;
return next();