⚠️ Es importante tener en cuenta que este interceptor se encuentra implementado en el package@tresdoce-nestjs-toolkit/paas
, ya que es una funcionalidad core para el starter.
Este módulo está pensado para ser utilizado en NestJS Starter, o cualquier proyecto que utilice una configuración centralizada, siguiendo la misma arquitectura del starter.
- NestJS Starter
- Node.js v18.20.4 or higher (Download)
- YARN v1.22.22 or higher
- NPM v10.8.3 or higher
- NestJS v10.4.4 or higher (Documentación)
npm install -S @tresdoce-nestjs-toolkit/utils
yarn add @tresdoce-nestjs-toolkit/utils
El módulo de Redact está pensado para el uso de ofuscamiento de datos sensibles para la implementación de una librería como asi también en el uso de una aplicación.
Este módulo utiliza como base fast-redact
, pero se implementaron
algunas mejoras.
Agregar los parámetros de configuración de fast-redact en configuration.ts
utilizando el key redact
y que
contenga el objeto con todas sus propiedades para utilizar en el ofuscamiento.
//./src/config/configuration.ts
import { Typings } from '@tresdoce-nestjs-toolkit/core';
import { registerAs } from '@nestjs/config';
import * as PACKAGE_JSON from '../../package.json';
export default registerAs('config', (): Typings.AppConfig => {
return {
//...
redact: {
paths: process.env.REDACT_OBFUSCATE ? process.env.REDACT_OBFUSCATE.split(',') : [],
censor: '****',
obfuscateFrom: 'right',
},
//...
};
});
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
paths
: Es un array de string, en el que se recomienda ser seteado por variables de entorno como strings
separados por coma para que pueda impactar rápidamente en la aplicación sin requerir un re-despliegue.
El path sigue la sintaxis standard de
EcmaScript. Más info
-
a.b.c
-
a['b'].c
-
a["b-c"].d
-
["a-b"].c
-
a.b.*
-
a[*].c
-
*.b
-
a[0].b
-
Type:
String[]
-
Example:
headers.request['authorization'],headers.request['apiKey']
censor
: Es el valor por el cual va a reemplazar el dato sensible, considerar que la longitud del censor es la
cantidad de caracteres que va a reemplazar al valor a ofuscar, es decir, si la longitud del censor es de 4 caracteres,
al valor a ofuscar va a reemplazar son los últimos 4 caracteres con el valor seteado.
- Type:
String
- Default:
****
- Example:
400012345678****
obfuscateFrom
: Indica de qué lado del valor a ofuscar va a realizarse el ofuscamiento, considerar que esta opción se
aplica a todos los datos a ofuscar, y no por path.
- Type:
String
- Default:
right
- Values:
left | right
- Example:
****123456784126 | 400012345678****
remove
: Remueve la key con su valor.
- Type:
Boolean
- Default:
false
serialize
: Maneja la salida del ofuscamiento. Si se proporciona una función, se utilizará para serializar el objeto
redactado, en caso de configurarlo en true
devuelve un JSON.stringify
, de lo contrario devuelve el JSON
.
- Type:
Boolean|Function
- Default:
false
Instanciar RedactModule
en el módulo correspondiente, si es global para una aplicación (recomendado), estaría en el
app.module.ts
, o bien en el módulo que requiera utilizar esta funcionalidad, en el caso de una lib estaría en el
módulo principal de esa lib.
//./src/app.module.ts
import { RedactModule } from '@tresdoce-nestjs-toolkit/paas';
@Module({
imports: [
//...
RedactModule,
//...
],
//...
})
export class AppModule {}
O bien puedes utilizar el metódo .register()
para configurar el módulo en caso de no querer usar la configuración
centralizada.
//./src/app.module.ts
import { RedactModule } from '@tresdoce-nestjs-toolkit/paas';
@Module({
imports: [
//...
RedactModule.register({
paths: ['my.path'],
censor: 'xxxx',
obfuscateFrom: 'left',
}),
//...
],
//...
})
export class AppModule {}
Cuando necesite pasar las opciones del módulo de forma asincrónica en lugar de estática, utilice el
método .registerAsync()
.
//./src/app.module.ts
import { RedactModule } from '@tresdoce-nestjs-toolkit/paas';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
//...
RedactModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => configService.get('config.redact'),
inject: [ConfigService],
}),
//...
],
//...
})
export class AppModule {}
O también puede hacerlo asi.
//./src/app.module.ts
import { RedactModule } from '@tresdoce-nestjs-toolkit/paas';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
//...
RedactModule.registerAsync({
useFactory: () => ({
paths: ['my.path'],
censor: 'xxxx',
obfuscateFrom: 'left',
}),
}),
//...
],
//...
})
export class AppModule {}
⚠️ Considerar que elRedactModule
realiza una mutación del valor del parámetro, por lo que si no se maneja adecuadamente, podría retornar el dato modificado.
// ./my-service.ts
import { RedactService } from '@tresdoce-nestjs-toolkit/paas';
export class MyService {
constructor(@Inject(RedactService) private redactService: RedactService) {}
async funcOfService(data) {
//...
console.log(this.redactService.obfuscate(data));
// Return { myKey: 'value-obfuscxxxx' }
console.log(this.redactService.obfuscate(data, false)); // retorna como string
// Return "{ \"myKey\": \"value-obfuscxxxx\" }"
//...
}
}
El servicio FormatService
tiene disponible la función .formatNumber()
que tiene como fin formatear números, utilizando
el método Intl.NumberFormat
que es un objeto integrado en JavaScript que permite el formateo numérico sensible al idioma.
Proporciona una forma flexible de convertir un número en una cadena con formato, teniendo en cuenta las convenciones
locales de formateo numérico cómo asi también soporta opciones personalizadas de formateo.
Importar el FormatService
como provider en el módulo que va a hacer uso de este servicio.
// ./src/my.module.ts
import { Module } from '@nestjs/common';
import { FormatService } from '@tresdoce-nestjs-toolkit/paas';
@Module({
//...
providers: [
//...
FormatService,
//...
],
//...
})
export class MyModule {}
Luego hay que inyectar el FormatService
en el servicio.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { FormatService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(@Inject(FormatService) private readonly formatService: FormatService) {}
formatNumberToUSDCurrency() {
const formatOptions = {
style: 'currency',
currency: 'USD',
currencyDisplay: 'narrowSymbol',
};
return this.formatService.formatNumber({ num: 123456.789, formatOptions, locale: 'es-AR' });
// Return: $ 123.456,79
}
}
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
La función .formatNumber()
admite un objeto con tres parámetros los cuales se detallan a continuación.
num
: El número a darle un formato el cual es requerido.
- Type:
Number
- Example:
'123456.789 | 16 | -3500'
formatOptions
: Es la customización para darle formato al número a formatear. Para más información sobre que parámetros
admite es recomendable leer la Documentación de Intl.NumberFormat
- Type:
Object
- Example:
{ style: 'currency', currency: 'USD' }
locale
: Este parámetro sirve para configurar la internalización para el formateo. Locales
- Type:
String
- Default:
'es-AR'
- Example:
'en-US' | 'de-DE' | 'en-IN' | 'en-GB'
El servicio FormatService
tiene disponible funciones que tiene como fin trabajar y manipular fechas utilizando
Luxon como dependencia base.
-
.dateTimeRef()
: Retorna la instanciaDateTime
de Luxon. -
.formatDate()
: Formatea un valor de tipoDate
. -
.dateToISO()
: Convierte un valor de tipoDate
a formato ISO 8601 (Default zone: 0) -
.calculateTimestampDiff()
: Calcula la diferencia entre dos valorestimestamp
.
Importar el FormatService
como provider en el módulo que va a hacer uso de este servicio.
// ./src/my.module.ts
import { Module } from '@nestjs/common';
import { FormatService } from '@tresdoce-nestjs-toolkit/paas';
@Module({
//...
providers: [
//...
FormatService,
//...
],
//...
})
export class MyModule {}
Luego hay que inyectar el FormatService
en el servicio.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import {
FormatService,
DEFAULT_TIMEZONE, // utc
DEFAULT_TIMEZONE_LOCALE, // 'America/Argentina/Buenos_Aires'
} from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(@Inject(FormatService) private readonly formatService: FormatService) {}
myFunction() {
const cDate = this.formatService.dateTimeRef().now();
return {
'1': cDate, // Return: Object DateTime
'2': cDate.toISO(), // Return: 2023-07-13T16:12:09.470+00:00
'3': cDate.setZone(DEFAULT_TIMEZONE).toISO(), // Return: 2023-07-13T16:12:09.473Z
'4': cDate.setZone(DEFAULT_TIMEZONE_LOCALE).toISO(), // Return: 2023-07-13T13:12:09.473-03:00
};
}
}
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { FormatService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(@Inject(FormatService) private readonly formatService: FormatService) {}
myFunction() {
const cDate = new Date();
const formatDateOpts = {
formatDate: 'fff',
timezone: 'Europe/Paris',
locale: 'fr'
};
return {
'1':this.formatService.formatDate({ date: cDate }) },// Return: 20/12/2022 14:37:17.020
'2':this.formatService.formatDate({ date: cDate, ...formatDateOpts}) }, // Return: 20 décembre 2022, 15:37.020 UTC+1
}
}
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
La función .formatDate()
admite un objeto con cuatro parámetros los cuales se detallan a continuación.
date
: Es la fecha a formatear.
- Type:
Date
- Example:
'2022-12-20T14:37:17.020Z'
formatDate
: Es el formato a convertir la fecha ingresada, Para más información sobre que formato puedes revisar la
documentación de Luxon
- Type:
String
- Default:
'dd/LL/yyyy TT.SSS'
timezone
: Es la zona horaria para ajustar la fecha ingresada.
- Type:
String
- Default:
'utc'
- Example:
'America/Argentina/Buenos_Aires' | 'Europe/Paris'
locale
: Este parámetro sirve para configurar la internalización para el formateo. Locales
- Type:
String
- Default:
'es-AR'
- Example:
'en-US' | 'de-DE' | 'en-IN' | 'en-GB'
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { FormatService, DEFAULT_TIMEZONE_LOCALE } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(@Inject(FormatService) private readonly formatService: FormatService) {}
myFunction() {
const cDate = new Date();
return {
'1': this.formatService.dateToISO({ date: cDate }), // Return: 2023-07-12T12:06:29.957Z
'2': this.formatService.dateToISO({ date: cDate, timezone: DEFAULT_TIMEZONE_LOCALE }), // Return: 2023-07-12T09:06:29.957-03:00
};
}
}
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
La función .dateToISO()
admite un objeto con dos parámetros los cuales se detallan a continuación.
date
: Es la fecha a formatear.
- Type:
Date
- Example:
'2022-12-20T14:37:17.020Z'
timezone
: Es la zona horaria para ajustar la fecha ingresada.
- Type:
String
- Default:
'utc'
- Example:
'America/Argentina/Buenos_Aires' | 'Europe/Paris'
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { FormatService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(@Inject(FormatService) private readonly formatService: FormatService) {}
myFunction() {
const startTimestamp = 1689208308510;
const endTimestamp = 1689208308525;
const optionsCalculate = { unit: 'seconds', addSuffix: true };
return {
'1': this.formatService.calculateTimestampDiff({
startTime: startTimestamp,
endTime: endTimestamp,
}), //Return: 15
'2': this.formatService.calculateTimestampDiff({
startTime: startTimestamp,
endTime: endTimestamp,
options: optionsCalculate,
}), //Return: '0.015s'
};
}
}
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
La función .calculateTimestampDiff()
admite un objeto con tres parámetros los cuales se detallan a continuación.
startTime
: Es el timestamp
de inicio o más viejo a comparar y obtener la diferencia.
- Type:
number
- Example:
1689208308510
endTime
: Es el timestamp
más reciente a comparar y obtener la diferencia con el startTime
.
- Type:
number
- Example:
1689208308525
options
: Es un objeto de configuración el cual admite dos propiedades. unit
es la unidad a retornar la diferencia
entre los datos ingresados y addSuffix
agrega la unidad en la salida, dependiendo el valor de este último, la salida
puede ser de tipo number
o string
- Type:
Object
- Default:
{ unit: 'milliseconds', addSuffix: false }
- Example:
{ unit: 'seconds', addSuffix: true }
El módulo Bcrypt proporciona funcionalidades para encriptar, hashear y comparar datos utilizando el algoritmo bcrypt.
Agregar los parámetros de configuración de Bcrypt en configuration.ts
utilizando el key bcrypt
y que
contenga el objeto con todas sus propiedades para utilizar la encriptación y hash con valores custom, en caso contrario,
no es necesario modificar el configuration.
//./src/config/configuration.ts
import { Typings } from '@tresdoce-nestjs-toolkit/paas';
import { registerAs } from '@nestjs/config';
export default registerAs('config', (): Typings.AppConfig => {
return {
//...
bcrypt: {
rounds: 16,
minor: 'b',
},
//...
};
});
💬 Para ver en detalle todas las propiedades de la configuración, hace clic acá.
rounds
: Número de rondas de sal para generar la sal
- Type:
Number
- Default:
16
- Example:
10
minor
: Versión menor de bcrypt a utilizar
- Type:
String
- Default:
b
- Example:
a
Importar el BcryptModule
en el módulo principal de la aplicación.
// ./src/my.module.ts
import { Module } from '@nestjs/common';
import { BcryptModule } from '@tresdoce-nestjs-toolkit/paas';
@Module({
//...
imports: [
//...
BcryptModule,
//...
],
//...
})
export class MyModule {}
Luego hay que inyectar el BcryptService
en el servicio para hacer uso de los métodos disponibles.
Encripta los datos asincrónicamente.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
async encryptExample() {
const data = 'password';
const encryptedData = await this.bcryptService.encrypt(data);
console.log('Encrypted data:', encryptedData);
}
}
Compara los datos con los datos encriptados asincrónicamente.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
async compareExample() {
const data = 'password';
const encryptedData = await this.bcryptService.encrypt(data);
const isMatch = await this.bcryptService.compare(data, encryptedData);
console.log('Data matches encrypted data:', isMatch);
}
}
Encripta los datos sincrónicamente.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
encryptSyncExample() {
const data = 'password';
const encryptedData = this.bcryptService.encryptSync(data);
console.log('Encrypted data:', encryptedData);
}
}
Compara los datos con los datos encriptados sincrónicamente.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
compareSyncExample() {
const data = 'password';
const encryptedData = this.bcryptService.encryptSync(data);
const isMatch = this.bcryptService.compareSync(data, encryptedData);
console.log('Data matches encrypted data:', isMatch);
}
}
Genera un hash seguro para una contraseña.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
generatePasswordHashExample() {
const password = 'password';
const hash = this.bcryptService.generatePasswordHash(password);
console.log('Password hash:', hash);
}
}
Válida si un hash es válido para las rondas de sal actuales.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {}
validateHashExample() {
const password = 'password';
const hash = this.bcryptService.generatePasswordHash(password);
const isValid = this.bcryptService.validateHash(hash);
console.log('Is hash valid?', isValid);
}
}
Genera una nueva sal para usar en el proceso de hash.
// ./src/my.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { BcryptService } from '@tresdoce-nestjs-toolkit/paas';
@Injectable()
export class MyService {
constructor(private readonly bcryptService: BcryptService) {
this.bcryptService.generateSalt(10, 'a');
}
//...
}
Todos los cambios notables de este paquete se documentarán en el archivo Changelog.