0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-03 21:48:55 -05:00
logto/packages/core/src/lib/user.ts

66 lines
1.8 KiB
TypeScript
Raw Normal View History

import { PasswordEncryptionMethod, User } from '@logto/schemas';
import { nanoid } from 'nanoid';
import pRetry from 'p-retry';
import { findUserByUsername, hasUserWithId } from '@/queries/user';
import assertThat from '@/utils/assert-that';
import { buildIdGenerator } from '@/utils/id';
import { encryptPassword } from '@/utils/password';
const userId = buildIdGenerator(12);
export const generateUserId = async (retries = 500) =>
pRetry(
async () => {
const id = userId();
if (!(await hasUserWithId(id))) {
return id;
}
throw new Error('Cannot generate user ID in reasonable retries');
},
{ retries, factor: 0 } // No need for exponential backoff
);
export const encryptUserPassword = (
userId: string,
password: string
): {
passwordEncryptionSalt: string;
passwordEncrypted: string;
passwordEncryptionMethod: PasswordEncryptionMethod;
} => {
const passwordEncryptionSalt = nanoid();
const passwordEncryptionMethod = PasswordEncryptionMethod.SaltAndPepper;
const passwordEncrypted = encryptPassword(
userId,
password,
passwordEncryptionSalt,
passwordEncryptionMethod
);
return { passwordEncrypted, passwordEncryptionMethod, passwordEncryptionSalt };
};
export const findUserByUsernameAndPassword = async (
username: string,
password: string
): Promise<User> => {
const user = await findUserByUsername(username);
const { id, passwordEncrypted, passwordEncryptionMethod, passwordEncryptionSalt } = user;
assertThat(
passwordEncrypted && passwordEncryptionMethod && passwordEncryptionSalt,
'session.invalid_sign_in_method'
);
assertThat(
encryptPassword(id, password, passwordEncryptionSalt, passwordEncryptionMethod) ===
passwordEncrypted,
'session.invalid_credentials'
);
return user;
};