0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-04-07 23:01:25 -05:00

fix(core): remove unavailable social sign in targets on save (#1201)

This commit is contained in:
Wang Sijie 2022-06-22 16:56:06 +08:00 committed by GitHub
parent c1b3e6088a
commit 012562e2a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 74 deletions

View file

@ -141,7 +141,7 @@ describe('validate sign-in methods', () => {
});
});
test('should throw when the social connector IDs are empty and social sign-in method is enabled', () => {
test('should throw when the social connector targets are empty and social sign-in method is enabled', () => {
expect(() => {
validateSignInMethods(
{ ...mockSignInMethods, social: SignInMethodState.Secondary },
@ -150,36 +150,4 @@ describe('validate sign-in methods', () => {
);
}).toMatchError(new RequestError('sign_in_experiences.empty_social_connectors'));
});
describe('Selected social connectors must be enabled only when social sign-in method is enabled.', () => {
test('should not validate selected social connectors when social sign-in method is disabled', () => {
expect(() => {
validateSignInMethods(
{ ...mockSignInMethods, social: SignInMethodState.Disabled },
['google', 'facebook'],
enabledConnectorInstances as ConnectorInstance[]
);
}).not.toThrow();
});
test('should throw when some selected social connector are disabled and social sign-in method is enabled', () => {
expect(() => {
validateSignInMethods(
{ ...mockSignInMethods, social: SignInMethodState.Secondary },
['google', 'facebook'],
enabledConnectorInstances as ConnectorInstance[]
);
}).toMatchError(new RequestError('sign_in_experiences.invalid_social_connectors'));
});
test('should not throw when all selected social connectors are enabled and social sign-in method is enabled', () => {
expect(() => {
validateSignInMethods(
{ ...mockSignInMethods, social: SignInMethodState.Secondary },
['facebook', 'github'],
enabledConnectorInstances as ConnectorInstance[]
);
}).not.toThrow();
});
});
});

View file

@ -70,15 +70,5 @@ export const validateSignInMethods = (
socialSignInConnectorTargets && socialSignInConnectorTargets.length > 0,
'sign_in_experiences.empty_social_connectors'
);
assertThat(
socialSignInConnectorTargets.every((connectorTarget) =>
enabledConnectorInstances.some(
({ metadata: { target, type } }) =>
target === connectorTarget && type === ConnectorType.Social
)
),
'sign_in_experiences.invalid_social_connectors'
);
}
};

View file

@ -14,6 +14,10 @@ jest.mock('@/queries/sign-in-experience', () => ({
),
}));
jest.mock('@/connectors', () => ({
getConnectorInstances: jest.fn(async () => []),
}));
const signInExperienceRequester = createRequester({ authedRoutes: signInExperiencesRoutes });
const expectPatchResponseStatus = async (signInExperience: any, status: number) => {

View file

@ -279,17 +279,4 @@ describe('socialSignInConnectorTargets', () => {
);
}
);
test.each([[[]], [[null, undefined]], [['', ' \t\n\r']], [[123, 456]]])(
'%p should fail',
async (socialSignInConnectorTargets: any[]) => {
await expectPatchResponseStatus(
{
signInMethods: { ...mockSignInMethods, social: SignInMethodState.Secondary },
socialSignInConnectorTargets,
},
400
);
}
);
});

View file

