jerkjs 2.0.0
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/LICENSE +200 -0
- package/README.md +171 -0
- package/doc/EXTENSION_MANUAL.md +958 -0
- package/doc/FIREWALL_MANUAL.md +419 -0
- package/doc/HOOKS_REFERENCE_IMPROVED.md +599 -0
- package/doc/MANUAL_API_SDK.md +539 -0
- package/doc/MANUAL_MVC.md +397 -0
- package/doc/MARIADB_TOKENS_IMPLEMENTATION.md +113 -0
- package/doc/MIDDLEWARE_MANUAL.md +521 -0
- package/doc/OAUTH2_GOOGLE_MANUAL.md +408 -0
- package/doc/frontend-and-sessions.md +356 -0
- package/examples/advanced/controllers/productController.js +64 -0
- package/examples/advanced/controllers/userController.js +85 -0
- package/examples/advanced/routes.json +51 -0
- package/examples/advanced_example.js +93 -0
- package/examples/basic/controllers/userController.js +85 -0
- package/examples/basic_example.js +72 -0
- package/examples/frontend/README.md +71 -0
- package/examples/frontend/app.js +71 -0
- package/examples/frontend/controllers/apiController.js +39 -0
- package/examples/frontend/controllers/authController.js +220 -0
- package/examples/frontend/controllers/formController.js +47 -0
- package/examples/frontend/controllers/messageController.js +96 -0
- package/examples/frontend/controllers/pageController.js +178 -0
- package/examples/frontend/controllers/staticController.js +167 -0
- package/examples/frontend/routes.json +90 -0
- package/examples/mvc_example/app.js +138 -0
- package/examples/mvc_example/views/home/index.html +26 -0
- package/examples/mvc_example/views/home/simple.html +3 -0
- package/examples/mvc_example/views/layout.html +23 -0
- package/examples/mvc_example/views/test.html +3 -0
- package/examples/mvc_example/views/user/invalid.html +6 -0
- package/examples/mvc_example/views/user/list.html +36 -0
- package/examples/mvc_example/views/user/notfound.html +6 -0
- package/examples/mvc_example/views/user/profile.html +11 -0
- package/examples/mvc_routes_example/app.js +34 -0
- package/examples/mvc_routes_example/controllers/mainController.js +27 -0
- package/examples/mvc_routes_example/controllers/productController.js +47 -0
- package/examples/mvc_routes_example/controllers/userController.js +76 -0
- package/examples/mvc_routes_example/routes.json +30 -0
- package/examples/mvc_routes_example/views/layout.html +31 -0
- package/examples/mvc_routes_example/views/main/index.html +11 -0
- package/examples/mvc_routes_example/views/product/catalog.html +24 -0
- package/examples/mvc_routes_example/views/user/invalid.html +6 -0
- package/examples/mvc_routes_example/views/user/list.html +40 -0
- package/examples/mvc_routes_example/views/user/notfound.html +6 -0
- package/examples/mvc_routes_example/views/user/profile.html +18 -0
- package/examples/public/README.md +92 -0
- package/examples/public/app.js +72 -0
- package/examples/public/controllers/healthController.js +20 -0
- package/examples/public/controllers/mainController.js +22 -0
- package/examples/public/controllers/userController.js +139 -0
- package/examples/public/routes.json +51 -0
- package/examples/v2/README.md +72 -0
- package/examples/v2/app.js +74 -0
- package/examples/v2/app_fixed.js +74 -0
- package/examples/v2/controllers/authController.js +64 -0
- package/examples/v2/controllers/mainController.js +24 -0
- package/examples/v2/controllers/protectedController.js +12 -0
- package/examples/v2/controllers/userController.js +16 -0
- package/examples/v2/package.json +27 -0
- package/examples/v2/routes.json +30 -0
- package/examples/v2/test_api.sh +47 -0
- package/examples/v2/tokens_example.sqlite +0 -0
- package/examples/v2.1_firewall_demo/README.md +113 -0
- package/examples/v2.1_firewall_demo/app.js +182 -0
- package/examples/v2.1_firewall_demo/package.json +27 -0
- package/examples/v2.1_hooks_demo/README.md +85 -0
- package/examples/v2.1_hooks_demo/app.js +101 -0
- package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
- package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
- package/examples/v2.1_hooks_demo/package.json +27 -0
- package/examples/v2.1_hooks_demo/routes.json +16 -0
- package/examples/v2.1_openapi_demo/README.md +82 -0
- package/examples/v2.1_openapi_demo/app.js +296 -0
- package/examples/v2.1_openapi_demo/package.json +26 -0
- package/examples/v2_cors/README.md +82 -0
- package/examples/v2_cors/app.js +108 -0
- package/examples/v2_cors/package.json +23 -0
- package/examples/v2_json_auth/README.md +83 -0
- package/examples/v2_json_auth/app.js +72 -0
- package/examples/v2_json_auth/controllers/authController.js +67 -0
- package/examples/v2_json_auth/controllers/mainController.js +16 -0
- package/examples/v2_json_auth/controllers/protectedController.js +12 -0
- package/examples/v2_json_auth/controllers/tokenController.js +28 -0
- package/examples/v2_json_auth/controllers/userController.js +15 -0
- package/examples/v2_json_auth/package.json +26 -0
- package/examples/v2_json_auth/routes.json +37 -0
- package/examples/v2_json_auth/tokens.json +20 -0
- package/examples/v2_mariadb_auth/README.md +94 -0
- package/examples/v2_mariadb_auth/app.js +81 -0
- package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
- package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
- package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
- package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
- package/examples/v2_mariadb_auth/package.json +27 -0
- package/examples/v2_mariadb_auth/routes.json +37 -0
- package/examples/v2_no_auth/README.md +75 -0
- package/examples/v2_no_auth/app.js +72 -0
- package/examples/v2_no_auth/controllers/healthController.js +14 -0
- package/examples/v2_no_auth/controllers/mainController.js +19 -0
- package/examples/v2_no_auth/controllers/productController.js +31 -0
- package/examples/v2_no_auth/controllers/publicController.js +16 -0
- package/examples/v2_no_auth/package.json +22 -0
- package/examples/v2_no_auth/routes.json +37 -0
- package/examples/v2_oauth/README.md +70 -0
- package/examples/v2_oauth/app.js +90 -0
- package/examples/v2_oauth/controllers/mainController.js +45 -0
- package/examples/v2_oauth/controllers/oauthController.js +247 -0
- package/examples/v2_oauth/controllers/protectedController.js +13 -0
- package/examples/v2_oauth/controllers/userController.js +17 -0
- package/examples/v2_oauth/package.json +26 -0
- package/examples/v2_oauth/routes.json +44 -0
- package/examples/v2_openapi/README.md +77 -0
- package/examples/v2_openapi/app.js +222 -0
- package/examples/v2_openapi/controllers/authController.js +52 -0
- package/examples/v2_openapi/controllers/mainController.js +26 -0
- package/examples/v2_openapi/controllers/productController.js +17 -0
- package/examples/v2_openapi/controllers/userController.js +27 -0
- package/examples/v2_openapi/package.json +26 -0
- package/examples/v2_openapi/routes.json +37 -0
- package/generate_token.js +10 -0
- package/index.js +85 -0
- package/jerk.jpg +0 -0
- package/lib/core/handler.js +86 -0
- package/lib/core/hooks.js +224 -0
- package/lib/core/router.js +204 -0
- package/lib/core/securityEnhancedServer.js +752 -0
- package/lib/core/server.js +369 -0
- package/lib/loader/controllerLoader.js +175 -0
- package/lib/loader/routeLoader.js +341 -0
- package/lib/middleware/auditLogger.js +208 -0
- package/lib/middleware/authenticator.js +565 -0
- package/lib/middleware/compressor.js +218 -0
- package/lib/middleware/cors.js +135 -0
- package/lib/middleware/firewall.js +443 -0
- package/lib/middleware/rateLimiter.js +210 -0
- package/lib/middleware/session.js +301 -0
- package/lib/middleware/validator.js +193 -0
- package/lib/mvc/controllerBase.js +207 -0
- package/lib/mvc/viewEngine.js +752 -0
- package/lib/utils/configParser.js +223 -0
- package/lib/utils/logger.js +145 -0
- package/lib/utils/mariadbTokenAdapter.js +226 -0
- package/lib/utils/openapiGenerator.js +140 -0
- package/lib/utils/sqliteTokenAdapter.js +224 -0
- package/lib/utils/tokenManager.js +254 -0
- package/package.json +47 -0
- package/v2examplle/v2_json_auth/README.md +83 -0
- package/v2examplle/v2_json_auth/app.js +72 -0
- package/v2examplle/v2_json_auth/controllers/authController.js +67 -0
- package/v2examplle/v2_json_auth/controllers/mainController.js +16 -0
- package/v2examplle/v2_json_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_json_auth/controllers/tokenController.js +28 -0
- package/v2examplle/v2_json_auth/controllers/userController.js +15 -0
- package/v2examplle/v2_json_auth/package.json +26 -0
- package/v2examplle/v2_json_auth/routes.json +37 -0
- package/v2examplle/v2_json_auth/tokens.json +20 -0
- package/v2examplle/v2_mariadb_auth/README.md +94 -0
- package/v2examplle/v2_mariadb_auth/app.js +81 -0
- package/v2examplle/v2_mariadb_auth/controllers/authController.js +95 -0
- package/v2examplle/v2_mariadb_auth/controllers/mainController.js +31 -0
- package/v2examplle/v2_mariadb_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_mariadb_auth/controllers/userController.js +17 -0
- package/v2examplle/v2_mariadb_auth/package.json +27 -0
- package/v2examplle/v2_mariadb_auth/routes.json +37 -0
- package/v2examplle/v2_sqlite_auth/README.md +72 -0
- package/v2examplle/v2_sqlite_auth/app.js +74 -0
- package/v2examplle/v2_sqlite_auth/app_fixed.js +74 -0
- package/v2examplle/v2_sqlite_auth/controllers/authController.js +64 -0
- package/v2examplle/v2_sqlite_auth/controllers/mainController.js +24 -0
- package/v2examplle/v2_sqlite_auth/controllers/protectedController.js +12 -0
- package/v2examplle/v2_sqlite_auth/controllers/userController.js +16 -0
- package/v2examplle/v2_sqlite_auth/package.json +27 -0
- package/v2examplle/v2_sqlite_auth/routes.json +30 -0
- package/v2examplle/v2_sqlite_auth/test_api.sh +47 -0
- package/v2examplle/v2_sqlite_auth/tokens_example.sqlite +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Simulación de base de datos en memoria
|
|
2
|
+
let users = [
|
|
3
|
+
{ id: 1, name: 'Juan Pérez', email: 'juan@example.com', age: 30 },
|
|
4
|
+
{ id: 2, name: 'María García', email: 'maria@example.com', age: 25 },
|
|
5
|
+
{ id: 3, name: 'Pedro Rodríguez', email: 'pedro@example.com', age: 35 }
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
let nextId = 4;
|
|
9
|
+
|
|
10
|
+
const userController = {
|
|
11
|
+
getAllUsers: (req, res) => {
|
|
12
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
13
|
+
res.end(JSON.stringify({
|
|
14
|
+
success: true,
|
|
15
|
+
data: users,
|
|
16
|
+
count: users.length
|
|
17
|
+
}));
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
getUserById: (req, res) => {
|
|
21
|
+
const userId = parseInt(req.params.id);
|
|
22
|
+
const user = users.find(u => u.id === userId);
|
|
23
|
+
|
|
24
|
+
if (!user) {
|
|
25
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
26
|
+
res.end(JSON.stringify({
|
|
27
|
+
success: false,
|
|
28
|
+
error: 'Usuario no encontrado'
|
|
29
|
+
}));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
34
|
+
res.end(JSON.stringify({
|
|
35
|
+
success: true,
|
|
36
|
+
data: user
|
|
37
|
+
}));
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
createUser: (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const { name, email, age } = req.body;
|
|
43
|
+
|
|
44
|
+
// Validación simple
|
|
45
|
+
if (!name || !email) {
|
|
46
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
47
|
+
res.end(JSON.stringify({
|
|
48
|
+
success: false,
|
|
49
|
+
error: 'Nombre y correo electrónico son obligatorios'
|
|
50
|
+
}));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Crear nuevo usuario
|
|
55
|
+
const newUser = {
|
|
56
|
+
id: nextId++,
|
|
57
|
+
name,
|
|
58
|
+
email,
|
|
59
|
+
age: age || null
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
users.push(newUser);
|
|
63
|
+
|
|
64
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
65
|
+
res.end(JSON.stringify({
|
|
66
|
+
success: true,
|
|
67
|
+
data: newUser,
|
|
68
|
+
message: 'Usuario creado exitosamente'
|
|
69
|
+
}));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
72
|
+
res.end(JSON.stringify({
|
|
73
|
+
success: false,
|
|
74
|
+
error: 'Error interno del servidor'
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
updateUser: (req, res) => {
|
|
80
|
+
try {
|
|
81
|
+
const userId = parseInt(req.params.id);
|
|
82
|
+
const { name, email, age } = req.body;
|
|
83
|
+
|
|
84
|
+
const userIndex = users.findIndex(u => u.id === userId);
|
|
85
|
+
|
|
86
|
+
if (userIndex === -1) {
|
|
87
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
88
|
+
res.end(JSON.stringify({
|
|
89
|
+
success: false,
|
|
90
|
+
error: 'Usuario no encontrado'
|
|
91
|
+
}));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Actualizar usuario
|
|
96
|
+
if (name) users[userIndex].name = name;
|
|
97
|
+
if (email) users[userIndex].email = email;
|
|
98
|
+
if (age !== undefined) users[userIndex].age = age;
|
|
99
|
+
|
|
100
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
101
|
+
res.end(JSON.stringify({
|
|
102
|
+
success: true,
|
|
103
|
+
data: users[userIndex],
|
|
104
|
+
message: 'Usuario actualizado exitosamente'
|
|
105
|
+
}));
|
|
106
|
+
} catch (error) {
|
|
107
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
108
|
+
res.end(JSON.stringify({
|
|
109
|
+
success: false,
|
|
110
|
+
error: 'Error interno del servidor'
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
deleteUser: (req, res) => {
|
|
116
|
+
const userId = parseInt(req.params.id);
|
|
117
|
+
const userIndex = users.findIndex(u => u.id === userId);
|
|
118
|
+
|
|
119
|
+
if (userIndex === -1) {
|
|
120
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
121
|
+
res.end(JSON.stringify({
|
|
122
|
+
success: false,
|
|
123
|
+
error: 'Usuario no encontrado'
|
|
124
|
+
}));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const deletedUser = users.splice(userIndex, 1)[0];
|
|
129
|
+
|
|
130
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
131
|
+
res.end(JSON.stringify({
|
|
132
|
+
success: true,
|
|
133
|
+
data: deletedUser,
|
|
134
|
+
message: 'Usuario eliminado exitosamente'
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
module.exports = userController;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "/",
|
|
4
|
+
"method": "GET",
|
|
5
|
+
"controller": "./controllers/mainController.js",
|
|
6
|
+
"handler": "home",
|
|
7
|
+
"auth": "none"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"path": "/users",
|
|
11
|
+
"method": "GET",
|
|
12
|
+
"controller": "./controllers/userController.js",
|
|
13
|
+
"handler": "getAllUsers",
|
|
14
|
+
"auth": "none"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "/users/:id",
|
|
18
|
+
"method": "GET",
|
|
19
|
+
"controller": "./controllers/userController.js",
|
|
20
|
+
"handler": "getUserById",
|
|
21
|
+
"auth": "none"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "/users",
|
|
25
|
+
"method": "POST",
|
|
26
|
+
"controller": "./controllers/userController.js",
|
|
27
|
+
"handler": "createUser",
|
|
28
|
+
"auth": "none"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "/users/:id",
|
|
32
|
+
"method": "PUT",
|
|
33
|
+
"controller": "./controllers/userController.js",
|
|
34
|
+
"handler": "updateUser",
|
|
35
|
+
"auth": "none"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "/users/:id",
|
|
39
|
+
"method": "DELETE",
|
|
40
|
+
"controller": "./controllers/userController.js",
|
|
41
|
+
"handler": "deleteUser",
|
|
42
|
+
"auth": "none"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "/health",
|
|
46
|
+
"method": "GET",
|
|
47
|
+
"controller": "./controllers/healthController.js",
|
|
48
|
+
"handler": "checkHealth",
|
|
49
|
+
"auth": "none"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Ejemplo API con Autenticación SQLite
|
|
2
|
+
|
|
3
|
+
Este ejemplo demuestra cómo crear una API con autenticación basada en tokens almacenados en SQLite utilizando el Framework API SDK.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- Autenticación JWT con tokens almacenados en SQLite
|
|
8
|
+
- Rutas protegidas y públicas
|
|
9
|
+
- Sistema de login para obtener tokens
|
|
10
|
+
- Controladores organizados por funcionalidad
|
|
11
|
+
|
|
12
|
+
## Configuración
|
|
13
|
+
|
|
14
|
+
1. Asegúrate de tener instaladas las dependencias del framework API SDK
|
|
15
|
+
2. Instala sqlite3 si aún no está instalado: `npm install sqlite3`
|
|
16
|
+
|
|
17
|
+
## Uso
|
|
18
|
+
|
|
19
|
+
1. Inicia el servidor:
|
|
20
|
+
```bash
|
|
21
|
+
node app.js
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
2. El servidor escuchará en `http://localhost:8088`
|
|
25
|
+
|
|
26
|
+
## Endpoints
|
|
27
|
+
|
|
28
|
+
- `GET /` - Página de inicio (público)
|
|
29
|
+
- `POST /login` - Iniciar sesión y obtener token (público)
|
|
30
|
+
- `GET /protected` - Contenido protegido (requiere token)
|
|
31
|
+
- `GET /profile` - Perfil de usuario (requiere token)
|
|
32
|
+
|
|
33
|
+
## Ejemplo de uso
|
|
34
|
+
|
|
35
|
+
1. Iniciar sesión:
|
|
36
|
+
```bash
|
|
37
|
+
curl -X POST http://localhost:8088/login \
|
|
38
|
+
-H "Content-Type: application/json" \
|
|
39
|
+
-d '{"username": "admin", "password": "password"}'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
2. Acceder a contenido protegido:
|
|
43
|
+
```bash
|
|
44
|
+
curl -X GET http://localhost:8088/protected \
|
|
45
|
+
-H "Authorization: Bearer TU_TOKEN_AQUI"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. Ver perfil de usuario:
|
|
49
|
+
```bash
|
|
50
|
+
curl -X GET http://localhost:8088/profile \
|
|
51
|
+
-H "Authorization: Bearer TU_TOKEN_AQUI"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Estructura del proyecto
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
examples/v2/
|
|
58
|
+
├── app.js # Punto de entrada de la aplicación
|
|
59
|
+
├── routes.json # Definición de rutas
|
|
60
|
+
├── controllers/ # Controladores de las rutas
|
|
61
|
+
│ ├── mainController.js
|
|
62
|
+
│ ├── authController.js
|
|
63
|
+
│ ├── protectedController.js
|
|
64
|
+
│ └── userController.js
|
|
65
|
+
└── tokens_example.sqlite # Base de datos SQLite para tokens (generada automáticamente)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Seguridad
|
|
69
|
+
|
|
70
|
+
- Los tokens se almacenan en una base de datos SQLite
|
|
71
|
+
- Los tokens expiran después de 1 hora
|
|
72
|
+
- Las rutas protegidas requieren un token válido en el header Authorization
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const {
|
|
2
|
+
APIServer,
|
|
3
|
+
Authenticator,
|
|
4
|
+
RouteLoader,
|
|
5
|
+
Logger,
|
|
6
|
+
SQLiteTokenAdapter
|
|
7
|
+
} = require('../../index.js');
|
|
8
|
+
|
|
9
|
+
async function startServer() {
|
|
10
|
+
// Crear instancia del servidor
|
|
11
|
+
const server = new APIServer({
|
|
12
|
+
port: 8088,
|
|
13
|
+
host: 'localhost'
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Crear instancia del logger
|
|
17
|
+
const logger = new Logger({ level: 'info' });
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Crear instancia del adaptador de tokens SQLite
|
|
21
|
+
const tokenAdapter = new SQLiteTokenAdapter({
|
|
22
|
+
dbPath: './tokens_example.sqlite',
|
|
23
|
+
tableName: 'example_tokens'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Inicializar el adaptador de tokens
|
|
27
|
+
await tokenAdapter.initialize();
|
|
28
|
+
logger.info('SQLite Token Adapter inicializado correctamente');
|
|
29
|
+
|
|
30
|
+
// Crear instancia del autenticador
|
|
31
|
+
const authenticator = new Authenticator({ logger });
|
|
32
|
+
|
|
33
|
+
// Registrar estrategia de autenticación JWT que utiliza el adaptador SQLite
|
|
34
|
+
authenticator.use('jwt-sqlite', async (req, options = {}) => {
|
|
35
|
+
const authHeader = req.headers.authorization;
|
|
36
|
+
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|
37
|
+
|
|
38
|
+
if (!token) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Validar el token contra la base de datos SQLite
|
|
43
|
+
const tokenRecord = await tokenAdapter.validateToken(token);
|
|
44
|
+
|
|
45
|
+
if (tokenRecord) {
|
|
46
|
+
// Agregar información del usuario a la solicitud
|
|
47
|
+
req.user = { userId: tokenRecord.user_id, tokenType: tokenRecord.token_type };
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return false;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
|
|
55
|
+
server.authenticator = authenticator;
|
|
56
|
+
|
|
57
|
+
// Cargar rutas desde archivo JSON
|
|
58
|
+
const routeLoader = new RouteLoader();
|
|
59
|
+
await routeLoader.loadRoutes(server, './routes.json');
|
|
60
|
+
|
|
61
|
+
// Iniciar el servidor
|
|
62
|
+
server.start();
|
|
63
|
+
|
|
64
|
+
logger.info('Servidor iniciado en http://localhost:8088');
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error('Error iniciando el servidor:', error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Iniciar el servidor
|
|
72
|
+
startServer();
|
|
73
|
+
|
|
74
|
+
module.exports = { startServer };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const {
|
|
2
|
+
APIServer,
|
|
3
|
+
Authenticator,
|
|
4
|
+
RouteLoader,
|
|
5
|
+
Logger,
|
|
6
|
+
SQLiteTokenAdapter
|
|
7
|
+
} = require('../../index.js');
|
|
8
|
+
|
|
9
|
+
async function startServer() {
|
|
10
|
+
// Crear instancia del servidor
|
|
11
|
+
const server = new APIServer({
|
|
12
|
+
port: 8088,
|
|
13
|
+
host: 'localhost'
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Crear instancia del logger
|
|
17
|
+
const logger = new Logger({ level: 'info' });
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Crear instancia del adaptador de tokens SQLite
|
|
21
|
+
const tokenAdapter = new SQLiteTokenAdapter({
|
|
22
|
+
dbPath: './tokens_example.sqlite',
|
|
23
|
+
tableName: 'example_tokens'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Inicializar el adaptador de tokens
|
|
27
|
+
await tokenAdapter.initialize();
|
|
28
|
+
logger.info('SQLite Token Adapter inicializado correctamente');
|
|
29
|
+
|
|
30
|
+
// Crear instancia del autenticador
|
|
31
|
+
const authenticator = new Authenticator({ logger });
|
|
32
|
+
|
|
33
|
+
// Registrar estrategia de autenticación JWT que utiliza el adaptador SQLite
|
|
34
|
+
authenticator.use('jwt-sqlite', async (req, options = {}) => {
|
|
35
|
+
const authHeader = req.headers.authorization;
|
|
36
|
+
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|
37
|
+
|
|
38
|
+
if (!token) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Validar el token contra la base de datos SQLite
|
|
43
|
+
const tokenRecord = await tokenAdapter.validateToken(token);
|
|
44
|
+
|
|
45
|
+
if (tokenRecord) {
|
|
46
|
+
// Agregar información del usuario a la solicitud
|
|
47
|
+
req.user = { userId: tokenRecord.user_id, tokenType: tokenRecord.token_type };
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return false;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
|
|
55
|
+
server.authenticator = authenticator;
|
|
56
|
+
|
|
57
|
+
// Cargar rutas desde archivo JSON
|
|
58
|
+
const routeLoader = new RouteLoader();
|
|
59
|
+
await routeLoader.loadRoutes(server, './routes.json');
|
|
60
|
+
|
|
61
|
+
// Iniciar el servidor
|
|
62
|
+
server.start();
|
|
63
|
+
|
|
64
|
+
logger.info('Servidor iniciado en http://localhost:8088');
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error('Error iniciando el servidor:', error.message);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Iniciar el servidor
|
|
72
|
+
startServer();
|
|
73
|
+
|
|
74
|
+
module.exports = { startServer };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
2
|
+
const { SQLiteTokenAdapter } = require('../../../index.js');
|
|
3
|
+
|
|
4
|
+
// Adaptador de tokens para este controlador
|
|
5
|
+
const tokenAdapter = new SQLiteTokenAdapter({
|
|
6
|
+
dbPath: './tokens_example.sqlite',
|
|
7
|
+
tableName: 'example_tokens'
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// Asegurarse de que el adaptador esté inicializado
|
|
11
|
+
tokenAdapter.initialize().catch(console.error);
|
|
12
|
+
|
|
13
|
+
const authController = {
|
|
14
|
+
login: async (req, res) => {
|
|
15
|
+
try {
|
|
16
|
+
const { username, password } = req.body;
|
|
17
|
+
|
|
18
|
+
// Validación simple de credenciales (esto debería ser más robusto en producción)
|
|
19
|
+
if (!username || !password) {
|
|
20
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
21
|
+
res.end(JSON.stringify({ error: 'Nombre de usuario y contraseña requeridos' }));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Simulación de autenticación (en una aplicación real, esto verificaría contra una base de datos)
|
|
26
|
+
if (username === 'admin' && password === 'password') {
|
|
27
|
+
// Generar un token JWT
|
|
28
|
+
const payload = {
|
|
29
|
+
userId: 1,
|
|
30
|
+
username: username,
|
|
31
|
+
role: 'admin'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Secret para firmar el token (en producción, debería estar en variables de entorno)
|
|
35
|
+
const secret = 'super-secret-key-for-example';
|
|
36
|
+
const token = jwt.sign(payload, secret, { expiresIn: '1h' });
|
|
37
|
+
|
|
38
|
+
// Guardar el token en la base de datos SQLite
|
|
39
|
+
await tokenAdapter.saveToken(
|
|
40
|
+
token,
|
|
41
|
+
{ userId: 1 },
|
|
42
|
+
'access',
|
|
43
|
+
new Date(Date.now() + 60 * 60 * 1000) // 1 hora
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
47
|
+
res.end(JSON.stringify({
|
|
48
|
+
message: 'Inicio de sesión exitoso',
|
|
49
|
+
token: token,
|
|
50
|
+
user: payload
|
|
51
|
+
}));
|
|
52
|
+
} else {
|
|
53
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
54
|
+
res.end(JSON.stringify({ error: 'Credenciales inválidas' }));
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Error en login:', error);
|
|
58
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
59
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
module.exports = authController;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const jwt = require('jsonwebtoken');
|
|
2
|
+
const { SQLiteTokenAdapter } = require('../../../index.js');
|
|
3
|
+
|
|
4
|
+
// Adaptador de tokens para este controlador
|
|
5
|
+
const tokenAdapter = new SQLiteTokenAdapter({
|
|
6
|
+
dbPath: './tokens_example.sqlite',
|
|
7
|
+
tableName: 'example_tokens'
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const mainController = {
|
|
11
|
+
home: (req, res) => {
|
|
12
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
13
|
+
res.end(JSON.stringify({
|
|
14
|
+
message: 'Bienvenido a la API de ejemplo con autenticación SQLite',
|
|
15
|
+
endpoints: {
|
|
16
|
+
'POST /login': 'Iniciar sesión y obtener token',
|
|
17
|
+
'GET /protected': 'Contenido protegido (requiere token)',
|
|
18
|
+
'GET /profile': 'Perfil de usuario (requiere token)'
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
module.exports = mainController;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const protectedController = {
|
|
2
|
+
getProtectedData: (req, res) => {
|
|
3
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4
|
+
res.end(JSON.stringify({
|
|
5
|
+
message: 'Datos protegidos accesados exitosamente',
|
|
6
|
+
user: req.user,
|
|
7
|
+
timestamp: new Date().toISOString()
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports = protectedController;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const userController = {
|
|
2
|
+
getProfile: (req, res) => {
|
|
3
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
4
|
+
res.end(JSON.stringify({
|
|
5
|
+
profile: {
|
|
6
|
+
id: req.user.userId,
|
|
7
|
+
username: req.user.username || 'Usuario',
|
|
8
|
+
role: req.user.role || 'guest',
|
|
9
|
+
tokenType: req.user.tokenType
|
|
10
|
+
},
|
|
11
|
+
message: 'Perfil de usuario obtenido exitosamente'
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = userController;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "api-sdk-example-v2",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Ejemplo de API con autenticación SQLite usando el Framework API SDK",
|
|
5
|
+
"main": "app.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node app.js",
|
|
8
|
+
"dev": "nodemon app.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"api",
|
|
12
|
+
"sdk",
|
|
13
|
+
"authentication",
|
|
14
|
+
"sqlite",
|
|
15
|
+
"jwt",
|
|
16
|
+
"framework"
|
|
17
|
+
],
|
|
18
|
+
"author": "API SDK Framework",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"jsonwebtoken": "^9.0.0",
|
|
22
|
+
"sqlite3": "^5.1.6"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"nodemon": "^3.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "/",
|
|
4
|
+
"method": "GET",
|
|
5
|
+
"controller": "./controllers/mainController.js",
|
|
6
|
+
"handler": "home",
|
|
7
|
+
"auth": "none"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"path": "/login",
|
|
11
|
+
"method": "POST",
|
|
12
|
+
"controller": "./controllers/authController.js",
|
|
13
|
+
"handler": "login",
|
|
14
|
+
"auth": "none"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "/protected",
|
|
18
|
+
"method": "GET",
|
|
19
|
+
"controller": "./controllers/protectedController.js",
|
|
20
|
+
"handler": "getProtectedData",
|
|
21
|
+
"auth": "jwt-sqlite"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "/profile",
|
|
25
|
+
"method": "GET",
|
|
26
|
+
"controller": "./controllers/userController.js",
|
|
27
|
+
"handler": "getProfile",
|
|
28
|
+
"auth": "jwt-sqlite"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "Iniciando prueba de la API con autenticación SQLite..."
|
|
4
|
+
|
|
5
|
+
# Iniciar el servidor en segundo plano
|
|
6
|
+
node app.js &
|
|
7
|
+
SERVER_PID=$!
|
|
8
|
+
|
|
9
|
+
# Esperar a que el servidor inicie
|
|
10
|
+
sleep 3
|
|
11
|
+
|
|
12
|
+
echo "Probando endpoints..."
|
|
13
|
+
|
|
14
|
+
# Probar endpoint público
|
|
15
|
+
echo "1. Probando endpoint público (/)"
|
|
16
|
+
curl -s -w "\n%{http_code}\n" -X GET http://localhost:8088/
|
|
17
|
+
|
|
18
|
+
# Probar login
|
|
19
|
+
echo -e "\n2. Probando login..."
|
|
20
|
+
TOKEN=$(curl -s -X POST http://localhost:8088/login \
|
|
21
|
+
-H "Content-Type: application/json" \
|
|
22
|
+
-d '{"username": "admin", "password": "password"}' | jq -r '.token')
|
|
23
|
+
|
|
24
|
+
if [ "$TOKEN" != "null" ] && [ -n "$TOKEN" ]; then
|
|
25
|
+
echo "Login exitoso, token obtenido: ${TOKEN:0:20}..."
|
|
26
|
+
|
|
27
|
+
# Probar endpoint protegido con token
|
|
28
|
+
echo -e "\n3. Probando endpoint protegido (/protected) con token..."
|
|
29
|
+
curl -s -w "\n%{http_code}\n" -X GET http://localhost:8088/protected \
|
|
30
|
+
-H "Authorization: Bearer $TOKEN"
|
|
31
|
+
|
|
32
|
+
# Probar endpoint de perfil con token
|
|
33
|
+
echo -e "\n4. Probando endpoint de perfil (/profile) con token..."
|
|
34
|
+
curl -s -w "\n%{http_code}\n" -X GET http://localhost:8088/profile \
|
|
35
|
+
-H "Authorization: Bearer $TOKEN"
|
|
36
|
+
else
|
|
37
|
+
echo "Error: No se pudo obtener el token de login"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Probar endpoint protegido sin token (debería fallar)
|
|
41
|
+
echo -e "\n5. Probando endpoint protegido (/protected) sin token (debería fallar)..."
|
|
42
|
+
curl -s -w "\n%{http_code}\n" -X GET http://localhost:8088/protected
|
|
43
|
+
|
|
44
|
+
echo -e "\nPrueba completada."
|
|
45
|
+
|
|
46
|
+
# Detener el servidor
|
|
47
|
+
kill $SERVER_PID
|
|
Binary file
|