@oondemand/oon-core-back 0.6.5 → 0.6.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oondemand/oon-core-back",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/oondemand/oon-platform.git",
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ const axios = require("axios");
4
+ const GenericError = require("./errors/GenericError");
5
+ const { operationalRequestHeaders } = require("./utils/instanceActivation");
6
+ const { getBaseUrl, getAppCode } = require("./utils/activationProvider");
7
+ const { isLocalRuntime } = require("./runtime/localDevelopment");
8
+
9
+ const BLOCKING_CODES = new Set(["APP_LICENSE_REQUIRED", "APP_LICENSE_NOT_STARTED", "APP_LICENSE_EXPIRED", "APP_LICENSE_SUSPENDED", "APP_LICENSE_CANCELLED", "APP_LICENSE_OVERDUE", "APP_LICENSE_INVALID", "LICENSE_REQUIRED", "LICENSE_INACTIVE", "LICENSE_EXPIRED", "LICENSE_NOT_STARTED", "APP_ENTITLEMENT_INACTIVE", "APP_ENTITLEMENT_REQUIRED", "APP_ENTITLEMENT_OUT_OF_TERM"]);
10
+ const TIMEOUT_MS = 3000;
11
+
12
+ function unavailable() {
13
+ return new GenericError("Não foi possível consultar a licença. A operação permanece pendente.", { statusCode: 503, code: "LICENSE_AUTHORITY_UNAVAILABLE" });
14
+ }
15
+ function blocked(code) {
16
+ return new GenericError("A licença não permite iniciar esta operação. Consulte o responsável pelo contrato.", { statusCode: 423, code });
17
+ }
18
+
19
+ // No positive cache and no retries. Call immediately before each new business effect.
20
+ async function assertBusinessOperation({ tenantId, correlationId } = {}, dependencies = {}) {
21
+ if (!tenantId) throw new GenericError("Contexto de tenant obrigatório.", { statusCode: 403, code: "TENANT_CONTEXT_REQUIRED" });
22
+ const headers = await (dependencies.operationalRequestHeaders || operationalRequestHeaders)({ tenantId, correlationId });
23
+ const appCode = (dependencies.getAppCode || getAppCode)();
24
+ const baseUrl = (dependencies.getBaseUrl || getBaseUrl)();
25
+ let response;
26
+ try {
27
+ response = await (dependencies.post || axios.post)(`${baseUrl}/licensing/decision`, {}, {
28
+ timeout: TIMEOUT_MS, maxRedirects: 0, maxContentLength: 16384, headers,
29
+ });
30
+ } catch (error) {
31
+ const code = error.response?.data?.error?.code || error.response?.data?.code;
32
+ if (BLOCKING_CODES.has(code) && [402, 403, 409, 423].includes(error.response?.status)) throw blocked(code);
33
+ throw unavailable();
34
+ }
35
+ const result = response?.data;
36
+ if (result?.schemaVersion !== 1 || result.tenantId !== String(tenantId) || result.appCode !== appCode
37
+ || !["desenvolvimento", "homologacao", "producao"].includes(result.environment)
38
+ || result.maxAgeSeconds !== 0 || typeof result.allowed !== "boolean") throw unavailable();
39
+ if (!result.allowed) {
40
+ if (BLOCKING_CODES.has(result.code)) throw blocked(result.code);
41
+ throw unavailable();
42
+ }
43
+ if (result.code != null || !Number.isSafeInteger(result.version) || result.version < 1) throw unavailable();
44
+ return Object.freeze({ ...result });
45
+ }
46
+
47
+ // An integration service authenticates the originating Deployment at the authority.
48
+ // Forward only this allowlist, never the gateway bearer or arbitrary request headers.
49
+ async function verifyConsumerRequest({ headers: input = {}, requireLicense = true } = {}, dependencies = {}) {
50
+ if (isLocalRuntime()) throw new GenericError("Identidade operacional indisponível localmente.", { statusCode: 403, code: "LOCAL_OPERATION_NOT_SUPPORTED" });
51
+ const headers = {};
52
+ for (const key of ["x-oon-deployment-id", "x-oon-deployment-token", "x-app-code", "x-oon-tenant-id"]) {
53
+ if (typeof input[key] !== "string" || !input[key] || input[key].length > 512) throw new GenericError("Credencial operacional inválida.", { statusCode: 401, code: "OPERATIONAL_CREDENTIAL_REQUIRED" });
54
+ headers[key] = input[key];
55
+ }
56
+ if (requireLicense) {
57
+ return assertBusinessOperation({ tenantId: headers["x-oon-tenant-id"] }, { ...dependencies,
58
+ getAppCode: () => headers["x-app-code"], operationalRequestHeaders: async () => headers });
59
+ }
60
+ try {
61
+ const response = await (dependencies.post || axios.post)(`${(dependencies.getBaseUrl || getBaseUrl)()}/licensing/identity`, {}, { timeout: TIMEOUT_MS, maxRedirects: 0, maxContentLength: 16384, headers });
62
+ const result = response?.data;
63
+ if (result?.schemaVersion !== 1 || result.appCode !== headers["x-app-code"] || result.tenantId !== headers["x-oon-tenant-id"] || !["desenvolvimento", "homologacao", "producao"].includes(result.environment) || result.maxAgeSeconds !== 0) throw unavailable();
64
+ return Object.freeze({ appCode: result.appCode, tenantId: result.tenantId, environment: result.environment });
65
+ } catch (error) {
66
+ if ([401, 403].includes(error.response?.status)) throw new GenericError("Credencial operacional inválida.", { statusCode: 401, code: "OPERATIONAL_CREDENTIAL_INVALID" });
67
+ throw unavailable();
68
+ }
69
+ }
70
+
71
+ module.exports = { assertBusinessOperation, verifyConsumerRequest, BLOCKING_CODES, TIMEOUT_MS };
package/src/index.js CHANGED
@@ -76,6 +76,10 @@ module.exports = {
76
76
  fields,
77
77
  capabilities,
78
78
  operationalRequestHeaders,
79
+ licensing: {
80
+ assertBusinessOperation: require("./core/licensing").assertBusinessOperation,
81
+ verifyConsumerRequest: require("./core/licensing").verifyConsumerRequest,
82
+ },
79
83
  localDevelopment,
80
84
  localExecutionPolicy,
81
85
  PdfRenderingError: capabilities.PdfRenderingError,