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:
parent
1d64ded7eb
commit
efd404e9aa
4 changed files with 84 additions and 2 deletions
|
@ -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' };
|
||||
|
||||
|
|
|
@ -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(*)
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue