mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(core): throw registered social email or phone info (#3199)
This commit is contained in:
parent
86b796e989
commit
c06e2d0985
3 changed files with 53 additions and 6 deletions
|
@ -125,7 +125,7 @@ describe('validateMandatoryUserProfile', () => {
|
||||||
).resolves.not.toThrow();
|
).resolves.not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('identifier includes social with verified email but email occupied should throw', async () => {
|
it('sign-in identifier includes social with verified email but email occupied should throw', async () => {
|
||||||
hasUserWithEmail.mockResolvedValueOnce(true);
|
hasUserWithEmail.mockResolvedValueOnce(true);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -144,6 +144,26 @@ describe('validateMandatoryUserProfile', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('register identifier includes social with verified email but email occupied should throw', async () => {
|
||||||
|
hasUserWithEmail.mockResolvedValueOnce(true);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
validateMandatoryUserProfile(users, emailRequiredCtx, {
|
||||||
|
...interaction,
|
||||||
|
event: InteractionEvent.Register,
|
||||||
|
identifiers: [
|
||||||
|
...interaction.identifiers,
|
||||||
|
{ key: 'social', userInfo: { email: 'email', id: 'foo' }, connectorId: 'logto' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
).rejects.toMatchError(
|
||||||
|
new RequestError(
|
||||||
|
{ code: 'user.missing_profile', status: 422 },
|
||||||
|
{ missingProfile: [MissingProfile.email] }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('identifier includes social with verified email should not throw', async () => {
|
it('identifier includes social with verified email should not throw', async () => {
|
||||||
hasUserWithEmail.mockResolvedValueOnce(false);
|
hasUserWithEmail.mockResolvedValueOnce(false);
|
||||||
|
|
||||||
|
@ -200,7 +220,7 @@ describe('validateMandatoryUserProfile', () => {
|
||||||
).resolves.not.toThrow();
|
).resolves.not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('identifier includes social with verified phone but phone occupied should throw', async () => {
|
it('sign-in identifier includes social with verified phone but phone occupied should throw', async () => {
|
||||||
hasUserWithPhone.mockResolvedValueOnce(true);
|
hasUserWithPhone.mockResolvedValueOnce(true);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -219,6 +239,26 @@ describe('validateMandatoryUserProfile', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('register identifier includes social with verified phone but phone occupied should throw', async () => {
|
||||||
|
hasUserWithPhone.mockResolvedValueOnce(true);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
validateMandatoryUserProfile(users, phoneRequiredCtx, {
|
||||||
|
...interaction,
|
||||||
|
event: InteractionEvent.Register,
|
||||||
|
identifiers: [
|
||||||
|
...interaction.identifiers,
|
||||||
|
{ key: 'social', userInfo: { phone: '123456', id: 'foo' }, connectorId: 'logto' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
).rejects.toMatchError(
|
||||||
|
new RequestError(
|
||||||
|
{ code: 'user.missing_profile', status: 422 },
|
||||||
|
{ missingProfile: [MissingProfile.phone] }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('identifier includes social with verified phone should not throw', async () => {
|
it('identifier includes social with verified phone should not throw', async () => {
|
||||||
hasUserWithPhone.mockResolvedValueOnce(false);
|
hasUserWithPhone.mockResolvedValueOnce(false);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { Profile, SignInExperience, User } from '@logto/schemas';
|
import type { Profile, SignInExperience, User } from '@logto/schemas';
|
||||||
import { InteractionEvent, MissingProfile, SignInIdentifier } from '@logto/schemas';
|
import { InteractionEvent, MissingProfile, SignInIdentifier } from '@logto/schemas';
|
||||||
import type { Nullable } from '@silverhand/essentials';
|
import type { Nullable } from '@silverhand/essentials';
|
||||||
|
import { conditional } from '@silverhand/essentials';
|
||||||
import type { Context } from 'koa';
|
import type { Context } from 'koa';
|
||||||
|
|
||||||
import RequestError from '#src/errors/RequestError/index.js';
|
import RequestError from '#src/errors/RequestError/index.js';
|
||||||
|
@ -119,7 +120,7 @@ const fillMissingProfileWithSocialIdentity = async (
|
||||||
interaction: MandatoryProfileValidationInteraction,
|
interaction: MandatoryProfileValidationInteraction,
|
||||||
userQueries: Queries['users']
|
userQueries: Queries['users']
|
||||||
): Promise<MandatoryProfileValidationInteraction> => {
|
): Promise<MandatoryProfileValidationInteraction> => {
|
||||||
const { identifiers, profile } = interaction;
|
const { identifiers, profile, event } = interaction;
|
||||||
|
|
||||||
const socialUserInfo = getSocialUserInfo(identifiers);
|
const socialUserInfo = getSocialUserInfo(identifiers);
|
||||||
|
|
||||||
|
@ -144,7 +145,10 @@ const fillMissingProfileWithSocialIdentity = async (
|
||||||
{ code: 'user.missing_profile', status: 422 },
|
{ code: 'user.missing_profile', status: 422 },
|
||||||
{
|
{
|
||||||
missingProfile: Array.from(missingProfileSet),
|
missingProfile: Array.from(missingProfileSet),
|
||||||
registeredSocialIdentity: { email },
|
// Throw taken email when it's sign-in event
|
||||||
|
...conditional(
|
||||||
|
event === InteractionEvent.SignIn && { registeredSocialIdentity: { email } }
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -178,7 +182,10 @@ const fillMissingProfileWithSocialIdentity = async (
|
||||||
{ code: 'user.missing_profile', status: 422 },
|
{ code: 'user.missing_profile', status: 422 },
|
||||||
{
|
{
|
||||||
missingProfile: Array.from(missingProfileSet),
|
missingProfile: Array.from(missingProfileSet),
|
||||||
registeredSocialIdentity: { phone },
|
// Throw taken phone when it's sign-in event
|
||||||
|
...conditional(
|
||||||
|
event === InteractionEvent.SignIn && { registeredSocialIdentity: { phone } }
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,7 +27,7 @@ const useRequiredProfileErrorHandler = ({ replace, linkSocial }: Options = {}) =
|
||||||
// Required as a sign up method but missing in the user profile
|
// Required as a sign up method but missing in the user profile
|
||||||
const missingProfile = data?.missingProfile[0];
|
const missingProfile = data?.missingProfile[0];
|
||||||
|
|
||||||
// Required as a sign up method can be found in Social Identity (email / phone), but registered with a different account
|
// Required as a sign up method, verified email or phone can be found in Social Identity, but registered with a different account
|
||||||
const registeredSocialIdentity = data?.registeredSocialIdentity;
|
const registeredSocialIdentity = data?.registeredSocialIdentity;
|
||||||
|
|
||||||
const linkSocialQueryString = linkSocial
|
const linkSocialQueryString = linkSocial
|
||||||
|
|
Loading…
Reference in a new issue