heimdall-api-platform 1.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -0
  3. package/lib/clients/http-client.js +296 -0
  4. package/lib/commons-cache.js +185 -0
  5. package/lib/commons-const.js +203 -0
  6. package/lib/commons-elasticsearch.js +49 -0
  7. package/lib/commons-errors.js +278 -0
  8. package/lib/commons-opensearch.js +37 -0
  9. package/lib/commons-splunk.js +105 -0
  10. package/lib/commons-util.js +669 -0
  11. package/lib/default-routes-docs.js +141 -0
  12. package/lib/default-routes-pos.js +111 -0
  13. package/lib/default-routes-pre.js +151 -0
  14. package/lib/environment.js +81 -0
  15. package/lib/factory/api-gateway.js +12 -0
  16. package/lib/factory/client-factory.js +41 -0
  17. package/lib/factory/function-factory.js +40 -0
  18. package/lib/factory/operation-flow-factory.js +64 -0
  19. package/lib/factory/server-factory.js +15 -0
  20. package/lib/factory/transformation-function-factory.js +47 -0
  21. package/lib/handle-route.js +472 -0
  22. package/lib/index.js +50 -0
  23. package/lib/jwt-util.js +38 -0
  24. package/lib/license/license-service.js +27 -0
  25. package/lib/models/base-context.js +77 -0
  26. package/lib/models/elastic-index-data.js +76 -0
  27. package/lib/models/flow-context.js +58 -0
  28. package/lib/models/flow-indexed.js +62 -0
  29. package/lib/models/operation-function-indexed.js +22 -0
  30. package/lib/models/operation-function-transformation-indexed.js +23 -0
  31. package/lib/models/operation-http-indexed.js +38 -0
  32. package/lib/models/operation-mock-indexed.js +22 -0
  33. package/lib/models/route-context.js +69 -0
  34. package/lib/models/security-route.js +41 -0
  35. package/lib/models/service-context.js +65 -0
  36. package/lib/models/service-group.js +15 -0
  37. package/lib/models/service-route.js +23 -0
  38. package/lib/models/splunk-data.js +70 -0
  39. package/lib/operations/abstract-operation.js +73 -0
  40. package/lib/operations/function.js +143 -0
  41. package/lib/operations/http.js +286 -0
  42. package/lib/operations/mock.js +34 -0
  43. package/lib/operations/monitor-check.js +151 -0
  44. package/lib/orchestration-flow.js +323 -0
  45. package/lib/public/redoc.html +152 -0
  46. package/lib/public/swagger.html +143 -0
  47. package/lib/router.js +29 -0
  48. package/lib/security-validation.js +46 -0
  49. package/lib/services/server.js +211 -0
  50. package/lib/services/template-monitorcheck-route.js +61 -0
  51. package/package.json +90 -0
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+
3
+ const Util = require("./commons-util");
4
+ const async = require("async");
5
+ const Step = require("step");
6
+ const errors = require("./commons-errors");
7
+ const Const = require("./commons-const");
8
+ const _ = require("underscore");
9
+ const Env = require("./environment").application;
10
+
11
+ class OrchestrationFlow {
12
+ constructor(redisClient) {
13
+ this.redisClient = redisClient;
14
+ }
15
+
16
+ execute(routeContext, mainCallback) {
17
+ let self = this;
18
+
19
+ routeContext.service.init();
20
+
21
+ async.mapSeries(
22
+ routeContext.service.flow,
23
+ (flowStep, callbackMapSeries) => {
24
+ //STEP 1 - VALIDATE CONDITION AND VALIDATION TO EXECUTE FLOW
25
+ flowStep.service = routeContext.service;
26
+
27
+ if (self.checkCondition(flowStep, routeContext) && self.checkValidation(flowStep, routeContext)) {
28
+ self.executeFlowStep(flowStep, routeContext, callbackMapSeries);
29
+ } else {
30
+ self.executeFlowFailed(flowStep, routeContext, callbackMapSeries);
31
+ }
32
+ },
33
+ () => {
34
+ routeContext.service.end();
35
+ mainCallback();
36
+ }
37
+ );
38
+ }
39
+
40
+ executeFlowFailed(flowStep, routeContext, callbackMapSeries) {
41
+ let self = this;
42
+
43
+ Util.info(
44
+ `stage=init method=OrchestrationFlow.executeFlowFailed Skip operation flow(${flowStep.operation.type.toUpperCase()}) name=${flowStep.operation.name
45
+ }`,
46
+ {
47
+ flowStepUuid: flowStep.uuid,
48
+ contextUuid: routeContext.uuid,
49
+ }
50
+ );
51
+
52
+ //Inicializa timers
53
+ flowStep.init();
54
+ routeContext.service.setCurrentFlow(flowStep);
55
+
56
+ flowStep.result = flowStep.condition.whenFail.result;
57
+ flowStep.statusCode = flowStep.condition.whenFail.statusCode;
58
+ flowStep.error = flowStep.condition.whenFail.error;
59
+
60
+ Step(
61
+ //STEP 4 - UPDATE MAIN CONTEXT
62
+ function () {
63
+ self.updateRouteContext(flowStep, routeContext, this);
64
+ },
65
+ //STEP 5 - SKIP ERROR?
66
+ function () {
67
+ flowStep.end();
68
+ callbackMapSeries(!flowStep.skipErrors && flowStep.error ? true : null);
69
+ }
70
+ );
71
+ }
72
+
73
+ executeFlowStep(flowStep, routeContext, callbackMapSeries) {
74
+ let self = this;
75
+
76
+ if (!flowStep.operation) {
77
+ callback(new errors.ApiGatewayError("An operation must be provided to execute the flow."));
78
+ } else {
79
+ //Inicializa timers
80
+ flowStep.init();
81
+ routeContext.service.setCurrentFlow(flowStep);
82
+
83
+ Step(
84
+ //STEP 1 - LOAD CACHE
85
+ function () {
86
+ self.getResponseFlowFromCache(flowStep, routeContext, this);
87
+ },
88
+ //STEP 2 - VALIDATE CACHE / EXECUTE FLOW
89
+ function (responseFlowCache) {
90
+ self.executeFlowOperation(responseFlowCache, flowStep, routeContext, this);
91
+ },
92
+ //STEP 4 - UPDATE MAIN CONTEXT
93
+ function () {
94
+ self.updateRouteContext(flowStep, routeContext, this);
95
+ },
96
+ //STEP 5 - SKIP ERROR?
97
+ function () {
98
+ flowStep.end();
99
+ callbackMapSeries(!flowStep.skipErrors && flowStep.error ? true : null);
100
+ }
101
+ );
102
+ }
103
+ }
104
+
105
+ executeFlowOperation(responseFlowCache, flowStep, routeContext, callbackStep) {
106
+ if (!responseFlowCache) {
107
+ flowStep.operation.execute(flowStep, routeContext, () => {
108
+ this.validateCache(flowStep, routeContext, callbackStep);
109
+ });
110
+ } else {
111
+ flowStep.statusCode = responseFlowCache.statusCode;
112
+ flowStep.setResult(Util.tryParseJSON(responseFlowCache.result));
113
+ callbackStep();
114
+ }
115
+ }
116
+
117
+ async getResponseFlowFromCache(flowStep, routeContext, callbackStep) {
118
+
119
+ let self = this;
120
+
121
+ if (this.redisClient.enableRedis && flowStep.cacheEnable) {
122
+
123
+ let cacheKey = self.generateCacheKey(flowStep, routeContext);
124
+
125
+ Util.info(
126
+ `stage=info method=OrchestrationFlow.getResponseFlowFromCache flow=${flowStep.operation.type.toUpperCase()} name=${flowStep.operation.name
127
+ } function=getResponseFlowFromCache cacheKey=${cacheKey}`
128
+ );
129
+
130
+ callbackStep(await this.redisClient.get(flowStep.cacheName || routeContext.service.name, cacheKey));
131
+
132
+ } else {
133
+ callbackStep(null);
134
+ }
135
+ }
136
+
137
+ async validateCache(flowStep, routeContext, callbackStep) {
138
+
139
+ if (!this.shouldCache(flowStep)) {
140
+ return callbackStep();
141
+ }
142
+
143
+ const cacheKey = this.generateCacheKey(flowStep, routeContext);
144
+ const cacheTtl = this.resolveCacheTtl(flowStep, routeContext, cacheKey);
145
+
146
+ Util.info(
147
+ `stage=info method=OrchestrationFlow.validateCache flow=${flowStep.operation.type.toUpperCase()} name=${flowStep.operation.name} cacheKey=${cacheKey} finalCacheTtl=${cacheTtl}`
148
+ );
149
+
150
+ await this.saveToCache(flowStep, routeContext, cacheKey, cacheTtl);
151
+
152
+ callbackStep();
153
+ }
154
+
155
+ shouldCache(flowStep) {
156
+ return this.redisClient?.enableRedis && flowStep?.cacheEnable && !flowStep?.error && flowStep.getResult();
157
+ }
158
+
159
+ resolveCacheTtl(flowStep, routeContext, cacheKey) {
160
+
161
+ let cacheTtl = flowStep.cacheTtl || 0;
162
+
163
+ try {
164
+ const cacheTtlExpression = this.generateCacheTTLExpression(flowStep, routeContext);
165
+ if (cacheTtlExpression) {
166
+ cacheTtl = cacheTtlExpression;
167
+ Util.info(
168
+ `stage=info method=OrchestrationFlow.resolveCacheTtl flow=${flowStep.operation.type.toUpperCase()} name=${flowStep.operation.name} cacheKey=${cacheKey} resolvedCacheTtl=${cacheTtl}`
169
+ );
170
+ } else {
171
+ Util.info(
172
+ `stage=info method=OrchestrationFlow.resolveCacheTtl flow=${flowStep.operation.type.toUpperCase()} name=${flowStep.operation.name} cacheKey=${cacheKey} message="No cacheTtlExpression found, using fallback cacheTtl=${cacheTtl}"`
173
+ );
174
+ }
175
+ } catch (error) {
176
+ Util.warn(
177
+ `stage=warn method=OrchestrationFlow.resolveCacheTtl flow=${flowStep.operation.type.toUpperCase()} name=${flowStep.operation.name} cacheKey=${cacheKey} message="Failed to evaluate cacheTtlExpression, falling back to cacheTtl=${cacheTtl}" error=${error.message}`
178
+ );
179
+ }
180
+
181
+ return cacheTtl;
182
+ }
183
+
184
+ async saveToCache(flowStep, routeContext, cacheKey, cacheTtl) {
185
+ await this.redisClient.put(
186
+ flowStep.cacheName || routeContext.service.name,
187
+ cacheKey,
188
+ {
189
+ result: flowStep.getResult(),
190
+ statusCode: flowStep.statusCode,
191
+ },
192
+ cacheTtl
193
+ );
194
+ }
195
+
196
+ getCompileContext(context) {
197
+ return _.extend(context, {
198
+ env: Env,
199
+ });
200
+ }
201
+
202
+ checkCondition(flowStep, routeContext) {
203
+ let { condition } = flowStep;
204
+
205
+ try {
206
+ return (
207
+ condition.compileExpression === true ||
208
+ _.template(condition.compileExpression)(this.getCompileContext(routeContext)) === "true"
209
+ );
210
+ } catch (error) {
211
+ Util.error(`stage=error method=OrchestrationFlow.checkCondition compile condition=${condition.compileExpression} error`, error);
212
+ return false;
213
+ }
214
+ }
215
+
216
+ checkValidation(flowStep, routeContext) {
217
+ let { validation } = flowStep;
218
+
219
+ try {
220
+ if (validation !== true && _.template(validation)(this.getCompileContext(routeContext)) !== "true") {
221
+ throw new errors.SecurityError("Unauthorized");
222
+ } else {
223
+ return true;
224
+ }
225
+ } catch (error) {
226
+ Util.error(`stage=error method=OrchestrationFlow.checkValidation compile condition=${validation} error`, error);
227
+ return false;
228
+ }
229
+ }
230
+
231
+ updateRouteContext(flowStep, routeContext, callbackStep) {
232
+ //FOR RESPONSE TO CLIENT USE THIS RESULT
233
+ if (flowStep.hasResult() || flowStep.resultVariable !== Const.OPERATION_RESULT_IS_ORCHESTRATION_RESULT) {
234
+ //Propagate Result Flow to Body for the Next Flow
235
+ if (flowStep.propagateResult) {
236
+ routeContext.setBody(flowStep.getResult());
237
+ }
238
+
239
+ //ADD ALL RESULTS TO SERVICE FOR HELP FLOWS
240
+ routeContext.service.addResult(flowStep.getResult());
241
+ routeContext.service.addHeaders(flowStep.responseHeaders);
242
+
243
+ if (flowStep.resultVariable === Const.OPERATION_RESULT_IS_ORCHESTRATION_RESULT) {
244
+ routeContext.setResult(flowStep.getResult());
245
+ } else {
246
+ routeContext.setResult(
247
+ Util.setValue(routeContext.getResult(), flowStep.resultVariable, flowStep.getResult())
248
+ );
249
+ }
250
+
251
+ routeContext.statusCode = flowStep.statusCode;
252
+ routeContext.error = flowStep.error;
253
+ }
254
+
255
+ callbackStep();
256
+ }
257
+
258
+ compileCacheKey(cacheKey, routeContext) {
259
+
260
+ try {
261
+ let contextData = {
262
+ ...routeContext,
263
+ queryHash: Util.generateQueryHash(routeContext.query),
264
+ result: typeof routeContext.getResult === "function" ? routeContext.getResult() : routeContext.result
265
+ };
266
+ let compiled = _.template(cacheKey);
267
+ return compiled(contextData);
268
+ } catch (error) {
269
+ Util.error(`stage=error method=OrchestrationFlow.compileCacheKey compile cacheKey=${cacheKey} error`, error);
270
+ return cacheKey;
271
+ }
272
+
273
+ }
274
+
275
+ generateCacheKey(flowStep, routeContext) {
276
+ let self = this;
277
+
278
+ if (flowStep.cacheKey) {
279
+ return self.compileCacheKey(flowStep.cacheKey, routeContext);
280
+ } else {
281
+ return self.getRequestDNA(routeContext);
282
+ }
283
+ }
284
+
285
+ generateCacheTTLExpression(flowStep, routeContext) {
286
+
287
+ let self = this;
288
+
289
+ if (flowStep.cacheTtlExpression) {
290
+ return self.compileCacheKey(flowStep.cacheTtlExpression, routeContext);
291
+ } else {
292
+ return 0;
293
+ }
294
+
295
+ }
296
+
297
+ getRequestDNA(routeContext) {
298
+ let body = JSON.stringify(Util.underscore().clone(routeContext.request.body || {}));
299
+
300
+ return Util.generateKey(
301
+ JSON.stringify({
302
+ url: {
303
+ protocol: routeContext.request.secure ? "https:" : "http:",
304
+ hostname: routeContext.request.hostname,
305
+ port: routeContext.request.connection.localPort,
306
+ path: routeContext.request.path,
307
+ },
308
+ socket: {
309
+ remoteAddress: routeContext.request.socket.remoteAddress,
310
+ encrypted: routeContext.request.secure,
311
+ },
312
+ httpVersion: routeContext.request.httpVersion,
313
+ method: routeContext.request.method,
314
+ body: body,
315
+ query: routeContext.query || {},
316
+ params: routeContext.params || {},
317
+ headers: routeContext.headers || {},
318
+ })
319
+ );
320
+ }
321
+ }
322
+
323
+ module.exports = OrchestrationFlow;
@@ -0,0 +1,152 @@
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <title>Documentação da API | Pay2B</title>
8
+
9
+ <link rel="icon" href="https://pay2b.com.br/favicon.ico" type="image/x-icon" />
10
+ <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
11
+
12
+ <style>
13
+ html,
14
+ body {
15
+ margin: 0;
16
+ padding: 0;
17
+ height: 100%;
18
+ font-family: "Segoe UI", Tahoma, sans-serif;
19
+ background-color: #f9fafc;
20
+ color: #333;
21
+ }
22
+
23
+ .navbar {
24
+ background-color: #1f2d3d;
25
+ color: #fff;
26
+ padding: 12px 24px;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: space-between;
30
+ }
31
+
32
+ .navbar__logo {
33
+ display: flex;
34
+ align-items: center;
35
+ }
36
+
37
+ .navbar__logo img {
38
+ height: 36px;
39
+ margin-right: 12px;
40
+ }
41
+
42
+ .navbar__title {
43
+ font-size: 18px;
44
+ font-weight: bold;
45
+ }
46
+
47
+ #redoc-container {
48
+ height: calc(100% - 120px);
49
+ /* espaço reservado para navbar e footer */
50
+ }
51
+
52
+ .pay2b-footer {
53
+ background-color: #1f2d3d;
54
+ color: #fff;
55
+ padding: 20px 40px;
56
+ font-size: 14px;
57
+ }
58
+
59
+ .footer__container {
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ flex-wrap: wrap;
64
+ }
65
+
66
+ .footer__left {
67
+ display: flex;
68
+ align-items: center;
69
+ }
70
+
71
+ .footer__logo {
72
+ height: 28px;
73
+ }
74
+
75
+ .footer__right {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ align-items: center;
79
+ gap: 12px;
80
+ font-weight: 400;
81
+ }
82
+
83
+ .footer__right a {
84
+ color: #fff;
85
+ text-decoration: none;
86
+ transition: opacity 0.2s;
87
+ }
88
+
89
+ .footer__right a:hover {
90
+ opacity: 0.75;
91
+ }
92
+
93
+ .sep {
94
+ color: #999;
95
+ }
96
+ </style>
97
+ </head>
98
+
99
+ <body>
100
+
101
+ <!-- Navbar -->
102
+ <div class="navbar">
103
+ <div class="navbar__logo">
104
+ <img src="https://cdn-email.s3.us-east-1.amazonaws.com/images/pay2b-logo-header.png" alt="Pay2B Logo" />
105
+ <span class="navbar__title">Documentação da API</span>
106
+ </div>
107
+ </div>
108
+
109
+ <!-- ReDoc container -->
110
+ <div id="redoc-container"></div>
111
+
112
+ <!-- Footer -->
113
+ <footer class="pay2b-footer">
114
+ <div class="footer__container">
115
+ <div class="footer__left">
116
+ <img src="https://cdn-email.s3.us-east-1.amazonaws.com/images/pay2b-logo-header.png" alt="Pay2B"
117
+ class="footer__logo" />
118
+ </div>
119
+ <div class="footer__right">
120
+ <a href="https://www.linkedin.com/company/pay2b" target="_blank" rel="noopener noreferrer">LinkedIn</a>
121
+ <span class="sep">|</span>
122
+ <a href="https://pay2b.com.br/termos" target="_blank">Termos e Condições</a>
123
+ <span class="sep">|</span>
124
+ <a href="https://www.pay2b.com.br/politica-de-privacidade" target="_blank">Política de Privacidade</a>
125
+ </div>
126
+ </div>
127
+ </footer>
128
+
129
+ <!-- Redoc script -->
130
+ <script>
131
+ Redoc.init('/docs/openapi.yaml', {
132
+ theme: {
133
+ colors: {
134
+ primary: {
135
+ main: '#5B2C6F'
136
+ }
137
+ },
138
+ typography: {
139
+ fontFamily: 'Segoe UI, Tahoma, sans-serif',
140
+ headings: {
141
+ fontWeight: 'bold'
142
+ }
143
+ }
144
+ },
145
+ scrollYOffset: 60,
146
+ hideDownloadButton: false,
147
+ expandResponses: '200,201'
148
+ }, document.getElementById('redoc-container'));
149
+ </script>
150
+ </body>
151
+
152
+ </html>
@@ -0,0 +1,143 @@
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <title>Pay2B API Reference</title>
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+
9
+ <link rel="icon" href="https://pay2b.com.br/favicon.ico" type="image/x-icon" />
10
+
11
+ <!-- Swagger UI assets -->
12
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui.css" />
13
+ <script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui-bundle.js"></script>
14
+ <script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui-standalone-preset.js"></script>
15
+
16
+ <style>
17
+ html,
18
+ body {
19
+ margin: 0;
20
+ padding: 0;
21
+ font-family: "Segoe UI", Roboto, sans-serif;
22
+ background-color: #f5f6fa;
23
+ }
24
+
25
+ .header {
26
+ background-color: #1f2d3d;
27
+ color: white;
28
+ padding: 16px 32px;
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: space-between;
32
+ }
33
+
34
+ .header-left {
35
+ display: flex;
36
+ align-items: center;
37
+ }
38
+
39
+ .header-left img {
40
+ height: 36px;
41
+ margin-right: 12px;
42
+ }
43
+
44
+ .header-left h1 {
45
+ font-size: 20px;
46
+ margin: 0;
47
+ font-weight: 600;
48
+ }
49
+
50
+ #swagger-ui {
51
+ margin: 0 auto;
52
+ max-width: 1400px;
53
+ padding: 24px;
54
+ background-color: white;
55
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.05);
56
+ }
57
+
58
+ footer {
59
+ background-color: #1f2d3d;
60
+ color: white;
61
+ padding: 20px 32px;
62
+ display: flex;
63
+ justify-content: space-between;
64
+ align-items: center;
65
+ flex-wrap: wrap;
66
+ font-size: 14px;
67
+ }
68
+
69
+ footer .footer-left img {
70
+ height: 26px;
71
+ }
72
+
73
+ footer .footer-right {
74
+ display: flex;
75
+ gap: 16px;
76
+ }
77
+
78
+ footer .footer-right a {
79
+ color: #fff;
80
+ text-decoration: none;
81
+ }
82
+
83
+ footer .footer-right a:hover {
84
+ opacity: 0.8;
85
+ }
86
+
87
+ @media (max-width: 768px) {
88
+
89
+ .header,
90
+ footer {
91
+ flex-direction: column;
92
+ align-items: flex-start;
93
+ gap: 12px;
94
+ }
95
+
96
+ #swagger-ui {
97
+ padding: 12px;
98
+ }
99
+ }
100
+ </style>
101
+ </head>
102
+
103
+ <body>
104
+
105
+ <div class="header">
106
+ <div class="header-left">
107
+ <img src="https://cdn-email.s3.us-east-1.amazonaws.com/images/pay2b-logo-header.png" alt="Pay2B Logo" />
108
+ <h1>API Reference</h1>
109
+ </div>
110
+ </div>
111
+
112
+ <div id="swagger-ui"></div>
113
+
114
+ <footer>
115
+ <div class="footer-left">
116
+ <img src="https://cdn-email.s3.us-east-1.amazonaws.com/images/pay2b-logo-header.png" alt="Pay2B Logo" />
117
+ </div>
118
+ <div class="footer-right">
119
+ <a href="https://www.linkedin.com/company/pay2b" target="_blank">LinkedIn</a>
120
+ <a href="https://www.instagram.com/pay2b.oficial" target="_blank">Instagram</a>
121
+ <a href="https://www.pay2b.com.br/politica-de-privacidade" target="_blank">Política de privacidade</a>
122
+ </div>
123
+ </footer>
124
+
125
+ <script>
126
+ window.onload = () => {
127
+ SwaggerUIBundle({
128
+ url: "/docs/openapi.yaml",
129
+ dom_id: "#swagger-ui",
130
+ deepLinking: true,
131
+ presets: [
132
+ SwaggerUIBundle.presets.apis,
133
+ SwaggerUIStandalonePreset
134
+ ],
135
+ layout: "StandaloneLayout",
136
+ docExpansion: "none",
137
+ operationsSorter: "alpha"
138
+ });
139
+ };
140
+ </script>
141
+ </body>
142
+
143
+ </html>
package/lib/router.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ const multer = require('multer');
4
+
5
+ class Router {
6
+
7
+ constructor(app) {
8
+ this.app = app;
9
+ const storage = multer.memoryStorage();
10
+ this.upload = multer({ storage });
11
+ }
12
+
13
+ addRoute(route, handler) {
14
+ const middleware = [];
15
+
16
+ // Adiciona o middleware de upload de arquivos se a propriedade 'enableUploader' estiver definida
17
+ if (route.enableUploader) {
18
+ middleware.push(this.upload.single(route.uploadFieldName || 'file'));
19
+ }
20
+
21
+ middleware.push((request, response, next) => {
22
+ handler.handleRequest(request, response, next);
23
+ });
24
+
25
+ this.app[route.getMethod()](route.getPath(), middleware);
26
+ }
27
+ }
28
+
29
+ module.exports = Router;
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ var Step = require('step');
4
+ var jwtUtil = require('./jwt-util');
5
+
6
+ var securityValidation = (function() {
7
+
8
+ function execute(context, callback) {
9
+
10
+ if (context.service.security) {
11
+
12
+ var xAccessToken = context.headers['x-access-token'];
13
+
14
+ Step(
15
+ function() {
16
+ jwtUtil.validateAccessToken(xAccessToken, this);
17
+ },
18
+ function(error, decodedPayload) {
19
+ if (!error) {
20
+ updateContext(context, decodedPayload);
21
+ }
22
+ return callback(error);
23
+ }
24
+ );
25
+
26
+ } else {
27
+ return callback();
28
+ }
29
+
30
+ }
31
+
32
+ function updateContext(context, decodedPayload) {
33
+ context.security.setCustomerUUID(decodedPayload.uuid);
34
+ context.security.setDeviceDNA(decodedPayload.deviceDNA);
35
+ context.security.setDevicePublicKeyDisgest(decodedPayload.devicePublicKeyDisgest);
36
+ context.security.setAccessToken(decodedPayload.accessToken);
37
+ }
38
+
39
+ return {
40
+ execute: execute
41
+ };
42
+
43
+ })();
44
+
45
+
46
+ module.exports = securityValidation;