jerkjs 2.0.1 → 2.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.
Files changed (131) hide show
  1. package/README.md +4 -6
  2. package/docs/EXTENSION_MANUAL.md +955 -0
  3. package/docs/FIREWALL_MANUAL.md +416 -0
  4. package/docs/HOOKS_REFERENCE_IMPROVED.md +596 -0
  5. package/docs/MANUAL_API_SDK.md +536 -0
  6. package/docs/MARIADB_TOKENS_IMPLEMENTATION.md +110 -0
  7. package/docs/MIDDLEWARE_MANUAL.md +518 -0
  8. package/docs/OAUTH2_GOOGLE_MANUAL.md +405 -0
  9. package/docs/frontend-and-sessions.md +6 -6
  10. package/examples/advanced/controllers/productController.js +64 -0
  11. package/examples/advanced/controllers/userController.js +85 -0
  12. package/examples/advanced/routes.json +51 -0
  13. package/examples/advanced_example.js +93 -0
  14. package/examples/basic/controllers/userController.js +85 -0
  15. package/examples/basic_example.js +72 -0
  16. package/examples/mvc_example/app.js +138 -0
  17. package/examples/mvc_example/views/home/index.html +26 -0
  18. package/examples/mvc_example/views/home/simple.html +3 -0
  19. package/examples/mvc_example/views/layout.html +23 -0
  20. package/examples/mvc_example/views/test.html +3 -0
  21. package/examples/mvc_example/views/user/invalid.html +6 -0
  22. package/examples/mvc_example/views/user/list.html +36 -0
  23. package/examples/mvc_example/views/user/notfound.html +6 -0
  24. package/examples/mvc_example/views/user/profile.html +11 -0
  25. package/examples/mvc_routes_example/app.js +34 -0
  26. package/examples/mvc_routes_example/controllers/mainController.js +27 -0
  27. package/examples/mvc_routes_example/controllers/productController.js +47 -0
  28. package/examples/mvc_routes_example/controllers/userController.js +76 -0
  29. package/examples/mvc_routes_example/routes.json +30 -0
  30. package/examples/mvc_routes_example/views/layout.html +31 -0
  31. package/examples/mvc_routes_example/views/main/index.html +11 -0
  32. package/examples/mvc_routes_example/views/product/catalog.html +24 -0
  33. package/examples/mvc_routes_example/views/user/invalid.html +6 -0
  34. package/examples/mvc_routes_example/views/user/list.html +40 -0
  35. package/examples/mvc_routes_example/views/user/notfound.html +6 -0
  36. package/examples/mvc_routes_example/views/user/profile.html +18 -0
  37. package/examples/mvc_welcome/README.md +34 -0
  38. package/examples/mvc_welcome/app.js +50 -0
  39. package/examples/mvc_welcome/controllers/welcomeController.js +41 -0
  40. package/examples/mvc_welcome/package.json +26 -0
  41. package/examples/mvc_welcome/views/home/welcome.html +82 -0
  42. package/examples/v2/README.md +72 -0
  43. package/examples/v2/app.js +74 -0
  44. package/examples/v2/app_fixed.js +74 -0
  45. package/examples/v2/controllers/authController.js +64 -0
  46. package/examples/v2/controllers/mainController.js +24 -0
  47. package/examples/v2/controllers/protectedController.js +12 -0
  48. package/examples/v2/controllers/userController.js +16 -0
  49. package/examples/v2/package.json +27 -0
  50. package/examples/v2/routes.json +30 -0
  51. package/examples/v2/test_api.sh +47 -0
  52. package/examples/v2/tokens_example.sqlite +0 -0
  53. package/examples/v2.1_firewall_demo/README.md +113 -0
  54. package/examples/v2.1_firewall_demo/app.js +182 -0
  55. package/examples/v2.1_firewall_demo/package.json +27 -0
  56. package/examples/v2.1_hooks_demo/README.md +85 -0
  57. package/examples/v2.1_hooks_demo/app.js +101 -0
  58. package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
  59. package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
  60. package/examples/v2.1_hooks_demo/package.json +27 -0
  61. package/examples/v2.1_hooks_demo/routes.json +16 -0
  62. package/examples/v2.1_openapi_demo/README.md +82 -0
  63. package/examples/v2.1_openapi_demo/app.js +296 -0
  64. package/examples/v2.1_openapi_demo/package.json +26 -0
  65. package/examples/v2_cors/README.md +82 -0
  66. package/examples/v2_cors/app.js +108 -0
  67. package/examples/v2_cors/package.json +23 -0
  68. package/examples/v2_json_auth/README.md +83 -0
  69. package/examples/v2_json_auth/app.js +72 -0
  70. package/examples/v2_json_auth/controllers/authController.js +67 -0
  71. package/examples/v2_json_auth/controllers/mainController.js +16 -0
  72. package/examples/v2_json_auth/controllers/protectedController.js +12 -0
  73. package/examples/v2_json_auth/controllers/tokenController.js +28 -0
  74. package/examples/v2_json_auth/controllers/userController.js +15 -0
  75. package/examples/v2_json_auth/package.json +26 -0
  76. package/examples/v2_json_auth/routes.json +37 -0
  77. package/examples/v2_json_auth/tokens.json +20 -0
  78. package/examples/v2_mariadb_auth/README.md +94 -0
  79. package/examples/v2_mariadb_auth/app.js +81 -0
  80. package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
  81. package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
  82. package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
  83. package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
  84. package/examples/v2_mariadb_auth/package.json +27 -0
  85. package/examples/v2_mariadb_auth/routes.json +37 -0
  86. package/examples/v2_no_auth/README.md +75 -0
  87. package/examples/v2_no_auth/app.js +72 -0
  88. package/examples/v2_no_auth/controllers/healthController.js +14 -0
  89. package/examples/v2_no_auth/controllers/mainController.js +19 -0
  90. package/examples/v2_no_auth/controllers/productController.js +31 -0
  91. package/examples/v2_no_auth/controllers/publicController.js +16 -0
  92. package/examples/v2_no_auth/package.json +22 -0
  93. package/examples/v2_no_auth/routes.json +37 -0
  94. package/examples/v2_oauth/README.md +70 -0
  95. package/examples/v2_oauth/app.js +90 -0
  96. package/examples/v2_oauth/controllers/mainController.js +45 -0
  97. package/examples/v2_oauth/controllers/oauthController.js +247 -0
  98. package/examples/v2_oauth/controllers/protectedController.js +13 -0
  99. package/examples/v2_oauth/controllers/userController.js +17 -0
  100. package/examples/v2_oauth/package.json +26 -0
  101. package/examples/v2_oauth/routes.json +44 -0
  102. package/examples/v2_openapi/README.md +77 -0
  103. package/examples/v2_openapi/app.js +222 -0
  104. package/examples/v2_openapi/controllers/authController.js +52 -0
  105. package/examples/v2_openapi/controllers/mainController.js +26 -0
  106. package/examples/v2_openapi/controllers/productController.js +17 -0
  107. package/examples/v2_openapi/controllers/userController.js +27 -0
  108. package/examples/v2_openapi/package.json +26 -0
  109. package/examples/v2_openapi/routes.json +37 -0
  110. package/index.js +11 -3
  111. package/lib/core/handler.js +1 -1
  112. package/lib/core/hooks.js +1 -1
  113. package/lib/core/router.js +1 -1
  114. package/lib/core/server.js +1 -1
  115. package/lib/loader/controllerLoader.js +1 -1
  116. package/lib/loader/routeLoader.js +1 -1
  117. package/lib/middleware/auditLogger.js +1 -1
  118. package/lib/middleware/authenticator.js +1 -1
  119. package/lib/middleware/compressor.js +1 -1
  120. package/lib/middleware/cors.js +1 -1
  121. package/lib/middleware/firewall.js +1 -1
  122. package/lib/middleware/rateLimiter.js +1 -1
  123. package/lib/middleware/session.js +1 -1
  124. package/lib/middleware/validator.js +1 -1
  125. package/lib/mvc/controllerBase.js +207 -0
  126. package/lib/mvc/viewEngine.js +752 -0
  127. package/lib/utils/configParser.js +1 -1
  128. package/lib/utils/logger.js +1 -1
  129. package/lib/utils/openapiGenerator.js +1 -1
  130. package/lib/utils/tokenManager.js +1 -1
  131. package/package.json +1 -1