@ -12,6 +12,7 @@ import {
mockBranding,
mockSignInExperience,
mockSignInMethods,
mockWechatConnectorInstance,
} from '@/__mocks__';
import * as signInExpLib from '@/lib/sign-in-experience';
import { createRequester } from '@/utils/test-utils';
@ -22,6 +23,7 @@ const connectorInstances = [
mockFacebookConnectorInstance,
mockGithubConnectorInstance,
mockGoogleConnectorInstance,
mockWechatConnectorInstance,
];
const getConnectorInstances = jest.fn(async () => connectorInstances);
@ -29,7 +31,7 @@ const getConnectorInstances = jest.fn(async () => connectorInstances);
jest.mock('@/connectors', () => {
return {
...jest.requireActual('@/connectors'),
getEnabledSocialConnectorIds: jest.fn(async () => ['facebook', 'github']),
getEnabledSocialConnectorIds: jest.fn(async () => ['facebook', 'github', 'wechat']),
getConnectorInstances: jest.fn(async () => getConnectorInstances()),
};
});
@ -62,7 +64,7 @@ describe('GET /sign-in-exp', () => {
});
describe('PATCH /sign-in-exp', () => {
it('should not update social connector ids when social sign-in is disabled', async () => {
it('should not update social connector targets when social sign-in is disabled', async () => {
const signInMethods = { ...mockSignInMethods, social: SignInMethodState.Disabled };
const response = await signInExperienceRequester.patch('/sign-in-exp').send({
signInMethods,
@ -77,7 +79,7 @@ describe('PATCH /sign-in-exp', () => {
});
});
it('should update enabled social connector IDs only when social sign-in is enabled', async () => {
it('should update enabled social connector targets only when social sign-in is enabled', async () => {
const signInMethods = { ...mockSignInMethods, social: SignInMethodState.Secondary };
const socialSignInConnectorTargets = ['facebook'];
const signInExperience = {
@ -95,7 +97,7 @@ describe('PATCH /sign-in-exp', () => {
});
});
it('should update social connector IDs in correct sorting order', async () => {
it('should update social connector targets in correct sorting order', async () => {
const signInMethods = { ...mockSignInMethods, social: SignInMethodState.Secondary };
const socialSignInConnectorTargets = ['github', 'facebook'];
const signInExperience = {
@ -113,6 +115,24 @@ describe('PATCH /sign-in-exp', () => {
});
});
it('should filter out unavailable social connector targets', async () => {
const signInMethods = { ...mockSignInMethods, social: SignInMethodState.Secondary };
const socialSignInConnectorTargets = ['github', 'facebook', 'google'];
const signInExperience = {
signInMethods,
socialSignInConnectorTargets,
};
const response = await signInExperienceRequester.patch('/sign-in-exp').send(signInExperience);
expect(response).toMatchObject({
status: 200,
body: {
...mockSignInExperience,
signInMethods,
socialSignInConnectorTargets: ['github', 'facebook'],
},
});
});
it('should succeed to update when the input is valid', async () => {
const termsOfUse: TermsOfUse = { enabled: false };
const socialSignInConnectorTargets = ['github', 'facebook', 'wechat'];
@ -133,7 +153,7 @@ describe('PATCH /sign-in-exp', () => {
expect(validateSignInMethods).toHaveBeenCalledWith(
mockSignInMethods,
socialSignInConnectorTargets,
[mockFacebookConnectorInstance, mockGithubConnectorInstance]
[mockFacebookConnectorInstance, mockGithubConnectorInstance, mockWechatConnectorInstance]
);
expect(response).toMatchObject({

View file

@ -1,4 +1,4 @@
import { SignInExperiences } from '@logto/schemas';
import { ConnectorType, SignInExperiences } from '@logto/schemas';
import { getConnectorInstances } from '@/connectors';
import {
@ -43,23 +43,35 @@ export default function signInExperiencesRoutes<T extends AuthedRouter>(router:
validateTermsOfUse(termsOfUse);
}
if (signInMethods) {
// TODO: LOG-2055 refactor connectors
const connectorInstances = await getConnectorInstances();
const enabledConnectorInstances = connectorInstances.filter(
(instance) => instance.connector.enabled
);
const connectorInstances = await getConnectorInstances();
const enabledConnectorInstances = connectorInstances.filter(
(instance) => instance.connector.enabled
);
// Remove unavailable connectors
const filteredSocialSignInConnectorTargets = socialSignInConnectorTargets?.filter((target) =>
enabledConnectorInstances.some(
(connector) =>
connector.metadata.target === target && connector.metadata.type === ConnectorType.Social
)
);
if (signInMethods) {
validateSignInMethods(
signInMethods,
socialSignInConnectorTargets,
filteredSocialSignInConnectorTargets,
enabledConnectorInstances
);
}
// Update socialSignInConnectorTargets only when social sign-in is enabled.
const signInExperience =
signInMethods && isEnabled(signInMethods.social) ? ctx.guard.body : rest;
signInMethods && isEnabled(signInMethods.social)
? {
...ctx.guard.body,
socialSignInConnectorTargets: filteredSocialSignInConnectorTargets,
}
: rest;
ctx.body = await updateDefaultSignInExperience(signInExperience);

View file

@ -682,8 +682,6 @@ const errors = {
empty_social_connectors:
'Empty social connectors. Please add enabled social connectors when the social sign-in method is enabled.',
enabled_connector_not_found: 'Enabled {{type}} connector not found.',
invalid_social_connectors:
'Invalid social connectors, Please confirm all your selected social connectors are enabled.',
not_one_and_only_one_primary_sign_in_method:
'There must be one and only one primary sign-in method. Please check your input.',
},

View file

@ -662,8 +662,6 @@ const errors = {
empty_social_connectors:
'空的 social 连接器。当启用社交网络连接器的登录方式时,请添加可用的 social 连接器。',
enabled_connector_not_found: '未找到可用的 {{type}} 类型的连接器。',
invalid_social_connectors:
'无效的 social 连接器。请确认你选择的所有连接器都可用,并且是 social 类型的。',
not_one_and_only_one_primary_sign_in_method: '主要的登录方式必须有且仅有一个,请检查你的输入。',
},
swagger: {