0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -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 { import {
findAllConnectors, findAllConnectors,
findConnectorById,
countConnectorByConnectorId, countConnectorByConnectorId,
deleteConnectorById, deleteConnectorById,
insertConnector, insertConnector,
@ -47,6 +48,28 @@ describe('connector queries', () => {
await expect(findAllConnectors()).resolves.toEqual([rowData]); 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 () => { it('countConnectorsByConnectorId', async () => {
const rowData = { id: 'foo', connectorId: 'bar' }; 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) => export const countConnectorByConnectorId = async (connectorId: string) =>
envSet.pool.one<{ count: number }>(sql` envSet.pool.one<{ count: number }>(sql`
select count(*) select count(*)

View file

@ -16,7 +16,12 @@ import {
import { defaultConnectorMethods } from '#src/connectors/consts.js'; import { defaultConnectorMethods } from '#src/connectors/consts.js';
import type { ConnectorFactory, LogtoConnector } from '#src/connectors/types.js'; import type { ConnectorFactory, LogtoConnector } from '#src/connectors/types.js';
import RequestError from '#src/errors/RequestError/index.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 assertThat from '#src/utils/assert-that.js';
import { createRequester } from '#src/utils/test-utils.js'; import { createRequester } from '#src/utils/test-utils.js';
@ -29,7 +34,12 @@ const getLogtoConnectorsPlaceHolder = jest.fn() as jest.MockedFunction<
() => Promise<LogtoConnector[]> () => Promise<LogtoConnector[]>
>; >;
jest.mock('#src/lib/sign-in-experience/index.js', () => ({
removeUnavailableSocialConnectorTargets: jest.fn(),
}));
jest.mock('#src/queries/connector.js', () => ({ jest.mock('#src/queries/connector.js', () => ({
findConnectorById: jest.fn(),
countConnectorByConnectorId: jest.fn(), countConnectorByConnectorId: jest.fn(),
deleteConnectorById: jest.fn(), deleteConnectorById: jest.fn(),
insertConnector: jest.fn(async (body: unknown) => body), insertConnector: jest.fn(async (body: unknown) => body),
@ -300,13 +310,44 @@ describe('connector route', () => {
}); });
describe('DELETE /connectors/:id', () => { describe('DELETE /connectors/:id', () => {
beforeEach(() => {
jest.resetAllMocks();
});
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); 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({}); await connectorRequest.delete('/connectors/id').send({});
expect(deleteConnectorById).toHaveBeenCalledTimes(1); 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 { removeUnavailableSocialConnectorTargets } from '#src/lib/sign-in-experience/index.js';
import koaGuard from '#src/middleware/koa-guard.js'; import koaGuard from '#src/middleware/koa-guard.js';
import { import {
findConnectorById,
countConnectorByConnectorId, countConnectorByConnectorId,
deleteConnectorById, deleteConnectorById,
insertConnector, insertConnector,
@ -291,8 +292,18 @@ export default function connectorRoutes<T extends AuthedRouter>(router: T) {
params: { id }, params: { id },
} = ctx.guard; } = ctx.guard;
const { connectorId } = await findConnectorById(id);
const connectorFactories = await loadConnectorFactories();
const connectorFactory = connectorFactories.find(
({ metadata }) => metadata.id === connectorId
);
await deleteConnectorById(id); await deleteConnectorById(id);
if (connectorFactory?.type === ConnectorType.Social) {
await removeUnavailableSocialConnectorTargets();
}
ctx.status = 204; ctx.status = 204;
return next(); return next();