@shushed/helpers 0.0.200-v2-20251127150547 → 0.0.200
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/dist/index.d.ts +34970 -0
- package/dist/index.js +113017 -0
- package/dist/package.json +3 -6
- package/package.json +4 -7
- package/dist/cjs/dist-dereferenced/asset.js +0 -4
- package/dist/cjs/dist-dereferenced/category.js +0 -4
- package/dist/cjs/dist-dereferenced/country.js +0 -4
- package/dist/cjs/dist-dereferenced/currency.js +0 -4
- package/dist/cjs/dist-dereferenced/customer-segment.js +0 -4
- package/dist/cjs/dist-dereferenced/development-colour.js +0 -4
- package/dist/cjs/dist-dereferenced/index.js +0 -69
- package/dist/cjs/dist-dereferenced/marketing-preferences.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/ean-change.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/index.js +0 -50
- package/dist/cjs/dist-dereferenced/messages/order/delivered.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/order/index.js +0 -18
- package/dist/cjs/dist-dereferenced/messages/order/new.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/order/processed.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/order/return-initiated.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/order/returned.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/order/shipped.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/price-change.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/product-category.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/product-draft.js +0 -4
- package/dist/cjs/dist-dereferenced/messages/product.js +0 -4
- package/dist/cjs/dist-dereferenced/money.js +0 -4
- package/dist/cjs/dist-dereferenced/order/address.js +0 -4
- package/dist/cjs/dist-dereferenced/order/customer.js +0 -4
- package/dist/cjs/dist-dereferenced/order/index.js +0 -51
- package/dist/cjs/dist-dereferenced/order/item.js +0 -4
- package/dist/cjs/dist-dereferenced/order/orderMain.js +0 -4
- package/dist/cjs/dist-dereferenced/order/payment.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/index.js +0 -45
- package/dist/cjs/dist-dereferenced/order/shipment/item/index.js +0 -11
- package/dist/cjs/dist-dereferenced/order/shipment/item/itemMain.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/item/returned.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/pos/index.js +0 -13
- package/dist/cjs/dist-dereferenced/order/shipment/pos/outbound.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/pos/posMain.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/pos/return.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/shipmentMain.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/shipped/index.js +0 -13
- package/dist/cjs/dist-dereferenced/order/shipment/shipped/outbound.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/shipped/return.js +0 -4
- package/dist/cjs/dist-dereferenced/order/shipment/shipped/shippedMain.js +0 -4
- package/dist/cjs/dist-dereferenced/price.js +0 -4
- package/dist/cjs/dist-dereferenced/product-category.js +0 -4
- package/dist/cjs/dist-dereferenced/product-draft.js +0 -4
- package/dist/cjs/dist-dereferenced/product.js +0 -4
- package/dist/cjs/dist-dereferenced/stock.js +0 -4
- package/dist/cjs/dist-dereferenced/total.js +0 -4
- package/dist/cjs/dist-types/asset.js +0 -2
- package/dist/cjs/dist-types/category.js +0 -2
- package/dist/cjs/dist-types/country.js +0 -2
- package/dist/cjs/dist-types/currency.js +0 -2
- package/dist/cjs/dist-types/customer-segment.js +0 -2
- package/dist/cjs/dist-types/development-colour.js +0 -2
- package/dist/cjs/dist-types/index.js +0 -38
- package/dist/cjs/dist-types/marketing-preferences.js +0 -2
- package/dist/cjs/dist-types/messages/ean-change.js +0 -2
- package/dist/cjs/dist-types/messages/index.js +0 -37
- package/dist/cjs/dist-types/messages/order/delivered.js +0 -2
- package/dist/cjs/dist-types/messages/order/index.js +0 -2
- package/dist/cjs/dist-types/messages/order/new.js +0 -2
- package/dist/cjs/dist-types/messages/order/processed.js +0 -2
- package/dist/cjs/dist-types/messages/order/return-initiated.js +0 -2
- package/dist/cjs/dist-types/messages/order/returned.js +0 -2
- package/dist/cjs/dist-types/messages/order/shipped.js +0 -2
- package/dist/cjs/dist-types/messages/price-change.js +0 -2
- package/dist/cjs/dist-types/messages/product-category.js +0 -2
- package/dist/cjs/dist-types/messages/product-draft.js +0 -2
- package/dist/cjs/dist-types/messages/product.js +0 -2
- package/dist/cjs/dist-types/money.js +0 -2
- package/dist/cjs/dist-types/order/address.js +0 -2
- package/dist/cjs/dist-types/order/customer.js +0 -2
- package/dist/cjs/dist-types/order/index.js +0 -37
- package/dist/cjs/dist-types/order/item.js +0 -2
- package/dist/cjs/dist-types/order/orderMain.js +0 -2
- package/dist/cjs/dist-types/order/payment.js +0 -2
- package/dist/cjs/dist-types/order/shipment/index.js +0 -39
- package/dist/cjs/dist-types/order/shipment/item/index.js +0 -2
- package/dist/cjs/dist-types/order/shipment/item/itemMain.js +0 -2
- package/dist/cjs/dist-types/order/shipment/item/returned.js +0 -2
- package/dist/cjs/dist-types/order/shipment/pos/index.js +0 -2
- package/dist/cjs/dist-types/order/shipment/pos/outbound.js +0 -2
- package/dist/cjs/dist-types/order/shipment/pos/posMain.js +0 -2
- package/dist/cjs/dist-types/order/shipment/pos/return.js +0 -2
- package/dist/cjs/dist-types/order/shipment/shipmentMain.js +0 -2
- package/dist/cjs/dist-types/order/shipment/shipped/index.js +0 -2
- package/dist/cjs/dist-types/order/shipment/shipped/outbound.js +0 -2
- package/dist/cjs/dist-types/order/shipment/shipped/return.js +0 -2
- package/dist/cjs/dist-types/order/shipment/shipped/shippedMain.js +0 -2
- package/dist/cjs/dist-types/price.js +0 -2
- package/dist/cjs/dist-types/product-category.js +0 -2
- package/dist/cjs/dist-types/product-draft.js +0 -2
- package/dist/cjs/dist-types/product.js +0 -2
- package/dist/cjs/dist-types/stock.js +0 -2
- package/dist/cjs/dist-types/total.js +0 -2
- package/dist/cjs/index.js +0 -39
- package/dist/cjs/src-public/airtable.js +0 -590
- package/dist/cjs/src-public/bigquery.js +0 -59
- package/dist/cjs/src-public/cloudtasks.js +0 -207
- package/dist/cjs/src-public/dato.js +0 -656
- package/dist/cjs/src-public/env.js +0 -897
- package/dist/cjs/src-public/getEventTime.js +0 -28
- package/dist/cjs/src-public/index.js +0 -50
- package/dist/cjs/src-public/ipValidation.js +0 -167
- package/dist/cjs/src-public/jwks.js +0 -108
- package/dist/cjs/src-public/pubsub.js +0 -423
- package/dist/cjs/src-public/rateLimit.js +0 -140
- package/dist/cjs/src-public/redisClient.js +0 -44
- package/dist/cjs/src-public/runtime.js +0 -141
- package/dist/cjs/src-public/sanitize.js +0 -25
- package/dist/cjs/src-public/scheduler.js +0 -247
- package/dist/cjs/src-public/secret.js +0 -16
- package/dist/cjs/src-public/setHeaders.js +0 -16
- package/dist/cjs/src-public/types.js +0 -2
- package/dist/cjs/src-public/utils.js +0 -454
- package/dist/cjs/src-public/validate.js +0 -40
- package/dist/types/dist-dereferenced/asset.d.ts +0 -51
- package/dist/types/dist-dereferenced/category.d.ts +0 -58
- package/dist/types/dist-dereferenced/country.d.ts +0 -8
- package/dist/types/dist-dereferenced/currency.d.ts +0 -8
- package/dist/types/dist-dereferenced/customer-segment.d.ts +0 -26
- package/dist/types/dist-dereferenced/development-colour.d.ts +0 -114
- package/dist/types/dist-dereferenced/index.d.ts +0 -16
- package/dist/types/dist-dereferenced/marketing-preferences.d.ts +0 -31
- package/dist/types/dist-dereferenced/messages/ean-change.d.ts +0 -17
- package/dist/types/dist-dereferenced/messages/index.d.ts +0 -6
- package/dist/types/dist-dereferenced/messages/order/delivered.d.ts +0 -3414
- package/dist/types/dist-dereferenced/messages/order/index.d.ts +0 -6
- package/dist/types/dist-dereferenced/messages/order/new.d.ts +0 -3414
- package/dist/types/dist-dereferenced/messages/order/processed.d.ts +0 -3408
- package/dist/types/dist-dereferenced/messages/order/return-initiated.d.ts +0 -3414
- package/dist/types/dist-dereferenced/messages/order/returned.d.ts +0 -3413
- package/dist/types/dist-dereferenced/messages/order/shipped.d.ts +0 -3412
- package/dist/types/dist-dereferenced/messages/price-change.d.ts +0 -67
- package/dist/types/dist-dereferenced/messages/product-category.d.ts +0 -33
- package/dist/types/dist-dereferenced/messages/product-draft.d.ts +0 -589
- package/dist/types/dist-dereferenced/messages/product.d.ts +0 -628
- package/dist/types/dist-dereferenced/money.d.ts +0 -41
- package/dist/types/dist-dereferenced/order/address.d.ts +0 -98
- package/dist/types/dist-dereferenced/order/customer.d.ts +0 -309
- package/dist/types/dist-dereferenced/order/index.d.ts +0 -3404
- package/dist/types/dist-dereferenced/order/item.d.ts +0 -336
- package/dist/types/dist-dereferenced/order/orderMain.d.ts +0 -3399
- package/dist/types/dist-dereferenced/order/payment.d.ts +0 -94
- package/dist/types/dist-dereferenced/order/shipment/index.d.ts +0 -253
- package/dist/types/dist-dereferenced/order/shipment/item/index.d.ts +0 -19
- package/dist/types/dist-dereferenced/order/shipment/item/itemMain.d.ts +0 -18
- package/dist/types/dist-dereferenced/order/shipment/item/returned.d.ts +0 -34
- package/dist/types/dist-dereferenced/order/shipment/pos/index.d.ts +0 -282
- package/dist/types/dist-dereferenced/order/shipment/pos/outbound.d.ts +0 -320
- package/dist/types/dist-dereferenced/order/shipment/pos/posMain.d.ts +0 -280
- package/dist/types/dist-dereferenced/order/shipment/pos/return.d.ts +0 -331
- package/dist/types/dist-dereferenced/order/shipment/shipmentMain.d.ts +0 -250
- package/dist/types/dist-dereferenced/order/shipment/shipped/index.d.ts +0 -288
- package/dist/types/dist-dereferenced/order/shipment/shipped/outbound.d.ts +0 -286
- package/dist/types/dist-dereferenced/order/shipment/shipped/return.d.ts +0 -287
- package/dist/types/dist-dereferenced/order/shipment/shipped/shippedMain.d.ts +0 -286
- package/dist/types/dist-dereferenced/price.d.ts +0 -58
- package/dist/types/dist-dereferenced/product-category.d.ts +0 -24
- package/dist/types/dist-dereferenced/product-draft.d.ts +0 -580
- package/dist/types/dist-dereferenced/product.d.ts +0 -619
- package/dist/types/dist-dereferenced/stock.d.ts +0 -74
- package/dist/types/dist-dereferenced/total.d.ts +0 -172
- package/dist/types/dist-types/asset.d.ts +0 -16
- package/dist/types/dist-types/category.d.ts +0 -20
- package/dist/types/dist-types/country.d.ts +0 -2
- package/dist/types/dist-types/currency.d.ts +0 -2
- package/dist/types/dist-types/customer-segment.d.ts +0 -6
- package/dist/types/dist-types/development-colour.d.ts +0 -31
- package/dist/types/dist-types/index.d.ts +0 -16
- package/dist/types/dist-types/marketing-preferences.d.ts +0 -9
- package/dist/types/dist-types/messages/ean-change.d.ts +0 -5
- package/dist/types/dist-types/messages/index.d.ts +0 -6
- package/dist/types/dist-types/messages/order/delivered.d.ts +0 -292
- package/dist/types/dist-types/messages/order/index.d.ts +0 -6
- package/dist/types/dist-types/messages/order/new.d.ts +0 -292
- package/dist/types/dist-types/messages/order/processed.d.ts +0 -292
- package/dist/types/dist-types/messages/order/return-initiated.d.ts +0 -292
- package/dist/types/dist-types/messages/order/returned.d.ts +0 -293
- package/dist/types/dist-types/messages/order/shipped.d.ts +0 -293
- package/dist/types/dist-types/messages/price-change.d.ts +0 -16
- package/dist/types/dist-types/messages/product-category.d.ts +0 -7
- package/dist/types/dist-types/messages/product-draft.d.ts +0 -136
- package/dist/types/dist-types/messages/product.d.ts +0 -144
- package/dist/types/dist-types/money.d.ts +0 -11
- package/dist/types/dist-types/order/address.d.ts +0 -27
- package/dist/types/dist-types/order/customer.d.ts +0 -81
- package/dist/types/dist-types/order/index.d.ts +0 -8
- package/dist/types/dist-types/order/item.d.ts +0 -85
- package/dist/types/dist-types/order/orderMain.d.ts +0 -289
- package/dist/types/dist-types/order/payment.d.ts +0 -26
- package/dist/types/dist-types/order/shipment/index.d.ts +0 -6
- package/dist/types/dist-types/order/shipment/item/index.d.ts +0 -4
- package/dist/types/dist-types/order/shipment/item/itemMain.d.ts +0 -6
- package/dist/types/dist-types/order/shipment/item/returned.d.ts +0 -11
- package/dist/types/dist-types/order/shipment/pos/index.d.ts +0 -5
- package/dist/types/dist-types/order/shipment/pos/outbound.d.ts +0 -76
- package/dist/types/dist-types/order/shipment/pos/posMain.d.ts +0 -71
- package/dist/types/dist-types/order/shipment/pos/return.d.ts +0 -75
- package/dist/types/dist-types/order/shipment/shipmentMain.d.ts +0 -62
- package/dist/types/dist-types/order/shipment/shipped/index.d.ts +0 -5
- package/dist/types/dist-types/order/shipment/shipped/outbound.d.ts +0 -68
- package/dist/types/dist-types/order/shipment/shipped/return.d.ts +0 -68
- package/dist/types/dist-types/order/shipment/shipped/shippedMain.d.ts +0 -69
- package/dist/types/dist-types/price.d.ts +0 -15
- package/dist/types/dist-types/product-category.d.ts +0 -6
- package/dist/types/dist-types/product-draft.d.ts +0 -135
- package/dist/types/dist-types/product.d.ts +0 -143
- package/dist/types/dist-types/stock.d.ts +0 -19
- package/dist/types/dist-types/total.d.ts +0 -44
- package/dist/types/index.d.ts +0 -3
- package/dist/types/src-public/airtable.d.ts +0 -220
- package/dist/types/src-public/bigquery.d.ts +0 -17
- package/dist/types/src-public/cloudtasks.d.ts +0 -74
- package/dist/types/src-public/dato.d.ts +0 -94
- package/dist/types/src-public/env.d.ts +0 -144
- package/dist/types/src-public/getEventTime.d.ts +0 -1
- package/dist/types/src-public/index.d.ts +0 -16
- package/dist/types/src-public/ipValidation.d.ts +0 -15
- package/dist/types/src-public/jwks.d.ts +0 -15
- package/dist/types/src-public/pubsub.d.ts +0 -95
- package/dist/types/src-public/rateLimit.d.ts +0 -21
- package/dist/types/src-public/redisClient.d.ts +0 -6
- package/dist/types/src-public/runtime.d.ts +0 -57
- package/dist/types/src-public/sanitize.d.ts +0 -4
- package/dist/types/src-public/scheduler.d.ts +0 -71
- package/dist/types/src-public/secret.d.ts +0 -6
- package/dist/types/src-public/setHeaders.d.ts +0 -13
- package/dist/types/src-public/types.d.ts +0 -264
- package/dist/types/src-public/utils.d.ts +0 -101
- package/dist/types/src-public/validate.d.ts +0 -9
|
@@ -1,897 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const crypto = __importStar(require("crypto"));
|
|
40
|
-
const crypto_1 = require("crypto");
|
|
41
|
-
const co_body_1 = __importDefault(require("co-body"));
|
|
42
|
-
const jose_1 = require("jose");
|
|
43
|
-
const lodash_omit_1 = __importDefault(require("lodash.omit"));
|
|
44
|
-
const rate_limiter_flexible_1 = require("rate-limiter-flexible");
|
|
45
|
-
const pubsub_1 = __importDefault(require("./pubsub"));
|
|
46
|
-
const redisClient_1 = require("./redisClient");
|
|
47
|
-
const runtime_1 = __importDefault(require("./runtime"));
|
|
48
|
-
const utils_1 = require("./utils");
|
|
49
|
-
const ENV_NAME_CONTAINING_SERVICE_ACCOUNTS = 'hush_trigger_allowed_service_accounts';
|
|
50
|
-
const ENV_NAME_RN_WORFKLOW_TRIGGER_ID = 'hush_trigger_rn_workflow_trigger_id';
|
|
51
|
-
const ENV_NAME_PUBSUB_PROJECT_ID = 'hush_pubsub_project_id';
|
|
52
|
-
const ENV_NAME_PUBSUB_SERVICE_ACCOUNT = 'hush_pubsub_service_account';
|
|
53
|
-
const ENV_NAME_SECRET_ENCRYPTION_KEY = 'SECRET_ENCRYPTION_KEY';
|
|
54
|
-
global.IN_MEMORY_REF = global.IN_MEMORY_REF || {
|
|
55
|
-
env: {},
|
|
56
|
-
workflow: {},
|
|
57
|
-
trigger: {},
|
|
58
|
-
};
|
|
59
|
-
class EnvEngine extends runtime_1.default {
|
|
60
|
-
globalInMemoryRef;
|
|
61
|
-
inMemoryRef;
|
|
62
|
-
docRef = null;
|
|
63
|
-
store;
|
|
64
|
-
_envCache = {};
|
|
65
|
-
_lockRateLimiter = null;
|
|
66
|
-
constructor(opts, _) {
|
|
67
|
-
super(opts);
|
|
68
|
-
Object.assign(global.IN_MEMORY_REF || {}, {
|
|
69
|
-
env: { [this.envName]: global.IN_MEMORY_REF?.env?.[this.envName] || {} },
|
|
70
|
-
workflow: { [this.envName + this.workflowId]: global.IN_MEMORY_REF?.workflow?.[this.envName + this.workflowId] || {} },
|
|
71
|
-
trigger: { [this.envName + this.workflowId + this.triggerId]: global.IN_MEMORY_REF?.trigger?.[this.envName + this.workflowId + this.triggerId] || {} },
|
|
72
|
-
});
|
|
73
|
-
this.globalInMemoryRef = {
|
|
74
|
-
env: global.IN_MEMORY_REF?.env?.[this.envName] || {},
|
|
75
|
-
workflow: global.IN_MEMORY_REF?.workflow?.[this.envName + this.workflowId] || {},
|
|
76
|
-
trigger: global.IN_MEMORY_REF?.trigger?.[this.envName + this.workflowId + this.triggerId] || {},
|
|
77
|
-
};
|
|
78
|
-
this.inMemoryRef = {
|
|
79
|
-
env: {},
|
|
80
|
-
workflow: {},
|
|
81
|
-
trigger: {},
|
|
82
|
-
};
|
|
83
|
-
this.store = {
|
|
84
|
-
env: null,
|
|
85
|
-
workflow: null,
|
|
86
|
-
trigger: null,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
initializeDocRef() {
|
|
90
|
-
if (this.docRef) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
const firestore = (0, utils_1.getFirestore)(this.systemEnvName);
|
|
94
|
-
this.docRef = {
|
|
95
|
-
env: firestore?.doc(`hush-${this.envName}/0-0`),
|
|
96
|
-
workflow: firestore?.doc(`hush-${this.envName}/${this.workflowId}-0`),
|
|
97
|
-
trigger: firestore?.doc(`hush-${this.envName}/${this.workflowId}-${this.triggerId}`),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
async set(envs, level = 'trigger', optionsOrEncryptWithValue) {
|
|
101
|
-
const options = typeof optionsOrEncryptWithValue === 'object' ? optionsOrEncryptWithValue : {
|
|
102
|
-
encrypted: !!optionsOrEncryptWithValue,
|
|
103
|
-
encryptionKey: optionsOrEncryptWithValue,
|
|
104
|
-
ephemeralMs: 0
|
|
105
|
-
};
|
|
106
|
-
let expirseAt = 0;
|
|
107
|
-
if ((options.ephemeralMs || 0) > 3 * 60 * 60 * 1000) {
|
|
108
|
-
throw new Error('Validation Error. The options.ephemeralMs cannot be set for the duration longer than 3 hours');
|
|
109
|
-
}
|
|
110
|
-
const now = Date.now();
|
|
111
|
-
expirseAt = now + (options.ephemeralMs || 0);
|
|
112
|
-
if (options.encrypted && !options.encryptionKey) {
|
|
113
|
-
if (!options.ephemeralMs) {
|
|
114
|
-
throw new Error(`Invariant while setting the value for ${this.systemEnvName}. If the options.encryptionKey is not set and the encryption with the default key is used, only the ephemeral storage can be used. Set the ephemeralMs`);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
if (!this._envCache[this.systemEnvName]) {
|
|
118
|
-
const jsonEnv = JSON.parse(process.env[`${this.systemEnvName}ProjectEnv`] || JSON.stringify({
|
|
119
|
-
__mock_invalid: true
|
|
120
|
-
}));
|
|
121
|
-
this._envCache[this.systemEnvName] = jsonEnv;
|
|
122
|
-
}
|
|
123
|
-
let cachedEnv = this._envCache[this.systemEnvName];
|
|
124
|
-
if (cachedEnv['__mock_invalid']) {
|
|
125
|
-
cachedEnv = process.env;
|
|
126
|
-
}
|
|
127
|
-
options.encryptionKey = cachedEnv[ENV_NAME_SECRET_ENCRYPTION_KEY];
|
|
128
|
-
if (!options.encryptionKey) {
|
|
129
|
-
throw new Error(`Invariant while setting the value for ${this.systemEnvName}. If the options.encryptionKey is not set and the encryption with the default key is used, only the ephemeral storage can be used. Set the ephemeralMs. The default key is missing.`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
let aes = null;
|
|
134
|
-
if (options.encryptionKey) {
|
|
135
|
-
aes = new AES256GCM(Buffer.from(options.encryptionKey, 'utf8'));
|
|
136
|
-
}
|
|
137
|
-
const objPlain = envs
|
|
138
|
-
.filter((env) => !!env.name)
|
|
139
|
-
.reduce((prev, curr) => {
|
|
140
|
-
const value = curr.value;
|
|
141
|
-
return ({ ...prev, [curr.name]: value });
|
|
142
|
-
}, {});
|
|
143
|
-
const objEncrypted = envs
|
|
144
|
-
.filter((env) => !!env.name)
|
|
145
|
-
.reduce((prev, curr) => {
|
|
146
|
-
let value = curr.value;
|
|
147
|
-
if (aes) {
|
|
148
|
-
value = aes.encrypt(curr.value);
|
|
149
|
-
}
|
|
150
|
-
return ({ ...prev, [curr.name]: value });
|
|
151
|
-
}, {});
|
|
152
|
-
Object.assign(this.inMemoryRef[level], Object.fromEntries(Object.entries(objPlain).map(([k, v]) => [k, `${expirseAt}/${now}/${v}`])));
|
|
153
|
-
if (options.ephemeralMs) {
|
|
154
|
-
if (!options.ignoreStores?.includes('global')) {
|
|
155
|
-
Object.assign(this.globalInMemoryRef[level], Object.fromEntries(Object.entries(objEncrypted).map(([k, v]) => [k, `${expirseAt}/${now}/${v}`])));
|
|
156
|
-
}
|
|
157
|
-
if (!options.ignoreStores?.includes('redis')) {
|
|
158
|
-
(async () => {
|
|
159
|
-
const redisClient = await (0, redisClient_1.getConnectedRedisClient)(this.systemEnvName).catch(() => null);
|
|
160
|
-
if (redisClient) {
|
|
161
|
-
Promise.allSettled(Object.entries(objEncrypted).map(([k, v]) => redisClient.set(k, `${expirseAt}/${now}/${v}`, { PX: expirseAt - Date.now() })));
|
|
162
|
-
}
|
|
163
|
-
})().catch(() => this.logging.error(`Failed to set the ${envs.map(x => x.name).join(', ')} in Redis`));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
await this.initializeDocRef();
|
|
168
|
-
if (this.docRef[level]) {
|
|
169
|
-
try {
|
|
170
|
-
await this.docRef[level].set(objEncrypted, { merge: true });
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
throw new Error(`Failed to set the ${envs.map(x => x.name).join(', ')}. Error: ${err.message}`);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else { }
|
|
177
|
-
}
|
|
178
|
-
return undefined;
|
|
179
|
-
}
|
|
180
|
-
async getFirestoreStore(level = 'trigger') {
|
|
181
|
-
await this.initializeDocRef();
|
|
182
|
-
const store = await this.docRef[level].get();
|
|
183
|
-
return store.data() || {};
|
|
184
|
-
}
|
|
185
|
-
async get(keys, level = 'trigger', decryptWithValueOrOptions) {
|
|
186
|
-
const options = typeof decryptWithValueOrOptions === 'object' ? decryptWithValueOrOptions : {
|
|
187
|
-
encrypted: !!decryptWithValueOrOptions,
|
|
188
|
-
encryptionKey: decryptWithValueOrOptions,
|
|
189
|
-
isEphemeral: false
|
|
190
|
-
};
|
|
191
|
-
const keysParsed = typeof keys === 'string' ? [keys] : keys;
|
|
192
|
-
const result = await this._get(keysParsed, level, options);
|
|
193
|
-
if (typeof keys === 'string') {
|
|
194
|
-
return result[keys].valid ? result[keys].value : '';
|
|
195
|
-
}
|
|
196
|
-
return Object.fromEntries(Object.entries(result).map(([k, v]) => [k, v.valid ? v.value : '']));
|
|
197
|
-
}
|
|
198
|
-
async _get(keysParsed, level = 'trigger', options) {
|
|
199
|
-
let aes = null;
|
|
200
|
-
if (options.encrypted && !options.encryptionKey) {
|
|
201
|
-
if (!options.isEphemeral) {
|
|
202
|
-
throw new Error(`Invariant while getting the value for ${this.systemEnvName}. If the options.encryptionKey is not set and the encryption with the default key is used, only the ephemeral storage can be used. Set the ephemeralMs`);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
if (!this._envCache[this.systemEnvName]) {
|
|
206
|
-
let jsonEnv;
|
|
207
|
-
if (process.env[`${this.systemEnvName}ProjectEnv`]) {
|
|
208
|
-
try {
|
|
209
|
-
jsonEnv = JSON.parse(process.env[`${this.systemEnvName}ProjectEnv`] || '');
|
|
210
|
-
}
|
|
211
|
-
catch (err) {
|
|
212
|
-
this.logging.error(`Invariant: Cannot parse the ${this.systemEnvName}ProjectEnv as JSON. ${err?.message}`);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
this._envCache[this.systemEnvName] = jsonEnv || {
|
|
216
|
-
__mock_invalid: true
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
let cachedEnv = this._envCache[this.systemEnvName];
|
|
220
|
-
if (cachedEnv['__mock_invalid']) {
|
|
221
|
-
cachedEnv = process.env;
|
|
222
|
-
}
|
|
223
|
-
options.encryptionKey = cachedEnv[ENV_NAME_SECRET_ENCRYPTION_KEY];
|
|
224
|
-
if (!options.encryptionKey) {
|
|
225
|
-
throw new Error(`Invariant while getting the value for ${this.systemEnvName}. If the options.encryptionKey is not set and the encryption with the default key is used, only the ephemeral storage can be used. Set the ephemeralMs. The default key is missing.`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (options.encryptionKey) {
|
|
230
|
-
aes = new AES256GCM(Buffer.from(options.encryptionKey, 'utf8'));
|
|
231
|
-
}
|
|
232
|
-
let store = {};
|
|
233
|
-
if (options.isEphemeral && !options.store || options.store === 'inMemory') {
|
|
234
|
-
store = this.inMemoryRef[level];
|
|
235
|
-
}
|
|
236
|
-
else if (options.store === 'global') {
|
|
237
|
-
store = this.globalInMemoryRef[level];
|
|
238
|
-
}
|
|
239
|
-
else if (options.store === 'redis') {
|
|
240
|
-
store = {};
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
store = await this.getFirestoreStore(level);
|
|
244
|
-
}
|
|
245
|
-
if (options.store === 'redis') {
|
|
246
|
-
const redisClient = await (0, redisClient_1.getConnectedRedisClient)(this.systemEnvName).catch(() => null);
|
|
247
|
-
if (redisClient) {
|
|
248
|
-
const values = await Promise.race([
|
|
249
|
-
redisClient.mGet(keysParsed),
|
|
250
|
-
new Promise((resolve) => setTimeout(() => {
|
|
251
|
-
resolve(keysParsed.map(() => null));
|
|
252
|
-
}, 30))
|
|
253
|
-
]);
|
|
254
|
-
for (let i = 0; i < keysParsed.length; i++) {
|
|
255
|
-
store[keysParsed[i]] = values[i] || '';
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
const parseEphemeral = !!options.isEphemeral;
|
|
260
|
-
const result = keysParsed.reduce((acc, k) => {
|
|
261
|
-
let v = store?.[k] || '';
|
|
262
|
-
let expiresAt = 0;
|
|
263
|
-
let createdAt = 0;
|
|
264
|
-
if (parseEphemeral && v.includes('/')) {
|
|
265
|
-
const valueParts = v.split('/');
|
|
266
|
-
v = valueParts.slice(2).join('/');
|
|
267
|
-
createdAt = parseInt(valueParts[1]);
|
|
268
|
-
expiresAt = parseInt(valueParts[0]);
|
|
269
|
-
}
|
|
270
|
-
let finalValue = '';
|
|
271
|
-
if (aes && v && typeof v === 'string' && options.store !== 'inMemory') {
|
|
272
|
-
try {
|
|
273
|
-
finalValue = aes.decrypt(v);
|
|
274
|
-
}
|
|
275
|
-
catch (err) {
|
|
276
|
-
finalValue = '';
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
finalValue = typeof v !== 'string' ? `${(v === null || typeof v === 'undefined') ? '' : `${v}`}` : v;
|
|
281
|
-
}
|
|
282
|
-
acc[k] = {
|
|
283
|
-
createdAt,
|
|
284
|
-
expiresAt,
|
|
285
|
-
value: finalValue,
|
|
286
|
-
valid: parseEphemeral ? (expiresAt > Date.now() - (options.expirationMarginMs || 0) && finalValue !== '') : (finalValue !== '')
|
|
287
|
-
};
|
|
288
|
-
return acc;
|
|
289
|
-
}, {});
|
|
290
|
-
return result;
|
|
291
|
-
}
|
|
292
|
-
withGoogleAccessToken() {
|
|
293
|
-
const serviceName = process.env.K_SERVICE || '<not-cloud-run>';
|
|
294
|
-
return this.with(`google_access_token_${serviceName}`, 'env', { encrypted: true, ephemeralMs: 10 * 60 * 1000, fetch: () => (0, utils_1.getAccessToken)() });
|
|
295
|
-
}
|
|
296
|
-
withGoogleIdentityToken(audience) {
|
|
297
|
-
const audienceNorm = {
|
|
298
|
-
workflowId: audience ? (audience.workflowId || this.workflowId) : null,
|
|
299
|
-
triggerId: audience ? (audience.triggerId || this.triggerId) : null
|
|
300
|
-
};
|
|
301
|
-
const serviceName = process.env.K_SERVICE || '<not-cloud-run>';
|
|
302
|
-
console.log('JAKUB8', serviceName);
|
|
303
|
-
const expectedAudience = [process.env.GCLOUD_PROJECT, audienceNorm.workflowId, audienceNorm.triggerId].filter(x => x !== null).join('-');
|
|
304
|
-
return this.with(`google_identity_token_${serviceName}_${expectedAudience}`, 'env', { encrypted: true, ephemeralMs: 10 * 60 * 1000, fetch: () => (0, utils_1.getIdentityToken)(expectedAudience) });
|
|
305
|
-
}
|
|
306
|
-
resolveEnvName(envName) {
|
|
307
|
-
if (envName.startsWith('process.env.')) {
|
|
308
|
-
envName = envName.slice('process.env.'.length);
|
|
309
|
-
}
|
|
310
|
-
if (!this._envCache[this.systemEnvName]) {
|
|
311
|
-
const jsonEnv = JSON.parse(process.env[`${this.systemEnvName}ProjectEnv`] || '{ "__mock_invalid": true }');
|
|
312
|
-
this._envCache[this.systemEnvName] = jsonEnv;
|
|
313
|
-
}
|
|
314
|
-
const envObj = this._envCache[this.systemEnvName];
|
|
315
|
-
return envObj[envName] || envName;
|
|
316
|
-
}
|
|
317
|
-
async checkGoogleIdentiyToken(accessToken, audience, allowedServiceAccounts = [`runtime@${process.env.GCLOUD_PROJECT}.iam.gserviceaccount.com`]) {
|
|
318
|
-
if (!accessToken) {
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
321
|
-
function equalToWildcard(stringWithWildcard, str) {
|
|
322
|
-
const escaped = stringWithWildcard.replace(/[-/\\^$+?.()|[\]{}]/g, '\\$&');
|
|
323
|
-
const pattern = '^' + escaped.replace(/\*/g, '.*') + '$';
|
|
324
|
-
const regex = new RegExp(pattern);
|
|
325
|
-
return regex.test(str);
|
|
326
|
-
}
|
|
327
|
-
const audienceNorm = {
|
|
328
|
-
workflowId: audience ? (audience.workflowId || this.workflowId) : null,
|
|
329
|
-
triggerId: audience ? (audience.triggerId || this.triggerId) : null
|
|
330
|
-
};
|
|
331
|
-
const expectedAudience = [process.env.GCLOUD_PROJECT, audienceNorm.triggerId, audienceNorm.workflowId].filter(x => x !== null).join('-');
|
|
332
|
-
const splitted = accessToken.split(".");
|
|
333
|
-
let keyMeta;
|
|
334
|
-
let meta;
|
|
335
|
-
try {
|
|
336
|
-
keyMeta = JSON.parse(Buffer.from(splitted[0], "base64").toString('utf-8')) || {};
|
|
337
|
-
meta = JSON.parse(Buffer.from(splitted[1], "base64").toString('utf-8')) || {};
|
|
338
|
-
}
|
|
339
|
-
catch (err) {
|
|
340
|
-
this.logging.error(`Authorization header - Malformed Token. ${err.message}`);
|
|
341
|
-
return false;
|
|
342
|
-
}
|
|
343
|
-
let tokenExpirationTime = meta.exp;
|
|
344
|
-
if (!tokenExpirationTime) {
|
|
345
|
-
this.logging.error(`Authorization header - Expiration time is missing`);
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
tokenExpirationTime = tokenExpirationTime * 1000;
|
|
349
|
-
if (tokenExpirationTime < Date.now()) {
|
|
350
|
-
this.logging.error(`Authorization header - Token expired`);
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
if (!meta.email_verified) {
|
|
354
|
-
this.logging.error(`Authorization header - Email not verified`);
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
if (!allowedServiceAccounts.some(x => equalToWildcard(x, meta.email))) {
|
|
358
|
-
this.logging.error(`Authorization header - Wrong service account, got ${meta?.email}, expected one of ${allowedServiceAccounts.join(', ')}`);
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
if (!keyMeta.kid || !keyMeta.alg) {
|
|
362
|
-
this.logging.error(`Authorization header - Malformed Authorization Header. KID is missing`);
|
|
363
|
-
return false;
|
|
364
|
-
}
|
|
365
|
-
if (meta.aud !== expectedAudience) {
|
|
366
|
-
const receivedMoreSpecific = (expectedAudience + '-' + this.triggerId) === meta.aud || (expectedAudience + '-' + this.workflowId + '-' + this.triggerId) === meta.aud || (expectedAudience + '-' + this.workflowId) === meta.aud || (expectedAudience + '/' + this.workflowId + '/' + this.triggerId) === meta.aud || (expectedAudience + '/' + this.workflowId) === meta.aud || (expectedAudience + '/' + this.triggerId) === meta.aud;
|
|
367
|
-
if (!receivedMoreSpecific) {
|
|
368
|
-
this.logging.error(`Authorization header - Wrong audience, got ${meta?.aud}, expected ${expectedAudience}`);
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
const tokenSignature = (0, crypto_1.createHash)('sha256').update(accessToken).digest('hex');
|
|
373
|
-
const tokensServiceAccount = await this.get('google_identity_token_signature_' + tokenSignature, 'env', { encrypted: false, isEphemeral: true, store: 'global' });
|
|
374
|
-
if (tokensServiceAccount && allowedServiceAccounts.some(x => equalToWildcard(x, tokensServiceAccount))) {
|
|
375
|
-
return tokensServiceAccount;
|
|
376
|
-
}
|
|
377
|
-
const publicKey = await this.with('google_public_keys', 'env', {
|
|
378
|
-
encrypted: false,
|
|
379
|
-
ephemeralMs: 20 * 60 * 1000,
|
|
380
|
-
fetch: async () => {
|
|
381
|
-
const res = await fetch('https://www.googleapis.com/oauth2/v3/certs');
|
|
382
|
-
if (!res.ok) {
|
|
383
|
-
throw new Error(`Failed to fetch public keys: ${await res.text().catch(() => 'Unknown error')}`);
|
|
384
|
-
}
|
|
385
|
-
return res.text();
|
|
386
|
-
}
|
|
387
|
-
})(async (publicKeys) => {
|
|
388
|
-
const jwks = JSON.parse(publicKeys);
|
|
389
|
-
const keyInStorage = jwks?.keys.find((x) => x.kid === keyMeta.kid);
|
|
390
|
-
if (!keyInStorage) {
|
|
391
|
-
throw new Error('Google JWKS - Key not found in the Google JWKS set');
|
|
392
|
-
}
|
|
393
|
-
return keyInStorage;
|
|
394
|
-
});
|
|
395
|
-
try {
|
|
396
|
-
await (0, jose_1.jwtVerify)(accessToken, await (0, jose_1.importJWK)(publicKey, keyMeta.alg), {
|
|
397
|
-
issuer: ['https://accounts.google.com', 'accounts.google.com'],
|
|
398
|
-
clockTolerance: 0,
|
|
399
|
-
audience: [expectedAudience, expectedAudience + '-' + this.workflowId, expectedAudience + '-' + this.workflowId + '-' + this.triggerId, expectedAudience + '/' + this.workflowId + '/' + this.triggerId, expectedAudience + '/' + this.workflowId, expectedAudience + '/' + this.triggerId, expectedAudience + '-' + this.triggerId],
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
catch (err) {
|
|
403
|
-
this.logging.log(`Authorization header - Signature verification failed: ${err.message}`);
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
await this.set([{
|
|
407
|
-
name: 'google_identity_token_signature_' + tokenSignature,
|
|
408
|
-
value: meta.email
|
|
409
|
-
}], 'env', { encrypted: false, ephemeralMs: Math.max(tokenExpirationTime - Date.now(), 5 * 60 * 1000), ignoreStores: ['redis'] });
|
|
410
|
-
return meta.email;
|
|
411
|
-
}
|
|
412
|
-
withSecret(key) {
|
|
413
|
-
if (key.startsWith('process.secret.')) {
|
|
414
|
-
key = key.slice('process.secret.'.length);
|
|
415
|
-
}
|
|
416
|
-
return this.with('__secret_' + key, 'env', {
|
|
417
|
-
encrypted: true,
|
|
418
|
-
ephemeralMs: 5 * 60 * 1000,
|
|
419
|
-
fetch: () => {
|
|
420
|
-
return this.withGoogleAccessToken()(async (accessToken) => {
|
|
421
|
-
const secret = await (0, utils_1.getSecret)(this, key, accessToken);
|
|
422
|
-
return secret;
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
with(key, level = 'trigger', options) {
|
|
428
|
-
return async (fn) => {
|
|
429
|
-
let lastError;
|
|
430
|
-
let lastResult;
|
|
431
|
-
let valueFoundAndWorking = false;
|
|
432
|
-
const injectedFunction = async (value) => {
|
|
433
|
-
let nextValueFoundAndWorking = true;
|
|
434
|
-
const requestCacheRefresh = () => {
|
|
435
|
-
nextValueFoundAndWorking = false;
|
|
436
|
-
};
|
|
437
|
-
try {
|
|
438
|
-
const result = await fn(value, requestCacheRefresh);
|
|
439
|
-
lastResult = result;
|
|
440
|
-
lastError = undefined;
|
|
441
|
-
}
|
|
442
|
-
catch (err) {
|
|
443
|
-
lastError = err;
|
|
444
|
-
lastResult = undefined;
|
|
445
|
-
requestCacheRefresh();
|
|
446
|
-
}
|
|
447
|
-
valueFoundAndWorking = nextValueFoundAndWorking;
|
|
448
|
-
return valueFoundAndWorking;
|
|
449
|
-
};
|
|
450
|
-
let possibleValue = null;
|
|
451
|
-
let stores;
|
|
452
|
-
if (options?.ephemeralMs) {
|
|
453
|
-
stores = ['inMemory', 'global', 'redis'];
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
stores = ['firestore'];
|
|
457
|
-
}
|
|
458
|
-
const checkedStores = [];
|
|
459
|
-
for (let i = 0; i < stores.length; i++) {
|
|
460
|
-
const store = stores[i];
|
|
461
|
-
checkedStores.push(store);
|
|
462
|
-
const value = await this._get([key], level, { ...options, store: store, isEphemeral: true });
|
|
463
|
-
if (value[key].valid) {
|
|
464
|
-
possibleValue = Object.assign({}, value[key], {
|
|
465
|
-
checkedStores
|
|
466
|
-
});
|
|
467
|
-
if (await injectedFunction(value[key].value)) {
|
|
468
|
-
if (store === 'redis') {
|
|
469
|
-
this.set([{
|
|
470
|
-
name: key,
|
|
471
|
-
value: value[key].value
|
|
472
|
-
}], level, { encrypted: options?.encrypted || false, ephemeralMs: value[key].expiresAt - Date.now(), ignoreStores: ['redis'] });
|
|
473
|
-
}
|
|
474
|
-
return lastResult;
|
|
475
|
-
}
|
|
476
|
-
possibleValue = null;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
if (!possibleValue && options?.fetch) {
|
|
480
|
-
this.logging.log(`Value ${key} not found in the cache, fetching from the source`);
|
|
481
|
-
const value = await options?.fetch?.();
|
|
482
|
-
possibleValue = {
|
|
483
|
-
value: value,
|
|
484
|
-
valid: true,
|
|
485
|
-
createdAt: Date.now(),
|
|
486
|
-
expiresAt: Date.now() + (options?.ephemeralMs || 0),
|
|
487
|
-
};
|
|
488
|
-
await injectedFunction(value);
|
|
489
|
-
this.set([{
|
|
490
|
-
name: key,
|
|
491
|
-
value: value
|
|
492
|
-
}], level, { encrypted: options?.encrypted || false, ephemeralMs: options?.ephemeralMs || 0 });
|
|
493
|
-
}
|
|
494
|
-
if (lastError) {
|
|
495
|
-
throw lastError;
|
|
496
|
-
}
|
|
497
|
-
return lastResult;
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
pauseRespectfulNudge(subscriptionName, partialConfig) {
|
|
501
|
-
const workflowTriggerId = this.resolveEnvName(ENV_NAME_RN_WORFKLOW_TRIGGER_ID);
|
|
502
|
-
if (!workflowTriggerId) {
|
|
503
|
-
throw new Error('RN Workflow Trigger ID is not set. Please set the ' + ENV_NAME_RN_WORFKLOW_TRIGGER_ID + ' environment variable.');
|
|
504
|
-
}
|
|
505
|
-
const pubSubProjectId = this.resolveEnvName(ENV_NAME_PUBSUB_PROJECT_ID);
|
|
506
|
-
if (!pubSubProjectId) {
|
|
507
|
-
throw new Error('PubSub Project ID is not set. Please set the ' + ENV_NAME_PUBSUB_PROJECT_ID + ' environment variable.');
|
|
508
|
-
}
|
|
509
|
-
const rnConfig = Object.assign({}, {
|
|
510
|
-
workflowTriggerId: workflowTriggerId,
|
|
511
|
-
pubSubProjectId: pubSubProjectId,
|
|
512
|
-
}, partialConfig);
|
|
513
|
-
const subscriptionQualifiedName = `projects/${rnConfig.pubSubProjectId}/subscriptions/${subscriptionName}`;
|
|
514
|
-
return this.withGoogleIdentityToken({
|
|
515
|
-
workflowId: rnConfig.workflowTriggerId.split('/')[0],
|
|
516
|
-
triggerId: rnConfig.workflowTriggerId.split('/')[1],
|
|
517
|
-
})(async (token) => {
|
|
518
|
-
if (!(await fetch(this.runtimeUrl + `/executeWorkflow/${rnConfig.workflowTriggerId}`, {
|
|
519
|
-
method: 'POST',
|
|
520
|
-
headers: {
|
|
521
|
-
'X-Buildship-Trigger-Authorization': `Bearer ${token}`,
|
|
522
|
-
Authorization: `Bearer ${token}`,
|
|
523
|
-
'Content-Type': 'application/json'
|
|
524
|
-
},
|
|
525
|
-
body: JSON.stringify({
|
|
526
|
-
subscriptionName: subscriptionQualifiedName,
|
|
527
|
-
operation: 'pause',
|
|
528
|
-
})
|
|
529
|
-
})).ok) {
|
|
530
|
-
throw new Error('Failed to deactivate the main subscription with respectful nudge');
|
|
531
|
-
}
|
|
532
|
-
return true;
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
getRespectfulNudgeConfig(subscriptionName, rnPartialConfig) {
|
|
536
|
-
const workflowTriggerId = this.resolveEnvName(ENV_NAME_RN_WORFKLOW_TRIGGER_ID);
|
|
537
|
-
if (!workflowTriggerId) {
|
|
538
|
-
throw new Error('RN Workflow Trigger ID is not set. Please set the ' + ENV_NAME_RN_WORFKLOW_TRIGGER_ID + ' environment variable.');
|
|
539
|
-
}
|
|
540
|
-
const pubSubProjectId = this.resolveEnvName(ENV_NAME_PUBSUB_PROJECT_ID);
|
|
541
|
-
if (!pubSubProjectId) {
|
|
542
|
-
throw new Error('PubSub Project ID is not set. Please set the ' + ENV_NAME_PUBSUB_PROJECT_ID + ' environment variable.');
|
|
543
|
-
}
|
|
544
|
-
const rnConfig = Object.assign({}, {
|
|
545
|
-
pubSubProjectId: pubSubProjectId,
|
|
546
|
-
noAllowedWorkers: 1,
|
|
547
|
-
workflowTriggerId: this.workflowId + '/' + this.triggerId,
|
|
548
|
-
workerGroup: this.envName,
|
|
549
|
-
errorThreshold: 0.80,
|
|
550
|
-
error429Threshold: 0.30,
|
|
551
|
-
pauseOnErrorThresholdExceededSeconds: 60 * 10,
|
|
552
|
-
pauseOnError429ThresholdExceededSeconds: 60 * 10,
|
|
553
|
-
pauseBeforeProcessingMessagesSeconds: 0,
|
|
554
|
-
maxOutstandingMessages: 5,
|
|
555
|
-
ackDeadline: 10,
|
|
556
|
-
retryMinDelay: 60,
|
|
557
|
-
retryMaxDelay: 60 * 10,
|
|
558
|
-
retryLimit: 5,
|
|
559
|
-
topicName: subscriptionName,
|
|
560
|
-
tableName: '',
|
|
561
|
-
tableAckDeadline: 60,
|
|
562
|
-
tableRetryMinDelay: 60 * 5,
|
|
563
|
-
tableRetryMaxDelay: 60 * 10,
|
|
564
|
-
tableRetryLimit: 10,
|
|
565
|
-
orderingIndexFields: [],
|
|
566
|
-
orderingSortField: '',
|
|
567
|
-
batchSize: 1,
|
|
568
|
-
subscriptionFilter: null,
|
|
569
|
-
batchWindowSeconds: 10,
|
|
570
|
-
}, Object.fromEntries(Object.entries(rnPartialConfig).filter(x => !(x === null || x === undefined))));
|
|
571
|
-
return rnConfig;
|
|
572
|
-
}
|
|
573
|
-
createOrUpdateRespectfulNudge(subscriptionName, rnPartialConfig) {
|
|
574
|
-
const workflowTriggerId = this.resolveEnvName(ENV_NAME_RN_WORFKLOW_TRIGGER_ID);
|
|
575
|
-
if (!workflowTriggerId) {
|
|
576
|
-
throw new Error('RN Workflow Trigger ID is not set. Please set the ' + ENV_NAME_RN_WORFKLOW_TRIGGER_ID + ' environment variable.');
|
|
577
|
-
}
|
|
578
|
-
const pubSubProjectId = this.resolveEnvName(ENV_NAME_PUBSUB_PROJECT_ID);
|
|
579
|
-
if (!pubSubProjectId) {
|
|
580
|
-
throw new Error('PubSub Project ID is not set. Please set the ' + ENV_NAME_PUBSUB_PROJECT_ID + ' environment variable.');
|
|
581
|
-
}
|
|
582
|
-
const rnConfig = this.getRespectfulNudgeConfig(subscriptionName, rnPartialConfig);
|
|
583
|
-
const subscriptionQualifiedName = `projects/${rnConfig.pubSubProjectId}/subscriptions/${subscriptionName}`;
|
|
584
|
-
return this.withGoogleIdentityToken({
|
|
585
|
-
workflowId: workflowTriggerId.split('/')[0],
|
|
586
|
-
triggerId: workflowTriggerId.split('/')[1],
|
|
587
|
-
})(async (token) => {
|
|
588
|
-
const response = await fetch(this.runtimeUrl + `/executeWorkflow/${workflowTriggerId}`, {
|
|
589
|
-
method: 'POST',
|
|
590
|
-
headers: {
|
|
591
|
-
'X-Buildship-Trigger-Authorization': `Bearer ${token}`,
|
|
592
|
-
Authorization: `Bearer ${token}`,
|
|
593
|
-
'Content-Type': 'application/json'
|
|
594
|
-
},
|
|
595
|
-
body: JSON.stringify({
|
|
596
|
-
...rnConfig,
|
|
597
|
-
subscriptionName: subscriptionQualifiedName,
|
|
598
|
-
operation: 'upsert',
|
|
599
|
-
})
|
|
600
|
-
});
|
|
601
|
-
if (!response.ok) {
|
|
602
|
-
throw new Error('Failed to register the main subscription with respectful nudge');
|
|
603
|
-
}
|
|
604
|
-
return true;
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
getRequestSource(request) {
|
|
608
|
-
const reqIsRespectfulNudge = (0, utils_1.isRespectfulNudge)(request.headers);
|
|
609
|
-
if (reqIsRespectfulNudge) {
|
|
610
|
-
return 'respectful-nudge';
|
|
611
|
-
}
|
|
612
|
-
const reqIsPubSub = (0, utils_1.isPubSubRequest)(request.headers);
|
|
613
|
-
if (reqIsPubSub) {
|
|
614
|
-
return 'pubsub';
|
|
615
|
-
}
|
|
616
|
-
const reqIsScheduler = (0, utils_1.isCronMessage)(request.headers);
|
|
617
|
-
if (reqIsScheduler) {
|
|
618
|
-
return 'scheduler';
|
|
619
|
-
}
|
|
620
|
-
const reqIsCloudTask = (0, utils_1.isCloudTask)(request.headers);
|
|
621
|
-
if (reqIsCloudTask) {
|
|
622
|
-
return 'cloud-task';
|
|
623
|
-
}
|
|
624
|
-
return 'direct';
|
|
625
|
-
}
|
|
626
|
-
async validateAuthorizationHeader(request) {
|
|
627
|
-
const authHeader = request.headers.authorization;
|
|
628
|
-
if (!authHeader || typeof authHeader !== 'string') {
|
|
629
|
-
throw new Error('Missing Authorization Header');
|
|
630
|
-
}
|
|
631
|
-
const allowedServiceAccounts = this.resolveEnvName(ENV_NAME_CONTAINING_SERVICE_ACCOUNTS).split(";").map(x => {
|
|
632
|
-
const [serviceAccount, ...flags] = x.trim().split(",").map(y => y.trim());
|
|
633
|
-
return {
|
|
634
|
-
flags,
|
|
635
|
-
serviceAccount
|
|
636
|
-
};
|
|
637
|
-
});
|
|
638
|
-
const serviceAccount = await this.checkGoogleIdentiyToken(authHeader.slice('Bearer '.length), undefined, allowedServiceAccounts.map(x => x.serviceAccount));
|
|
639
|
-
if (!serviceAccount) {
|
|
640
|
-
throw new Error('Invalid Authorization Header');
|
|
641
|
-
}
|
|
642
|
-
const flags = allowedServiceAccounts.find(x => x.serviceAccount === serviceAccount)?.flags || [];
|
|
643
|
-
if (!flags.includes('env-' + this.envName)) {
|
|
644
|
-
throw new Error('No permissions to access the environment ' + this.envName);
|
|
645
|
-
}
|
|
646
|
-
return {
|
|
647
|
-
serviceAccount,
|
|
648
|
-
flags: flags
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
async decodeRequests(request, nodeReq) {
|
|
652
|
-
const requestSource = this.getRequestSource(request);
|
|
653
|
-
let requestBody = null;
|
|
654
|
-
const rawRequestBody = null;
|
|
655
|
-
if (requestSource === 'pubsub' || requestSource === 'respectful-nudge' || request.headers['content-type'] === 'application/json') {
|
|
656
|
-
const rawRequestBody = co_body_1.default.text(nodeReq, {
|
|
657
|
-
limit: '2mb'
|
|
658
|
-
});
|
|
659
|
-
requestBody = await (rawRequestBody.then(x => JSON.parse(x || 'null')).catch(err => {
|
|
660
|
-
throw new Error('Could not parse the request of the body. Body provided: ' + requestBody + '. Error message: ' + err.message);
|
|
661
|
-
}));
|
|
662
|
-
}
|
|
663
|
-
const receivedArrayOfRequests = Array.isArray(requestBody);
|
|
664
|
-
const requestBodies = receivedArrayOfRequests ? requestBody : [requestBody];
|
|
665
|
-
const messages = [];
|
|
666
|
-
for (let i = 0; i < requestBodies.length; i++) {
|
|
667
|
-
const requestBody = requestBodies[i];
|
|
668
|
-
let messageBody;
|
|
669
|
-
let messageBodyRaw = null;
|
|
670
|
-
if (typeof requestBody?.message?.data === 'string' && Buffer.from(requestBody.message.data, "base64").toString('base64') === requestBody.message.data) {
|
|
671
|
-
messageBodyRaw = Buffer.from(requestBody.message.data, "base64").toString('utf-8');
|
|
672
|
-
messageBody = await (Promise.resolve(messageBodyRaw).then(x => JSON.parse(x)).catch((_) => ({
|
|
673
|
-
error: 'Could not parse the message body. Original body: ' + messageBodyRaw + ' . Error: ' + _.message,
|
|
674
|
-
})));
|
|
675
|
-
}
|
|
676
|
-
else if (typeof requestBody?.message?.data === 'object' && typeof requestBody.subscription === 'string') {
|
|
677
|
-
messageBodyRaw = JSON.stringify(requestBody.message.data);
|
|
678
|
-
messageBody = requestBody.message.data;
|
|
679
|
-
}
|
|
680
|
-
else {
|
|
681
|
-
messageBody = requestBody;
|
|
682
|
-
messageBodyRaw = receivedArrayOfRequests ? rawRequestBody : JSON.stringify(requestBody);
|
|
683
|
-
}
|
|
684
|
-
const message = {
|
|
685
|
-
requestSource: requestSource,
|
|
686
|
-
messageId: requestBody?.message?.messageId || undefined,
|
|
687
|
-
sourceSystem: requestBody?.message?.attributes?.source_system || 'unknown',
|
|
688
|
-
targetSystem: requestBody?.message?.attributes?.target_system || 'unknown',
|
|
689
|
-
buildshipId: requestBody?.message?.attributes?.buildship_id || 'unknown',
|
|
690
|
-
publishTime: (0, utils_1.parseDateOrDefault)(requestBody?.message?.publish_time),
|
|
691
|
-
body: messageBody,
|
|
692
|
-
bodyTxt: messageBodyRaw,
|
|
693
|
-
exportableToBigQuery: !!requestBody?.message?.attributes?.bigquery,
|
|
694
|
-
extraAttributes: Object.assign({}, request.query, (0, lodash_omit_1.default)(requestBody?.message?.attributes || {}, ['source_system', 'target_system', 'buildship_id', 'bigquery'])),
|
|
695
|
-
subscriptionName: (requestBody?.subscription?.split('/')?.pop() || request.query.subscriptionName)?.replace(/^rn\./, ''),
|
|
696
|
-
};
|
|
697
|
-
messages.push(message);
|
|
698
|
-
}
|
|
699
|
-
return messages;
|
|
700
|
-
}
|
|
701
|
-
async decodeRequest(request, nodeReq) {
|
|
702
|
-
const requests = await this.decodeRequests(request, nodeReq);
|
|
703
|
-
if (requests.length > 0) {
|
|
704
|
-
this.logging.error('Received multiple requests in the same batch. This is not supported. Picking the first message from the request');
|
|
705
|
-
}
|
|
706
|
-
return requests[0];
|
|
707
|
-
}
|
|
708
|
-
async fetchLogEntries(triggerId, retries = 3, delay = 1000, filterOverride = null) {
|
|
709
|
-
const getAccessToken = async () => {
|
|
710
|
-
const response = await fetch("http://metadata/computeMetadata/v1/instance/service-accounts/default/token", {
|
|
711
|
-
headers: { "Metadata-Flavor": "Google" },
|
|
712
|
-
});
|
|
713
|
-
if (!response.ok) {
|
|
714
|
-
throw new Error(`Failed to obtain access token: ${response.statusText}`);
|
|
715
|
-
}
|
|
716
|
-
const data = await response.json();
|
|
717
|
-
return {
|
|
718
|
-
accessToken: data.access_token,
|
|
719
|
-
expiresAt: new Date(new Date().getTime() + ((data.expires_in * 1000)) - ((data.expires_in * 1000) * 9 / 10))
|
|
720
|
-
};
|
|
721
|
-
};
|
|
722
|
-
const projectId = process.env.GCLOUD_PROJECT;
|
|
723
|
-
const accessToken = (await getAccessToken()).accessToken;
|
|
724
|
-
let filter = `logName="projects/${projectId}/logs/buildship-node-io" AND jsonPayload.nId="${triggerId}"`;
|
|
725
|
-
if (filterOverride) {
|
|
726
|
-
filter = filterOverride;
|
|
727
|
-
}
|
|
728
|
-
const requestBody = {
|
|
729
|
-
resourceNames: [`projects/${projectId}`],
|
|
730
|
-
filter: filter,
|
|
731
|
-
pageSize: 1,
|
|
732
|
-
orderBy: "timestamp desc",
|
|
733
|
-
};
|
|
734
|
-
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
735
|
-
try {
|
|
736
|
-
const response = await fetch("https://logging.googleapis.com/v2/entries:list", {
|
|
737
|
-
method: "POST",
|
|
738
|
-
headers: {
|
|
739
|
-
Authorization: `Bearer ${accessToken}`,
|
|
740
|
-
"Content-Type": "application/json",
|
|
741
|
-
},
|
|
742
|
-
body: JSON.stringify(requestBody),
|
|
743
|
-
});
|
|
744
|
-
if (!response.ok) {
|
|
745
|
-
const errorText = await response.text();
|
|
746
|
-
throw new Error(`Error fetching log entries: ${response.statusText} - ${errorText}`);
|
|
747
|
-
}
|
|
748
|
-
const data = await response.json();
|
|
749
|
-
const entries = data.entries || [];
|
|
750
|
-
if (entries.length > 0) {
|
|
751
|
-
return entries;
|
|
752
|
-
}
|
|
753
|
-
if (attempt < retries) {
|
|
754
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
catch (error) {
|
|
758
|
-
console.error(`Attempt ${attempt} failed due to an error:`, error);
|
|
759
|
-
if (attempt < retries) {
|
|
760
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
throw new Error(`Failed to get data after ${retries} attempts.`);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
throw new Error("No data found. Send a request to the API and try again.");
|
|
768
|
-
}
|
|
769
|
-
;
|
|
770
|
-
getPubSubHelper(PubSubClass) {
|
|
771
|
-
const pubSubProjectId = this.resolveEnvName(ENV_NAME_PUBSUB_PROJECT_ID);
|
|
772
|
-
if (!pubSubProjectId) {
|
|
773
|
-
throw new Error('PubSub Project ID is not set. Please set the ' + ENV_NAME_PUBSUB_PROJECT_ID + ' environment variable.');
|
|
774
|
-
}
|
|
775
|
-
const serviceAccount = this.resolveEnvName(ENV_NAME_PUBSUB_SERVICE_ACCOUNT);
|
|
776
|
-
if (!serviceAccount) {
|
|
777
|
-
throw new Error('PubSub Service Account is not set. Please set the ' + ENV_NAME_PUBSUB_SERVICE_ACCOUNT + ' environment variable.');
|
|
778
|
-
}
|
|
779
|
-
const pubSub = global.HUSH_PUBSUB_INSTANCE || new PubSubClass({
|
|
780
|
-
projectId: pubSubProjectId
|
|
781
|
-
});
|
|
782
|
-
global.HUSH_PUBSUB_INSTANCE = pubSub;
|
|
783
|
-
return new pubsub_1.default(this, {
|
|
784
|
-
serviceAccountEmail: serviceAccount
|
|
785
|
-
}, pubSub);
|
|
786
|
-
}
|
|
787
|
-
static LOCK_NOT_ACQUIRED_ERROR = Symbol('Lock not acquired');
|
|
788
|
-
async withLock(key, maxWaitTimeMs = 200, fn) {
|
|
789
|
-
let result = EnvEngine.LOCK_NOT_ACQUIRED_ERROR;
|
|
790
|
-
if (await this.acquireLock(key, maxWaitTimeMs)) {
|
|
791
|
-
try {
|
|
792
|
-
result = await fn();
|
|
793
|
-
}
|
|
794
|
-
catch (err) {
|
|
795
|
-
await this.releaseLock(key);
|
|
796
|
-
throw err;
|
|
797
|
-
}
|
|
798
|
-
await this.releaseLock(key);
|
|
799
|
-
}
|
|
800
|
-
return result;
|
|
801
|
-
}
|
|
802
|
-
async acquireLock(key, maxWaitTimeMs = 200) {
|
|
803
|
-
if (!this._lockRateLimiter) {
|
|
804
|
-
return true;
|
|
805
|
-
}
|
|
806
|
-
try {
|
|
807
|
-
await this._lockRateLimiter.consume(key);
|
|
808
|
-
}
|
|
809
|
-
catch (err) {
|
|
810
|
-
if (err instanceof Error) {
|
|
811
|
-
throw err;
|
|
812
|
-
}
|
|
813
|
-
if (maxWaitTimeMs > 0) {
|
|
814
|
-
await new Promise((resolve) => setTimeout(resolve, maxWaitTimeMs));
|
|
815
|
-
return this.acquireLock(key, 0);
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
return false;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
return true;
|
|
822
|
-
}
|
|
823
|
-
async releaseLock(key) {
|
|
824
|
-
if (this._lockRateLimiter) {
|
|
825
|
-
await this._lockRateLimiter.reward(key, 1);
|
|
826
|
-
}
|
|
827
|
-
return true;
|
|
828
|
-
}
|
|
829
|
-
async getLockRateLimiter() {
|
|
830
|
-
const redisClient = await (0, redisClient_1.getConnectedRedisClient)(this.systemEnvName);
|
|
831
|
-
if (!redisClient) {
|
|
832
|
-
return null;
|
|
833
|
-
}
|
|
834
|
-
if (!this._lockRateLimiter) {
|
|
835
|
-
const lockMemory = new rate_limiter_flexible_1.RateLimiterMemory({
|
|
836
|
-
points: 1,
|
|
837
|
-
duration: 60 * 3,
|
|
838
|
-
});
|
|
839
|
-
const lockRedis = new rate_limiter_flexible_1.RateLimiterRedis({
|
|
840
|
-
storeClient: redisClient,
|
|
841
|
-
points: 1,
|
|
842
|
-
duration: 60 * 3,
|
|
843
|
-
insuranceLimiter: lockMemory,
|
|
844
|
-
});
|
|
845
|
-
this._lockRateLimiter = lockRedis;
|
|
846
|
-
}
|
|
847
|
-
return this._lockRateLimiter;
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
class AES256GCM {
|
|
851
|
-
normalizedKey;
|
|
852
|
-
constructor(key) {
|
|
853
|
-
this.normalizedKey = crypto
|
|
854
|
-
.createHash("sha256")
|
|
855
|
-
.update(key)
|
|
856
|
-
.digest()
|
|
857
|
-
.slice(0, 32);
|
|
858
|
-
}
|
|
859
|
-
pad(payload) {
|
|
860
|
-
const padLength = 8 - (payload.length % 8);
|
|
861
|
-
return Buffer.concat([payload, Buffer.alloc(padLength, padLength)]);
|
|
862
|
-
}
|
|
863
|
-
getNormalizedKey() {
|
|
864
|
-
return this.getNormalizedKey;
|
|
865
|
-
}
|
|
866
|
-
encrypt(payload) {
|
|
867
|
-
const normalizedWrappingKey = this.normalizedKey;
|
|
868
|
-
const paddedPayload = this.pad(Buffer.from(payload));
|
|
869
|
-
const iv = crypto.randomBytes(12);
|
|
870
|
-
const cipher = crypto.createCipheriv("aes-256-gcm", normalizedWrappingKey, iv);
|
|
871
|
-
const encryptedPayload = Buffer.concat([
|
|
872
|
-
cipher.update(paddedPayload),
|
|
873
|
-
cipher.final(),
|
|
874
|
-
]);
|
|
875
|
-
const authTag = cipher.getAuthTag();
|
|
876
|
-
return (encryptedPayload.toString("base64") +
|
|
877
|
-
"." +
|
|
878
|
-
iv.toString("base64") +
|
|
879
|
-
"." +
|
|
880
|
-
authTag.toString("base64"));
|
|
881
|
-
}
|
|
882
|
-
decrypt(payload) {
|
|
883
|
-
const [encryptedKey64, iv64, authTag64] = payload.split(".");
|
|
884
|
-
const encryptedPayload = Buffer.from(encryptedKey64, "base64");
|
|
885
|
-
const iv = Buffer.from(iv64, "base64");
|
|
886
|
-
const authTag = Buffer.from(authTag64, "base64");
|
|
887
|
-
const decipher = crypto.createDecipheriv("aes-256-gcm", this.normalizedKey, iv);
|
|
888
|
-
decipher.setAuthTag(authTag);
|
|
889
|
-
const paddedKey = Buffer.concat([
|
|
890
|
-
decipher.update(encryptedPayload),
|
|
891
|
-
decipher.final(),
|
|
892
|
-
]);
|
|
893
|
-
const padLength = paddedKey[paddedKey.length - 1];
|
|
894
|
-
return paddedKey.slice(0, -padLength).toString();
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
exports.default = EnvEngine;
|