0
Fork 0
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:
simeng-li 2022-05-20 10:04:52 +08:00 committed by GitHub
parent 9859213e19
commit 67f080e862
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 6 deletions

View file

@ -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;

View file

@ -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]) }
);
}

View 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');
});
});

View 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}`;
};