From 57234cee660dd732e6f9ef594787c9ed60185ee8 Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Tue, 6 Dec 2022 17:04:36 +0800 Subject: [PATCH] fix: drop empty string, undefined and null fields of connector configurable metadata (#2576) --- packages/core/src/routes/connector.test.ts | 2 + packages/core/src/routes/connector.ts | 14 ++++++- .../core/src/routes/connector.update.test.ts | 40 ++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/core/src/routes/connector.test.ts b/packages/core/src/routes/connector.test.ts index 1b96b0bac..6ef17d060 100644 --- a/packages/core/src/routes/connector.test.ts +++ b/packages/core/src/routes/connector.test.ts @@ -244,6 +244,7 @@ describe('connector route', () => { const response = await connectorRequest.post('/connectors').send({ connectorId: 'id0', config: { cliend_id: 'client_id', client_secret: 'client_secret' }, + metadata: { target: 'target', name: { en: '' }, logo: '', logoDark: null }, }); expect(response).toHaveProperty('statusCode', 200); expect(response.body).toMatchObject( @@ -253,6 +254,7 @@ describe('connector route', () => { cliend_id: 'client_id', client_secret: 'client_secret', }, + metadata: { target: 'target' }, }) ); expect(deleteConnectorByIds).toHaveBeenCalledWith(['id']); diff --git a/packages/core/src/routes/connector.ts b/packages/core/src/routes/connector.ts index 995919e74..673448a3a 100644 --- a/packages/core/src/routes/connector.ts +++ b/packages/core/src/routes/connector.ts @@ -3,6 +3,8 @@ import { emailRegEx, phoneRegEx } from '@logto/core-kit'; import type { ConnectorFactoryResponse, ConnectorResponse } from '@logto/schemas'; import { arbitraryObjectGuard, Connectors, ConnectorType } from '@logto/schemas'; import { buildIdGenerator } from '@logto/shared'; +import { conditional } from '@silverhand/essentials'; +import cleanDeep from 'clean-deep'; import { object, string } from 'zod'; import { @@ -134,9 +136,12 @@ export default function connectorRoutes(router: T) { ); const insertConnectorId = generateConnectorId(); + const { metadata, ...rest } = body; + ctx.body = await insertConnector({ id: insertConnectorId, - ...body, + ...conditional(metadata && { metadata: cleanDeep(metadata) }), + ...rest, }); /** @@ -193,7 +198,12 @@ export default function connectorRoutes(router: T) { validateConfig(config); } - await updateConnector({ set: body, where: { id }, jsonbMode: 'replace' }); + const { metadata: databaseMetadata, ...rest } = body; + await updateConnector({ + set: databaseMetadata ? { metadata: cleanDeep(databaseMetadata), ...rest } : rest, + where: { id }, + jsonbMode: 'replace', + }); const connector = await getLogtoConnectorById(id); ctx.body = transpileLogtoConnector(connector); diff --git a/packages/core/src/routes/connector.update.test.ts b/packages/core/src/routes/connector.update.test.ts index ee0b82f71..e20d8a4fb 100644 --- a/packages/core/src/routes/connector.update.test.ts +++ b/packages/core/src/routes/connector.update.test.ts @@ -105,7 +105,6 @@ describe('connector PATCH routes', () => { target: 'target', name: { en: 'connector_name', fr: 'connector_name' }, logo: 'new_logo.png', - logoDark: null, }, }); const response = await connectorRequest.patch('/connectors/id').send({ @@ -126,7 +125,6 @@ describe('connector PATCH routes', () => { target: 'target', name: { en: 'connector_name', fr: 'connector_name' }, logo: 'new_logo.png', - logoDark: null, }, }, jsonbMode: 'replace', @@ -135,6 +133,44 @@ describe('connector PATCH routes', () => { expect(response).toHaveProperty('statusCode', 200); }); + it('successfully clear connector config metadata', async () => { + getLogtoConnectorsPlaceholder.mockResolvedValueOnce([ + { + dbEntry: mockConnector, + metadata: { ...mockMetadata, isStandard: true }, + type: ConnectorType.Social, + ...mockLogtoConnector, + }, + ]); + mockedUpdateConnector.mockResolvedValueOnce({ + ...mockConnector, + metadata: { + target: '', + name: { en: '' }, + logo: '', + logoDark: '', + }, + }); + const response = await connectorRequest.patch('/connectors/id').send({ + metadata: { + target: '', + name: { en: '' }, + logo: '', + logoDark: '', + }, + }); + expect(updateConnector).toHaveBeenCalledWith( + expect.objectContaining({ + where: { id: 'id' }, + set: { + metadata: {}, + }, + jsonbMode: 'replace', + }) + ); + expect(response).toHaveProperty('statusCode', 200); + }); + it('throws when set syncProfile to `true` and with non-social connector', async () => { getLogtoConnectorsPlaceholder.mockResolvedValueOnce([ {