import bcrypt from 'bcryptjs'; import { Op } from 'sequelize'; import { Optional } from '~/types'; import Role from './Role'; import RoleName from './RoleName'; class User { public id: number; public username: string; public password: string; public email: string; public firstName: Optional<string>; public lastName: Optional<string>; public createdAt: Optional<Date>; constructor({ id, username, email, password, firstName = null, lastName = null, createdAt = null, }: User) { this.id = id; this.username = username; this.email = email; this.password = password; this.firstName = firstName; this.lastName = lastName; this.createdAt = createdAt; } public static hashPassword(password: string): string { return bcrypt.hashSync(password, bcrypt.genSaltSync(10)); } public checkPassword(password: string): boolean { return bcrypt.compareSync(password, this.password); } public async roles(): Promise<Role[]> { return ( await $db.UserRole().findAll({ where: { userId: this.id, }, }) ).map((role) => new Role(role.dataValues)); } public async setRoles(roles: (Role | RoleName | number | string)[]): Promise<void> { const inputRoleIds = new Set( roles.filter((role) => { role instanceof Role || typeof role === 'number' }).map((role) => { if (role instanceof Role) { return role.id; } return role; }) ); const inputRoleNames = new Set( roles.filter((role) => { typeof role === 'string' }).map((role) => { return role; }) ); if (!inputRoleIds.size && !inputRoleNames.size) { return; // No roles to set } const query: Record<string, any> = {} if (inputRoleIds.size) { query['id'] = [...inputRoleIds]; } if (inputRoleNames.size) { query['name'] = [...inputRoleNames]; } const roleIds = new Set( ( await $db.Role().findAll({ where: { [Op.or]: query, }, }) ).map((role) => (role as any).id) ); const userRoles = await $db.UserRole().findAll({ where: { userId: this.id, }, }); const userRoleIds = new Set(userRoles.map((role) => (role as any).roleId)); const toAdd = [...roleIds].filter((roleId) => !userRoleIds.has(roleId)); const toRemove = userRoles.filter((role) => !roleIds.has((role as any).roleId)).map((role) => (role as any).roleId); await $db.UserRole().bulkCreate( toAdd.map((roleId) => ({ userId: this.id, roleId: roleId, })), ); await $db.UserRole().destroy({ where: { userId: this.id, roleId: toRemove, }, }); } public async save(): Promise<void> { this.password = User.hashPassword(this.password); await $db.User().update(this, { where: { id: this.id, }, }); } } export default User;