From a39b84e107aabefa4f7796624132f70c8237cfb8 Mon Sep 17 00:00:00 2001 From: Alvar San Martin Date: Tue, 10 Feb 2026 15:57:03 +0100 Subject: [PATCH] Validaciones para los endpints --- .env | 1 + packages/sim-consumidor-objenious/.env | 2 + .../aplication/Sim.controller.ts | 9 +- .../config/env/index.ts | 4 +- .../sim-consumidor-objenious/package.json | 1 - .../aplication/Sim.controller.ts | 95 +++++++++++-------- .../aplication/httpValidators.ts | 50 ++++++++++ .../sim-entrada-eventos/domain/companies.ts | 22 +++++ .../infrastructure/simRoutes.http.ts | 1 + packages/sim-entrada-eventos/package.json | 1 + .../sim-shared/aplication/BodyValidator.ts | 25 +++++ packages/sim-shared/package.json | 8 ++ yarn.lock | 4 +- 13 files changed, 175 insertions(+), 48 deletions(-) create mode 100644 packages/sim-entrada-eventos/aplication/httpValidators.ts create mode 100644 packages/sim-entrada-eventos/domain/companies.ts create mode 100644 packages/sim-shared/aplication/BodyValidator.ts diff --git a/.env b/.env index f7b9e8a..3ef3fad 100644 --- a/.env +++ b/.env @@ -1,4 +1,5 @@ PORT=3000 +API_HOSTNAME=0.0.0.0 RABBITMQ_USER=guest RABBITMQ_PASSWORD=guest diff --git a/packages/sim-consumidor-objenious/.env b/packages/sim-consumidor-objenious/.env index 919cf75..6c91653 100644 --- a/packages/sim-consumidor-objenious/.env +++ b/packages/sim-consumidor-objenious/.env @@ -5,4 +5,6 @@ OBJ_CLI_ASSERTION=XOc7FtwXD8hUX2SFVX94XSty8wkOmChkwDNF09O_aIxPubMDdFUdCDCB4zpzSI OBJ_CLIENT_ID=savefamily_rest_ws OBJ_KID=xNfbMiyL1ORXGP8lElhcv8nVaG3EJKye4Lc1YoN3I1E OBJ_BASE_URL=https://api-getway.objenious.com/ws + +OBJ_CUSTOMER_CODE=9.49411.10 //OBJ_BASE_URL=https://api-getway.objenious.com/ws/test diff --git a/packages/sim-consumidor-objenious/aplication/Sim.controller.ts b/packages/sim-consumidor-objenious/aplication/Sim.controller.ts index 82041ce..3797703 100644 --- a/packages/sim-consumidor-objenious/aplication/Sim.controller.ts +++ b/packages/sim-consumidor-objenious/aplication/Sim.controller.ts @@ -3,6 +3,8 @@ import { ConsumeMessage } from "amqplib"; import { SimUseCases } from "./Sim.usecases.js"; import { SimEvents } from "sim-shared/domain/SimEvents.js"; import { Result } from "sim-shared/domain/Result.js"; +import { env } from "#config/env/index.js"; +import { s } from "node_modules/vitest/dist/chunks/reporters.d.CWXNI2jG.js"; /** * La clase usa generadores de funciones para mantener el contexto @@ -64,6 +66,8 @@ export class SimController { } public activate() { + const DUE_DATE_SECONDS = 2 * 60 + return async (msg: ConsumeMessage) => { let msgData; try { @@ -81,8 +85,8 @@ export class SimController { } this.tryUseCase(msg, this.useCases.activate({ - dueDate: this.genDueDate(2 * 60).toISOString(), - customerAccountCode: "9.49411.10", // TODO: Al .env + dueDate: this.genDueDate(DUE_DATE_SECONDS).toISOString(), + customerAccountCode: env.OBJ_CUSTOMER_CODE, identifier: { identifierType: "ICCID", identifiers: [iccid] @@ -213,3 +217,4 @@ export class SimController { return dueDate } } + diff --git a/packages/sim-consumidor-objenious/config/env/index.ts b/packages/sim-consumidor-objenious/config/env/index.ts index 8977540..19d0262 100644 --- a/packages/sim-consumidor-objenious/config/env/index.ts +++ b/packages/sim-consumidor-objenious/config/env/index.ts @@ -28,7 +28,7 @@ export const env = { OBJ_CLI_ASSERTION: String(process.env.OBJ_CLI_ASSERTION), OBJ_CLIENT_ID: String(process.env.OBJ_CLIENT_ID), OBJ_KID: String(process.env.OBJ_KID), - OBJ_BASE_URL: String(process.env.OBJ_BASE_URL) - + OBJ_BASE_URL: String(process.env.OBJ_BASE_URL), + OBJ_CUSTOMER_CODE: String(process.env.OBJ_CUSTOMER_CODE) }; diff --git a/packages/sim-consumidor-objenious/package.json b/packages/sim-consumidor-objenious/package.json index 756a2c7..135c24e 100644 --- a/packages/sim-consumidor-objenious/package.json +++ b/packages/sim-consumidor-objenious/package.json @@ -68,7 +68,6 @@ "cors": "*", "dotenv": "*", "express": "*", - "sim-consumidor-objenious": "sim-consumidor-objenious:*", "sim-shared": "sim-shared:*", "typescript": "*" }, diff --git a/packages/sim-entrada-eventos/aplication/Sim.controller.ts b/packages/sim-entrada-eventos/aplication/Sim.controller.ts index 9f4da0a..b53c1df 100644 --- a/packages/sim-entrada-eventos/aplication/Sim.controller.ts +++ b/packages/sim-entrada-eventos/aplication/Sim.controller.ts @@ -1,16 +1,8 @@ import { Request, Response } from "express" import { SimUsecases } from "./Sim.usecases.js" +import { activationValidator, iccidValidator } from "./httpValidators.js" +import { companyFromIccid } from "#domain/companies.js" -// Partiendo del caracter 3 2 de pais + 2 de compañia -// Metiendolo a la BDD podria ser mas dinamico pero perderia -// tiempo de query -// Puede que esté bien crear un endpoint para administrarlo -const COMPAÑIASICCID = new Map( - [ - ["3490", "alai"], - ["3510", "nos"], - ["3320", "objenious"] - ]) export class SimController { private simUseCases: SimUsecases @@ -25,11 +17,19 @@ export class SimController { public preactivation() { return async (req: Request, res: Response) => { - const valido = this.validateBody(req.body, res) - if (valido == false) return; + console.warn("[!] Se deberia de usar la peticion /sim/activate directamente") + try { + iccidValidator.validate(req.body) + } catch (e) { + res.status(422).json({ + errors: { + msg: e + } + }) + } const { iccid } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) if (compañia == undefined) { res.status(500).json({ @@ -62,13 +62,19 @@ export class SimController { public activation() { return async (req: Request, res: Response) => { - const valido = this.validateBody(req.body, res) - - if (valido == false) return; // Si no es valido ya se ha enviado el error + try { + activationValidator.validate(req.body) + } catch (e) { + res.status(422).json({ + errors: { + msg: e + } + }) + } const { iccid, offer } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) if (compañia == undefined) { res.status(500).json({ @@ -101,12 +107,18 @@ export class SimController { public cancelation() { return async (req: Request, res: Response) => { - const valido = this.validateBody(req.body, res) - - if (valido == false) return; // Si no es valido ya se ha enviado el error + try { + iccidValidator.validate(req.body) + } catch (e) { + res.status(422).json({ + errors: { + msg: e + } + }) + } const { iccid } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) try { await this.simUseCases.cancelation({ iccid, compañia }) @@ -127,12 +139,18 @@ export class SimController { public pause() { return async (req: Request, res: Response) => { - const valido = this.validateBody(req.body, res) - - if (valido == false) return; // Si no es valido ya se ha enviado el error + try { + iccidValidator.validate(req.body) + } catch (e) { + res.status(422).json({ + errors: { + msg: e + } + }) + } const { iccid } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) try { await this.simUseCases.pause({ iccid, compañia }) @@ -153,12 +171,18 @@ export class SimController { public free() { return async (req: Request, res: Response) => { - const valido = this.validateBody(req.body, res) - - if (valido == false) return; // Si no es valido ya se ha enviado el error + try { + iccidValidator.validate(req.body) + } catch (e) { + res.status(422).json({ + errors: { + msg: e + } + }) + } const { iccid } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) try { await this.simUseCases.cancelation({ iccid, compañia }) @@ -185,7 +209,7 @@ export class SimController { if (valido == false) return; // Si no es valido ya se ha enviado el error const { iccid } = req.body - const compañia = this.compañiaFromIccid(iccid) + const compañia = companyFromIccid(iccid) try { await this.simUseCases.cancelation({ iccid, compañia }) @@ -228,15 +252,4 @@ export class SimController { return valid; } - /** - * A partir del iccid completo devuelve la compañia a la que pertenece - * @throws Error si no hay una compañia definida en COMPAÑIASICCID con el codigo - */ - private compañiaFromIccid(iccid: string) { - const caracteresCommpañia = iccid.slice(2, 6) - const compañia = COMPAÑIASICCID.get(caracteresCommpañia) - - if (compañia == undefined) throw new Error("El la compañia es desconocida: " + caracteresCommpañia) - return compañia - } } diff --git a/packages/sim-entrada-eventos/aplication/httpValidators.ts b/packages/sim-entrada-eventos/aplication/httpValidators.ts new file mode 100644 index 0000000..10cae2a --- /dev/null +++ b/packages/sim-entrada-eventos/aplication/httpValidators.ts @@ -0,0 +1,50 @@ +import { companyFromIccid } from "#domain/companies.js"; +import { BodyValidator, Validator } from "sim-shared/aplication/BodyValidator.js"; + +const offers = new Map([ + ["mensual", "SAVEFAMILY1"], + ["anual", "SAVEFAMILY2"] +]) + +const iccidLongitudValidator = >{ + field: "iccid", + errorMsg: "La longitud del iccid es incorrecta debera ser de 19 caracteres", + validationFunc: (a: { iccid: string }) => a.iccid.length == 19, +} + +const iccidRequired = >{ + field: "iccid", + errorMsg: "El iccid debe estara definido", + validationFunc: (a: { iccid: string }) => a.iccid != undefined, +} + +const iccidWithValidCompany = >{ + field: "iccid", + errorMsg: "El iccid no corresponde a una compañia registrada", + validationFunc: (a: { iccid: string }) => companyFromIccid(a.iccid) != undefined, +} + + +const offerExists = >{ + field: "offer", + errorMsg: "La oferta introducida no es valida", + validationFunc: (a: { offer: string }) => offers.has(a.offer), +} + + +export const activationValidator = new BodyValidator<{ iccid: string, offer: string }>( + [ + iccidRequired, + iccidLongitudValidator, + iccidWithValidCompany, + offerExists, + ] +) + +export const iccidValidator = new BodyValidator<{ iccid: string, offer: string }>( + [ + iccidRequired, + iccidLongitudValidator, + iccidWithValidCompany, + ] +) diff --git a/packages/sim-entrada-eventos/domain/companies.ts b/packages/sim-entrada-eventos/domain/companies.ts new file mode 100644 index 0000000..ad42687 --- /dev/null +++ b/packages/sim-entrada-eventos/domain/companies.ts @@ -0,0 +1,22 @@ +// Partiendo del caracter 3 2 de pais + 2 de compañia +// Metiendolo a la BDD podria ser mas dinamico pero perderia +// tiempo de query +// Puede que esté bien crear un endpoint para administrarlo +export const COMPANYICCID = new Map( + [ + ["3490", "alai"], + ["3510", "nos"], + ["3320", "objenious"] + ]) + +/** +* A partir del iccid completo devuelve la compañia a la que pertenece +* @throws Error si no hay una compañia definida en COMPAÑIASICCID con el codigo +*/ +export function companyFromIccid(iccid: string) { + const caracteresCommpañia = iccid.slice(2, 6) + const compañia = COMPANYICCID.get(caracteresCommpañia) + + if (compañia == undefined) throw new Error("El la compañia es desconocida: " + caracteresCommpañia) + return compañia +} diff --git a/packages/sim-entrada-eventos/infrastructure/simRoutes.http.ts b/packages/sim-entrada-eventos/infrastructure/simRoutes.http.ts index af47d27..c163d37 100644 --- a/packages/sim-entrada-eventos/infrastructure/simRoutes.http.ts +++ b/packages/sim-entrada-eventos/infrastructure/simRoutes.http.ts @@ -13,6 +13,7 @@ const simController = new SimController({ simUseCases: simUseCases }) +// TODO: status de todos los proyectos simRoutes.get("/status", () => { }) simRoutes.post("/save", simController.save()) diff --git a/packages/sim-entrada-eventos/package.json b/packages/sim-entrada-eventos/package.json index 7c7d826..98e5824 100644 --- a/packages/sim-entrada-eventos/package.json +++ b/packages/sim-entrada-eventos/package.json @@ -59,6 +59,7 @@ "cors": "*", "dotenv": "*", "express": "*", + "sim-shared": "sim-shared:*", "typescript": "*" }, "devDependencies": { diff --git a/packages/sim-shared/aplication/BodyValidator.ts b/packages/sim-shared/aplication/BodyValidator.ts new file mode 100644 index 0000000..15ed2b9 --- /dev/null +++ b/packages/sim-shared/aplication/BodyValidator.ts @@ -0,0 +1,25 @@ +export type Validator = { + field: keyof T, + errorMsg: string, + validationFunc: (obj: T) => boolean +} + +/** + * Ejecuta una lista de validadores en orden, si alguno + * falla devuelve un Error + */ +export class BodyValidator { + validatorList: Validator[] = [] + constructor( + validators: Validator[] + ) { + this.validatorList = validators + } + + public validate(obj: T) { + for (const validator of this.validatorList) { + if (validator.validationFunc(obj) == false) throw new Error(validator.errorMsg) + } + return true; + } +} diff --git a/packages/sim-shared/package.json b/packages/sim-shared/package.json index ab5a0d0..80432eb 100644 --- a/packages/sim-shared/package.json +++ b/packages/sim-shared/package.json @@ -4,6 +4,14 @@ "version": "1.0.0", "description": "", "exports": { + "./aplication/*.js": { + "types": "./aplication/*.ts", + "default": "./aplication/*.js" + }, + "./aplication/*": { + "types": "./aplication/*.ts", + "default": "./aplication/*.js" + }, "./infrastructure/*.js": { "types": "./infrastructure/*.ts", "default": "./infrastructure/*.js" diff --git a/yarn.lock b/yarn.lock index e77082f..f215766 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2769,7 +2769,7 @@ __metadata: languageName: unknown linkType: soft -"sim-consumidor-objenious@sim-consumidor-objenious:*, sim-consumidor-objenious@workspace:packages/sim-consumidor-objenious": +"sim-consumidor-objenious@workspace:packages/sim-consumidor-objenious": version: 0.0.0-use.local resolution: "sim-consumidor-objenious@workspace:packages/sim-consumidor-objenious" dependencies: @@ -2784,7 +2784,6 @@ __metadata: dotenv: "npm:*" express: "npm:*" prettier: "npm:*" - sim-consumidor-objenious: "sim-consumidor-objenious:*" sim-shared: "sim-shared:*" supertest: "npm:*" tsc-alias: "npm:^1.8.16" @@ -2809,6 +2808,7 @@ __metadata: dotenv: "npm:*" express: "npm:*" prettier: "npm:*" + sim-shared: "sim-shared:*" supertest: "npm:*" tsc-alias: "npm:^1.8.16" tsx: "npm:*"