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:
parent
c1b3e6088a
commit
012562e2a8
8 changed files with 51 additions and 74 deletions
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.',
|
||||
},
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Add table
Reference in a new issue