mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
feat(core): add phone number and email mask (#891)
* feat(core): add phone number and email mask add phone number and email mask * fix(core): fix typo fix typo
This commit is contained in:
parent
9859213e19
commit
67f080e862
4 changed files with 35 additions and 6 deletions
|
@ -1,4 +1,5 @@
|
|||
import { User } from '@logto/schemas';
|
||||
import { Nullable } from '@silverhand/essentials';
|
||||
import { InteractionResults } from 'oidc-provider';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
@ -77,19 +78,17 @@ export const getUserInfoFromInteractionResult = async (
|
|||
*/
|
||||
export const findSocialRelatedUser = async (
|
||||
info: SocialUserInfo
|
||||
// FIXME:
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
): Promise<null | [string, User]> => {
|
||||
): Promise<Nullable<[{ type: 'email' | 'phone'; value: string }, User]>> => {
|
||||
if (info.phone && (await hasUserWithPhone(info.phone))) {
|
||||
const user = await findUserByPhone(info.phone);
|
||||
|
||||
return [info.phone, user];
|
||||
return [{ type: 'phone', value: info.phone }, user];
|
||||
}
|
||||
|
||||
if (info.email && (await hasUserWithEmail(info.email))) {
|
||||
const user = await findUserByEmail(info.email);
|
||||
|
||||
return [info.email, user];
|
||||
return [{ type: 'email', value: info.email }, user];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -44,6 +44,7 @@ import {
|
|||
findUserByIdentity,
|
||||
} from '@/queries/user';
|
||||
import assertThat from '@/utils/assert-that';
|
||||
import { maskUserInfo } from '@/utils/format';
|
||||
|
||||
import { AnonymousRouter } from './types';
|
||||
|
||||
|
@ -231,12 +232,13 @@ export default function sessionRoutes<T extends AnonymousRouter>(router: T, prov
|
|||
true
|
||||
);
|
||||
const relatedInfo = await findSocialRelatedUser(userInfo);
|
||||
|
||||
throw new RequestError(
|
||||
{
|
||||
code: 'user.identity_not_exists',
|
||||
status: 422,
|
||||
},
|
||||
relatedInfo && { relatedUser: relatedInfo[0] }
|
||||
relatedInfo && { relatedUser: maskUserInfo(relatedInfo[0]) }
|
||||
);
|
||||
}
|
||||
|
||||
|
|
13
packages/core/src/utils/format.test.ts
Normal file
13
packages/core/src/utils/format.test.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { maskUserInfo } from './format';
|
||||
|
||||
describe('maskUserInfo', () => {
|
||||
it('phone', () => {
|
||||
expect(maskUserInfo({ type: 'phone', value: '1234567890' })).toBe('****7890');
|
||||
});
|
||||
it('email with name less than 5', () => {
|
||||
expect(maskUserInfo({ type: 'email', value: 'test@logto.io' })).toBe('****@logto.io');
|
||||
});
|
||||
it('email with name more than 4', () => {
|
||||
expect(maskUserInfo({ type: 'email', value: 'foo_test@logto.io' })).toBe('foo_****@logto.io');
|
||||
});
|
||||
});
|
15
packages/core/src/utils/format.ts
Normal file
15
packages/core/src/utils/format.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
export const maskUserInfo = ({ type, value }: { type: 'email' | 'phone'; value: string }) => {
|
||||
if (!value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (type === 'phone') {
|
||||
return `****${value.slice(-4)}`;
|
||||
}
|
||||
|
||||
const [name = '', domain = ''] = value.split('@');
|
||||
|
||||
const preview = name.length > 4 ? `${name.slice(0, 4)}` : '';
|
||||
|
||||
return `${preview}****@${domain}`;
|
||||
};
|
Loading…
Reference in a new issue