@@ -0,0 +1,37 @@
1
+ [
2
+ {
3
+ "path": "/",
4
+ "method": "GET",
5
+ "controller": "./controllers/mainController.js",
6
+ "handler": "home",
7
+ "auth": "none"
8
+ },
9
+ {
10
+ "path": "/public",
11
+ "method": "GET",
12
+ "controller": "./controllers/publicController.js",
13
+ "handler": "getPublicData",
14
+ "auth": "none"
15
+ },
16
+ {
17
+ "path": "/products",
18
+ "method": "GET",
19
+ "controller": "./controllers/productController.js",
20
+ "handler": "getAllProducts",
21
+ "auth": "none"
22
+ },
23
+ {
24
+ "path": "/products/:id",
25
+ "method": "GET",
26
+ "controller": "./controllers/productController.js",
27
+ "handler": "getProductById",
28
+ "auth": "none"
29
+ },
30
+ {
31
+ "path": "/health",
32
+ "method": "GET",
33
+ "controller": "./controllers/healthController.js",
34
+ "handler": "getStatus",
35
+ "auth": "none"
36
+ }
37
+ ]
@@ -0,0 +1,70 @@
1
+ # Ejemplo API con Funcionalidad OAuth 2.0
2
+
3
+ Este ejemplo demuestra cómo implementar autenticación OAuth 2.0 usando el Framework JERK.
4
+
5
+ ## Características
6
+
7
+ - Implementación de flujo OAuth 2.0 (simulado para demostración)
8
+ - Generación de tokens JWT tras autenticación OAuth
9
+ - Rutas protegidas que requieren tokens JWT
10
+ - Simulación del proceso de autorización y callback
11
+ - Controladores organizados por funcionalidad
12
+
13
+ ## Configuración
14
+
15
+ Este ejemplo simula el flujo OAuth para fines de demostración. En un entorno real, necesitarías:
16
+
17
+ 1. Registrar tu aplicación con un proveedor OAuth (Google, GitHub, etc.)
18
+ 2. Obtener Client ID y Client Secret
19
+ 3. Configurar la URL de callback en tu aplicación
20
+ 4. Ajustar las rutas y controladores según tus necesidades
21
+
22
+ ## Uso
23
+
24
+ 1. Inicia el servidor:
25
+ ```bash
26
+ node app.js
27
+ ```
28
+
29
+ 2. El servidor escuchará en `http://localhost:8093`
30
+
31
+ ## Endpoints
32
+
33
+ - `GET /` - Página de inicio con instrucciones
34
+ - `GET /auth/google` - Iniciar flujo OAuth con Google (simulado)
35
+ - `GET /auth/callback` - Callback de OAuth (simulado)
36
+ - `GET /profile` - Perfil de usuario (requiere token JWT)
37
+ - `GET /protected` - Contenido protegido (requiere token JWT)
38
+
39
+ ## Flujo de OAuth simulado
40
+
41
+ 1. Visita `/auth/google` para iniciar el proceso OAuth
42
+ 2. El sistema simulará la redirección a Google y el callback
43
+ 3. Se generará un token JWT para el usuario autenticado
44
+ 4. Usa el token para acceder a endpoints protegidos
45
+
46
+ ## Estructura del proyecto
47
+
48
+ ```
49
+ examples/v2_oauth/
50
+ ├── app.js # Punto de entrada de la aplicación
51
+ ├── routes.json # Definición de rutas
52
+ ├── controllers/ # Controladores de las rutas
53
+ │ ├── mainController.js
54
+ │ ├── oauthController.js
55
+ │ ├── userController.js
56
+ │ └── protectedController.js
57
+ └── README.md
58
+ ```
59
+
60
+ ## Implementación real
61
+
62
+ Para implementar OAuth en un entorno real:
63
+
64
+ 1. Registra tu aplicación con un proveedor OAuth
65
+ 2. Configura las credenciales en el código
66
+ 3. Implementa la lógica para intercambiar el código de autorización por tokens
67
+ 4. Almacena de forma segura los tokens de acceso y refresh
68
+ 5. Usa los tokens para acceder a las APIs del proveedor
69
+
70
+ El framework proporciona la estrategia `oauth2Strategy` que puedes usar con tus credenciales reales.
@@ -0,0 +1,90 @@
1
+ const {
2
+ APIServer,
3
+ Authenticator,
4
+ RouteLoader,
5
+ Logger,
6
+ TokenManager
7
+ } = require('../../index.js');
8
+
9
+ async function startServer() {
10
+ // Crear instancia del servidor
11
+ const server = new APIServer({
12
+ port: 8093,
13
+ host: 'localhost'
14
+ });
15
+
16
+ // Crear instancia del logger
17
+ const logger = new Logger({ level: 'info' });
18
+
19
+ try {
20
+ // Crear instancia del TokenManager
21
+ const tokenManager = new TokenManager({
22
+ storage: 'memory'
23
+ });
24
+
25
+ // Crear instancia del autenticador
26
+ const authenticator = new Authenticator({ logger });
27
+
28
+ // Registrar estrategia de autenticación OAuth2 REAL del framework
29
+ // Esta es la verdadera implementación del framework
30
+ authenticator.use('oauth2', authenticator.oauth2Strategy({
31
+ clientId: process.env.OAUTH_CLIENT_ID || 'tu-client-id-aqui',
32
+ clientSecret: process.env.OAUTH_CLIENT_SECRET || 'tu-client-secret-aqui',
33
+ callbackURL: 'http://localhost:8093/auth/callback',
34
+ authorizationURL: 'https://accounts.google.com/o/oauth2/v2/auth',
35
+ tokenURL: 'https://oauth2.googleapis.com/token'
36
+ }));
37
+
38
+ // Registrar estrategia JWT para tokens generados internamente
39
+ authenticator.use('jwt-oauth', async (req, options = {}) => {
40
+ const authHeader = req.headers.authorization;
41
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
42
+
43
+ if (!token) {
44
+ return false;
45
+ }
46
+
47
+ // Validar el token usando el secreto de las variables de entorno
48
+ const secret = process.env.JWT_SECRET;
49
+
50
+ // Verificar que el secreto esté definido
51
+ if (!secret) {
52
+ logger.error('JWT_SECRET no está definido en las variables de entorno');
53
+ return false;
54
+ }
55
+
56
+ const decoded = tokenManager.validateToken(token, secret);
57
+
58
+ if (decoded) {
59
+ req.user = decoded;
60
+ return true;
61
+ }
62
+
63
+ return false;
64
+ });
65
+
66
+ // Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
67
+ server.authenticator = authenticator;
68
+
69
+ // Cargar rutas desde archivo JSON
70
+ const routeLoader = new RouteLoader();
71
+ await routeLoader.loadRoutes(server, './routes.json');
72
+
73
+ // Iniciar el servidor
74
+ server.start();
75
+
76
+ logger.info('Servidor iniciado en http://localhost:8093');
77
+ logger.info('Configura tus credenciales OAuth para usar la autenticación real');
78
+ logger.info('Variables de entorno necesarias:');
79
+ logger.info('- OAUTH_CLIENT_ID: Tu Client ID de Google OAuth');
80
+ logger.info('- OAUTH_CLIENT_SECRET: Tu Client Secret de Google OAuth');
81
+ } catch (error) {
82
+ logger.error('Error iniciando el servidor:', error.message);
83
+ process.exit(1);
84
+ }
85
+ }
86
+
87
+ // Iniciar el servidor
88
+ startServer();
89
+
90
+ module.exports = { startServer };
@@ -0,0 +1,45 @@
1
+ const mainController = {
2
+ home: (req, res) => {
3
+ res.writeHead(200, { 'Content-Type': 'text/html' });
4
+ res.end(`
5
+ <!DOCTYPE html>
6
+ <html>
7
+ <head>
8
+ <title>Ejemplo OAuth con JERK Framework</title>
9
+ <style>
10
+ body { font-family: Arial, sans-serif; margin: 40px; }
11
+ .endpoint { margin: 10px 0; padding: 10px; background-color: #f0f0f0; border-radius: 5px; }
12
+ a { color: #007bff; text-decoration: none; }
13
+ a:hover { text-decoration: underline; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <h1>Ejemplo OAuth con JERK Framework</h1>
18
+ <p>Este ejemplo demuestra la funcionalidad OAuth 2.0 del framework.</p>
19
+
20
+ <h2>Endpoints disponibles:</h2>
21
+ <div class="endpoint">
22
+ <strong><a href="/auth/google">GET /auth/google</a></strong> - Iniciar flujo OAuth con Google
23
+ </div>
24
+ <div class="endpoint">
25
+ <strong><a href="/profile">GET /profile</a></strong> - Perfil de usuario (requiere token JWT)
26
+ </div>
27
+ <div class="endpoint">
28
+ <strong><a href="/protected">GET /protected</a></strong> - Contenido protegido (requiere token JWT)
29
+ </div>
30
+
31
+ <h2>Instrucciones:</h2>
32
+ <ol>
33
+ <li>Visita <a href="/auth/google">/auth/google</a> para iniciar el flujo OAuth</li>
34
+ <li>El callback OAuth manejará la autenticación y generará un token JWT</li>
35
+ <li>Usa el token generado para acceder a los endpoints protegidos</li>
36
+ </ol>
37
+
38
+ <p><em>Nota: Este es un ejemplo funcional. En un entorno real, necesitarías configurar credenciales reales de OAuth con un proveedor como Google, GitHub, etc.</em></p>
39
+ </body>
40
+ </html>
41
+ `);
42
+ }
43
+ };
44
+
45
+ module.exports = mainController;
@@ -0,0 +1,247 @@
1
+ const jwt = require('jsonwebtoken');
2
+ const { Authenticator, TokenManager } = require('../../../index.js');
3
+
4
+ // TokenManager para este controlador
5
+ const tokenManager = new TokenManager({
6
+ storage: 'memory'
7
+ });
8
+
9
+ const oauthController = {
10
+ initiateGoogleAuth: (req, res) => {
11
+ // Obtener las credenciales de OAuth
12
+ const clientId = process.env.OAUTH_CLIENT_ID;
13
+ const clientSecret = process.env.OAUTH_CLIENT_SECRET;
14
+
15
+ // Verificar si las credenciales están configuradas
16
+ if (!clientId || clientId === 'tu-client-id-aqui' || !clientSecret || clientSecret === 'tu-client-secret-aqui') {
17
+ res.writeHead(200, { 'Content-Type': 'text/html' });
18
+ res.end(`
19
+ <!DOCTYPE html>
20
+ <html>
21
+ <head>
22
+ <title>Configurar OAuth con Google</title>
23
+ <style>
24
+ body { font-family: Arial, sans-serif; margin: 40px; text-align: center; }
25
+ .container { max-width: 800px; margin: 0 auto; }
26
+ .setup-instructions {
27
+ margin: 20px 0;
28
+ padding: 20px;
29
+ background-color: #fff3cd;
30
+ border: 1px solid #ffeaa7;
31
+ border-radius: 4px;
32
+ text-align: left;
33
+ }
34
+ .credentials-form {
35
+ margin: 20px 0;
36
+ padding: 20px;
37
+ background-color: #f8f9fa;
38
+ border: 1px solid #dee2e6;
39
+ border-radius: 4px;
40
+ }
41
+ input[type="text"], input[type="password"] {
42
+ width: 100%;
43
+ padding: 8px;
44
+ margin: 5px 0;
45
+ box-sizing: border-box;
46
+ }
47
+ button {
48
+ background-color: #007bff;
49
+ color: white;
50
+ border: none;
51
+ padding: 10px 20px;
52
+ cursor: pointer;
53
+ margin: 10px 5px;
54
+ }
55
+ button:hover {
56
+ background-color: #0056b3;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+ <div class="container">
62
+ <h1>Configurar OAuth con Google</h1>
63
+
64
+ <div class="setup-instructions">
65
+ <h3>Para usar la autenticación OAuth real:</h3>
66
+ <ol>
67
+ <li>Registra tu aplicación en <a href="https://console.cloud.google.com/" target="_blank">Google Cloud Console</a></li>
68
+ <li>Ve a "APIs & Services" > "Credentials"</li>
69
+ <li>Crea un "OAuth 2.0 Client IDs"</li>
70
+ <li>Configura "Authorized redirect URIs" con: <code>http://localhost:8093/auth/callback</code></li>
71
+ <li>Copia tu Client ID y Client Secret</li>
72
+ </ol>
73
+ </div>
74
+
75
+ <div class="credentials-form">
76
+ <h3>Ingresa tus credenciales OAuth</h3>
77
+ <form id="credentialsForm">
78
+ <label for="clientId">Client ID:</label>
79
+ <input type="text" id="clientId" name="clientId" placeholder="Ingresa tu Client ID">
80
+
81
+ <label for="clientSecret">Client Secret:</label>
82
+ <input type="password" id="clientSecret" name="clientSecret" placeholder="Ingresa tu Client Secret">
83
+
84
+ <div style="margin-top: 15px;">
85
+ <button type="submit">Guardar Credenciales</button>
86
+ <button type="button" onclick="location.href='/'">Volver al inicio</button>
87
+ </div>
88
+ </form>
89
+
90
+ <div id="statusMessage" style="margin-top: 15px; display: none;"></div>
91
+ </div>
92
+
93
+ <script>
94
+ document.getElementById('credentialsForm').addEventListener('submit', function(e) {
95
+ e.preventDefault();
96
+
97
+ const clientId = document.getElementById('clientId').value;
98
+ const clientSecret = document.getElementById('clientSecret').value;
99
+
100
+ // Enviar credenciales al servidor
101
+ fetch('/auth/setup', {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json'
105
+ },
106
+ body: JSON.stringify({ clientId, clientSecret })
107
+ })
108
+ .then(response => response.json())
109
+ .then(data => {
110
+ const statusDiv = document.getElementById('statusMessage');
111
+ statusDiv.style.display = 'block';
112
+
113
+ if (data.success) {
114
+ statusDiv.innerHTML = '<p style="color: green;">Credenciales guardadas exitosamente. <a href="/auth/google">Haz clic aquí para iniciar OAuth</a></p>';
115
+ document.getElementById('credentialsForm').reset();
116
+ } else {
117
+ statusDiv.innerHTML = '<p style="color: red;">Error: ' + data.message + '</p>';
118
+ }
119
+ })
120
+ .catch(error => {
121
+ console.error('Error:', error);
122
+ document.getElementById('statusMessage').innerHTML = '<p style="color: red;">Error al guardar credenciales</p>';
123
+ document.getElementById('statusMessage').style.display = 'block';
124
+ });
125
+ });
126
+ </script>
127
+ </div>
128
+ </body>
129
+ </html>
130
+ `);
131
+ return;
132
+ }
133
+
134
+ // Si las credenciales están configuradas, crear la URL de autorización OAuth
135
+ const redirectUri = encodeURIComponent('http://localhost:8093/auth/callback');
136
+ const scope = encodeURIComponent('email profile');
137
+ const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?` +
138
+ `client_id=${clientId}&` +
139
+ `redirect_uri=${redirectUri}&` +
140
+ `response_type=code&` +
141
+ `scope=${scope}&` +
142
+ `access_type=offline&` +
143
+ `prompt=consent`;
144
+
145
+ // Redirigir al usuario a la URL de autorización de Google
146
+ res.writeHead(302, { 'Location': authUrl });
147
+ res.end();
148
+ },
149
+
150
+ handleCallback: async (req, res) => {
151
+ const { code } = req.query;
152
+
153
+ if (!code) {
154
+ res.writeHead(400, { 'Content-Type': 'application/json' });
155
+ res.end(JSON.stringify({ error: 'No authorization code received' }));
156
+ return;
157
+ }
158
+
159
+ try {
160
+ // En una implementación real, intercambiaríamos el código por tokens de acceso
161
+ const clientId = process.env.OAUTH_CLIENT_ID;
162
+ const clientSecret = process.env.OAUTH_CLIENT_SECRET;
163
+ const redirectUri = 'http://localhost:8093/auth/callback';
164
+
165
+ // Simular la obtención de tokens (en una implementación real, haríamos una solicitud HTTP real)
166
+ // Aquí es donde el framework realmente haría el trabajo pesado
167
+
168
+ // Simular la obtención de información del usuario desde Google
169
+ // En una implementación real, usaríamos el access token para llamar a la API de Google
170
+ const userInfo = {
171
+ id: 'demo_user_id',
172
+ email: 'demo@example.com',
173
+ name: 'Demo User',
174
+ picture: 'https://via.placeholder.com/150'
175
+ };
176
+
177
+ // Generar un token JWT para el usuario autenticado
178
+ const secret = 'super-secret-key-for-oauth-example';
179
+ const tokenPayload = {
180
+ userId: userInfo.id,
181
+ email: userInfo.email,
182
+ name: userInfo.name,
183
+ provider: 'google',
184
+ iat: Math.floor(Date.now() / 1000),
185
+ exp: Math.floor(Date.now() / 1000) + (60 * 60) // Expira en 1 hora
186
+ };
187
+
188
+ const token = jwt.sign(tokenPayload, secret);
189
+
190
+ // Enviar respuesta con el token
191
+ res.writeHead(200, { 'Content-Type': 'text/html' });
192
+ res.end(`
193
+ <h2>¡Autenticación OAuth exitosa!</h2>
194
+ <p>Usuario autenticado: <strong>${userInfo.name}</strong></p>
195
+ <p>Email: <strong>${userInfo.email}</strong></p>
196
+ <p>Proveedor: <strong>Google</strong></p>
197
+
198
+ <div style="margin: 20px 0; padding: 15px; background-color: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;">
199
+ <p><strong>Token JWT generado:</strong></p>
200
+ <textarea readonly style="width: 100%; height: 80px; font-family: monospace;">${token}</textarea>
201
+ <p>Este token puede usarse en el header <code>Authorization: Bearer &lt;token&gt;</code> para acceder a endpoints protegidos</p>
202
+ </div>
203
+
204
+ <p><a href="/profile">Ir al perfil del usuario</a> | <a href="/">Volver a la página principal</a></p>
205
+ `);
206
+ } catch (error) {
207
+ console.error('Error en el callback OAuth:', error);
208
+ res.writeHead(500, { 'Content-Type': 'text/html' });
209
+ res.end(`
210
+ <h2>Error en el proceso de autenticación</h2>
211
+ <p>${error.message}</p>
212
+ <p><a href="/auth/google">Intentar de nuevo</a></p>
213
+ `);
214
+ }
215
+ },
216
+
217
+ setupCredentials: (req, res) => {
218
+ // Este endpoint es para fines de demostración
219
+ // En una implementación real, las credenciales se configurarían en variables de entorno
220
+ let body = '';
221
+ req.on('data', chunk => {
222
+ body += chunk.toString();
223
+ });
224
+ req.on('end', () => {
225
+ try {
226
+ const data = JSON.parse(body);
227
+
228
+ // En una implementación real, esto se haría de forma segura
229
+ // Aquí solo simulamos el proceso para fines de demostración
230
+
231
+ res.writeHead(200, { 'Content-Type': 'application/json' });
232
+ res.end(JSON.stringify({
233
+ success: true,
234
+ message: 'Credenciales recibidas. En una implementación real, estas se configurarían como variables de entorno.'
235
+ }));
236
+ } catch (error) {
237
+ res.writeHead(400, { 'Content-Type': 'application/json' });
238
+ res.end(JSON.stringify({
239
+ success: false,
240
+ message: 'Error al procesar las credenciales'
241
+ }));
242
+ }
243
+ });
244
+ }
245
+ };
246
+
247
+ module.exports = oauthController;
@@ -0,0 +1,13 @@
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
+ provider: 'Este contenido fue protegido usando autenticación JWT generada tras OAuth'
9
+ }));
10
+ }
11
+ };
12
+
13
+ module.exports = protectedController;
@@ -0,0 +1,17 @@
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
+ email: req.user.email,
8
+ name: req.user.name,
9
+ provider: req.user.provider,
10
+ authenticatedAt: new Date().toISOString()
11
+ },
12
+ message: 'Perfil de usuario obtenido exitosamente'
13
+ }));
14
+ }
15
+ };
16
+
17
+ module.exports = userController;
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "jerk-oauth-example",
3
+ "version": "1.0.0",
4
+ "description": "Ejemplo de API con funcionalidad OAuth 2.0 usando el Framework JERK",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "start": "node app.js",
8
+ "dev": "nodemon app.js"
9
+ },
10
+ "keywords": [
11
+ "api",
12
+ "sdk",
13
+ "oauth",
14
+ "oauth2",
15
+ "authentication",
16
+ "framework"
17
+ ],
18
+ "author": "JERK Framework",
19
+ "license": "MIT",
20
+ "dependencies": {
21
+ "jsonwebtoken": "^9.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "nodemon": "^3.0.0"
25
+ }
26
+ }
@@ -0,0 +1,44 @@
1
+ [
2
+ {
3
+ "path": "/",
4
+ "method": "GET",
5
+ "controller": "./controllers/mainController.js",
6
+ "handler": "home",
7
+ "auth": "none"
8
+ },
9
+ {
10
+ "path": "/auth/google",
11
+ "method": "GET",
12
+ "controller": "./controllers/oauthController.js",
13
+ "handler": "initiateGoogleAuth",
14
+ "auth": "none"
15
+ },
16
+ {
17
+ "path": "/auth/callback",
18
+ "method": "GET",
19
+ "controller": "./controllers/oauthController.js",
20
+ "handler": "handleCallback",
21
+ "auth": "none"
22
+ },
23
+ {
24
+ "path": "/auth/setup",
25
+ "method": "POST",
26
+ "controller": "./controllers/oauthController.js",
27
+ "handler": "setupCredentials",
28
+ "auth": "none"
29
+ },
30
+ {
31
+ "path": "/profile",
32
+ "method": "GET",
33
+ "controller": "./controllers/userController.js",
34
+ "handler": "getProfile",
35
+ "auth": "jwt-oauth"
36
+ },
37
+ {
38
+ "path": "/protected",
39
+ "method": "GET",
40
+ "controller": "./controllers/protectedController.js",
41
+ "handler": "getProtectedData",
42
+ "auth": "jwt-oauth"
43
+ }
44
+ ]
@@ -0,0 +1,77 @@
1
+ # Ejemplo API con Funcionalidad OpenAPI
2
+
3
+ Este ejemplo demuestra cómo crear una API con funcionalidad OpenAPI integrada utilizando el Framework JERK.
4
+
5
+ ## Características
6
+
7
+ - API con autenticación JWT
8
+ - Documentación OpenAPI 3.0 generada automáticamente
9
+ - Interfaz Swagger UI para explorar y probar la API
10
+ - Rutas protegidas y públicas
11
+ - Controladores organizados por funcionalidad
12
+ - Esquemas OpenAPI definidos para modelos de datos
13
+
14
+ ## Configuración
15
+
16
+ No se requieren dependencias adicionales más allá del Framework JERK.
17
+
18
+ ## Uso
19
+
20
+ 1. Inicia el servidor:
21
+ ```bash
22
+ node app.js
23
+ ```
24
+
25
+ 2. El servidor escuchará en `http://localhost:8092`
26
+
27
+ ## Endpoints
28
+
29
+ - `GET /` - Página de inicio
30
+ - `POST /login` - Iniciar sesión y obtener token
31
+ - `GET /users` - Lista de usuarios (requiere token)
32
+ - `GET /products` - Lista de productos (requiere token)
33
+ - `GET /profile` - Perfil de usuario (requiere token)
34
+ - `GET /docs` - Documentación interactiva OpenAPI/Swagger
35
+ - `GET /openapi.json` - Especificación OpenAPI
36
+
37
+ ## Ejemplo de uso
38
+
39
+ 1. Iniciar sesión:
40
+ ```bash
41
+ curl -X POST http://localhost:8092/login \
42
+ -H "Content-Type: application/json" \
43
+ -d '{"username": "admin", "password": "password"}'
44
+ ```
45
+
46
+ 2. Acceder a usuarios con el token:
47
+ ```bash
48
+ curl -X GET http://localhost:8092/users \
49
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
50
+ ```
51
+
52
+ 3. Ver documentación interactiva:
53
+ Visita `http://localhost:8092/docs` en tu navegador
54
+
55
+ ## Estructura del proyecto
56
+
57
+ ```
58
+ examples/v2_openapi/
59
+ ├── app.js # Punto de entrada de la aplicación
60
+ ├── routes.json # Definición de rutas
61
+ ├── controllers/ # Controladores de las rutas
62
+ │ ├── mainController.js
63
+ │ ├── authController.js
64
+ │ ├── userController.js
65
+ │ └── productController.js
66
+ └── README.md
67
+ ```
68
+
69
+ ## Documentación OpenAPI
70
+
71
+ El framework genera automáticamente:
72
+ - Una especificación OpenAPI 3.0 en `/openapi.json`
73
+ - Una interfaz Swagger UI interactiva en `/docs`
74
+ - Esquemas de datos definidos para reutilización
75
+ - Documentación detallada de endpoints, parámetros y respuestas
76
+ - Soporte para diferentes códigos de respuesta HTTP
77
+ - Definición de esquemas de seguridad