From 6997e13d28022ccafb530b4ce83658302e4cdec6 Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 13 Dec 2023 10:20:24 +0100 Subject: [PATCH 1/9] removed logs --- src/services/common/IdNotService/IdNotService.ts | 5 +---- src/services/common/OvhService/OvhService.ts | 1 - src/services/common/SmsFactorService/SmsFactorService.ts | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/services/common/IdNotService/IdNotService.ts b/src/services/common/IdNotService/IdNotService.ts index d5a0eac8..5f9f9fda 100644 --- a/src/services/common/IdNotService/IdNotService.ts +++ b/src/services/common/IdNotService/IdNotService.ts @@ -120,10 +120,7 @@ export default class IdNotService extends BaseService { redirect_uri: this.variables.IDNOT_REDIRECT_URL, code: code, grant_type: "authorization_code", - }); - - console.log(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query); - + }); const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" }); if(token.status !== 200) console.error(await token.text()); diff --git a/src/services/common/OvhService/OvhService.ts b/src/services/common/OvhService/OvhService.ts index f6550900..79036fcb 100644 --- a/src/services/common/OvhService/OvhService.ts +++ b/src/services/common/OvhService/OvhService.ts @@ -27,7 +27,6 @@ export default class OvhService extends BaseService { console.error('Error sending Ovh Sms'); return false; } else { - console.log('SMS sent successfully via Ovh'); return true; } }); diff --git a/src/services/common/SmsFactorService/SmsFactorService.ts b/src/services/common/SmsFactorService/SmsFactorService.ts index 1bc3f714..c756ca3d 100644 --- a/src/services/common/SmsFactorService/SmsFactorService.ts +++ b/src/services/common/SmsFactorService/SmsFactorService.ts @@ -21,7 +21,6 @@ export default class SmsFactorService extends BaseService { {}, ) .then((response) => { - console.log("SMS sent successfully via Sms Factor"); return true; }) .catch((error) => { From a6bdd8708867b2947ed1bbe9cd34f7f240bbefeb Mon Sep 17 00:00:00 2001 From: Vins Date: Fri, 15 Dec 2023 13:16:45 +0100 Subject: [PATCH 2/9] done --- package.json | 2 +- src/app/api/admin/CustomersController.ts | 4 +++- src/app/api/notary/CustomersController.ts | 2 ++ src/app/api/super-admin/CustomersController.ts | 4 +++- src/app/middlewares/AuthHandler.ts | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e9f75855..162504e4 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.104", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.105", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", diff --git a/src/app/api/admin/CustomersController.ts b/src/app/api/admin/CustomersController.ts index 90e05691..8a81eaa6 100644 --- a/src/app/api/admin/CustomersController.ts +++ b/src/app/api/admin/CustomersController.ts @@ -56,7 +56,7 @@ export default class CustomersController extends ApiController { /** * @description Create a new customer */ - @Post("/api/v1/notary/customers", [authHandler, ruleHandler]) + @Post("/api/v1/admin/customers", [authHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -69,6 +69,8 @@ export default class CustomersController extends ApiController { return; } + if (!customerEntity.contact?.cell_phone_number) return; + const customers = await this.customersService.get({ where: { contact: { email: customerEntity.contact?.email }, diff --git a/src/app/api/notary/CustomersController.ts b/src/app/api/notary/CustomersController.ts index 0c63db1f..ada54166 100644 --- a/src/app/api/notary/CustomersController.ts +++ b/src/app/api/notary/CustomersController.ts @@ -68,6 +68,8 @@ export default class CustomersController extends ApiController { return; } + if (!customerEntity.contact?.cell_phone_number) return; + const customers = await this.customersService.get({ where: { contact: { email: customerEntity.contact?.email }, diff --git a/src/app/api/super-admin/CustomersController.ts b/src/app/api/super-admin/CustomersController.ts index fdb8ff01..28366c9f 100644 --- a/src/app/api/super-admin/CustomersController.ts +++ b/src/app/api/super-admin/CustomersController.ts @@ -57,7 +57,7 @@ export default class CustomersController extends ApiController { /** * @description Create a new customer */ - @Post("/api/v1/notary/customers", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/customers", [authHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -70,6 +70,8 @@ export default class CustomersController extends ApiController { return; } + if (!customerEntity.contact?.cell_phone_number) return; + const customers = await this.customersService.get({ where: { contact: { email: customerEntity.contact?.email }, diff --git a/src/app/middlewares/AuthHandler.ts b/src/app/middlewares/AuthHandler.ts index bd3f1293..28c1f082 100644 --- a/src/app/middlewares/AuthHandler.ts +++ b/src/app/middlewares/AuthHandler.ts @@ -13,7 +13,7 @@ export default function authHandler(req: Request, response: Response, next: Next return; } - const authService = Container.get(AuthService); + const authService = Container.get(AuthService); authService.verifyAccessToken(token, (err, userPayload) => { if (err) { response.status(HttpCodes.UNAUTHORIZED).send("Error while verifying token"); From 67dfcaec5f8b98266c4938d3c3c9feb43e86b2cd Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Fri, 15 Dec 2023 16:03:31 +0100 Subject: [PATCH 3/9] :sparkles: Errors in french for front --- .../CustomersService/CustomersService.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index ce8d6fff..f307e2cc 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -12,43 +12,43 @@ import SmsFactorService from "@Services/common/SmsFactorService/SmsFactorService export class SmsNotExpiredError extends Error { constructor() { - super("SMS code not expired"); + super("Code déjà envoyé"); } } export class TotpCodeExpiredError extends Error { constructor() { - super("Totp code not found or expired"); + super("Code non trouvé ou expiré"); } } export class InvalidTotpCodeError extends Error { constructor() { - super("Invalid Totp code"); + super("Code invalide"); } } export class NotRegisteredCustomerError extends Error { constructor() { - super("Customer not registered"); + super("Ce client n'existe pas"); } } export class InvalidPasswordError extends Error { constructor() { - super("Invalid password"); + super("Mot de passe incorrect"); } } export class PasswordAlreadySetError extends Error { constructor() { - super("Password already set"); + super("Le mot de passe a déjà été défini"); } } export class TooSoonForNewCode extends Error { constructor() { - super("You need to wait at least 30 seconds before asking for a new code"); + super("Vous devez attendre 30 secondes avant de pouvoir demander un nouveau code"); } } @Service() @@ -110,7 +110,7 @@ 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 +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 - if(this.variables.ENV !== 'dev') 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 * 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,14 +356,13 @@ 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?.cell_phone_number) return; - let success = await this.ovhService.sendSms(customer.contact?.cell_phone_number, message); - + let success = await this.ovhService.sendSms(customer.contact?.cell_phone_number, message); // Si l'envoi échoue, basculez automatiquement sur le second fournisseur if (!success) { From 12744ea98e5d34e57988bcf2199d39ddf2336db4 Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Mon, 18 Dec 2023 11:02:47 +0100 Subject: [PATCH 4/9] :bug: Changing error on code expired --- src/services/customer/CustomersService/CustomersService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts index f307e2cc..234238c8 100644 --- a/src/services/customer/CustomersService/CustomersService.ts +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -18,7 +18,7 @@ export class SmsNotExpiredError extends Error { export class TotpCodeExpiredError extends Error { constructor() { - super("Code non trouvé ou expiré"); + super("Code non trouvé ou expiré, veuillez raffraîchir la page"); } } From 34eb644940926c25c49e0d122126bfced2ef4da8 Mon Sep 17 00:00:00 2001 From: Vins Date: Tue, 19 Dec 2023 15:11:13 +0100 Subject: [PATCH 5/9] cell_phone not required --- package.json | 2 +- src/app/api/customer/AuthController.ts | 6 +++--- .../migration.sql | 2 ++ src/common/databases/schema.prisma | 2 +- src/common/repositories/UsersRepository.ts | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 src/common/databases/migrations/20231219140925_20231219_cellphone_not_required/migration.sql diff --git a/package.json b/package.json index 162504e4..65a5d8c7 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.105", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.106", "module-alias": "^2.2.2", "monocle-ts": "^2.3.13", "multer": "^1.4.5-lts.1", diff --git a/src/app/api/customer/AuthController.ts b/src/app/api/customer/AuthController.ts index ab47bf6e..e62ea8b0 100644 --- a/src/app/api/customer/AuthController.ts +++ b/src/app/api/customer/AuthController.ts @@ -35,7 +35,7 @@ export default class AuthController extends ApiController { return; } this.httpSuccess(response, { - partialPhoneNumber: res.customer.contact?.cell_phone_number.replace(/\s/g, "").slice(-4), + partialPhoneNumber: res.customer.contact?.cell_phone_number?.replace(/\s/g, "").slice(-4), totpCodeUid: res.totpCode.uid, }); } catch (error) { @@ -58,7 +58,7 @@ export default class AuthController extends ApiController { this.httpNotFoundRequest(response, "Customer not found"); return; } - this.httpSuccess(response, { partialPhoneNumber: customer.contact?.cell_phone_number.replace(/\s/g, "").slice(-4) }); + this.httpSuccess(response, { partialPhoneNumber: customer.contact?.cell_phone_number?.replace(/\s/g, "").slice(-4) }); } catch (error) { if (error instanceof SmsNotExpiredError) { this.httpTooEarlyRequest(response, error.message); @@ -229,7 +229,7 @@ export default class AuthController extends ApiController { return; } this.httpSuccess(response, { - partialPhoneNumber: res.customer.contact?.cell_phone_number.replace(/\s/g, "").slice(-4), + partialPhoneNumber: res.customer.contact?.cell_phone_number?.replace(/\s/g, "").slice(-4), totpCodeUid: res.totpCode.uid, }); } catch (error) { diff --git a/src/common/databases/migrations/20231219140925_20231219_cellphone_not_required/migration.sql b/src/common/databases/migrations/20231219140925_20231219_cellphone_not_required/migration.sql new file mode 100644 index 00000000..4763e7c0 --- /dev/null +++ b/src/common/databases/migrations/20231219140925_20231219_cellphone_not_required/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "contacts" ALTER COLUMN "cell_phone_number" DROP NOT NULL; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index 77d5f2d3..9d72ec44 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -37,7 +37,7 @@ model Contacts { last_name String @db.VarChar(255) email String @db.VarChar(255) phone_number String? @db.VarChar(50) - cell_phone_number String @db.VarChar(50) + cell_phone_number String? @db.VarChar(50) civility ECivility @default(MALE) address Addresses? @relation(fields: [address_uid], references: [uid], onDelete: Cascade) address_uid String? @unique @db.VarChar(255) diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index 718f6066..c0f466e6 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -56,7 +56,7 @@ export default class UsersRepository extends BaseRepository { last_name: user.contact!.last_name, email: user.contact!.email, phone_number: user.contact?.phone_number, - cell_phone_number: user.contact!.cell_phone_number, + cell_phone_number: user.contact!.cell_phone_number || null, civility: ECivility[user.contact?.civility as keyof typeof ECivility], }, }, From 4544b7209b11324d2cab734624548cccc26555be Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 20 Dec 2023 11:15:59 +0100 Subject: [PATCH 6/9] Whitelist ready --- src/app/api/idnot/UserController.ts | 29 +++++++++++++- .../20231220084359_whitelist/migration.sql | 16 ++++++++ src/common/databases/schema.prisma | 9 +++++ .../repositories/WhitelistRepository.ts | 39 +++++++++++++++++++ .../controller-pattern/BaseController.ts | 4 ++ .../WhitelistService/WhitelistService.ts | 14 +++++++ 6 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/common/databases/migrations/20231220084359_whitelist/migration.sql create mode 100644 src/common/repositories/WhitelistRepository.ts create mode 100644 src/services/common/WhitelistService/WhitelistService.ts diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 60d13059..77d79065 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -5,11 +5,14 @@ import { Service } from "typedi"; import AuthService, { IUserJwtPayload } from "@Services/common/AuthService/AuthService"; import IdNotService from "@Services/common/IdNotService/IdNotService"; +import WhitelistService from "@Services/common/WhitelistService/WhitelistService"; +import User from "le-coffre-resources/dist/SuperAdmin"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; @Controller() @Service() export default class UserController extends ApiController { - constructor(private authService: AuthService, private idNotService: IdNotService) { + constructor(private authService: AuthService, private idNotService: IdNotService, private whitelistService: WhitelistService, private userService: UsersService) { super(); } @@ -25,6 +28,7 @@ export default class UserController extends ApiController { if (!code) throw new Error("code is required"); const idNotToken = await this.idNotService.getIdNotToken(code); + if(!idNotToken) { this.httpValidationError(response, "IdNot token undefined"); return; @@ -35,7 +39,28 @@ export default class UserController extends ApiController { this.httpUnauthorized(response); return; } - await this.idNotService.updateUser(user.uid); + + //Whitelist feature + //Get user with contact + const prismaUser = await this.userService.getByUid(user.uid, {contact: true }); + if (!prismaUser) { + this.httpNotFoundRequest(response, "user not found"); + return; + } + + //Hydrate user to be able to use his contact + const userHydrated = User.hydrate(prismaUser, { strategy: "excludeAll" }); + + //Check if user is whitelisted + const isWhitelisted = await this.whitelistService.getByEmail(userHydrated.contact!.email); + + //If not whitelisted, return 409 Not whitelisted + if (!isWhitelisted) { + this.httpNotWhitelisted(response); + return; + } + + await this.idNotService.updateUser(user.uid); await this.idNotService.updateOffice(user.office_uid); const payload = await this.authService.getUserJwtPayload(user.idNot); diff --git a/src/common/databases/migrations/20231220084359_whitelist/migration.sql b/src/common/databases/migrations/20231220084359_whitelist/migration.sql new file mode 100644 index 00000000..3a252b3e --- /dev/null +++ b/src/common/databases/migrations/20231220084359_whitelist/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "whitelist" ( + "uid" TEXT NOT NULL, + "email" VARCHAR(255) NOT NULL, + "active" BOOLEAN NOT NULL DEFAULT true, + "created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3), + + CONSTRAINT "whitelist_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "whitelist_uid_key" ON "whitelist"("uid"); + +-- CreateIndex +CREATE UNIQUE INDEX "whitelist_email_key" ON "whitelist"("email"); diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index 9d72ec44..de4afe97 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -72,6 +72,15 @@ model Users { @@map("users") } +model Whitelist { + uid String @id @unique @default(uuid()) + email String @unique @db.VarChar(255) + active Boolean @default(true) + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + @@map("whitelist") +} + model Offices { uid String @id @unique @default(uuid()) idNot String @unique @db.VarChar(255) diff --git a/src/common/repositories/WhitelistRepository.ts b/src/common/repositories/WhitelistRepository.ts new file mode 100644 index 00000000..5f26c087 --- /dev/null +++ b/src/common/repositories/WhitelistRepository.ts @@ -0,0 +1,39 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Prisma } from "prisma/prisma-client"; + +@Service() +export default class WhitelistRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().whitelist; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many whitelist + */ + public async findMany(query: Prisma.WhitelistFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + return this.model.findMany(query); + } + + /** + * @description : find unique by email + */ + public async findOneByEmail(email: string) { + return this.model.findUnique({ + where: { + email: email, + }, + }); + } + + + +} diff --git a/src/common/system/controller-pattern/BaseController.ts b/src/common/system/controller-pattern/BaseController.ts index 0e5003cc..0603c480 100644 --- a/src/common/system/controller-pattern/BaseController.ts +++ b/src/common/system/controller-pattern/BaseController.ts @@ -48,6 +48,10 @@ export default abstract class BaseController { return this.httpResponse(response, HttpCodes.FORBIDDEN, responseData); } + protected httpNotWhitelisted(response: Response, responseData: IResponseData = "Not whitelisted") { + return this.httpResponse(response, HttpCodes.VALIDATION_ERROR, responseData); + } + protected httpResponse(response: Response, httpCode: HttpCodes, responseData: IResponseData = {}) { if (responseData instanceof Error) { throw responseData; diff --git a/src/services/common/WhitelistService/WhitelistService.ts b/src/services/common/WhitelistService/WhitelistService.ts new file mode 100644 index 00000000..9e98a35e --- /dev/null +++ b/src/services/common/WhitelistService/WhitelistService.ts @@ -0,0 +1,14 @@ +import WhitelistRepository from "@Repositories/WhitelistRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; + +@Service() +export default class WhitelistService extends BaseService { + constructor(private whitelistRepository: WhitelistRepository) { + super(); + } + + public async getByEmail(email: string): Promise { + return this.whitelistRepository.findOneByEmail(email); + } +} From 2f4bd04ab3669add179727e6bb18cc00e436afba Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 20 Dec 2023 15:07:59 +0100 Subject: [PATCH 7/9] email not found error --- src/app/api/idnot/UserController.ts | 10 +++++++++- src/services/common/IdNotService/IdNotService.ts | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 77d79065..f614b419 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -33,7 +33,15 @@ export default class UserController extends ApiController { this.httpValidationError(response, "IdNot token undefined"); return; } - const user = await this.idNotService.getOrCreateUser(idNotToken); + + let user; + + try { + user = await this.idNotService.getOrCreateUser(idNotToken); + } catch (error: any) { + this.httpUnauthorized(error); + return; + } if(!user) { this.httpUnauthorized(response); diff --git a/src/services/common/IdNotService/IdNotService.ts b/src/services/common/IdNotService/IdNotService.ts index 5f9f9fda..edc58508 100644 --- a/src/services/common/IdNotService/IdNotService.ts +++ b/src/services/common/IdNotService/IdNotService.ts @@ -359,6 +359,10 @@ export default class IdNotService extends BaseService { updated_at: null, }, }; + + if(!userToAdd.contact.email) { + throw new Error("No email found"); + } let userHydrated = User.hydrate(userToAdd); const user = await this.userService.create(userHydrated); From 7031bb1d4888c698d0c26966815ce89c2c56f77e Mon Sep 17 00:00:00 2001 From: Vins Date: Wed, 20 Dec 2023 15:14:03 +0100 Subject: [PATCH 8/9] Email not found error returned correctyl --- src/app/api/idnot/UserController.ts | 11 ++--------- src/services/common/IdNotService/IdNotService.ts | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index f614b419..8b448b2b 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -34,17 +34,10 @@ export default class UserController extends ApiController { return; } - let user; - - try { - user = await this.idNotService.getOrCreateUser(idNotToken); - } catch (error: any) { - this.httpUnauthorized(error); - return; - } + const user = await this.idNotService.getOrCreateUser(idNotToken); if(!user) { - this.httpUnauthorized(response); + this.httpUnauthorized(response, "Email not found"); return; } diff --git a/src/services/common/IdNotService/IdNotService.ts b/src/services/common/IdNotService/IdNotService.ts index edc58508..eca8fe37 100644 --- a/src/services/common/IdNotService/IdNotService.ts +++ b/src/services/common/IdNotService/IdNotService.ts @@ -361,7 +361,7 @@ export default class IdNotService extends BaseService { }; if(!userToAdd.contact.email) { - throw new Error("No email found"); + return null; } let userHydrated = User.hydrate(userToAdd); From 15bb52015e66ebfef03b23fc37fb63284e9f416f Mon Sep 17 00:00:00 2001 From: Maxime Lalo Date: Tue, 2 Jan 2024 17:52:22 +0100 Subject: [PATCH 9/9] :sparkles: Installing sentry --- package.json | 1 + src/app/middlewares/ErrorHandler.ts | 13 +++++++++++++ src/entries/App.ts | 3 ++- src/sentry.config.ts | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/sentry.config.ts diff --git a/package.json b/package.json index 65a5d8c7..a7ad6158 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@mailchimp/mailchimp_transactional": "^1.0.50", "@pinata/sdk": "^2.1.0", "@prisma/client": "^4.11.0", + "@sentry/node": "^7.91.0", "adm-zip": "^0.5.10", "axios": "^1.6.2", "bcrypt": "^5.1.1", diff --git a/src/app/middlewares/ErrorHandler.ts b/src/app/middlewares/ErrorHandler.ts index 274f5923..662e7f7f 100644 --- a/src/app/middlewares/ErrorHandler.ts +++ b/src/app/middlewares/ErrorHandler.ts @@ -1,6 +1,7 @@ import HttpException from "@Common/system/controller-pattern/exceptions/HttpException"; import HttpCodes from "@Common/system/controller-pattern/HttpCodes"; import { NextFunction, Request, Response } from "express"; +import * as Sentry from "@sentry/node"; export default function errorHandler(error: any, req: Request, response: Response, next: NextFunction) { const errorStatus: number = error["status"]; @@ -15,6 +16,18 @@ export default function errorHandler(error: any, req: Request, response: Respons return; } + const transaction = Sentry.startTransaction({ + op: "Crashed Application", + name: "Crashed Application", + }); + + if (error instanceof Error) { + Sentry.captureException(error.stack); + } else { + Sentry.captureException(error); + } + transaction.finish(); + if (error instanceof HttpException) { response.status(error.httpCode).send(error.message); return; diff --git a/src/entries/App.ts b/src/entries/App.ts index fcee2984..5dd1bd04 100644 --- a/src/entries/App.ts +++ b/src/entries/App.ts @@ -8,12 +8,13 @@ import bodyParser from "body-parser"; import errorHandler from "@App/middlewares/ErrorHandler"; import { BackendVariables } from "@Common/config/variables/Variables"; import multer from "multer"; +import "../sentry.config"; const storage = multer.memoryStorage(); (async () => { try { - const variables = await Container.get(BackendVariables).validate(); + const variables = await Container.get(BackendVariables).validate(); const port = variables.APP_PORT; const rootUrl = variables.APP_ROOT_URL; const label = variables.APP_LABEL ?? "Unknown Service"; diff --git a/src/sentry.config.ts b/src/sentry.config.ts new file mode 100644 index 00000000..a921142d --- /dev/null +++ b/src/sentry.config.ts @@ -0,0 +1,16 @@ +import { BackendVariables } from "@Common/config/variables/Variables"; +import * as Sentry from "@sentry/node"; +import Container from "typedi"; + +const variables = Container.get(BackendVariables); + +Sentry.init({ + dsn: "https://ca6a89e8b480c814e1b5828b8412c681@o4506382103281664.ingest.sentry.io/4506399972130816", + + // We recommend adjusting this value in production, or using tracesSampler + // for finer control + tracesSampleRate: 1.0, + environment: variables.ENV, +}); + +Sentry.setTag("service", "leCoffre-back");