111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { getRepository } from '@/lib/db/client';
|
|
import { SessionClaims } from '@/lib/feature/user/clerk.model';
|
|
import { UserEntity } from '@/lib/feature/user/user.entity';
|
|
import {
|
|
CreateUserModel,
|
|
UpdateUserModel,
|
|
UserModel,
|
|
} from '@/lib/feature/user/user.model';
|
|
|
|
export const userEntityToModel = (userEntity: UserEntity): UserModel => {
|
|
return {
|
|
id: userEntity.id,
|
|
name: userEntity.name,
|
|
email: userEntity.email,
|
|
role: userEntity.role,
|
|
externalId: userEntity.externalId,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Retrieves a user by their email address.
|
|
* @param email - The email address of the user to retrieve.
|
|
* @returns {Promise<UserModel | null>} The user model if found, otherwise null.
|
|
*/
|
|
export const getUserByEmail = async (
|
|
email: string
|
|
): Promise<UserModel | null> => {
|
|
const userRepository = await getRepository(UserEntity);
|
|
|
|
const userEntity = await userRepository.findOneBy({ email });
|
|
|
|
if (!userEntity) {
|
|
return null;
|
|
}
|
|
|
|
return userEntityToModel(userEntity);
|
|
};
|
|
|
|
/**
|
|
* Saves a new user to the database.
|
|
* @param user - The user data to save.
|
|
* @returns {Promise<UserModel>} The saved user model.
|
|
* @throws {Error} If a user with the same email already exists.
|
|
*/
|
|
export const saveUser = async (user: CreateUserModel): Promise<UserModel> => {
|
|
const userRepository = await getRepository(UserEntity);
|
|
|
|
if (!!(await userRepository.findOneBy({ email: user.email }))) {
|
|
throw new Error(`User with email ${user.email} already exists`);
|
|
}
|
|
|
|
const newUser = userRepository.create(user);
|
|
return userEntityToModel(await userRepository.save(newUser));
|
|
};
|
|
|
|
/**
|
|
* Updates an existing user in the database.
|
|
* @param userId - The ID of the user to update.
|
|
* @param user - The new user data.
|
|
* @returns {Promise<UserModel>} The updated user model.
|
|
* @throws {Error} If the user with the given ID does not exist.
|
|
*/
|
|
export const updateUser = async (
|
|
userId: string,
|
|
user: UpdateUserModel
|
|
): Promise<UserModel> => {
|
|
const userRepository = await getRepository(UserEntity);
|
|
|
|
const existingUser = await userRepository.findOneBy({ id: userId });
|
|
if (!existingUser) {
|
|
throw new Error(`User with ID ${userId} not found`);
|
|
}
|
|
|
|
if (!!user.email) existingUser.email = user.email;
|
|
if (!!user.name) existingUser.name = user.name;
|
|
if (!!user.role) existingUser.role = user.role;
|
|
|
|
return userEntityToModel(await userRepository.save(existingUser));
|
|
};
|
|
|
|
/**
|
|
* Synchronizes a user with the database.
|
|
* If the user already exists, it skips saving and returns the existing user.
|
|
* If the user does not exist, it creates a new user record.
|
|
* @returns {Promise<UserModel>} The synchronized user model.
|
|
* @throws {Error} If the user email is not provided or if there is an issue
|
|
* saving the user.
|
|
* @param sessionClaims Session Claims from the Auth Provider
|
|
*/
|
|
export const syncUser = async (
|
|
sessionClaims: SessionClaims
|
|
): Promise<UserModel> => {
|
|
const { full_name, email } = sessionClaims.user;
|
|
const role = sessionClaims.user.public_metadata.role;
|
|
|
|
const existingUser = await getUserByEmail(email);
|
|
if (!existingUser) {
|
|
return await saveUser({
|
|
name: full_name,
|
|
email: email,
|
|
role: role,
|
|
});
|
|
}
|
|
|
|
return await updateUser(existingUser.id, {
|
|
name: full_name,
|
|
email: existingUser.email,
|
|
role: role,
|
|
});
|
|
};
|