✨ Refacto login
This commit is contained in:
parent
fc8b86b7ca
commit
d3f9527f85
@ -3,7 +3,13 @@ import { Controller, Post } from "@ControllerPattern/index";
|
|||||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||||
import { Service } from "typedi";
|
import { Service } from "typedi";
|
||||||
import { EnrollmentResponse } from "@Services/common/Id360Service/Id360Service";
|
import { EnrollmentResponse } from "@Services/common/Id360Service/Id360Service";
|
||||||
import CustomersService, { SmsNotExpiredError } from "@Services/customer/CustomersService/CustomersService";
|
import CustomersService, {
|
||||||
|
InvalidPasswordError,
|
||||||
|
InvalidTotpCodeError,
|
||||||
|
NotRegisteredCustomerError,
|
||||||
|
SmsNotExpiredError,
|
||||||
|
TotpCodeExpiredError,
|
||||||
|
} from "@Services/customer/CustomersService/CustomersService";
|
||||||
import AuthService, { ICustomerJwtPayload } from "@Services/common/AuthService/AuthService";
|
import AuthService, { ICustomerJwtPayload } from "@Services/common/AuthService/AuthService";
|
||||||
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
|
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
|
||||||
|
|
||||||
@ -28,7 +34,7 @@ export default class AuthController extends ApiController {
|
|||||||
this.httpNotFoundRequest(response, "Customer not found");
|
this.httpNotFoundRequest(response, "Customer not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.httpSuccess(response, { partialPhoneNumber: customer.contact?.cell_phone_number.slice(-4) });
|
this.httpSuccess(response, { partialPhoneNumber: customer.contact?.cell_phone_number.replace(/\s/g, "").slice(-4) });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof SmsNotExpiredError) {
|
if (error instanceof SmsNotExpiredError) {
|
||||||
this.httpTooEarlyRequest(response, error.message);
|
this.httpTooEarlyRequest(response, error.message);
|
||||||
@ -60,56 +66,28 @@ export default class AuthController extends ApiController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let customer = await this.customerService.getOne({
|
try {
|
||||||
where: {
|
const customer = await this.customerService.login(email, smsCode, password);
|
||||||
contact: {
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
contact: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!customer) {
|
if (!customer) {
|
||||||
this.httpNotFoundRequest(response, "Customer not found");
|
this.httpBadRequest(response, "Customer not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!customer.smsCode) {
|
|
||||||
this.httpBadRequest(response, "No sms code found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!customer.smsCodeExpire || new Date().getTime() > customer.smsCodeExpire.getTime()) {
|
|
||||||
this.httpBadRequest(response, "Sms code expired");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customer.smsCode !== smsCode) {
|
|
||||||
this.httpBadRequest(response, "Invalid sms code");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!customer.password) {
|
|
||||||
this.httpBadRequest(response, "Customer not registered");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compare password to the hash
|
|
||||||
const isPasswordValid = await this.authService.comparePassword(password, customer.password);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
this.httpBadRequest(response, "Invalid password");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const customerHydrated = Customer.hydrate<Customer>(customer);
|
const customerHydrated = Customer.hydrate<Customer>(customer);
|
||||||
const payload = await this.authService.getCustomerJwtPayload([customerHydrated]);
|
const payload = await this.authService.getCustomerJwtPayload([customerHydrated]);
|
||||||
const accessToken = this.authService.generateAccessToken(payload);
|
const accessToken = this.authService.generateAccessToken(payload);
|
||||||
const refreshToken = this.authService.generateRefreshToken(payload);
|
const refreshToken = this.authService.generateRefreshToken(payload);
|
||||||
try {
|
|
||||||
this.httpSuccess(response, { accessToken, refreshToken });
|
this.httpSuccess(response, { accessToken, refreshToken });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof TotpCodeExpiredError || error instanceof NotRegisteredCustomerError) {
|
||||||
|
this.httpBadRequest(response, error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof InvalidTotpCodeError || error instanceof InvalidPasswordError) {
|
||||||
|
this.httpUnauthorized(response, error.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
this.httpInternalError(response);
|
this.httpInternalError(response);
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Customers, Prisma } from "@prisma/client";
|
import { Customers, Prisma } from "@prisma/client";
|
||||||
import CustomersRepository from "@Repositories/CustomersRepository";
|
import CustomersRepository from "@Repositories/CustomersRepository";
|
||||||
import BaseService from "@Services/BaseService";
|
import BaseService from "@Services/BaseService";
|
||||||
|
import AuthService from "@Services/common/AuthService/AuthService";
|
||||||
import { Customer } from "le-coffre-resources/dist/Notary";
|
import { Customer } from "le-coffre-resources/dist/Notary";
|
||||||
import { Service } from "typedi";
|
import { Service } from "typedi";
|
||||||
|
|
||||||
@ -9,9 +10,33 @@ export class SmsNotExpiredError extends Error {
|
|||||||
super("SMS code not expired");
|
super("SMS code not expired");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class TotpCodeExpiredError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super("Totp code not found or expired");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidTotpCodeError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super("Invalid Totp code");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NotRegisteredCustomerError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super("Customer not registered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InvalidPasswordError extends Error {
|
||||||
|
constructor() {
|
||||||
|
super("Invalid password");
|
||||||
|
}
|
||||||
|
}
|
||||||
@Service()
|
@Service()
|
||||||
export default class CustomersService extends BaseService {
|
export default class CustomersService extends BaseService {
|
||||||
constructor(private customerRepository: CustomersRepository) {
|
constructor(private customerRepository: CustomersRepository, private authService: AuthService) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,4 +136,41 @@ export default class CustomersService extends BaseService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description : Login a customer
|
||||||
|
* 1: Check if the customer exists
|
||||||
|
* 2: Check if the SMS code is existing and is not expired
|
||||||
|
* 3: Check if the SMS code is valid
|
||||||
|
* 4: Check if the user has a password or it's their first login
|
||||||
|
* 5: Check if the password is valid
|
||||||
|
* 6: Return the customer
|
||||||
|
* @param email
|
||||||
|
* @param smsCode
|
||||||
|
* @param password
|
||||||
|
* @returns Customer | null
|
||||||
|
*/
|
||||||
|
public async login(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;
|
||||||
|
|
||||||
|
// 2: 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();
|
||||||
|
|
||||||
|
// 3: Check if the SMS code is valid
|
||||||
|
if (customer.smsCode !== smsCode) throw new InvalidTotpCodeError();
|
||||||
|
|
||||||
|
// 4: Check if the user has a password or it's their first login
|
||||||
|
if (!customer.password) throw new NotRegisteredCustomerError();
|
||||||
|
|
||||||
|
// 5: Check if the password is valid
|
||||||
|
const isPasswordValid = await this.authService.comparePassword(password, customer.password);
|
||||||
|
if (!isPasswordValid) throw new InvalidPasswordError();
|
||||||
|
|
||||||
|
// 6: Return the customer
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user