Debug para tokens de Alai
This commit is contained in:
@@ -7,6 +7,7 @@ ALAI_API_URL=https://wsaccess.alaisecure.com/bssrest
|
||||
|
||||
ALAI_CERTIFICATES_DIR=./certificates/
|
||||
ALAI_CERTIFICATE_NAME=wsaccess_alaisecure_com_cert_client_new.p12
|
||||
ALAI_CERTIFICATE_PASSWORD=iHaaek+zyzWz6cH6rg==
|
||||
ALAI_USERNAME=palomaibanez
|
||||
ALAI_PASSWORD=palomaibanez1234
|
||||
ALAI_BRANDID=savefamily
|
||||
|
||||
@@ -15,6 +15,8 @@ export class AlaiTokenManager implements JWTProvider<{}> {
|
||||
|
||||
if (res.error != undefined) {
|
||||
console.error("Error obteniendo el token de ALAI", res.error)
|
||||
} else {
|
||||
this.authToken = new JWTToken(res.data.accessToken)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
50
packages/sim-consumidor-alai/aplication/DebugTokenManager.ts
Normal file
50
packages/sim-consumidor-alai/aplication/DebugTokenManager.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { JWTToken } from "sim-shared/domain/JWT.js";
|
||||
import { JWTProvider } from "sim-shared/infrastructure/HTTPClient.js";
|
||||
import { LegacyJWTTokenRepository } from "#infrastructure/LegacyJWTTokensRepository.js";
|
||||
import { env } from "#config/env/env.js";
|
||||
|
||||
const tokenDir = String(env.ALAI_CERTIFICATES_DIR)
|
||||
const tokenFile = ".debugToken"
|
||||
|
||||
/**
|
||||
* Usa un token guardado a mano en archivo para no gastar tokens de Alai
|
||||
*/
|
||||
export class DebugTokenManager implements JWTProvider<{}> {
|
||||
|
||||
isRefreshing: boolean = false;
|
||||
authToken: JWTToken<{}> | undefined;
|
||||
|
||||
private async getNewAuthToken() {
|
||||
// TODO: Si no funcionase hay que reprogramar los mensajes para ser
|
||||
// consumidos mas tarde.
|
||||
const res = LegacyJWTTokenRepository.getTokenFromFile(tokenDir, tokenFile)
|
||||
|
||||
|
||||
if (res.error != undefined) {
|
||||
console.error("Error obteniendo el token de ALAI", res.error)
|
||||
} else {
|
||||
this.authToken = new JWTToken(res.data)
|
||||
console.log("[d] Token DEBUG: ", this.authToken)
|
||||
}
|
||||
}
|
||||
|
||||
public tryRefreshToken(): Promise<JWTToken<{}>> {
|
||||
// En Alai no existe el concepto de refresh, se solicita otro token nuevo
|
||||
return this.getAccessToken()
|
||||
};
|
||||
|
||||
public async getAccessToken(): Promise<JWTToken<{}>> {
|
||||
// Caso 1: El token actual es valido
|
||||
if (this.authToken != undefined && !this.authToken.isExpired()) {
|
||||
return this.authToken
|
||||
} else {
|
||||
// Caso 2: El token actual no existe o ha expirado
|
||||
await this.getNewAuthToken()
|
||||
}
|
||||
|
||||
// Si después de todo no se ha generado el token es un error catastrofico
|
||||
if (this.authToken == undefined) throw new Error("Error obteniendo tokens de auth")
|
||||
|
||||
return this.authToken
|
||||
};
|
||||
}
|
||||
@@ -74,7 +74,6 @@ export class SimAlaiController {
|
||||
iccid: iccid,
|
||||
correlation_id: correlation_id
|
||||
}))
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -99,6 +98,7 @@ export class SimAlaiController {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public reActivate() {
|
||||
return async (msg: ConsumeMessage) => {
|
||||
console.log("Evento reActivate ", msg.fields)
|
||||
@@ -113,6 +113,7 @@ export class SimAlaiController {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Select especificamente por REST para evitar pasar por las colas.
|
||||
@@ -136,7 +137,7 @@ export class SimAlaiController {
|
||||
// TODO: Automatizar la paginacion
|
||||
//const usecaseRes = this.uscases.selectMany({ iccid })
|
||||
} else {
|
||||
const usecaseRes = await this.uscases.selectOne({ iccid })
|
||||
const usecaseRes = await this.uscases.selectOne(iccid)
|
||||
if (usecaseRes.error != undefined) {
|
||||
res.status(500).json(usecaseRes)
|
||||
return;
|
||||
@@ -150,28 +151,29 @@ export class SimAlaiController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public selectPageREST() {
|
||||
return async (req: Request, res: Response) => {
|
||||
const { offset, limit, filter, orderBy } = req.query
|
||||
const params = {
|
||||
offset: (offset != undefined) ? Number(offset) : undefined,
|
||||
limit: (limit != undefined) ? Number(limit) : undefined,
|
||||
filter: (filter != undefined) ? String(filter) : undefined,
|
||||
orderBy: (orderBy != undefined) ? String(orderBy) : undefined
|
||||
}
|
||||
|
||||
const usecaseRes = await this.uscases.selectPage(params)
|
||||
|
||||
if (usecaseRes.error != undefined) {
|
||||
res.status(500).json(usecaseRes)
|
||||
return;
|
||||
} else {
|
||||
res.status(200).send(usecaseRes.data)
|
||||
return;
|
||||
/**
|
||||
public selectPageREST() {
|
||||
return async (req: Request, res: Response) => {
|
||||
const { offset, limit, filter, orderBy } = req.query
|
||||
const params = {
|
||||
offset: (offset != undefined) ? Number(offset) : undefined,
|
||||
limit: (limit != undefined) ? Number(limit) : undefined,
|
||||
filter: (filter != undefined) ? String(filter) : undefined,
|
||||
orderBy: (orderBy != undefined) ? String(orderBy) : undefined
|
||||
}
|
||||
|
||||
const usecaseRes = await this.uscases.selectPage(params)
|
||||
|
||||
if (usecaseRes.error != undefined) {
|
||||
res.status(500).json(usecaseRes)
|
||||
return;
|
||||
} else {
|
||||
res.status(200).send(usecaseRes.data)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
**/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@ type FuncType = ((m: ConsumeMessage) => Promise<Result<string, any>>)
|
||||
export class SimAlaiRouter {
|
||||
private readonly routes: Map<string, FuncType>;
|
||||
|
||||
// WIP
|
||||
constructor(
|
||||
private readonly simController: SimAlaiController,
|
||||
private readonly eventBus: EventBus
|
||||
) {
|
||||
this.routes = new Map<string, FuncType>([
|
||||
//["select", undefined],
|
||||
["activate", this.simController.activate()],
|
||||
["pause", this.simController.suspend()],
|
||||
["reactivate", this.simController.reActivate()],
|
||||
//["reactivate", this.simController.reActivate()],
|
||||
//["cancel", this.simController.terminate()],
|
||||
//["preActivate", this.simController.preActivate()]
|
||||
]);
|
||||
|
||||
@@ -59,6 +59,10 @@ export class SimAlaiUsecases {
|
||||
return order
|
||||
}
|
||||
|
||||
/**
|
||||
* Gestiona el ciclo de vida de una petición. No aplica
|
||||
* a peticiones de lectura (no pasan por la cola y no generan un order)
|
||||
*/
|
||||
public usecaseTemplate<T, R>(
|
||||
func: (_: T) => Promise<Result<string, R>>,
|
||||
args: T,
|
||||
@@ -70,6 +74,8 @@ export class SimAlaiUsecases {
|
||||
this.setRunning(correlation_id)
|
||||
.then()
|
||||
.catch(e => console.error("Error actualizando el order", e))
|
||||
else
|
||||
console.warn("[!] Se ha lanzado una caso de uso sin correlation_id")
|
||||
|
||||
try {
|
||||
const res = await func(args)
|
||||
@@ -129,4 +135,9 @@ export class SimAlaiUsecases {
|
||||
return reserved
|
||||
}, args.iccid, args.correlation_id)
|
||||
}
|
||||
|
||||
public async selectOne(iccid: string) {
|
||||
const sim = await this.alaiRepository.getSimByICCID(iccid)
|
||||
return sim
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ export type SSLCert = {
|
||||
keypem: string
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* - Se ha usado https.Agent en su lugar, eliminar si no se usa
|
||||
*/
|
||||
export class SSLCertificateLoader {
|
||||
|
||||
constructor(
|
||||
|
||||
1
packages/sim-consumidor-alai/certificates/.debugToken
Normal file
1
packages/sim-consumidor-alai/certificates/.debugToken
Normal file
@@ -0,0 +1 @@
|
||||
eyJhbGciOiJIUzM4NCJ9.eyJiciI6InNhdmVmYW1pbHkiLCJpcCI6IjUyLjIxNC4xMTIuMTgxIiwic3ViIjoiaW5mb3NhdmVmYW1pbHkiLCJzIjoiRVdTMTY0NjI4YjE0MmRlZWI3IiwicG9zIjoic2F2ZWZhbWlseUNhYyIsImlkV3NVc2VyIjoiODkiLCJpc012bmEiOmZhbHNlLCJkb21haW4iOiJBbGFpfHNhdmVmYW1pbHkiLCJpYXQiOjE3Nzc4OTA0ODEsImV4cCI6MTc3NzkwMTI4MX0.SNO14ONoayy7MEnauSsT7H4To7bbW_GYTq1ZvC2IdcdHZq8oOLlVPAJyu3uMXHRk
|
||||
@@ -38,6 +38,8 @@ export const env = {
|
||||
// ESPECIFICO ALAI
|
||||
ALAI_API_URL: process.env.ALAI_API_URL,
|
||||
ALAI_CERTIFICATES_DIR: process.env.ALAI_CERTIFICATES_DIR,
|
||||
ALAI_CERTIFICATE_NAME: process.env.ALAI_CERTIFICATE_NAME,
|
||||
ALAI_CERTIFICATE_PASSWORD: process.env.ALAI_CERTIFICATE_PASSWORD,
|
||||
ALAI_USERNAME: process.env.ALAI_USERNAME,
|
||||
ALAI_PASSWORD: process.env.ALAI_PASSWORD,
|
||||
ALAI_BRANDID: process.env.ALAI_BRANDID,
|
||||
@@ -52,3 +54,7 @@ assert.ok(env.ALAI_USERNAME != undefined, "ALAI_USERNAME no definido")
|
||||
assert.ok(env.ALAI_PASSWORD != undefined, "ALAI_PASSWORD no definido")
|
||||
assert.ok(env.ALAI_BRANDID != undefined, "ALAI_BRANDID no definido")
|
||||
assert.ok(env.ALAI_API_URL != undefined, "ALAI_API_URL no definido")
|
||||
|
||||
assert.ok(env.ALAI_CERTIFICATE_NAME != undefined, "ALAI_CERTIFICATE_NAME no definido")
|
||||
assert.ok(env.ALAI_CERTIFICATES_DIR != undefined, "ALAI_CERTIFICATES_DIR no definido")
|
||||
assert.ok(env.ALAI_CERTIFICATE_PASSWORD != undefined, "ALAI_CERTIFICATE_PASSWORD no definido")
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { HttpClient } from "sim-shared/infrastructure/HTTPClient.js"
|
||||
import { AlaiTokenManager } from "#aplication/AlaiTokenManager.js"
|
||||
import { env } from "#config/env/env.js";
|
||||
import { httpsAgent } from "./httpsAgent.js"
|
||||
import { DebugTokenManager } from "#aplication/DebugTokenManager.js";
|
||||
|
||||
const tokenManager = new AlaiTokenManager()
|
||||
const debugTokenManagr = new DebugTokenManager()
|
||||
console.error("USANDO DebugTokenManager! Eliminar en prod")
|
||||
|
||||
|
||||
export const alaiHttp = new HttpClient({
|
||||
baseURL: env.ALAI_API_URL as string,
|
||||
headers: {},
|
||||
jwtManager: tokenManager
|
||||
jwtManager: debugTokenManagr,
|
||||
httpsAgent: httpsAgent
|
||||
})
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import fs from 'fs';
|
||||
import https from 'https';
|
||||
import axios from 'axios';
|
||||
import { env } from './env/env.js';
|
||||
import path from 'path';
|
||||
|
||||
const certificatesDir = env.ALAI_CERTIFICATES_DIR
|
||||
const certificateName = env.ALAI_CERTIFICATE_NAME
|
||||
// ...
|
||||
const httpsAgent = new https.Agent({
|
||||
pfx: fs.readFileSync(path.join(certificatesDir, 'keystore.p12')),
|
||||
passphrase: '<your_keystore_passphrase_here>'
|
||||
const certificatesDir = String(env.ALAI_CERTIFICATES_DIR)
|
||||
const certificateName = String(env.ALAI_CERTIFICATE_NAME)
|
||||
const certificatePassword = String(env.ALAI_CERTIFICATE_PASSWORD)
|
||||
|
||||
export const httpsAgent = new https.Agent({
|
||||
pfx: fs.readFileSync(path.join(certificatesDir, certificateName)),
|
||||
passphrase: certificatePassword
|
||||
});
|
||||
|
||||
// TODO: EJEMPLO, METER EN EL HTTP CLIENT
|
||||
const result = await axios.get('https://myserver.internal.net:9443', { httpsAgent });
|
||||
// do something with the result
|
||||
|
||||
// ...
|
||||
|
||||
@@ -52,11 +52,11 @@ async function startWorker() {
|
||||
|
||||
// WIP
|
||||
app.get("/select", alaiController.selectREST())
|
||||
app.get("/selectPage", alaiController.selectPageREST())
|
||||
//app.get("/selectPage", alaiController.selectPageREST())
|
||||
|
||||
app.listen(PORT, HOSTNAME, (e) => {
|
||||
if (e == undefined) {
|
||||
console.log("[o] Servidor iniciado en el puerto %d", PORT)
|
||||
console.log("[o] Servidor (Alai) iniciado en el puerto %d", PORT)
|
||||
} else {
|
||||
console.error("Error express ", e)
|
||||
}
|
||||
@@ -66,10 +66,10 @@ async function startWorker() {
|
||||
|
||||
startWorker()
|
||||
.then(e => {
|
||||
console.log("[o] Worker de SIM de NOS iniciado")
|
||||
console.log("[o] Worker de SIM de Alai iniciado")
|
||||
})
|
||||
.catch(e => {
|
||||
console.log("[x] Error iniciando worker de SIM de NOS")
|
||||
console.log("[x] Error iniciando worker de SIM de Alai")
|
||||
})
|
||||
|
||||
export default {}
|
||||
|
||||
@@ -108,7 +108,7 @@ export class AlaiRepository {
|
||||
|
||||
public async getSimByICCID(iccid: string) {
|
||||
const endpoint = `/v1/sim/${iccid}`
|
||||
const promReq = this.httpClient.post<AlaiAPI.Sim>(endpoint, undefined)
|
||||
const promReq = this.httpClient.post<AlaiAPI.Sim | undefined>(endpoint, undefined)
|
||||
const res = await this.manageRequest(promReq)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import path from "path";
|
||||
import fs from 'fs';
|
||||
import { Result } from "sim-shared/domain/Result.js";
|
||||
import { PgClient } from "sim-shared/infrastructure/PgClient.js";
|
||||
|
||||
type TokenLine = {
|
||||
id: number,
|
||||
url: string,
|
||||
user_name: string,
|
||||
pass: string,
|
||||
brand_id: string,
|
||||
cert_file: string,
|
||||
key_file: string,
|
||||
ca_file: string,
|
||||
p12_file: string,
|
||||
cert_password: string,
|
||||
token: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Repositorio para usar los tokens guardados en la bdd de intranet o en un archivo
|
||||
*/
|
||||
export class LegacyJWTTokenRepository {
|
||||
constructor(
|
||||
// En prod (no deberia usarse) tiene que apuntar a intranet
|
||||
private pgClient: PgClient
|
||||
) {
|
||||
}
|
||||
|
||||
public async getTokenFromDB(): Promise<Result<string, string>> {
|
||||
const query = "SELECT * FROM alai_api_credentials;"
|
||||
|
||||
try {
|
||||
const res = await this.pgClient.query<TokenLine>(query)
|
||||
if (res.rowCount == 0) {
|
||||
return {
|
||||
error: "Error recuperando el token actual"
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
data: res.rows[0].token
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
error: String(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getTokenFromFile(dir: string, file: string): Result<string, string> {
|
||||
try {
|
||||
const tokenPath = path.join(dir, file)
|
||||
const fileContent = fs.readFileSync(tokenPath).toString()
|
||||
return {
|
||||
data: fileContent
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
error: "[d!] No se ha podido leer el archivo del token de debug" + String(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import axios, { AxiosInstance } from "axios"
|
||||
import { IJWTService, JWTToken } from "../domain/JWT.js"
|
||||
import https from "https"
|
||||
|
||||
// Cambiar por IJWRGeneralService
|
||||
|
||||
@@ -20,11 +21,14 @@ export class HttpClient {
|
||||
constructor(args: {
|
||||
baseURL: string,
|
||||
headers: Record<string, string>,
|
||||
jwtManager: JWTProvider<{}> // todo: asociar el tipo de token,
|
||||
jwtService?: IJWTService<any>
|
||||
jwtManager: JWTProvider<{}>, // todo: asociar el tipo de token
|
||||
jwtService?: IJWTService<any>,
|
||||
httpsAgent: https.Agent
|
||||
}) {
|
||||
this.client = axios.create({
|
||||
...args
|
||||
baseURL: args.baseURL,
|
||||
headers: args.headers,
|
||||
httpsAgent: args.httpsAgent
|
||||
})
|
||||
|
||||
this.jwtManager = args.jwtManager
|
||||
|
||||
Reference in New Issue
Block a user