ngx-redi-core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # NgxRediCore
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.2.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project ngx-redi-core` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngx-redi-core`.
8
+ > Note: Don't forget to add `--project ngx-redi-core` or else it will be added to the default project in your `angular.json` file.
9
+
10
+ ## Build
11
+
12
+ Run `ng build ngx-redi-core` to build the project. The build artifacts will be stored in the `dist/` directory.
13
+
14
+ ## Publishing
15
+
16
+ After building your library with `ng build ngx-redi-core`, go to the dist folder `cd dist/ngx-redi-core` and run `npm publish`.
17
+
18
+ ## Running unit tests
19
+
20
+ Run `ng test ngx-redi-core` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
+
22
+ ## Further help
23
+
24
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/ngx-redi-core",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ }
7
+ }
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "ngx-redi-core",
3
+ "version": "0.0.2",
4
+ "peerDependencies": {
5
+ "@angular/common": "^15.2.0",
6
+ "@angular/core": "^15.2.0"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.3.0"
10
+ },
11
+ "sideEffects": false
12
+ }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { SecureInterceptor } from './secure.interceptor';
4
+
5
+ describe('SecureInterceptor', () => {
6
+ beforeEach(() => TestBed.configureTestingModule({
7
+ providers: [
8
+ SecureInterceptor
9
+ ]
10
+ }));
11
+
12
+ it('should be created', () => {
13
+ const interceptor: SecureInterceptor = TestBed.inject(SecureInterceptor);
14
+ expect(interceptor).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,211 @@
1
+ import 'reflect-metadata';
2
+ import { Injectable } from '@angular/core';
3
+ import {
4
+ HttpRequest,
5
+ HttpHandler,
6
+ HttpEvent,
7
+ HttpInterceptor,
8
+ HttpContextToken,
9
+ HttpResponse
10
+ } from '@angular/common/http';
11
+ import { Observable } from 'rxjs';
12
+ import { map } from 'rxjs/operators';
13
+ import { CifradoService } from '../secure/services/cifrado.service';
14
+ import { TOKEN_SECURE } from '../secure/model/secure-factory.model';
15
+
16
+ /** Request token para el contexto Http */
17
+ export const REQUEST_TOKEN = new HttpContextToken<any>(() => { });
18
+ /** Response token para el contexto Http */
19
+ export const RESPONSE_TOKEN = new HttpContextToken<any>(() => { });
20
+
21
+ /**
22
+ * Interceptor de seguridad que cifra y descifra información sensible en las peticiones Web
23
+ * @decorator `@Injectable()`
24
+ */
25
+ @Injectable()
26
+ export class SecureInterceptor implements HttpInterceptor {
27
+ constructor(private cifradoService: CifradoService) { }
28
+
29
+ intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
30
+ /** Ciframos los datos de la petición */
31
+ return next.handle(this.cifrarRequest(request))
32
+ .pipe(map(event => {
33
+ if (event instanceof HttpResponse) {
34
+ return event.clone({
35
+ body: this.descifrarResponse(request, event)
36
+ });
37
+ }
38
+ return event
39
+ }));
40
+ }
41
+
42
+ /**
43
+ * Regresa una respuesta HTTP descifrada
44
+ * @param request - Petición web
45
+ * @param response - Respuesta web a descifrar
46
+ * @returns Respuesta http descifrada
47
+ */
48
+ private descifrarResponse(request: HttpRequest<any>, response: HttpResponse<any>): any {
49
+ let responseDefinition = request.context.get(RESPONSE_TOKEN);
50
+ if (responseDefinition && response.body) {
51
+ return this.descifrarDatos(response.body, responseDefinition)
52
+ }
53
+ return response.body;
54
+ }
55
+
56
+ /**
57
+ * Cifra los datos de la petición interceptada y regresa una nueva petición con los datos cifrados
58
+ * @param request - Petición Http
59
+ * @returns - Petición con datos cifrados
60
+ */
61
+ private cifrarRequest(request: HttpRequest<any>): HttpRequest<any> {
62
+ let newRequest: HttpRequest<any> = request;
63
+ switch (request.method) {
64
+ case 'POST':
65
+ newRequest = request.clone({ body: this.cifrarDatos(request.body) });
66
+ break;
67
+ default:
68
+ newRequest = request.clone({ url: this.cifrarPeticionUrl(request) });
69
+ break;
70
+ }
71
+ return newRequest;
72
+ }
73
+
74
+ /**
75
+ * Realiza el cifrado de la petición cuando los datos a cifrar se mandan en la URL
76
+ * @param request - Petición HTTP
77
+ * @returns StringQueryParams cifrados en URL
78
+ */
79
+ private cifrarPeticionUrl(request: HttpRequest<any>): string {
80
+ let requestData = request.context.get(REQUEST_TOKEN);
81
+ let queryParams: string[] = [];
82
+ let queryObject = Object.fromEntries(new URL(request.url).searchParams.entries());
83
+ if (typeof requestData === 'object') {
84
+ Object.entries(queryObject).forEach(([key, value]) => {
85
+ if (!requestData[key]) {
86
+ requestData[key] = value;
87
+ }
88
+ });
89
+ Object.entries(this.cifrarDatos(requestData)).forEach(([key, value]) => {
90
+ if (value && typeof value !== 'object') {
91
+ queryParams.push(`${key}=${encodeURI((value || '') as string)}`);
92
+ }
93
+ });
94
+ }
95
+ return `${(request.url || '').split('?')[0]}${queryParams.length ? '?' + queryParams.join('&') : ''}`
96
+ }
97
+
98
+ /**
99
+ * Valida si la propiedad de un objeto es segura
100
+ * @param data - Objeto a validar
101
+ * @param key - Propiedad del objeto a validar
102
+ * @returns True si es una propiedad segura
103
+ */
104
+ private isValidDecorator(data: any, key: string): boolean {
105
+ return data != null && this.propertyHasDecorator(data, key);
106
+ }
107
+
108
+ /**
109
+ * Valida si la propiedad tiene el decorador de seguridad
110
+ * @param data - Entidad objetivo
111
+ * @param key - Nombre de la propiedad
112
+ */
113
+ private propertyHasDecorator(data: any, key: string): boolean {
114
+ return Reflect.hasMetadata(TOKEN_SECURE, data, key);
115
+ }
116
+
117
+ /**
118
+ * Valida si un objeto es seguro
119
+ * @param data - Objeto a validar
120
+ * @returns True si existe el decorador @Secure
121
+ */
122
+ private hasDecorator(data: any): boolean {
123
+ return data != null && Reflect.hasMetadata(TOKEN_SECURE, data);
124
+ }
125
+
126
+ /**
127
+ * Valida si es un objeto y no esta nulo
128
+ * @param object - Objeto a validar
129
+ * @returns True si es un objeto valido
130
+ */
131
+ private isValidObject(object: any): boolean {
132
+ return object != null && typeof object === 'object';
133
+ }
134
+
135
+ /**
136
+ * Cifra los datos especificados
137
+ * @param datos - Datos a cifrar
138
+ * @returns Regresa el objeto con los datos cifrados
139
+ */
140
+ private cifrarDatos(datos: any): any {
141
+ if (this.isValidObject(datos)) {
142
+ const contenedor: any = {};
143
+ Object.entries(datos).forEach(([key, value]) => {
144
+ if (this.isValidObject(value)) {
145
+ contenedor[key] = this.cifrarDatos(value)
146
+ }
147
+ else if (this.isValidDecorator(datos, key)) {
148
+ contenedor[key] = this.cifrarTexto(value as string);
149
+ }
150
+ else {
151
+ contenedor[key] = value;
152
+ }
153
+ });
154
+ return this.hasDecorator(datos) ? this.cifrarTexto(JSON.stringify(contenedor)) : contenedor;
155
+ }
156
+ return datos;
157
+ }
158
+
159
+ /**
160
+ * Descifra los datos a partir de una definición
161
+ * @param datos - Datos a descifrar
162
+ * @param definition - Definición de los datos con los decoradores seguros
163
+ * @returns Datos descifrados
164
+ */
165
+ private descifrarDatos(datos: any, definition: any): any {
166
+ let contenedor: any = datos;
167
+ if (datos && definition) {
168
+
169
+ if (Array.isArray(datos)) {
170
+ contenedor = [];
171
+ Object.entries(datos).forEach(([, value]) => {
172
+ contenedor.push(this.descifrarDatos(value, definition));
173
+ })
174
+ }
175
+ else {
176
+ contenedor = {};
177
+ Object.entries(datos).forEach(([key, value]) => {
178
+ if (this.isValidObject(value)) {
179
+ contenedor[key] = this.descifrarDatos(value, definition.prototype[key])
180
+ }
181
+ else if (this.propertyHasDecorator(definition.prototype, key)) {
182
+ contenedor[key] = this.decifrarTexto(value as string);
183
+ }
184
+ else {
185
+ contenedor[key] = value;
186
+ }
187
+ });
188
+ }
189
+ }
190
+ return contenedor;
191
+ }
192
+
193
+ /**
194
+ * Cifra el texto especificado
195
+ * @param datos - Contiene los datos que se cifraran
196
+ * @returns Datos cifrados
197
+ */
198
+ private cifrarTexto(datos: string): string {
199
+ return this.cifradoService.cifrar(datos);
200
+ }
201
+
202
+ /**
203
+ * Descifra el texto proporcionado
204
+ * @param datos - Contiene los datos que se descifraran
205
+ * @returns Datos descifrados
206
+ */
207
+ private decifrarTexto(datosCifrados: string): string {
208
+ return this.cifradoService.descifrar(datosCifrados);
209
+ }
210
+ }
211
+
@@ -0,0 +1,7 @@
1
+ import { secure } from "./secure-factory.model";
2
+
3
+ describe('SecureFactory', () => {
4
+ it('should create an instance', () => {
5
+ expect(secure).toBeTruthy();
6
+ });
7
+ });
@@ -0,0 +1,28 @@
1
+ import 'reflect-metadata'
2
+
3
+ /**
4
+ * Fabrica de decoradores para del modulo de seguridad
5
+ * @param cipher Indica el algoritmo de cifrado
6
+ */
7
+ export function secure(cipher?: string) {
8
+ /**
9
+ * Función para la fabrica de decoradores de clases y propiedades
10
+ * @param target Target del decorador
11
+ * @param propertyKey Nombre de la propiedad
12
+ * @returns Function de devolución para la fabrica de decoradores
13
+ */
14
+ return function (target: any, propertyKey?: string) {
15
+ if (propertyKey) {
16
+ Reflect.defineProperty(target, propertyKey, { writable: true });
17
+ Reflect.defineMetadata(TOKEN_SECURE, cipher, target, propertyKey);
18
+ }
19
+ else {
20
+ Reflect.defineMetadata(TOKEN_SECURE, cipher, target.prototype);
21
+ }
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Token para decorador de seguridad
27
+ */
28
+ export const TOKEN_SECURE = secure.name;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Enumera los tipos de operación para el modulo de seguridad
3
+ */
4
+ export enum TipoOperacion {
5
+ /**
6
+ * Indica que la operación a realizar es una codificación
7
+ */
8
+ Codificar,
9
+
10
+ /**
11
+ * Indica que la operación a realizar es una decodificación
12
+ */
13
+ Decodificar,
14
+
15
+ /**
16
+ * Indica que se deberá realizar la codificación y decodificación
17
+ */
18
+ CodificarYDecodificar
19
+ }
@@ -0,0 +1,15 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+
4
+
5
+
6
+ @NgModule({
7
+ declarations: [],
8
+ imports: [
9
+ CommonModule
10
+ ],
11
+ exports:[
12
+
13
+ ]
14
+ })
15
+ export class SecureModule { }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { CifradoService } from './cifrado.service';
4
+
5
+ describe('CifradoService', () => {
6
+ let service: CifradoService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(CifradoService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,32 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ /**
4
+ * Servicio de cifrado y descifrado de información
5
+ * @decorator `@Injectable()`
6
+ */
7
+ @Injectable({
8
+ providedIn: 'root'
9
+ })
10
+ export class CifradoService {
11
+
12
+ constructor() {
13
+ }
14
+
15
+ /**
16
+ * Método que realiza el cifrado de los datos tipo Texto
17
+ * @param data - Texto a cifrar
18
+ * @returns Datos cifrados en modo tex
19
+ */
20
+ public cifrar(data: string): string {
21
+ return window.btoa(encodeURIComponent(data));
22
+ }
23
+
24
+ /**
25
+ * Método que descifra el texto
26
+ * @params data - Texto a descifrar
27
+ * @returns Texto descifrado
28
+ */
29
+ public descifrar(data: string): string {
30
+ return window.atob(decodeURIComponent(data));
31
+ }
32
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { NgxRediCoreComponent } from './ngx-redi-core.component';
4
+
5
+ describe('NgxRediCoreComponent', () => {
6
+ let component: NgxRediCoreComponent;
7
+ let fixture: ComponentFixture<NgxRediCoreComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [ NgxRediCoreComponent ]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(NgxRediCoreComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,15 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'lib-ngx-redi-core',
5
+ template: `
6
+ <p>
7
+ ngx-redi-core works!
8
+ </p>
9
+ `,
10
+ styles: [
11
+ ]
12
+ })
13
+ export class NgxRediCoreComponent {
14
+
15
+ }
@@ -0,0 +1,16 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { NgxRediCoreComponent } from './ngx-redi-core.component';
3
+
4
+
5
+
6
+ @NgModule({
7
+ declarations: [
8
+ NgxRediCoreComponent
9
+ ],
10
+ imports: [
11
+ ],
12
+ exports: [
13
+ NgxRediCoreComponent
14
+ ]
15
+ })
16
+ export class NgxRediCoreModule { }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { NgxRediCoreService } from './ngx-redi-core.service';
4
+
5
+ describe('NgxRediCoreService', () => {
6
+ let service: NgxRediCoreService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(NgxRediCoreService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,9 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root'
5
+ })
6
+ export class NgxRediCoreService {
7
+
8
+ constructor() { }
9
+ }
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Public API Surface of ngx-redi-core
3
+ */
4
+
5
+ export * from './lib/ngx-redi-core.service';
6
+ export * from './lib/ngx-redi-core.component';
7
+ export * from './lib/ngx-redi-core.module';
@@ -0,0 +1,14 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/lib",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "exclude": [
12
+ "**/*.spec.ts"
13
+ ]
14
+ }
@@ -0,0 +1,10 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "./tsconfig.lib.json",
4
+ "compilerOptions": {
5
+ "declarationMap": false
6
+ },
7
+ "angularCompilerOptions": {
8
+ "compilationMode": "partial"
9
+ }
10
+ }
@@ -0,0 +1,14 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/spec",
6
+ "types": [
7
+ "jasmine"
8
+ ]
9
+ },
10
+ "include": [
11
+ "**/*.spec.ts",
12
+ "**/*.d.ts"
13
+ ]
14
+ }