From 56fe8a43b4293e234498ebcb23d103c52d0b2d3d Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 1 Dec 2023 16:36:20 +0100 Subject: [PATCH 01/10] :sparkles: Can now resend sms right away --- package.json | 2 +- .../20231201150833_resent_totp/migration.sql | 2 + src/common/databases/schema.prisma | 1 + .../repositories/TotpCodesRepository.ts | 2 + .../CustomersService/CustomersService.ts | 42 +++++++++++-------- 5 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 src/common/databases/migrations/20231201150833_resent_totp/migration.sql diff --git a/package.json b/package.json index 33f4337d..7d1cb4f0 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "file-type-checker": "^1.0.8", "fp-ts": "^2.16.1", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.99", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", diff --git a/src/common/databases/migrations/20231201150833_resent_totp/migration.sql b/src/common/databases/migrations/20231201150833_resent_totp/migration.sql new file mode 100644 index 00000000..bf3805f6 --- /dev/null +++ b/src/common/databases/migrations/20231201150833_resent_totp/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "totp_codes" ADD COLUMN "resent" BOOLEAN NOT NULL DEFAULT false; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index be5c663b..77d5f2d3 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -348,6 +348,7 @@ model TotpCodes { customer_uid String @db.VarChar(255) code String @db.VarChar(255) reason TotpCodesReasons @default(LOGIN) + resent Boolean @default(false) expire_at DateTime? @default(now()) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt diff --git a/src/common/repositories/TotpCodesRepository.ts b/src/common/repositories/TotpCodesRepository.ts index 8d1ebf48..4a78e4e5 100644 --- a/src/common/repositories/TotpCodesRepository.ts +++ b/src/common/repositories/TotpCodesRepository.ts @@ -48,6 +48,7 @@ export default class TotpCodesRepository extends BaseRepository { }, }, expire_at: totpCode.expire_at!, + resent: totpCode.resent!, }, }; @@ -64,6 +65,7 @@ export default class TotpCodesRepository extends BaseRepository { }, data: { expire_at: new Date(), + resent: true, }, }); } diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index cf03f0c8..67dc09a5 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -1,10 +1,10 @@ import { BackendVariables } from "@Common/config/variables/Variables"; -import { Customers, Prisma } from "@prisma/client"; +import { Customers, Prisma, TotpCodes } from "@prisma/client"; import CustomersRepository from "@Repositories/CustomersRepository"; import TotpCodesRepository from "@Repositories/TotpCodesRepository"; import BaseService from "@Services/BaseService"; import AuthService from "@Services/common/AuthService/AuthService"; -import TotpCodes, { TotpCodesReasons } from "le-coffre-resources/dist/Customer/TotpCodes"; +import TotpCodesResource, { TotpCodesReasons } from "le-coffre-resources/dist/Customer/TotpCodes"; import { Customer } from "le-coffre-resources/dist/Notary"; import { Service } from "typedi"; import OvhService from "@Services/common/OvhService/OvhService"; @@ -88,7 +88,7 @@ export default class CustomersService extends BaseService { * 4: Save the SMS code in database * 5: Send the SMS code to the customer */ - public async verifyEmail2FASms(email: string): Promise<{ customer: Customer; totpCode: TotpCodes } | null> { + public async verifyEmail2FASms(email: string): Promise<{ customer: Customer; totpCode: TotpCodesResource } | null> { // 1: Check if the customer exists const customer = await this.getByEmail(email); if (!customer) return null; @@ -108,10 +108,16 @@ export default class CustomersService extends BaseService { const reason = customer.password ? TotpCodesReasons.LOGIN : TotpCodesReasons.FIRST_LOGIN; // 4: Save the SMS code in database const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), reason); - + if (!totpCode) return null; // 5: Send the SMS code to the customer await this.sendSmsCodeToCustomer(totpPin, customer); - return { customer, totpCode }; + return { + customer, + totpCode: TotpCodesResource.hydrate({ + ...totpCode, + reason: totpCode.reason as TotpCodesReasons, + }), + }; } /** @@ -273,7 +279,8 @@ export default class CustomersService extends BaseService { if (!totpCodeToResend) throw new TotpCodeExpiredError(); // 3: Check if it was created more than 30 seconds ago - if (totpCodeToResend.created_at && totpCodeToResend.created_at.getTime() > now - 30000) throw new TooSoonForNewCode(); + if (totpCodeToResend.created_at && totpCodeToResend.created_at.getTime() > now - 30000 && totpCodeToResend.resent) + throw new TooSoonForNewCode(); // 4: Generate a new SMS code const totpPin = this.generateTotp(); @@ -282,7 +289,7 @@ export default class CustomersService extends BaseService { await this.totpCodesRepository.disable(totpCodeToResend); // 6: Save the SMS code in database - const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), totpCodeToResend.reason!); + const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), totpCodeToResend.reason!, true); // 7: Send the SMS code to the customer await this.sendSmsCodeToCustomer(totpPin, customer); @@ -322,22 +329,23 @@ export default class CustomersService extends BaseService { /** * @description : Saves a TotpPin in database */ - private async saveTotpPin(customer: Customer, totpPin: number, expireAt: Date, reason: TotpCodesReasons) { + private async saveTotpPin( + customer: Customer, + totpPin: number, + expireAt: Date, + reason: TotpCodesReasons, + resent?: boolean, + ): Promise { // Create the totpCode in table using repository - await this.totpCodesRepository.create( - TotpCodes.hydrate({ + return await this.totpCodesRepository.create( + TotpCodesResource.hydrate({ reason, customer_uid: customer.uid, customer: Customer.hydrate(customer), created_at: new Date(), code: totpPin.toString(), expire_at: expireAt, - }), - ); - return await this.customerRepository.update( - customer.uid as string, - Customer.hydrate({ - ...customer, + resent: resent || false, }), ); } @@ -371,7 +379,7 @@ export default class CustomersService extends BaseService { * @param email * @returns */ - public async verifyTotpCode(totpCode: string, email: string): Promise { + public async verifyTotpCode(totpCode: string, email: string): Promise { // 1: Check if the customer exists const customer = await this.getByEmail(email); if (!customer) return null; From 869a30fac01aa61e7e94f1948e6a29c558fd8e69 Mon Sep 17 00:00:00 2001 From: Vins Date: Mon, 4 Dec 2023 02:30:31 +0100 Subject: [PATCH 02/10] Added ovh sms service name variable and cleaned code --- src/common/config/variables/Variables.ts | 4 +++ src/services/common/OvhService/OvhService.ts | 36 ++++++++----------- .../SmsFactorService/SmsFactorService.ts | 4 +-- .../CustomersService/CustomersService.ts | 2 +- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/common/config/variables/Variables.ts b/src/common/config/variables/Variables.ts index 5a46fd26..1a618ab6 100644 --- a/src/common/config/variables/Variables.ts +++ b/src/common/config/variables/Variables.ts @@ -121,6 +121,9 @@ export class BackendVariables { @IsNotEmpty() public readonly OVH_CONSUMER_KEY!: string; + @IsNotEmpty() + public readonly OVH_SMS_SERVICE_NAME!: string; + @IsNotEmpty() public readonly SMS_FACTOR_TOKEN!: string; @@ -165,6 +168,7 @@ export class BackendVariables { this.OVH_APP_KEY = process.env["OVH_APP_KEY"]!; this.OVH_APP_SECRET = process.env["OVH_APP_SECRET"]!; this.OVH_CONSUMER_KEY = process.env["OVH_CONSUMER_KEY"]!; + this.OVH_SMS_SERVICE_NAME = process.env["OVH_SMS_SERVICE_NAME"]!; this.SMS_FACTOR_TOKEN = process.env["SMS_FACTOR_TOKEN"]!; diff --git a/src/services/common/OvhService/OvhService.ts b/src/services/common/OvhService/OvhService.ts index f70b59d2..94fb0e05 100644 --- a/src/services/common/OvhService/OvhService.ts +++ b/src/services/common/OvhService/OvhService.ts @@ -14,30 +14,22 @@ export default class OvhService extends BaseService { appSecret: this.variables.OVH_APP_SECRET, consumerKey: this.variables.OVH_CONSUMER_KEY, }); - - ovh.request("GET", "/sms", function (err: any, serviceName: string) { - if (err) { - console.log(err, serviceName); - return false; + + const serviceName = this.variables.OVH_SMS_SERVICE_NAME; + + ovh.request('POST', '/sms/' + serviceName + '/jobs/', { + message: message, + sender: "LeCoffre", + receivers: [phoneNumber], + }, (error: any, response: any) => { + if (error) { + console.error('Error sending Ovh Sms:', error); + return false; } else { - console.log("My account SMS is " + serviceName); - - // Send a simple SMS with a short number using your serviceName - ovh.request( - "POST", - "/sms/" + serviceName + "/jobs", - { - message: message, - senderForResponse: true, - receivers: [phoneNumber], - }, - function (errsend: any, result: any) { - console.log(errsend, result); - }, - ); - return true; + console.log('SMS sent successfully via Ovh:', response); + return true; } }); - return false; + return false; } } diff --git a/src/services/common/SmsFactorService/SmsFactorService.ts b/src/services/common/SmsFactorService/SmsFactorService.ts index 851152ed..32bd38ea 100644 --- a/src/services/common/SmsFactorService/SmsFactorService.ts +++ b/src/services/common/SmsFactorService/SmsFactorService.ts @@ -17,12 +17,12 @@ export default class SmsFactorService extends BaseService { to: phoneNumber, text: message, }).then(response => { - console.log('SMS sent successfully:', response.data); + console.log('SMS sent successfully via Sms Factor :', response.data); return true; }) .catch(error => { - console.error('Error sending SMS:', error.response.data); + console.error('Error sending Sms Factor SMS:', error.response.data); return false; }); return false; diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index 67dc09a5..46a0843b 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -360,7 +360,7 @@ export default class CustomersService extends BaseService { // Envoi du SMS if (!customer.contact?.phone_number) return; - let success = await selectedProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); + let success = await selectedProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); // Si l'envoi échoue, basculez automatiquement sur le second fournisseur if (!success) { From 70845595dfdd09531671661fd245494275c63593 Mon Sep 17 00:00:00 2001 From: Vins Date: Mon, 4 Dec 2023 03:07:56 +0100 Subject: [PATCH 03/10] Sms factor done in simulate mode --- .../SmsFactorService/SmsFactorService.ts | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/services/common/SmsFactorService/SmsFactorService.ts b/src/services/common/SmsFactorService/SmsFactorService.ts index 32bd38ea..14f93b6b 100644 --- a/src/services/common/SmsFactorService/SmsFactorService.ts +++ b/src/services/common/SmsFactorService/SmsFactorService.ts @@ -5,26 +5,29 @@ import axios from "axios"; @Service() export default class SmsFactorService extends BaseService { - - constructor(private variables: BackendVariables) { + constructor(private variables: BackendVariables) { super(); } - public async sendSms(phoneNumber: string, message: string): Promise { - axios.post('https://api.smsfactor.com/send/', { - token: this.variables.SMS_FACTOR_TOKEN, - sender: "LeCoffre", - to: phoneNumber, - text: message, - }).then(response => { - console.log('SMS sent successfully via Sms Factor :', response.data); - return true; - - }) - .catch(error => { - console.error('Error sending Sms Factor SMS:', error.response.data); - return false; - }); - return false; - } -} \ No newline at end of file + public async sendSms(phoneNumber: string, message: string): Promise { + axios + .get( + "https://api.smsfactor.com/send/simulate?to=" + + phoneNumber + + "&sender=LeCoffre&text=" + + message + + "token=" + + this.variables.SMS_FACTOR_TOKEN, + {}, + ) + .then((response) => { + console.log("SMS sent successfully via Sms Factor:", response.status); + return true; + }) + .catch((error) => { + console.error("Error sending Sms Factor SMS:", error); + return false; + }); + return false; + } +} From 1d8642b61fed3d3467463f805bc31ec49767cc08 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 11:17:31 +0100 Subject: [PATCH 04/10] :sparkles: Improving comprehension of code --- src/app/api/customer/AuthController.ts | 5 ++--- .../customer/CustomersService/CustomersService.ts | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/app/api/customer/AuthController.ts b/src/app/api/customer/AuthController.ts index f4067dd9..55c922a2 100644 --- a/src/app/api/customer/AuthController.ts +++ b/src/app/api/customer/AuthController.ts @@ -6,7 +6,6 @@ import CustomersService, { InvalidPasswordError, InvalidTotpCodeError, NotRegisteredCustomerError, - PasswordAlreadySetError, SmsNotExpiredError, TooSoonForNewCode, TotpCodeExpiredError, @@ -141,7 +140,7 @@ export default class AuthController extends ApiController { } try { - const customer = await this.customerService.setFirstPassword(email, totpCode, password); + const customer = await this.customerService.setPassword(email, totpCode, password); if (!customer) { this.httpBadRequest(response, "Customer not found"); return; @@ -153,7 +152,7 @@ export default class AuthController extends ApiController { const refreshToken = this.authService.generateRefreshToken(payload); this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { - if (error instanceof TotpCodeExpiredError || error instanceof PasswordAlreadySetError) { + if (error instanceof TotpCodeExpiredError) { this.httpBadRequest(response, error.message); return; } diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index 46a0843b..922455f8 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -180,7 +180,7 @@ export default class CustomersService extends BaseService { * @param password * @returns */ - public async setFirstPassword(email: string, totpCode: string, password: string): Promise { + public async setPassword(email: string, totpCode: string, password: string): Promise { // 1: Check if the customer exists const customer = await this.getByEmail(email); if (!customer) return null; @@ -212,7 +212,7 @@ export default class CustomersService extends BaseService { const hashedPassword = await this.authService.hashPassword(password); // 7: Set the password in database and return the result of the update - return await this.setPassword(customer, hashedPassword); + return await this.setPasswordInDatabase(customer, hashedPassword); } /** @@ -300,7 +300,7 @@ export default class CustomersService extends BaseService { * @description : Set password for a customer * @throws {Error} If customer cannot be updated */ - private async setPassword(customer: Customer, password: string) { + private async setPasswordInDatabase(customer: Customer, password: string) { return await this.customerRepository.update( customer.uid as string, Customer.hydrate({ @@ -360,7 +360,7 @@ export default class CustomersService extends BaseService { // Envoi du SMS if (!customer.contact?.phone_number) return; - let success = await selectedProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); + let success = await selectedProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); // Si l'envoi échoue, basculez automatiquement sur le second fournisseur if (!success) { From cc316aeb2f472d6235bcd8ae6fed905acecd72f1 Mon Sep 17 00:00:00 2001 From: Vins Date: Mon, 4 Dec 2023 11:23:22 +0100 Subject: [PATCH 05/10] Sms feature finished + desactivate in dev --- src/services/common/OvhService/OvhService.ts | 1 + .../common/SmsFactorService/SmsFactorService.ts | 4 ++-- .../customer/CustomersService/CustomersService.ts | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/services/common/OvhService/OvhService.ts b/src/services/common/OvhService/OvhService.ts index 94fb0e05..eaa9196b 100644 --- a/src/services/common/OvhService/OvhService.ts +++ b/src/services/common/OvhService/OvhService.ts @@ -20,6 +20,7 @@ export default class OvhService extends BaseService { ovh.request('POST', '/sms/' + serviceName + '/jobs/', { message: message, sender: "LeCoffre", + senderForResponse: true, receivers: [phoneNumber], }, (error: any, response: any) => { if (error) { diff --git a/src/services/common/SmsFactorService/SmsFactorService.ts b/src/services/common/SmsFactorService/SmsFactorService.ts index 14f93b6b..13332750 100644 --- a/src/services/common/SmsFactorService/SmsFactorService.ts +++ b/src/services/common/SmsFactorService/SmsFactorService.ts @@ -16,12 +16,12 @@ export default class SmsFactorService extends BaseService { phoneNumber + "&sender=LeCoffre&text=" + message + - "token=" + + "&token=" + this.variables.SMS_FACTOR_TOKEN, {}, ) .then((response) => { - console.log("SMS sent successfully via Sms Factor:", response.status); + console.log("SMS sent successfully via Sms Factor :" + response); return true; }) .catch((error) => { diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index 922455f8..7a5789f6 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -110,7 +110,7 @@ export default class CustomersService extends BaseService { const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), reason); if (!totpCode) return null; // 5: Send the SMS code to the customer - await this.sendSmsCodeToCustomer(totpPin, customer); + if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); return { customer, totpCode: TotpCodesResource.hydrate({ @@ -162,7 +162,7 @@ export default class CustomersService extends BaseService { await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), TotpCodesReasons.RESET_PASSWORD); // 5: Send the SMS code to the customer - await this.sendSmsCodeToCustomer(totpPin, customer); + if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); return customer; } @@ -292,7 +292,7 @@ export default class CustomersService extends BaseService { const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), totpCodeToResend.reason!, true); // 7: Send the SMS code to the customer - await this.sendSmsCodeToCustomer(totpPin, customer); + if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); return { customer, totpCode }; } @@ -355,17 +355,18 @@ export default class CustomersService extends BaseService { } private async sendSmsCodeToCustomer(totpPin: number, customer: Customer) { + const message = "Votre code de vérification LEcoffre.io est : " + totpPin.toString(); // Sélectionnez le fournisseur de SMS en fonction de la variable d'environnement const selectedProvider = this.variables.SMS_PROVIDER === "OVH" ? this.ovhService : this.smsFactorService; // Envoi du SMS if (!customer.contact?.phone_number) return; - let success = await selectedProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); + let success = await selectedProvider.sendSms(customer.contact?.phone_number, message); // Si l'envoi échoue, basculez automatiquement sur le second fournisseur if (!success) { const alternateProvider = this.variables.SMS_PROVIDER === "OVH" ? this.smsFactorService : this.ovhService; - success = await alternateProvider.sendSms(customer.contact?.phone_number, totpPin.toString()); + success = await alternateProvider.sendSms(customer.contact?.phone_number, message); } } From 542e4ae24cc30cdd6ed56664bfdac2ac40cf1797 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 11:30:05 +0100 Subject: [PATCH 06/10] :sparkles: Improving comprehension of code --- .../customer/CustomersService/CustomersService.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index 7a5789f6..8af9653e 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -107,7 +107,7 @@ export default class CustomersService extends BaseService { const reason = customer.password ? TotpCodesReasons.LOGIN : TotpCodesReasons.FIRST_LOGIN; // 4: Save the SMS code in database - const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), reason); + const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60 * 1000), reason); if (!totpCode) return null; // 5: Send the SMS code to the customer if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); @@ -272,13 +272,13 @@ export default class CustomersService extends BaseService { const customerHydrated = Customer.hydrate(customer); - // 2: Get last code sent + // 2: Get last code sent and check if it's still valid const totpCodeToResend = customerHydrated.totpCodes?.find((totpCode) => { return totpCode.uid === totpCodeUid && totpCode.expire_at && totpCode.expire_at.getTime() > now; }); if (!totpCodeToResend) throw new TotpCodeExpiredError(); - // 3: Check if it was created more than 30 seconds ago + // 3: Check if it was created more than 30 seconds ago and hasn't been resent yet if (totpCodeToResend.created_at && totpCodeToResend.created_at.getTime() > now - 30000 && totpCodeToResend.resent) throw new TooSoonForNewCode(); @@ -288,8 +288,8 @@ export default class CustomersService extends BaseService { // 5: Disable the old code await this.totpCodesRepository.disable(totpCodeToResend); - // 6: Save the SMS code in database - const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), totpCodeToResend.reason!, true); + // 6: Save the SMS code in database with the same reason as the old one + const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60 * 1000), totpCodeToResend.reason!, true); // 7: Send the SMS code to the customer if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); From ff60250d5ce2cdd138bca620fc20fa49edca940e Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 11:38:11 +0100 Subject: [PATCH 07/10] :sparkles: Fix seeder with valid number --- src/common/databases/seeders/seeder.ts | 82 +++++++++++++------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index 33f9ec37..2e7b3f30 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -173,8 +173,8 @@ export default async function main() { first_name: "Angela", last_name: "Dubois", email: "angela.dubois@gmail.com", - phone_number: "06 12 34 56 78", - cell_phone_number: "06 12 34 56 78", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -185,8 +185,8 @@ export default async function main() { first_name: "Maxime", last_name: "Lalo", email: "maxime.lalo@smart-chain.fr", - phone_number: "06 23 45 67 89", - cell_phone_number: "06 23 45 67 89", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -197,8 +197,8 @@ export default async function main() { first_name: "Vincent", last_name: "Alamelle", email: "vincent.alamelle@smart-chain.fr", - phone_number: "06 34 56 78 90", - cell_phone_number: "06 34 56 78 90", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -209,8 +209,8 @@ export default async function main() { first_name: "Melissa", last_name: "Desde", email: "melissa.desde@smart-chain.fr", - phone_number: "06 45 67 89 01", - cell_phone_number: "06 45 67 89 01", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -221,8 +221,8 @@ export default async function main() { first_name: "Maxime", last_name: "Leroy", email: "maxime.leroy@hotmail.fr", - phone_number: "06 56 78 90 12", - cell_phone_number: "06 56 78 90 12", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -233,8 +233,8 @@ export default async function main() { first_name: "Paul", last_name: "Dupont", email: "paul.dupont@outlook.com", - phone_number: "06 67 89 01 23", - cell_phone_number: "06 67 89 01 23", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -245,8 +245,8 @@ export default async function main() { first_name: "Jean", last_name: "Dubignot", email: "jean.dubignot@gmail.com", - phone_number: "06 78 90 12 34", - cell_phone_number: "06 78 90 12 34", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -257,8 +257,8 @@ export default async function main() { first_name: "Vincent", last_name: "Martin", email: "vincent.martin@gmail.com", - phone_number: "06 89 01 23 45", - cell_phone_number: "06 89 01 23 45", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -269,8 +269,8 @@ export default async function main() { first_name: "Lucie", last_name: "Chevalier", email: "lucie.chevalier@outlook.com", - phone_number: "07 12 34 56 78", - cell_phone_number: "07 12 34 56 78", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -281,8 +281,8 @@ export default async function main() { first_name: "Sébastien", last_name: "Dubois", email: "sebastien.dubois@gmail.com", - phone_number: "07 23 45 67 89", - cell_phone_number: "07 23 45 67 89", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -293,8 +293,8 @@ export default async function main() { first_name: "Mathilde", last_name: "Durand", email: "mathilde.durand@gmail.com", - phone_number: "07 34 56 78 90", - cell_phone_number: "07 34 56 78 90", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -305,8 +305,8 @@ export default async function main() { first_name: "Antoine", last_name: "Bernard", email: "antoine.bernard@outlook.com", - phone_number: "07 45 67 89 01", - cell_phone_number: "07 45 67 89 01", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -317,8 +317,8 @@ export default async function main() { first_name: "Camille", last_name: "Laurent", email: "camille.laurent@gmail.com", - phone_number: "07 56 78 90 12", - cell_phone_number: "07 56 78 90 12", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -329,8 +329,8 @@ export default async function main() { first_name: "Julien", last_name: "Mercier", email: "julien.mercier@hotmail.fr", - phone_number: "07 67 89 01 23", - cell_phone_number: "07 67 89 01 23", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -341,8 +341,8 @@ export default async function main() { first_name: "Charlotte", last_name: "Lefebvre", email: "charlotte.lefebvre@gmail.com", - phone_number: "07 78 90 12 34", - cell_phone_number: "07 78 90 12 34", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -353,8 +353,8 @@ export default async function main() { first_name: "Caroline", last_name: "Pallut", email: "caroline.pallut@gmail.com", - phone_number: "07 89 01 23 45", - cell_phone_number: "07 89 01 23 45", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -365,8 +365,8 @@ export default async function main() { first_name: "Nadège", last_name: "Gauchet", email: "nedege.gauchet@outlook.com", - phone_number: "06 11 22 33 44", - cell_phone_number: "06 11 22 33 44", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -377,8 +377,8 @@ export default async function main() { first_name: "Matthieu", last_name: "Bougeard", email: "matthieu.bougeard@gmail.com", - phone_number: "07 22 33 44 55", - cell_phone_number: "07 22 33 44 55", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -389,8 +389,8 @@ export default async function main() { first_name: "Cécile", last_name: "Celton", email: "cecile.celton@outlook.com", - phone_number: "06 55 66 77 88", - cell_phone_number: "06 55 66 77 88", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -401,8 +401,8 @@ export default async function main() { first_name: "Gwendal", last_name: "Texier", email: "gwendal.texier@gmail.com", - phone_number: "07 88 99 00 11", - cell_phone_number: "07 88 99 00 11", + phone_number: "+33785186013", + cell_phone_number: "+33785186013", birthdate: null, created_at: new Date(), updated_at: new Date(), @@ -1548,7 +1548,7 @@ export default async function main() { office: offices[0], created_at: new Date(), updated_at: new Date(), - } + }, ]; const deedTypes: DeedType[] = [ From 63bb7e49357b8ff22feb4945dc651630e8075c94 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 4 Dec 2023 15:59:39 +0100 Subject: [PATCH 08/10] :sparkles: Updating resources version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d1cb4f0..e9f75855 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "file-type-checker": "^1.0.8", "fp-ts": "^2.16.1", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.102", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.104", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", From 00b46a24078d42c14b284dd75a34792883bf7a93 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 5 Dec 2023 09:49:48 +0100 Subject: [PATCH 09/10] :sparkles: Password verification --- src/app/api/customer/AuthController.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/app/api/customer/AuthController.ts b/src/app/api/customer/AuthController.ts index 55c922a2..ab47bf6e 100644 --- a/src/app/api/customer/AuthController.ts +++ b/src/app/api/customer/AuthController.ts @@ -125,17 +125,23 @@ export default class AuthController extends ApiController { const password = req.body["password"]; if (!email) { - this.httpBadRequest(response, "Email is required"); + this.httpBadRequest(response, "email is required"); return; } if (!totpCode) { - this.httpBadRequest(response, "Sms code is required"); + this.httpBadRequest(response, "totpCode is required"); return; } if (!password) { - this.httpBadRequest(response, "Password is required"); + this.httpBadRequest(response, "password is required"); + return; + } + + const passwordRegex = new RegExp(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,}$/); + if (!passwordRegex.test(password)) { + this.httpBadRequest(response, "Password must contain at least 8 characters, 1 uppercase, 1 lowercase and 1 number"); return; } From 8f00d3e4bdd2a7127dba9bee007e899030636fbb Mon Sep 17 00:00:00 2001 From: Vins Date: Tue, 5 Dec 2023 10:56:22 +0100 Subject: [PATCH 10/10] Fixed cellphonenumber --- src/services/common/OvhService/OvhService.ts | 8 +++--- .../SmsFactorService/SmsFactorService.ts | 7 +++--- .../CustomersService/CustomersService.ts | 25 +++++++++++-------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/services/common/OvhService/OvhService.ts b/src/services/common/OvhService/OvhService.ts index eaa9196b..b4868daf 100644 --- a/src/services/common/OvhService/OvhService.ts +++ b/src/services/common/OvhService/OvhService.ts @@ -17,20 +17,20 @@ export default class OvhService extends BaseService { const serviceName = this.variables.OVH_SMS_SERVICE_NAME; - ovh.request('POST', '/sms/' + serviceName + '/jobs/', { + await ovh.request('POST', '/sms/' + serviceName + '/jobs/', { message: message, sender: "LeCoffre", senderForResponse: true, receivers: [phoneNumber], }, (error: any, response: any) => { if (error) { - console.error('Error sending Ovh Sms:', error); + console.error('Error sending Ovh Sms'); return false; } else { - console.log('SMS sent successfully via Ovh:', response); + console.log('SMS sent successfully via Ovh'); return true; } }); - return false; + return true; } } diff --git a/src/services/common/SmsFactorService/SmsFactorService.ts b/src/services/common/SmsFactorService/SmsFactorService.ts index 13332750..1bc3f714 100644 --- a/src/services/common/SmsFactorService/SmsFactorService.ts +++ b/src/services/common/SmsFactorService/SmsFactorService.ts @@ -9,7 +9,7 @@ export default class SmsFactorService extends BaseService { super(); } - public async sendSms(phoneNumber: string, message: string): Promise { + public async sendSms(phoneNumber: string, message: string){ axios .get( "https://api.smsfactor.com/send/simulate?to=" + @@ -21,13 +21,12 @@ export default class SmsFactorService extends BaseService { {}, ) .then((response) => { - console.log("SMS sent successfully via Sms Factor :" + response); + console.log("SMS sent successfully via Sms Factor"); return true; }) .catch((error) => { - console.error("Error sending Sms Factor SMS:", error); + console.error("Error sending Sms Factor SMS"); return false; }); - return false; } } diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index 8af9653e..8870873d 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -1,4 +1,4 @@ -import { BackendVariables } from "@Common/config/variables/Variables"; +// import { BackendVariables } from "@Common/config/variables/Variables"; import { Customers, Prisma, TotpCodes } from "@prisma/client"; import CustomersRepository from "@Repositories/CustomersRepository"; import TotpCodesRepository from "@Repositories/TotpCodesRepository"; @@ -57,7 +57,7 @@ export default class CustomersService extends BaseService { private customerRepository: CustomersRepository, private authService: AuthService, private totpCodesRepository: TotpCodesRepository, - private variables: BackendVariables, + // private variables: BackendVariables, private ovhService: OvhService, private smsFactorService: SmsFactorService, ) { @@ -110,7 +110,8 @@ export default class CustomersService extends BaseService { const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60 * 1000), reason); if (!totpCode) return null; // 5: Send the SMS code to the customer - if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); + // if(this.variables.ENV !== 'dev') + await this.sendSmsCodeToCustomer(totpPin, customer); return { customer, totpCode: TotpCodesResource.hydrate({ @@ -162,7 +163,8 @@ export default class CustomersService extends BaseService { await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60000), TotpCodesReasons.RESET_PASSWORD); // 5: Send the SMS code to the customer - if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); + // if(this.variables.ENV !== 'dev') + await this.sendSmsCodeToCustomer(totpPin, customer); return customer; } @@ -292,7 +294,8 @@ export default class CustomersService extends BaseService { const totpCode = await this.saveTotpPin(customer, totpPin, new Date(now + 5 * 60 * 1000), totpCodeToResend.reason!, true); // 7: Send the SMS code to the customer - if(this.variables.ENV !== 'dev') await this.sendSmsCodeToCustomer(totpPin, customer); + // if(this.variables.ENV !== 'dev') + await this.sendSmsCodeToCustomer(totpPin, customer); return { customer, totpCode }; } @@ -356,17 +359,19 @@ export default class CustomersService extends BaseService { private async sendSmsCodeToCustomer(totpPin: number, customer: Customer) { const message = "Votre code de vérification LEcoffre.io est : " + totpPin.toString(); + // Sélectionnez le fournisseur de SMS en fonction de la variable d'environnement - const selectedProvider = this.variables.SMS_PROVIDER === "OVH" ? this.ovhService : this.smsFactorService; + //const selectedProvider = this.variables.SMS_PROVIDER === "OVH" ? this.ovhService : this.smsFactorService; // Envoi du SMS - if (!customer.contact?.phone_number) return; - let success = await selectedProvider.sendSms(customer.contact?.phone_number, message); + if (!customer.contact?.cell_phone_number) return; + let success = await this.ovhService.sendSms(customer.contact?.cell_phone_number, message); + // Si l'envoi échoue, basculez automatiquement sur le second fournisseur if (!success) { - const alternateProvider = this.variables.SMS_PROVIDER === "OVH" ? this.smsFactorService : this.ovhService; - success = await alternateProvider.sendSms(customer.contact?.phone_number, message); + //const alternateProvider = this.variables.SMS_PROVIDER === "OVH" ? this.smsFactorService : this.ovhService; + await this.smsFactorService.sendSms(customer.contact?.cell_phone_number, message); } }