✨ Refacto set first password
This commit is contained in:
parent
d3f9527f85
commit
97fd3f0d86
@ -7,6 +7,7 @@ import CustomersService, {
|
||||
InvalidPasswordError,
|
||||
InvalidTotpCodeError,
|
||||
NotRegisteredCustomerError,
|
||||
PasswordAlreadySetError,
|
||||
SmsNotExpiredError,
|
||||
TotpCodeExpiredError,
|
||||
} from "@Services/customer/CustomersService/CustomersService";
|
||||
@ -115,47 +116,29 @@ export default class AuthController extends ApiController {
|
||||
return;
|
||||
}
|
||||
|
||||
const customer = await this.customerService.getOne({
|
||||
where: {
|
||||
contact: {
|
||||
email,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
contact: true,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const customer = await this.customerService.setFirstPassword(email, smsCode, password);
|
||||
if (!customer) {
|
||||
this.httpNotFoundRequest(response, "Customer not found");
|
||||
this.httpBadRequest(response, "Customer not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (customer.password) {
|
||||
this.httpBadRequest(response, "Password already set, please login");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!customer.smsCode) {
|
||||
this.httpBadRequest(response, "No sms code found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (customer.smsCode !== smsCode) {
|
||||
this.httpBadRequest(response, "Invalid sms code");
|
||||
return;
|
||||
}
|
||||
|
||||
const hashedPassword = await this.authService.hashPassword(password);
|
||||
await this.customerService.setPassword(customer, hashedPassword);
|
||||
|
||||
const customerHydrated = Customer.hydrate<Customer>(customer);
|
||||
const payload = await this.authService.getCustomerJwtPayload([customerHydrated]);
|
||||
const accessToken = this.authService.generateAccessToken(payload);
|
||||
const refreshToken = this.authService.generateRefreshToken(payload);
|
||||
try {
|
||||
this.httpSuccess(response, { accessToken, refreshToken });
|
||||
} catch (error) {
|
||||
if (error instanceof TotpCodeExpiredError || error instanceof PasswordAlreadySetError) {
|
||||
this.httpBadRequest(response, error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error instanceof InvalidTotpCodeError) {
|
||||
this.httpUnauthorized(response, error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(error);
|
||||
this.httpInternalError(response);
|
||||
return;
|
||||
|
@ -34,6 +34,12 @@ export class InvalidPasswordError extends Error {
|
||||
super("Invalid password");
|
||||
}
|
||||
}
|
||||
|
||||
export class PasswordAlreadySetError extends Error {
|
||||
constructor() {
|
||||
super("Password already set");
|
||||
}
|
||||
}
|
||||
@Service()
|
||||
export default class CustomersService extends BaseService {
|
||||
constructor(private customerRepository: CustomersRepository, private authService: AuthService) {
|
||||
@ -56,10 +62,6 @@ export default class CustomersService extends BaseService {
|
||||
return this.customerRepository.findOne(query);
|
||||
}
|
||||
|
||||
public async userExistsByEmail(email: string): Promise<boolean> {
|
||||
return !!(await this.getByEmail(email));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Send SMS to verify the email of a customer (2FA)
|
||||
* 1: Check if the customer exists
|
||||
@ -85,56 +87,42 @@ export default class CustomersService extends BaseService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Saves a TotpPin in database
|
||||
* @description : Set the password of a customer when it's the first time they connect
|
||||
* 1: Check if the customer exists
|
||||
* 2: Check if the password is already set
|
||||
* 3: Check if the SMS code is existing and is not expired
|
||||
* 4: Check if the SMS code is valid
|
||||
* 5: Hash the password
|
||||
* 6: Set the password in database
|
||||
* 7: Returns the customer
|
||||
* @param email
|
||||
* @param smsCode
|
||||
* @param password
|
||||
* @returns
|
||||
*/
|
||||
private async saveTotpPin(customer: Customer, totpPin: number, expireAt: Date) {
|
||||
return await this.customerRepository.update(
|
||||
customer.uid as string,
|
||||
Customer.hydrate<Customer>({
|
||||
...customer,
|
||||
}),
|
||||
{
|
||||
smsCode: totpPin.toString(),
|
||||
smsCodeExpire: expireAt,
|
||||
},
|
||||
);
|
||||
}
|
||||
public async setFirstPassword(email: string, smsCode: string, password: string): Promise<Customer | null> {
|
||||
// 1: Check if the customer exists
|
||||
const customer = await this.getByEmail(email);
|
||||
if (!customer) return null;
|
||||
|
||||
private generateTotp() {
|
||||
return Math.floor(100000 + Math.random() * 900000);
|
||||
}
|
||||
// 2: Check if the password is already set
|
||||
if (customer.password) throw new PasswordAlreadySetError();
|
||||
|
||||
private async sendSmsCodeToCustomer(totpPin: number, customer: Customer) {
|
||||
console.log(totpPin);
|
||||
}
|
||||
// 3: Check if the SMS code is existing and is not expired
|
||||
if (!customer.smsCode || !customer.smsCodeExpire || new Date().getTime() > customer.smsCodeExpire.getTime())
|
||||
throw new TotpCodeExpiredError();
|
||||
|
||||
/**
|
||||
* @description : Set password for a customer
|
||||
* @throws {Error} If customer cannot be updated
|
||||
*/
|
||||
public async setPassword(customer: Customer, password: string) {
|
||||
return await this.customerRepository.update(
|
||||
customer.uid as string,
|
||||
Customer.hydrate<Customer>({
|
||||
...customer,
|
||||
}),
|
||||
{
|
||||
password,
|
||||
},
|
||||
);
|
||||
}
|
||||
// 4: Check if the SMS code is valid
|
||||
if (customer.smsCode !== smsCode) throw new InvalidTotpCodeError();
|
||||
|
||||
private getByEmail(email: string) {
|
||||
return this.customerRepository.findOne({
|
||||
where: {
|
||||
contact: {
|
||||
email,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
contact: true,
|
||||
},
|
||||
});
|
||||
// 5: Hash the password
|
||||
const hashedPassword = await this.authService.hashPassword(password);
|
||||
|
||||
// 6: Set the password in database
|
||||
await this.setPassword(customer, hashedPassword);
|
||||
|
||||
// 7: Returns the customer
|
||||
return customer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,4 +161,57 @@ export default class CustomersService extends BaseService {
|
||||
// 6: Return the customer
|
||||
return customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Set password for a customer
|
||||
* @throws {Error} If customer cannot be updated
|
||||
*/
|
||||
private async setPassword(customer: Customer, password: string) {
|
||||
return await this.customerRepository.update(
|
||||
customer.uid as string,
|
||||
Customer.hydrate<Customer>({
|
||||
...customer,
|
||||
}),
|
||||
{
|
||||
password,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private getByEmail(email: string) {
|
||||
return this.customerRepository.findOne({
|
||||
where: {
|
||||
contact: {
|
||||
email,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
contact: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Saves a TotpPin in database
|
||||
*/
|
||||
private async saveTotpPin(customer: Customer, totpPin: number, expireAt: Date) {
|
||||
return await this.customerRepository.update(
|
||||
customer.uid as string,
|
||||
Customer.hydrate<Customer>({
|
||||
...customer,
|
||||
}),
|
||||
{
|
||||
smsCode: totpPin.toString(),
|
||||
smsCodeExpire: expireAt,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private generateTotp() {
|
||||
return Math.floor(100000 + Math.random() * 900000);
|
||||
}
|
||||
|
||||
private async sendSmsCodeToCustomer(totpPin: number, customer: Customer) {
|
||||
console.log(totpPin);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user