mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
feat(core): remove unselected demo social connectors (#3454)
This commit is contained in:
parent
d909b48649
commit
f247ce5f86
4 changed files with 89 additions and 5 deletions
|
@ -23,6 +23,7 @@ import * as pageLayout from '@/onboarding/scss/layout.module.scss';
|
|||
import { Authentication, OnboardingPage } from '@/onboarding/types';
|
||||
import type { OnboardingSieConfig } from '@/onboarding/types';
|
||||
import { getOnboardingPage } from '@/onboarding/utils';
|
||||
import { buildUrl } from '@/utils/url';
|
||||
import { uriValidator } from '@/utils/validator';
|
||||
|
||||
import InspireMe from './components/InspireMe';
|
||||
|
@ -83,7 +84,7 @@ const SignInExperience = () => {
|
|||
}
|
||||
|
||||
const updatedData = await api
|
||||
.patch('api/sign-in-exp', {
|
||||
.patch(buildUrl('api/sign-in-exp', { removeUnusedDemoSocialConnector: '1' }), {
|
||||
json: parser.onboardSieConfigToSignInExperience(formData, signInExperience),
|
||||
})
|
||||
.json<SignInExperienceType>();
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { ConnectorFactory } from '@logto/cli/lib/connector/index.js';
|
|||
import { ConnectorPlatform } from '@logto/connector-kit';
|
||||
import type { Connector } from '@logto/schemas';
|
||||
import { ConnectorType } from '@logto/schemas';
|
||||
import { DemoConnector } from '@logto/shared';
|
||||
import { any } from 'zod';
|
||||
|
||||
import type { LogtoConnector } from '#src/utils/connectors/types.js';
|
||||
|
@ -222,6 +223,21 @@ export const mockGoogleConnector: LogtoConnector = {
|
|||
...mockLogtoConnector,
|
||||
};
|
||||
|
||||
export const mockDemoSocialConnector: LogtoConnector = {
|
||||
dbEntry: {
|
||||
...mockConnector,
|
||||
id: 'demo-social',
|
||||
},
|
||||
metadata: {
|
||||
...mockMetadata,
|
||||
id: DemoConnector.Social,
|
||||
target: 'github',
|
||||
platform: null,
|
||||
},
|
||||
type: ConnectorType.Social,
|
||||
...mockLogtoConnector,
|
||||
};
|
||||
|
||||
export const mockLogtoConnectors = [
|
||||
mockAliyunDmConnector,
|
||||
mockAliyunSmsConnector,
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
mockAliyunSmsConnector,
|
||||
mockTermsOfUseUrl,
|
||||
mockPrivacyPolicyUrl,
|
||||
mockDemoSocialConnector,
|
||||
} from '#src/__mocks__/index.js';
|
||||
import { MockTenant } from '#src/test-utils/tenant.js';
|
||||
import { createRequester } from '#src/utils/test-utils.js';
|
||||
|
@ -50,13 +51,19 @@ const signInExperiences = {
|
|||
const { findDefaultSignInExperience } = signInExperiences;
|
||||
|
||||
const validateLanguageInfo = jest.fn();
|
||||
const mockGetLogtoConnectors = jest.fn(async () => logtoConnectors);
|
||||
const mockDeleteConnectorById = jest.fn();
|
||||
|
||||
const tenantContext = new MockTenant(
|
||||
undefined,
|
||||
{ signInExperiences, customPhrases: { findAllCustomLanguageTags: async () => [] } },
|
||||
{
|
||||
signInExperiences,
|
||||
customPhrases: { findAllCustomLanguageTags: async () => [] },
|
||||
connectors: { deleteConnectorById: mockDeleteConnectorById },
|
||||
},
|
||||
{
|
||||
signInExperiences: { validateLanguageInfo },
|
||||
connectors: { getLogtoConnectors: async () => logtoConnectors },
|
||||
connectors: { getLogtoConnectors: mockGetLogtoConnectors },
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -80,6 +87,10 @@ describe('GET /sign-in-exp', () => {
|
|||
});
|
||||
|
||||
describe('PATCH /sign-in-exp', () => {
|
||||
afterEach(() => {
|
||||
mockDeleteConnectorById.mockClear();
|
||||
});
|
||||
|
||||
it('should update social connector targets in correct sorting order', async () => {
|
||||
const socialSignInConnectorTargets = ['github', 'facebook'];
|
||||
const signInExperience = {
|
||||
|
@ -110,6 +121,40 @@ describe('PATCH /sign-in-exp', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should remove unselected demo social connectors', async () => {
|
||||
mockGetLogtoConnectors.mockResolvedValueOnce([...logtoConnectors, mockDemoSocialConnector]);
|
||||
const socialSignInConnectorTargets = ['facebook', 'google'];
|
||||
const signInExperience = {
|
||||
socialSignInConnectorTargets,
|
||||
};
|
||||
await signInExperienceRequester
|
||||
.patch('/sign-in-exp?removeUnusedDemoSocialConnector=1')
|
||||
.send(signInExperience);
|
||||
expect(mockDeleteConnectorById).toHaveBeenCalledWith(mockDemoSocialConnector.dbEntry.id);
|
||||
});
|
||||
|
||||
it('should remove unselected demo social connectors when removeUnusedDemoSocialConnector is not set', async () => {
|
||||
mockGetLogtoConnectors.mockResolvedValueOnce([...logtoConnectors, mockDemoSocialConnector]);
|
||||
const socialSignInConnectorTargets = ['facebook', 'google'];
|
||||
const signInExperience = {
|
||||
socialSignInConnectorTargets,
|
||||
};
|
||||
await signInExperienceRequester.patch('/sign-in-exp').send(signInExperience);
|
||||
expect(mockDeleteConnectorById).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not remove selected demo social connectors', async () => {
|
||||
mockGetLogtoConnectors.mockResolvedValueOnce([...logtoConnectors, mockDemoSocialConnector]);
|
||||
const socialSignInConnectorTargets = ['github', 'facebook', 'google'];
|
||||
const signInExperience = {
|
||||
socialSignInConnectorTargets,
|
||||
};
|
||||
await signInExperienceRequester
|
||||
.patch('/sign-in-exp?removeUnusedDemoSocialConnector=1')
|
||||
.send(signInExperience);
|
||||
expect(mockDeleteConnectorById).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should succeed to update when the input is valid', async () => {
|
||||
const socialSignInConnectorTargets = ['github', 'facebook', 'wechat'];
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ConnectorType, SignInExperiences } from '@logto/schemas';
|
||||
import { literal, object, string } from 'zod';
|
||||
import { DemoConnector } from '@logto/shared';
|
||||
import { literal, object, string, z } from 'zod';
|
||||
|
||||
import { validateSignUp, validateSignIn } from '#src/libraries/sign-in-experience/index.js';
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
|
@ -10,6 +11,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
|||
...[router, { queries, libraries }]: RouterInitArgs<T>
|
||||
) {
|
||||
const { findDefaultSignInExperience, updateDefaultSignInExperience } = queries.signInExperiences;
|
||||
const { deleteConnectorById } = queries.connectors;
|
||||
const {
|
||||
signInExperiences: { validateLanguageInfo },
|
||||
connectors: { getLogtoConnectors },
|
||||
|
@ -28,6 +30,7 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
|||
router.patch(
|
||||
'/sign-in-exp',
|
||||
koaGuard({
|
||||
query: z.object({ removeUnusedDemoSocialConnector: z.string().optional() }),
|
||||
body: SignInExperiences.createGuard
|
||||
.omit({ id: true, termsOfUseUrl: true, privacyPolicyUrl: true })
|
||||
.merge(
|
||||
|
@ -39,7 +42,10 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
|||
.partial(),
|
||||
}),
|
||||
async (ctx, next) => {
|
||||
const { socialSignInConnectorTargets, ...rest } = ctx.guard.body;
|
||||
const {
|
||||
query: { removeUnusedDemoSocialConnector },
|
||||
body: { socialSignInConnectorTargets, ...rest },
|
||||
} = ctx.guard;
|
||||
const { languageInfo, signUp, signIn } = rest;
|
||||
|
||||
if (languageInfo) {
|
||||
|
@ -66,6 +72,22 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(
|
|||
const signInExperience = await findDefaultSignInExperience();
|
||||
validateSignIn(signIn, signInExperience.signUp, connectors);
|
||||
}
|
||||
|
||||
// Remove unused demo social connectors, those that are not selected in onboarding SIE config.
|
||||
if (removeUnusedDemoSocialConnector && filteredSocialSignInConnectorTargets) {
|
||||
await Promise.all(
|
||||
connectors
|
||||
.filter((connector) => {
|
||||
return (
|
||||
connector.type === ConnectorType.Social &&
|
||||
connector.metadata.id === DemoConnector.Social &&
|
||||
!filteredSocialSignInConnectorTargets.includes(connector.metadata.target)
|
||||
);
|
||||
})
|
||||
.map(async (connector) => deleteConnectorById(connector.dbEntry.id))
|
||||
);
|
||||
}
|
||||
|
||||
ctx.body = await updateDefaultSignInExperience(
|
||||
filteredSocialSignInConnectorTargets
|
||||
? {
|
||||
|
|
Loading…
Add table
Reference in a new issue