2024-05-15 19:56:22 +00:00
|
|
|
import bCrypt from "bcryptjs";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
AggregateRoot,
|
|
|
|
|
Email,
|
|
|
|
|
IDomainError,
|
2024-05-16 11:56:46 +00:00
|
|
|
Name,
|
2024-05-15 19:56:22 +00:00
|
|
|
Result,
|
|
|
|
|
UniqueID,
|
|
|
|
|
} from "@shared/contexts";
|
|
|
|
|
|
|
|
|
|
export interface IUserProps {
|
2024-05-16 11:56:46 +00:00
|
|
|
name: Name;
|
2024-05-15 19:56:22 +00:00
|
|
|
email: Email;
|
|
|
|
|
password?: string;
|
|
|
|
|
hashed_password?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IUser {
|
|
|
|
|
id: UniqueID;
|
2024-05-16 11:56:46 +00:00
|
|
|
name: Name;
|
2024-05-15 19:56:22 +00:00
|
|
|
email: Email;
|
|
|
|
|
hashed_password: string;
|
|
|
|
|
|
|
|
|
|
verifyPassword: (candidatePassword: string) => boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class User extends AggregateRoot<IUserProps> implements IUser {
|
|
|
|
|
public static create(
|
|
|
|
|
props: IUserProps,
|
|
|
|
|
id?: UniqueID,
|
|
|
|
|
): Result<User, IDomainError> {
|
|
|
|
|
//const isNew = !!id === false;
|
|
|
|
|
|
|
|
|
|
// Se hace en el constructor de la Entidad
|
|
|
|
|
/* if (isNew) {
|
|
|
|
|
id = UniqueEntityID.create();
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
const user = new User(props, id);
|
|
|
|
|
|
|
|
|
|
return Result.ok<User>(user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async hashPassword(password): Promise<string> {
|
|
|
|
|
return hashPassword(password, await genSalt());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _hashed_password: string;
|
|
|
|
|
|
|
|
|
|
private constructor(props: IUserProps, id?: UniqueID) {
|
|
|
|
|
super({ ...props, password: "", hashed_password: "" }, id);
|
|
|
|
|
|
|
|
|
|
this._protectPassword(props);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-16 11:56:46 +00:00
|
|
|
get name(): Name {
|
|
|
|
|
return this.props.name;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 19:56:22 +00:00
|
|
|
get email(): Email {
|
|
|
|
|
return this.props.email;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get hashed_password(): string {
|
|
|
|
|
return this._hashed_password;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public verifyPassword(candidatePassword: string): boolean {
|
|
|
|
|
return bCrypt.compareSync(candidatePassword, this._hashed_password!);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async _protectPassword(props: IUserProps) {
|
|
|
|
|
const { password, hashed_password } = props;
|
|
|
|
|
|
|
|
|
|
if (password) {
|
|
|
|
|
this._hashed_password = await User.hashPassword(password);
|
|
|
|
|
} else {
|
|
|
|
|
this._hashed_password = hashed_password!;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function genSalt(rounds = 10): Promise<string> {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
bCrypt.genSalt(rounds, function (err, salt) {
|
|
|
|
|
if (err) return reject(err);
|
|
|
|
|
return resolve(salt);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function hashPassword(password: string, salt: string): Promise<string> {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
bCrypt.hash(password, salt, function (err, hash) {
|
|
|
|
|
if (err) return reject(err);
|
|
|
|
|
return resolve(hash);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
User.hashPassword("123456").then((value) => console.log(value));
|