Validaciones para los endpints
This commit is contained in:
1
.env
1
.env
@@ -1,4 +1,5 @@
|
||||
PORT=3000
|
||||
API_HOSTNAME=0.0.0.0
|
||||
RABBITMQ_USER=guest
|
||||
RABBITMQ_PASSWORD=guest
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@
|
||||
"cors": "*",
|
||||
"dotenv": "*",
|
||||
"express": "*",
|
||||
"sim-consumidor-objenious": "sim-consumidor-objenious:*",
|
||||
"sim-shared": "sim-shared:*",
|
||||
"typescript": "*"
|
||||
},
|
||||
|
||||
@@ -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<string, string>(
|
||||
[
|
||||
["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
|
||||
}
|
||||
}
|
||||
|
||||
50
packages/sim-entrada-eventos/aplication/httpValidators.ts
Normal file
50
packages/sim-entrada-eventos/aplication/httpValidators.ts
Normal file
@@ -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 = <Validator<{ iccid: string }>>{
|
||||
field: "iccid",
|
||||
errorMsg: "La longitud del iccid es incorrecta debera ser de 19 caracteres",
|
||||
validationFunc: (a: { iccid: string }) => a.iccid.length == 19,
|
||||
}
|
||||
|
||||
const iccidRequired = <Validator<{ iccid: string }>>{
|
||||
field: "iccid",
|
||||
errorMsg: "El iccid debe estara definido",
|
||||
validationFunc: (a: { iccid: string }) => a.iccid != undefined,
|
||||
}
|
||||
|
||||
const iccidWithValidCompany = <Validator<{ iccid: string }>>{
|
||||
field: "iccid",
|
||||
errorMsg: "El iccid no corresponde a una compañia registrada",
|
||||
validationFunc: (a: { iccid: string }) => companyFromIccid(a.iccid) != undefined,
|
||||
}
|
||||
|
||||
|
||||
const offerExists = <Validator<{ offer: string }>>{
|
||||
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,
|
||||
]
|
||||
)
|
||||
22
packages/sim-entrada-eventos/domain/companies.ts
Normal file
22
packages/sim-entrada-eventos/domain/companies.ts
Normal file
@@ -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<string, string>(
|
||||
[
|
||||
["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
|
||||
}
|
||||
@@ -13,6 +13,7 @@ const simController = new SimController({
|
||||
simUseCases: simUseCases
|
||||
})
|
||||
|
||||
// TODO: status de todos los proyectos
|
||||
simRoutes.get("/status", () => { })
|
||||
|
||||
simRoutes.post("/save", simController.save())
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"cors": "*",
|
||||
"dotenv": "*",
|
||||
"express": "*",
|
||||
"sim-shared": "sim-shared:*",
|
||||
"typescript": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
25
packages/sim-shared/aplication/BodyValidator.ts
Normal file
25
packages/sim-shared/aplication/BodyValidator.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export type Validator<T extends Object> = {
|
||||
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<T extends Object> {
|
||||
validatorList: Validator<T>[] = []
|
||||
constructor(
|
||||
validators: Validator<T>[]
|
||||
) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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:*"
|
||||
|
||||
Reference in New Issue
Block a user