@hemia/core 0.0.2 → 0.0.4
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 +17 -0
- package/dist/hemia-core.esm.js +83 -5
- package/dist/hemia-core.js +81 -3
- package/dist/types/guards/api-key.guard.d.ts +11 -0
- package/dist/types/guards/auth.guard.d.ts +4 -0
- package/dist/types/guards/index.d.ts +2 -0
- package/dist/types/guards/jwt.guard.d.ts +13 -0
- package/dist/types/hemia-factory.d.ts +1 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -12,6 +12,10 @@ Paquete generado con [Hemia CLI](https://www.npmjs.com/package/@hemia/cli)
|
|
|
12
12
|
npm install @hemia/hemia-core
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
```bash
|
|
16
|
+
bun add @hemia/hemia-core
|
|
17
|
+
```
|
|
18
|
+
|
|
15
19
|
---
|
|
16
20
|
|
|
17
21
|
## 🛠️ Scripts disponibles
|
|
@@ -32,5 +36,18 @@ npm install @hemia/hemia-core
|
|
|
32
36
|
|
|
33
37
|
---
|
|
34
38
|
|
|
39
|
+
## 🚀 Funciones y Clases Exportadas
|
|
40
|
+
|
|
41
|
+
| Nombre | Tipo | Descripción breve |
|
|
42
|
+
|-------------------------|---------|-------------------|
|
|
43
|
+
| `HemiaFactory` | Clase | Inicializa la app Hemia conectando Express con Inversify y registra controladores. |
|
|
44
|
+
| `ResponseSerializer` | Clase | Transforma entidades a DTO usando class-transformer. |
|
|
45
|
+
| `GuardsConsumer` | Clase | Ejecuta guards secuencialmente y lanza error si alguno falla. |
|
|
46
|
+
| `AuthGuard` | Clase | Guard de autenticación y autorización basado en roles/permisos. |
|
|
47
|
+
| `HemiaExecutionContext` | Clase | Contexto de ejecución para requests HTTP, accede a argumentos y request/response. |
|
|
48
|
+
| `Reflector` | Clase | Utilidad para obtener metadata de clases y métodos (roles, permisos, etc). |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
35
52
|
## ✨ Generado con Hemia CLI
|
|
36
53
|
|
package/dist/hemia-core.esm.js
CHANGED
|
@@ -4,7 +4,8 @@ import { METADATA_KEYS, ParamType, isRedirectResponse, ApiResponse } from '@hemi
|
|
|
4
4
|
import { TRACE_METADATA_KEY } from '@hemia/trace-manager';
|
|
5
5
|
import { traceMiddleware } from '@hemia/app-context';
|
|
6
6
|
import { plainToInstance } from 'class-transformer';
|
|
7
|
-
import { injectable } from 'inversify';
|
|
7
|
+
import { injectable, inject } from 'inversify';
|
|
8
|
+
import { AUTH_SERVICE_ID, AuthService } from '@hemia/auth-sdk';
|
|
8
9
|
|
|
9
10
|
class GuardsConsumer {
|
|
10
11
|
/**
|
|
@@ -206,6 +207,10 @@ function __decorate(decorators, target, key, desc) {
|
|
|
206
207
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
207
208
|
}
|
|
208
209
|
|
|
210
|
+
function __param(paramIndex, decorator) {
|
|
211
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
212
|
+
}
|
|
213
|
+
|
|
209
214
|
function __metadata(metadataKey, metadataValue) {
|
|
210
215
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
211
216
|
}
|
|
@@ -261,6 +266,11 @@ class HemiaFactory {
|
|
|
261
266
|
const app = express();
|
|
262
267
|
app.use(express.json());
|
|
263
268
|
app.use(express.urlencoded({ extended: true }));
|
|
269
|
+
if (options.middlewares && Array.isArray(options.middlewares)) {
|
|
270
|
+
options.middlewares.forEach(middleware => {
|
|
271
|
+
app.use(middleware);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
264
274
|
app.use((req, res, next) => {
|
|
265
275
|
const defaultHeaders = {
|
|
266
276
|
'Access-Control-Allow-Origin': req.headers.origin || '*',
|
|
@@ -294,6 +304,10 @@ class HemiaFactory {
|
|
|
294
304
|
}
|
|
295
305
|
}
|
|
296
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
309
|
+
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
310
|
+
*/
|
|
297
311
|
let AuthGuard = class AuthGuard {
|
|
298
312
|
constructor(reflector) {
|
|
299
313
|
this.reflector = reflector;
|
|
@@ -310,17 +324,19 @@ let AuthGuard = class AuthGuard {
|
|
|
310
324
|
}
|
|
311
325
|
const request = context.switchToHttp().getRequest();
|
|
312
326
|
const user = request.user;
|
|
313
|
-
|
|
327
|
+
const permissions = request.permissions;
|
|
328
|
+
const contextData = request.context;
|
|
329
|
+
if (!user) {
|
|
314
330
|
return false;
|
|
315
331
|
}
|
|
316
332
|
if (requiredRoles) {
|
|
317
|
-
const userRoleNames =
|
|
333
|
+
const userRoleNames = Array.isArray(contextData.roles) ? contextData.roles : [];
|
|
318
334
|
const hasRole = requiredRoles.some((role) => userRoleNames.includes(role));
|
|
319
335
|
if (!hasRole)
|
|
320
336
|
return false;
|
|
321
337
|
}
|
|
322
338
|
if (requiredPermissions) {
|
|
323
|
-
const userPermissions =
|
|
339
|
+
const userPermissions = Array.isArray(permissions) ? permissions : [];
|
|
324
340
|
const hasPermission = requiredPermissions.some((perm) => userPermissions.includes(perm));
|
|
325
341
|
if (!hasPermission)
|
|
326
342
|
return false;
|
|
@@ -333,4 +349,66 @@ AuthGuard = __decorate([
|
|
|
333
349
|
__metadata("design:paramtypes", [Reflector])
|
|
334
350
|
], AuthGuard);
|
|
335
351
|
|
|
336
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Guardia para validar la presencia y validez de una API Key en las solicitudes entrantes.
|
|
354
|
+
* La API Key se espera en el encabezado 'x-api-key' o como parámetro de consulta 'api_key'.
|
|
355
|
+
* Las claves válidas se configuran mediante la variable de entorno 'API_KEY' y pueden ser múltiples, separadas por comas.
|
|
356
|
+
*/
|
|
357
|
+
let ApiKeyGuard = class ApiKeyGuard {
|
|
358
|
+
constructor() {
|
|
359
|
+
this.validApiKeys = (process.env.API_KEY || "")
|
|
360
|
+
.split(",")
|
|
361
|
+
.map(key => key.trim())
|
|
362
|
+
.filter(key => !!key);
|
|
363
|
+
}
|
|
364
|
+
canActivate(context) {
|
|
365
|
+
const request = context.switchToHttp().getRequest();
|
|
366
|
+
const apiKey = request.headers['x-api-key'] || request.query['api_key'];
|
|
367
|
+
if (!apiKey)
|
|
368
|
+
return false;
|
|
369
|
+
return this.validApiKeys.includes(apiKey);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
ApiKeyGuard = __decorate([
|
|
373
|
+
injectable(),
|
|
374
|
+
__metadata("design:paramtypes", [])
|
|
375
|
+
], ApiKeyGuard);
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Guardia para validar y procesar tokens JWT en las solicitudes entrantes.
|
|
379
|
+
* Extrae el token de sesión del encabezado 'x-session' o de las cookies,
|
|
380
|
+
* y utiliza el AuthService para validar el token y obtener los datos del usuario.
|
|
381
|
+
* Si el token es válido, adjunta la información del usuario, permisos y contexto a la solicitud.
|
|
382
|
+
*/
|
|
383
|
+
let JWTGuard = class JWTGuard {
|
|
384
|
+
constructor(authService) {
|
|
385
|
+
this.authService = authService;
|
|
386
|
+
}
|
|
387
|
+
async canActivate(context) {
|
|
388
|
+
const request = context.switchToHttp().getRequest();
|
|
389
|
+
const sessionId = request.headers['x-session'] || request.cookies['x-session'];
|
|
390
|
+
if (!sessionId) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
const accessTokenData = await this.authService.getSessionAccess(sessionId);
|
|
395
|
+
if (!accessTokenData) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
request.user = accessTokenData.user;
|
|
399
|
+
request.permissions = accessTokenData.permissions;
|
|
400
|
+
request.context = accessTokenData.context;
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
JWTGuard = __decorate([
|
|
409
|
+
injectable(),
|
|
410
|
+
__param(0, inject(AUTH_SERVICE_ID)),
|
|
411
|
+
__metadata("design:paramtypes", [AuthService])
|
|
412
|
+
], JWTGuard);
|
|
413
|
+
|
|
414
|
+
export { ApiKeyGuard, AuthGuard, GuardsConsumer, HemiaExecutionContext, HemiaFactory, JWTGuard, Reflector, ResponseSerializer, registerRoutes };
|
package/dist/hemia-core.js
CHANGED
|
@@ -7,6 +7,7 @@ var traceManager = require('@hemia/trace-manager');
|
|
|
7
7
|
var appContext = require('@hemia/app-context');
|
|
8
8
|
var classTransformer = require('class-transformer');
|
|
9
9
|
var inversify = require('inversify');
|
|
10
|
+
var authSdk = require('@hemia/auth-sdk');
|
|
10
11
|
|
|
11
12
|
class GuardsConsumer {
|
|
12
13
|
/**
|
|
@@ -208,6 +209,10 @@ function __decorate(decorators, target, key, desc) {
|
|
|
208
209
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
209
210
|
}
|
|
210
211
|
|
|
212
|
+
function __param(paramIndex, decorator) {
|
|
213
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
214
|
+
}
|
|
215
|
+
|
|
211
216
|
function __metadata(metadataKey, metadataValue) {
|
|
212
217
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
213
218
|
}
|
|
@@ -263,6 +268,11 @@ class HemiaFactory {
|
|
|
263
268
|
const app = express();
|
|
264
269
|
app.use(express.json());
|
|
265
270
|
app.use(express.urlencoded({ extended: true }));
|
|
271
|
+
if (options.middlewares && Array.isArray(options.middlewares)) {
|
|
272
|
+
options.middlewares.forEach(middleware => {
|
|
273
|
+
app.use(middleware);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
266
276
|
app.use((req, res, next) => {
|
|
267
277
|
const defaultHeaders = {
|
|
268
278
|
'Access-Control-Allow-Origin': req.headers.origin || '*',
|
|
@@ -296,6 +306,10 @@ class HemiaFactory {
|
|
|
296
306
|
}
|
|
297
307
|
}
|
|
298
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
311
|
+
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
312
|
+
*/
|
|
299
313
|
exports.AuthGuard = class AuthGuard {
|
|
300
314
|
constructor(reflector) {
|
|
301
315
|
this.reflector = reflector;
|
|
@@ -312,17 +326,19 @@ exports.AuthGuard = class AuthGuard {
|
|
|
312
326
|
}
|
|
313
327
|
const request = context.switchToHttp().getRequest();
|
|
314
328
|
const user = request.user;
|
|
315
|
-
|
|
329
|
+
const permissions = request.permissions;
|
|
330
|
+
const contextData = request.context;
|
|
331
|
+
if (!user) {
|
|
316
332
|
return false;
|
|
317
333
|
}
|
|
318
334
|
if (requiredRoles) {
|
|
319
|
-
const userRoleNames =
|
|
335
|
+
const userRoleNames = Array.isArray(contextData.roles) ? contextData.roles : [];
|
|
320
336
|
const hasRole = requiredRoles.some((role) => userRoleNames.includes(role));
|
|
321
337
|
if (!hasRole)
|
|
322
338
|
return false;
|
|
323
339
|
}
|
|
324
340
|
if (requiredPermissions) {
|
|
325
|
-
const userPermissions =
|
|
341
|
+
const userPermissions = Array.isArray(permissions) ? permissions : [];
|
|
326
342
|
const hasPermission = requiredPermissions.some((perm) => userPermissions.includes(perm));
|
|
327
343
|
if (!hasPermission)
|
|
328
344
|
return false;
|
|
@@ -335,6 +351,68 @@ exports.AuthGuard = __decorate([
|
|
|
335
351
|
__metadata("design:paramtypes", [exports.Reflector])
|
|
336
352
|
], exports.AuthGuard);
|
|
337
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Guardia para validar la presencia y validez de una API Key en las solicitudes entrantes.
|
|
356
|
+
* La API Key se espera en el encabezado 'x-api-key' o como parámetro de consulta 'api_key'.
|
|
357
|
+
* Las claves válidas se configuran mediante la variable de entorno 'API_KEY' y pueden ser múltiples, separadas por comas.
|
|
358
|
+
*/
|
|
359
|
+
exports.ApiKeyGuard = class ApiKeyGuard {
|
|
360
|
+
constructor() {
|
|
361
|
+
this.validApiKeys = (process.env.API_KEY || "")
|
|
362
|
+
.split(",")
|
|
363
|
+
.map(key => key.trim())
|
|
364
|
+
.filter(key => !!key);
|
|
365
|
+
}
|
|
366
|
+
canActivate(context) {
|
|
367
|
+
const request = context.switchToHttp().getRequest();
|
|
368
|
+
const apiKey = request.headers['x-api-key'] || request.query['api_key'];
|
|
369
|
+
if (!apiKey)
|
|
370
|
+
return false;
|
|
371
|
+
return this.validApiKeys.includes(apiKey);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
exports.ApiKeyGuard = __decorate([
|
|
375
|
+
inversify.injectable(),
|
|
376
|
+
__metadata("design:paramtypes", [])
|
|
377
|
+
], exports.ApiKeyGuard);
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Guardia para validar y procesar tokens JWT en las solicitudes entrantes.
|
|
381
|
+
* Extrae el token de sesión del encabezado 'x-session' o de las cookies,
|
|
382
|
+
* y utiliza el AuthService para validar el token y obtener los datos del usuario.
|
|
383
|
+
* Si el token es válido, adjunta la información del usuario, permisos y contexto a la solicitud.
|
|
384
|
+
*/
|
|
385
|
+
exports.JWTGuard = class JWTGuard {
|
|
386
|
+
constructor(authService) {
|
|
387
|
+
this.authService = authService;
|
|
388
|
+
}
|
|
389
|
+
async canActivate(context) {
|
|
390
|
+
const request = context.switchToHttp().getRequest();
|
|
391
|
+
const sessionId = request.headers['x-session'] || request.cookies['x-session'];
|
|
392
|
+
if (!sessionId) {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
try {
|
|
396
|
+
const accessTokenData = await this.authService.getSessionAccess(sessionId);
|
|
397
|
+
if (!accessTokenData) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
request.user = accessTokenData.user;
|
|
401
|
+
request.permissions = accessTokenData.permissions;
|
|
402
|
+
request.context = accessTokenData.context;
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
exports.JWTGuard = __decorate([
|
|
411
|
+
inversify.injectable(),
|
|
412
|
+
__param(0, inversify.inject(authSdk.AUTH_SERVICE_ID)),
|
|
413
|
+
__metadata("design:paramtypes", [authSdk.AuthService])
|
|
414
|
+
], exports.JWTGuard);
|
|
415
|
+
|
|
338
416
|
exports.GuardsConsumer = GuardsConsumer;
|
|
339
417
|
exports.HemiaExecutionContext = HemiaExecutionContext;
|
|
340
418
|
exports.HemiaFactory = HemiaFactory;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from "@hemia/common";
|
|
2
|
+
/**
|
|
3
|
+
* Guardia para validar la presencia y validez de una API Key en las solicitudes entrantes.
|
|
4
|
+
* La API Key se espera en el encabezado 'x-api-key' o como parámetro de consulta 'api_key'.
|
|
5
|
+
* Las claves válidas se configuran mediante la variable de entorno 'API_KEY' y pueden ser múltiples, separadas por comas.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ApiKeyGuard implements CanActivate {
|
|
8
|
+
private readonly validApiKeys;
|
|
9
|
+
constructor();
|
|
10
|
+
canActivate(context: ExecutionContext): boolean;
|
|
11
|
+
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { CanActivate, ExecutionContext } from '@hemia/common';
|
|
2
2
|
import { Reflector } from '../services';
|
|
3
|
+
/**
|
|
4
|
+
* Guardia de autorización que verifica roles y permisos definidos en los controladores y métodos.
|
|
5
|
+
* Utiliza los metadatos definidos con los decoradores @Roles y @Permissions.
|
|
6
|
+
*/
|
|
3
7
|
export declare class AuthGuard implements CanActivate {
|
|
4
8
|
private reflector;
|
|
5
9
|
constructor(reflector: Reflector);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from "@hemia/common";
|
|
2
|
+
import { AuthService } from "@hemia/auth-sdk";
|
|
3
|
+
/**
|
|
4
|
+
* Guardia para validar y procesar tokens JWT en las solicitudes entrantes.
|
|
5
|
+
* Extrae el token de sesión del encabezado 'x-session' o de las cookies,
|
|
6
|
+
* y utiliza el AuthService para validar el token y obtener los datos del usuario.
|
|
7
|
+
* Si el token es válido, adjunta la información del usuario, permisos y contexto a la solicitud.
|
|
8
|
+
*/
|
|
9
|
+
export declare class JWTGuard implements CanActivate {
|
|
10
|
+
private readonly authService;
|
|
11
|
+
constructor(authService: AuthService);
|
|
12
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hemia/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Core utilities for Hemia projects",
|
|
5
5
|
"main": "dist/hemia-core.js",
|
|
6
6
|
"module": "dist/hemia-core.esm.js",
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"@rollup/plugin-commonjs": "^26.0.1",
|
|
18
18
|
"@rollup/plugin-json": "^6.1.0",
|
|
19
19
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
20
|
-
"@hemia/common": "^0.0.
|
|
20
|
+
"@hemia/common": "^0.0.5",
|
|
21
21
|
"@hemia/app-context": "^0.0.6",
|
|
22
22
|
"@hemia/trace-manager": "^0.0.9",
|
|
23
|
+
"@hemia/auth-sdk": "^0.0.9",
|
|
23
24
|
"@types/express": "^5.0.5",
|
|
24
25
|
"express": "^5.1.0",
|
|
25
26
|
"inversify": "^7.10.4",
|
|
@@ -45,6 +46,6 @@
|
|
|
45
46
|
"class-transformer": "^0.5.1",
|
|
46
47
|
"express": "^5.0.0",
|
|
47
48
|
"inversify": "^7.0.0",
|
|
48
|
-
"reflect-metadata": "^0.
|
|
49
|
+
"reflect-metadata": "^0.2.2"
|
|
49
50
|
}
|
|
50
51
|
}
|