piper-utils 1.1.61 → 1.1.62

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/bin/main.js CHANGED
@@ -1,1264 +1,368 @@
1
- /******/ (() => { // webpackBootstrap
2
- /******/ "use strict";
3
- /******/ var __webpack_modules__ = ({
4
-
5
- /***/ "./src/database/dbSetup/migrations.js"
6
- /*!********************************************!*\
7
- !*** ./src/database/dbSetup/migrations.js ***!
8
- \********************************************/
9
- (__unused_webpack_module, exports, __webpack_require__) {
10
-
11
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.runMigrations = runMigrations;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
12
- var _umzug = __webpack_require__(/*! umzug */ "umzug");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
13
-
1
+ /******/(()=>{// webpackBootstrap
2
+ /******/"use strict";
3
+ /******/var __webpack_modules__={
4
+ /***/31(module){module.exports=require("sequelize");
5
+ /***/},
6
+ /***/43(module){module.exports=require("@aws-sdk/client-s3");
7
+ /***/},
8
+ /***/59(module){module.exports=require("dayjs/plugin/customParseFormat");
9
+ /***/},
10
+ /***/64(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _libDynamodb=__webpack_require__(515),_clientDynamodb=__webpack_require__(929);const dynamoUtil={get:params=>
14
11
  /**
15
- * Execute database migrations
16
- * @param {string} databaseName - name of database to create (or verify existence)
17
- * @param {object} sequelizeInstance - instance of Sequelize (must be initialized)
18
- * @param {function} initializeModels - function to run to sync Sequelize models with database
19
- * @param {string} pathToMigrationFolder - pass in the path if using windows. windows and linux PWD will be different
20
- */
21
- async function runMigrations(databaseName,
22
- sequelizeInstance,
23
- initializeModels,
24
- pathToMigrationFolder = `${process.env.PWD}/migrations/*.js`) {
25
- const umzug = new _umzug.Umzug({
26
- migrations: { glob: pathToMigrationFolder },
27
- context: sequelizeInstance.getQueryInterface(),
28
- storage: new _umzug.SequelizeStorage({ sequelize: sequelizeInstance }),
29
- logger: console
30
- });
31
-
32
- const pendingMigrations = await umzug.pending();
33
- console.log('------->UTIL Pending Migrations:', pendingMigrations, pathToMigrationFolder);
34
- await umzug.up().catch((upError) => {
35
- console.error('Migration Error: ', upError);
36
- return umzug.down({
37
- migrations: _lodash.default.chain(pendingMigrations).
38
- map('file').
39
- reverse().
40
- value()
41
- }).then(() => {
42
- const msg = 'UTIL Error: Error with migrating up:' + upError;
43
- console.error(msg);
44
- throw new Error(msg);
45
- }, (downError) => {
46
- const msg = 'UTIL Error: Error with migrating down:' + downError;
47
- console.error(msg);
48
- throw new Error(msg);
49
- });
50
- });
51
-
52
- // The following line is needed to sync (create) tables, but not to database updates
53
- // in the past it worked to leave it in, but now the tags module causes foreign key problems
54
- // The tables are still initiated by being passed in to run migrations
55
- await initializeModels();
56
- }
57
-
58
- /***/ },
59
-
60
- /***/ "./src/database/dbUtils/queryStringUtils/accessRightsUtils.js"
61
- /*!********************************************************************!*\
62
- !*** ./src/database/dbUtils/queryStringUtils/accessRightsUtils.js ***!
63
- \********************************************************************/
64
- (__unused_webpack_module, exports, __webpack_require__) {
65
-
66
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.accessRightsUtils = accessRightsUtils;exports.checkIsSuper = checkIsSuper;exports.checkModule = checkModule;exports.checkWriteAccess = checkWriteAccess;exports.enrichEventWithPartnerAccess = enrichEventWithPartnerAccess;exports.getAccessRightsInfo = getAccessRightsInfo;exports.getBelongsToPartnerId = getBelongsToPartnerId;exports.getBusinessesInfo = getBusinessesInfo;exports.getCompanySettings = getCompanySettings;exports.getDefaultBusinessIDInfo = getDefaultBusinessIDInfo;exports.getEffectivePartnerId = getEffectivePartnerId;exports.getModuleInfo = getModuleInfo;exports.getRequestedBusinessIds = getRequestedBusinessIds;exports.isPartnerUser = isPartnerUser;exports.isSuperUser = isSuperUser;exports.isSystemUser = isSystemUser;exports.userDefaultBid = userDefaultBid;exports.userRoles = void 0;var _lodash = _interopRequireWildcard(__webpack_require__(/*! lodash */ "lodash"));
67
- var _errorCodes = __webpack_require__(/*! ../../../requestResponse/errorCodes.js */ "./src/requestResponse/errorCodes.js");
68
- var _requestResponse = __webpack_require__(/*! ../../../requestResponse/requestResponse.js */ "./src/requestResponse/requestResponse.js");function _interopRequireWildcard(e, t) {if ("function" == typeof WeakMap) var r = new WeakMap(),n = new WeakMap();return (_interopRequireWildcard = function (e, t) {if (!t && e && e.__esModule) return e;var o,i,f = { __proto__: null, default: e };if (null === e || "object" != typeof e && "function" != typeof e) return f;if (o = t ? n : r) {if (o.has(e)) return o.get(e);o.set(e, f);}for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]);return f;})(e, t);}
69
-
70
- function isSystemUser(event) {
71
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:SYSTEM') ||
72
- _lodash.default.get(event, 'requestContext.authorizer.custom:SYSTEM') ||
73
- 'false';
74
- let isSys = false;
75
- try {
76
- isSys = JSON.parse(jsonToParse);
77
- return isSys;
78
- } catch (e) {
79
- console.error('error with system user:', e);
80
-
81
- return false;
82
- }
83
- }
84
-
85
- function isSuperUser(event) {
86
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:SUPER') ||
87
- _lodash.default.get(event, 'requestContext.authorizer.custom:SUPER') ||
88
- 'false';
89
- let isSys = false;
90
-
91
- try {
92
- isSys = JSON.parse(jsonToParse);
93
-
94
- return isSys;
95
- } catch (e) {
96
-
97
- return false;
98
- }
99
- }
100
-
101
- /**
102
- * Throws unauthorized error if the user is not a super user.
103
- * Mirrors the behavior and style of checkModule but focused on SUPER role.
104
- *
105
- * @param {object} event - The lambda event passed in by a validated api request.
106
- */
107
- function checkIsSuper(event) {
108
- // Super or System users are always allowed
109
- if (isSuperUser(event)) {
110
- return;
111
- }
112
- if (isSystemUser(event)) {
113
- return;
114
- }
115
-
116
- // In local builds allow bypass to ease development and tests
117
- if (process.env.BUILD_ENV === 'local') {
118
- return;
119
- }
120
-
121
- throw _errorCodes.errorList.unauthorized;
122
- }
123
-
124
- /**
125
- * Get the allowed businessIds for a user from the lambda event, compare it to businessIds, return what user has access to.
126
- *
127
- * @param {object} event - The lambda event passed in by a validated api request.
128
- * @param {{useCognitoBid:boolean}} [options] - An object with options, useCognitoBid prefers the businessId set in cognito if set and does not return the local bid of 1 if a bid is in the claim.
129
- * @returns {array} A list of businessIds that have been requested and are allowed to for some user.
130
- */
131
- function accessRightsUtils(event, options) {
132
- const useCognitoBid = _lodash.default.get(options, 'useCognitoBid', false);
133
- const requestedBusinessIds = getRequestedBusinessIds(event);
134
- const allowedBusinessIds = getAllowedBusinessIds(event, useCognitoBid);
135
-
136
- if (isSuperUser(event)) {
137
- let v = requestedBusinessIds;
138
- if (_lodash.default.isEmpty(requestedBusinessIds)) {
139
- v = allowedBusinessIds;
140
- }
141
-
142
- return v;
143
- }
144
- if (isSystemUser(event)) {
145
- return requestedBusinessIds;
146
- }
147
-
148
- if (requestedBusinessIds.length === 0) {
149
- return allowedBusinessIds;
150
- }
151
-
152
- return _lodash.default.intersection(requestedBusinessIds, allowedBusinessIds);
153
- }
154
-
155
- /**
156
- * Get the businessID set in cognito as custom:DBI.
157
- *
158
- * @param {object} event - The lambda event passed in by a validated api request.
159
- * @returns {string} The businessID set in cognito as custom:DBI
160
- */
161
- function userDefaultBid(event) {
162
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:DBI') ||
163
- _lodash.default.get(event, 'requestContext.authorizer.custom:DBI') ||
164
- '{}';
165
-
166
- const dbi = JSON.parse(jsonToParse);
167
- return _lodash.default.get(dbi, 'defaultBid', '') || '1';
168
- }
169
-
170
- /**
171
- * Get requested businessIds from the query string.
172
- *
173
- * @param {object} event - The lambda event passed in by a validated api request.
174
- * @returns {array} The businessID requested by the query string
175
- */
176
- function getRequestedBusinessIds(event) {
177
- let requestedBusinessIds = _lodash.default.get(event, 'queryStringParameters.businessIds', null);
178
- const body = (0, _requestResponse.parseBody)(event);
179
- const bodyBid = body?.businessId;
180
- if (requestedBusinessIds) {
181
- return requestedBusinessIds ? requestedBusinessIds.split(',') : [];
182
- } else if (bodyBid) {
183
- return [bodyBid];
184
- } else {
185
- return [];
186
- }
187
- }
188
-
189
- /**
190
- * Get the allowed businessIds for a user from cognito custom:AR property.
191
- *
192
- * @param {object} event - The lambda event passed in by a validated api request.
193
- * @param useCognitoBid
194
- * @returns {array} The businessID requested by the query string
12
+ * @param {{TableName:string, Key:{key:string}}} params
195
13
  */
196
- function getAllowedBusinessIds(event, useCognitoBid) {
197
- const businesses = getBusinessesInfo(event, useCognitoBid);
198
- return Object.keys(businesses);
199
- }
200
-
201
- function getAccessRightsInfo(event) {
202
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:AR') ||
203
- _lodash.default.get(event, 'requestContext.authorizer.custom:AR') ||
204
- '{}';
205
- const accessRights = JSON.parse(jsonToParse);
206
- return _lodash.default.get(accessRights, 'businessIds', {});
207
- }
208
-
209
- function getDefaultBusinessIDInfo(event) {
210
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:DBI') ||
211
- _lodash.default.get(event, 'requestContext.authorizer.custom:DBI') ||
212
- '{}';
213
- const dbi = JSON.parse(jsonToParse);
214
-
215
- return _lodash.default.get(dbi, 'defaultBid', '1');
216
- }
217
-
218
- function getBusinessesInfo(event, useCognitoBid = false) {
219
- const json = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:AR') ||
220
- _lodash.default.get(event, 'requestContext.authorizer.custom:AR') ||
221
- '{}';
222
-
223
- let businessIds = _lodash.default.get(JSON.parse(json), 'businessIds', {});
224
-
225
- // Local environment tweaks
226
- if (process.env.BUILD_ENV === 'local') {
227
- let b;
228
- try {
229
- b = JSON.parse(event?.body);
230
- } catch (e) {
231
- }
232
- const bodyBid = b?.businessId;
233
- // Always inject the default local BID “1” unless the caller explicitly wants
234
- // what Cognito says **and** Cognito actually returned something.
235
- if (!useCognitoBid) {
236
- businessIds = { ...businessIds, '1': 'A' };
237
- }
238
-
239
- // If Cognito gave no BIDs at all, fall back to the local default.
240
- if ((0, _lodash.isEmpty)(businessIds)) {
241
- businessIds = { '1': 'A' };
242
- }
243
- // a businessId is found on the body for local allow it
244
- if (bodyBid) {
245
- businessIds[bodyBid] = 'A';
246
- }
247
- }
248
-
249
- return businessIds;
250
- }
251
-
252
- /**
253
- * Get the modules listed in custom:MOD.
254
- *
255
- * @param {object} event - The lambda event passed in by a validated api request.
256
- * @returns {array} The Module access list
14
+ async function get(params){return _libDynamodb.DynamoDBDocument.from(new _clientDynamodb.DynamoDB).get(params)}(params)};exports.default=dynamoUtil;
15
+ /***/},
16
+ /***/95(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleDirectS3WriteEvent=function handleDirectS3WriteEvent(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders=!1,userImportTypes){if(!event||!event.Records)return _bluebird.default.resolve();let hasErrors=!1;return _bluebird.default.map(event.Records,record=>{const s3Bucket=record.s3.bucket.name,file=record.s3.object.key||[];let path=decodeURIComponent(file);if(path)return(0,_handleFile.handleFile)(path,s3Bucket,transformer,{shouldSkipFailedFolders,userImportTypes}).catch(err=>{errorHandlerPerFile&&!errorHandlerPerFile(err,path)&&(console.error("HANDLE-FILE-CATCH:",err),hasErrors=!0)})}).then(()=>{if(hasErrors)throw new Error("ERROR: HANDLE-FILE (DIRECT S3 EVENT)")})}
17
+ /***/,exports.handleEvents=function handleEvents(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders=!1,userImportTypes){if(!event||!event.Records)return _bluebird.default.resolve();let hasErrors=!1;return _bluebird.default.map(event.Records,record=>{const snsInfo=JSON.parse(_lodash.default.get(record,"Sns.Message","{}")),s3Bucket=snsInfo.bucket,files=snsInfo.files||[];return _bluebird.default.map(files,file=>{let path=decodeURIComponent(file);if(path)return(0,_handleFile.handleFile)(path,s3Bucket,transformer,{shouldSkipFailedFolders,userImportTypes}).catch(err=>{errorHandlerPerFile&&!errorHandlerPerFile(err,path)&&(console.error("HANDLE-FILE-CATCH: ",err),hasErrors=!0)})})}).then(()=>{if(hasErrors)throw new Error("ERROR: HANDLE-FILE")})};var _handleFile=__webpack_require__(876),_lodash=_interopRequireDefault(__webpack_require__(825)),_bluebird=_interopRequireDefault(__webpack_require__(564));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},
18
+ /***/137(module){module.exports=require("dayjs/plugin/utc.js");
19
+ /***/},
20
+ /***/183(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.watchBucket=
21
+ /**
22
+ * bucket watcher watches a s3 bucket and publishes events to a sns topic, this allows you to process files in s3 with a some transformer function
23
+ * prefix objects with DIRECT to listen to direct s3 events
24
+ *
25
+ * @param {object} params - The parameters for watchBucket, see below
26
+ * @param {object} params.event - The event of the lambda
27
+ * @param {string} params.dynamoConfigTable - The Dynamo DB table where to get the chunkSize and maxMessage size
28
+ * @param {string} params.dynamoConfigKey - The key to the item in the Dynamo DB table that holds the chunkSize and maxMessage size
29
+ * @param {string} params.s3Bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created
30
+ * @param {string} params.snsTopic - The name of the snsEvent to publish
31
+ * @param {function} params.transformer - the function to run on each file
32
+ * @param {function} [params.errorHandlerPerFile] - the function to run on as a catch on each file
33
+ * @param {boolean} [params.shouldSkipFailedFolders] - whether to use the failed-once, failed-twice, error or just error folders
34
+ * @param {object} [params.userImportTypes] - user import subdirectories object map
257
35
  */
258
- function getModuleInfo(event) {
259
- let jsonToParse =
260
- _lodash.default.get(event, 'requestContext.authorizer.claims.custom:MOD') ||
261
- _lodash.default.get(event, 'requestContext.authorizer.custom:MOD') ||
262
- _lodash.default.get(event, 'requestContext.authorizer.claims.custom:AR') ||
263
- _lodash.default.get(event, 'requestContext.authorizer.custom:AR') ||
264
-
265
- '{}';
266
-
267
- const moduleRights = JSON.parse(jsonToParse);
268
- return _lodash.default.get(moduleRights, 'module', {});
269
- }
270
-
271
- /**
272
- * Get the modules listed in custom:MOD.
273
- *
274
- * @param {string} moduleName - A sting name for a module.
275
- * @param {object} event - The lambda event passed in by a validated api request.
276
- * @returns {array} The Module access list
36
+ function watchBucket({event,dynamoConfigTable,dynamoConfigKey,s3Bucket,snsTopic,transformer,errorHandlerPerFile=_lodash.default.noop,shouldSkipFailedFolders=!1,userImportTypes}){if(!(event&&dynamoConfigTable&&dynamoConfigKey&&s3Bucket&&snsTopic&&transformer))throw new Error("Missing required parameters. Need event, dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, transformer");const EventSource=_lodash.default.get(event,"Records[0].eventSource")||_lodash.default.get(event,"Records[0].EventSource");if(_lodash.default.isEqual(EventSource,"aws:sns"))return(0,_handleEvents.handleEvents)(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders,userImportTypes);if(!_lodash.default.isEqual(EventSource,"aws:s3"))
37
+ // the function is being run from the cron job so publish SNS events
38
+ return(0,_publishEvents.publishEvents)(dynamoConfigTable,dynamoConfigKey,s3Bucket,snsTopic,userImportTypes);{const failedOnce="failed-once",failedTwice="failed-twice",error="error",direct="DIRECT",key=_lodash.default.get(event,"Records[0].s3.object.key")||"",startsWithDirect=_lodash.default.startsWith(key,direct);if(key.includes(failedOnce)||key.includes(failedTwice)||key.includes(error))
39
+ // this used to throw, but the throw raised useless alarms, I believed turing throw in to a return was ok
40
+ return;if(startsWithDirect)return console.log("-------\x3eDIRECT WRITE FIRE"),(0,_handleEvents.handleDirectS3WriteEvent)(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders,userImportTypes)}}
41
+ /***/;var _publishEvents=__webpack_require__(864),_handleEvents=__webpack_require__(95),_lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825))},
42
+ /***/207(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.addFiltersFromSchema=addFiltersFromSchema,exports.defaultFilters=
43
+ /**
44
+ * Create an object with default filters for a given sequeliaze Schema Object, and set of sub schemas
45
+ *
46
+ * @param {object} schema - type is sequelize data type
47
+ * @param {object} subSchemas - An object with alias as the key and sequelize schema as the value http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-method-define
48
+ * sub schema can be {location: locationSchema} or {location: {as: "asAlias", schema: schema}}
49
+ * @returns {object} An Object with a default filter for each dataType CHAR and TEXT will get a $like operator, INTEGER, DECIMAL and BOOLEAN will get a $eq.
277
50
  */
278
- function checkModule(moduleName, event) {
279
- const moduleRights = getModuleInfo(event);
280
- let allowAccess = _lodash.default.get(moduleRights, moduleName, false);
281
-
282
- if (isSuperUser(event)) {
283
- return;
284
- }
285
- if (isSystemUser(event)) {
286
- return;
287
- }
288
-
289
- if (process.env.BUILD_ENV === 'local') {
290
- return;
291
- }
292
- if (!allowAccess) {
293
- throw _errorCodes.errorList.unauthorized;
294
- }
295
- }
296
-
297
- const userRoles = exports.userRoles = {
298
- admin: 'A',
299
- read: 'R',
300
- write: 'W'
301
- };
302
-
303
- /**
304
- * Get the partner ID from custom:PID if the user is a partner admin.
305
- *
306
- * @param {object} event - The lambda event passed in by a validated api request.
307
- * @returns {string|false} The partner ID or false if not a partner user.
51
+ function defaultFilters(schema,subSchemas={}){schema=_lodash.default.clone(schema);const filters={};return addFiltersFromSchema(schema,filters),Object.keys(subSchemas).forEach(key=>{addFiltersFromSchema(subSchemas[key],filters,key)}),filters};var _lodash=_interopRequireDefault(__webpack_require__(825)),_sequelize=_interopRequireDefault(__webpack_require__(31));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function addFiltersFromSchema(schema,filters,keyPrefix=""){const asLinkAlias=_lodash.default.get(schema,"as",null);return schema=_lodash.default.get(schema,"schema")||schema,Object.keys(schema).reduce((acc,item)=>{let key=item;if(asLinkAlias&&(acc[asLinkAlias]={type:_sequelize.default.STRING,filterType:_sequelize.default.Op.eq}),keyPrefix&&(key=`${keyPrefix}.${item}`),schema[item].filterType)return acc[key]={filterType:schema[item].filterType},acc;const itemType=schema[item].type;
52
+ //new sequelize uses class symbols instead of objects
53
+ return itemType instanceof _sequelize.default.STRING||itemType instanceof _sequelize.default.CHAR||itemType instanceof _sequelize.default.TEXT?acc[key]={filterType:_sequelize.default.Op.iLike}:itemType instanceof _sequelize.default.DECIMAL||itemType instanceof _sequelize.default.INTEGER||itemType instanceof _sequelize.default.BIGINT?acc[key]={filterType:_sequelize.default.Op.or}:itemType instanceof _sequelize.default.BOOLEAN?acc[key]={type:_sequelize.default.BOOLEAN,filterType:_sequelize.default.Op.eq}:itemType instanceof _sequelize.default.JSONB||itemType===_sequelize.default.JSONB?acc[key]={type:"jsonb",field:item}:itemType instanceof _sequelize.default.DATE?acc[key]={filterType:_sequelize.default.Op.between}:itemType instanceof _sequelize.default.DATEONLY&&(acc[key]={filterType:_sequelize.default.Op.eq}),
54
+ //these are automatically part of the models, so add them always
55
+ acc.createdAt={type:_sequelize.default.DATE,filterType:_sequelize.default.Op.between},acc.updatedAt={type:_sequelize.default.DATE,filterType:_sequelize.default.Op.between},acc.id={type:_sequelize.default.INTEGER,filterType:_sequelize.default.Op.eq},acc},filters)}
56
+ /***/},
57
+ /***/288(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.createFilters=void 0;var _lodash=_interopRequireDefault(__webpack_require__(825)),_sequelize=_interopRequireDefault(__webpack_require__(31)),_dayjs=_interopRequireDefault(__webpack_require__(293)),_utc=_interopRequireDefault(__webpack_require__(137)),_errorCodes=__webpack_require__(953),_accessRightsUtils=__webpack_require__(673);function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}_dayjs.default.extend(_utc.default);exports.createFilters=function(event,objectFilters){let query=_lodash.default.get(event,"queryStringParameters",{})||{};
58
+ // Extract the three convenience params before iterating.
59
+ // These are handled separately from the per-field filter logic below.
60
+ const searchString=_lodash.default.get(query,"searchString"),startDate=_lodash.default.get(query,"startDate"),endDate=_lodash.default.get(query,"endDate"),caseInsensitiveConditions=[],where=Object.keys(query).reduce((acc,item)=>{const val=_lodash.default.get(objectFilters,item,null);if(val){
61
+ // JSONB fields are handled entirely in Step 4 below.
62
+ // Skip them here so they don't fall into the catch-all else branch.
63
+ if("jsonb"===val.type)return acc;
64
+ // Dot-notation keys (e.g. "snowman.snowmanType") reference columns
65
+ // on joined/included models. Sequelize requires these to be wrapped
66
+ // in $...$ syntax in the WHERE object so it can resolve them.
67
+ const itemName=item.includes(".")?`$${item}$`:item;
68
+ // STRING / CHAR / TEXT fields — case-insensitive partial match
69
+ // Generates: WHERE LOWER("column") LIKE '%lowered_value%'
70
+ if(val.filterType===_sequelize.default.Op.iLike)caseInsensitiveConditions.push(_sequelize.default.where(_sequelize.default.fn("LOWER",_sequelize.default.col(item)),{[_sequelize.default.Op.like]:`%${query[item]?.toLowerCase()}%`}));
71
+ // INTEGER / DECIMAL fields — match positive or negative value
72
+ // Generates: WHERE "column" IN (-value, value)
73
+ // Useful for fields like amounts where sign may vary.
74
+ else if(val.filterType===_sequelize.default.Op.or)acc[itemName]={},acc[itemName][val.filterType]=[-1*+query[item],+query[item]];else if(val.filterType===_sequelize.default.Op.in)acc[itemName]={},acc[itemName][val.filterType]=query[item].split(",");else{let parsedJson;acc[itemName]={};try{parsedJson=JSON.parse(query[item])}catch(e){parsedJson=query[item]}acc[itemName][val.filterType]=parsedJson}
75
+ // BOOLEAN override — runs after the block above so it can replace
76
+ // the value set by the catch-all. Query strings are always strings
77
+ // ("true", "false", "null"), so we coerce them to actual booleans/null.
78
+ if(val.type===_sequelize.default.BOOLEAN){const queryValue=_lodash.default.get(query,item,"").toLowerCase(),booleanMap={false:!1,null:null,true:!0};acc[itemName][val.filterType]=booleanMap[queryValue]}}return acc},{});
79
+ // Merge the case-insensitive string conditions into WHERE using Op.and.
80
+ // This keeps them alongside the key-based conditions built above.
81
+ // Example result: WHERE decimal = 100 AND LOWER("name") LIKE '%john%'
82
+ caseInsensitiveConditions.length&&(where[_sequelize.default.Op.and]=[...where[_sequelize.default.Op.and]||[],...caseInsensitiveConditions]),
83
+ // ──────────────────────────────────────────────────────────────────────
84
+ // STEP 2 — Apply automatic filters (active flag, businessId, dates)
85
+ // These are appended to every query regardless of what the caller sent.
86
+ // ──────────────────────────────────────────────────────────────────────
87
+ // If the model has an "active" column and the caller did not explicitly
88
+ // filter by it, default to only returning active records.
89
+ objectFilters?.active&&!where?.active&&(where.active=!0);
90
+ // Scope every query to the caller's authorized business IDs.
91
+ // accessRightsUtils extracts them from the JWT claims on the event.
92
+ const filterAdds={businessId:(0,_accessRightsUtils.accessRightsUtils)(event)};
93
+ // Date range filter — when both startDate and endDate are provided,
94
+ // automatically filter createdAt with a BETWEEN clause.
95
+ // Generates: WHERE "createdAt" BETWEEN '2024-01-01' AND '2024-12-31'
96
+ if(startDate&&endDate){const s=_dayjs.default.utc(startDate),e=_dayjs.default.utc(endDate),dates={[_sequelize.default.Op.between]:[s.toDate(),e.toDate()]};if(!s.isValid())throw{..._errorCodes.errorList.invalidStartDate};if(!e.isValid())throw{..._errorCodes.errorList.invalidEndDate};filterAdds.createdAt=dates}
97
+ // ──────────────────────────────────────────────────────────────────────
98
+ // STEP 3 — searchString: search one value across many fields with OR
99
+
100
+ // When ?searchString=john is provided, we build an OR array that checks
101
+ // every filterable field for a match. This lets a single search box
102
+ // query across name, title, email, etc. simultaneously.
103
+
104
+ // String fields (Op.iLike) get a case-insensitive LOWER + LIKE condition.
105
+ // Numeric fields (Op.eq) get an exact match, but only when the search
106
+ // value is a valid number (and the field is not a boolean).
107
+
108
+ // Generates: WHERE (LOWER("name") LIKE '%john%'
109
+ // OR LOWER("title") LIKE '%john%'
110
+ // OR "id" = 123)
111
+ // ──────────────────────────────────────────────────────────────────────
112
+ if(searchString){const adds=Object.keys(objectFilters).reduce((acc,item)=>{const type=objectFilters[item].filterType,dataType=objectFilters[item].type;
113
+ // Numeric fields — exact match only when the search value is numeric.
114
+ // Booleans are excluded because a search for "1" should not match
115
+ // boolean true.
116
+ if(
117
+ // String fields — case-insensitive partial match via LOWER + LIKE
118
+ type===_sequelize.default.Op.iLike&&acc.push(_sequelize.default.where(_sequelize.default.fn("LOWER",_sequelize.default.col(item)),{[_sequelize.default.Op.like]:`%${query.searchString.toLowerCase()}%`})),!(_lodash.default.isNaN(Number(query.searchString))||dataType instanceof _sequelize.default.BOOLEAN)&&type===_sequelize.default.Op.eq){const newOr={};newOr[item.includes(".")?`$${item}$`:item]={[_sequelize.default.Op.eq]:`${query.searchString}`},acc.push(newOr)}return acc},[]);filterAdds[_sequelize.default.Op.or]=adds}
119
+ // Merge the automatic filters (businessId, createdAt, searchString OR)
120
+ // into the where object built in Step 1.
121
+ const withDate=Object.assign(where,filterAdds);
122
+ // ──────────────────────────────────────────────────────────────────────
123
+ // STEP 4 — JSONB field filters: case-insensitive search inside JSON columns
124
+
125
+ // JSONB columns store structured data (e.g. a "token" column containing
126
+ // { cardType: "mastercard", cardHolderName: "GREGORY HERBERT" }).
127
+
128
+ // Query params use dot-notation to target nested keys:
129
+ // ?token.cardHolderName=gregory
130
+ // ?paymentProviderData.payment.result.message=approved
131
+
132
+ // For each matching param we:
133
+ // 1. Split the path after the column prefix into individual key segments
134
+ // 2. Use jsonb_extract_path_text(column, key1, key2, ...) to pull the
135
+ // value out of the JSON as plain text
136
+ // 3. Wrap it in LOWER() and compare with Op.like for case-insensitive match
137
+
138
+ // Generates: WHERE LOWER(jsonb_extract_path_text("token", 'cardHolderName'))
139
+ // LIKE '%gregory%'
140
+
141
+ // jsonb_extract_path_text is used via DB.fn() so Sequelize parameterizes
142
+ // the path arguments, keeping it safe from SQL injection.
143
+ // ──────────────────────────────────────────────────────────────────────
144
+ return Object.keys(objectFilters||{}).forEach(k=>{const def=objectFilters[k];if(def&&"jsonb"===def.type&&def.field){const prefix=`${def.field}.`;Object.keys(query).forEach(qKey=>{if(qKey.startsWith(prefix)){
145
+ // Dot-notation: ?token.cardHolderName=gregory
146
+ // e.g. "token.cardHolderName" -> pathParts = ["cardHolderName"]
147
+ // e.g. "data.payment.result.message" -> pathParts = ["payment","result","message"]
148
+ const pathParts=qKey.substring(prefix.length).split("."),value=query[qKey];withDate[_sequelize.default.Op.and]||(withDate[_sequelize.default.Op.and]=[]),withDate[_sequelize.default.Op.and].push(_sequelize.default.where(_sequelize.default.fn("LOWER",_sequelize.default.fn("jsonb_extract_path_text",_sequelize.default.col(def.field),...pathParts)),{[_sequelize.default.Op.like]:`%${value?.toLowerCase()}%`}))}else if(qKey===def.field){
149
+ // JSON-object-as-value: ?token={"cardHolderName":"Test"}
150
+ // Parse the JSON and create a condition for each key-value pair.
151
+ // Nested objects are flattened recursively into deeper path segments.
152
+ let parsed;try{parsed=JSON.parse(query[qKey])}catch(e){return}if(parsed&&"object"==typeof parsed&&!Array.isArray(parsed)){const addJsonbConditions=(obj,pathParts)=>{Object.entries(obj).forEach(([key,value])=>{const currentPath=[...pathParts,key];value&&"object"==typeof value&&!Array.isArray(value)?addJsonbConditions(value,currentPath):null===value||Array.isArray(value)||(withDate[_sequelize.default.Op.and]||(withDate[_sequelize.default.Op.and]=[]),withDate[_sequelize.default.Op.and].push(_sequelize.default.where(_sequelize.default.fn("LOWER",_sequelize.default.fn("jsonb_extract_path_text",_sequelize.default.col(def.field),...currentPath)),{[_sequelize.default.Op.like]:`%${String(value)?.toLowerCase()}%`})))})};addJsonbConditions(parsed,[])}}})}}),withDate}},
153
+ /***/293(module){module.exports=require("dayjs");
154
+ /***/},
155
+ /***/306(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _clientSns=__webpack_require__(793);const SNSUtil={publish:params=>async function publish(params){const sns=new _clientSns.SNS;return await sns.publish(params)}(params),createTopic:params=>async function createTopic(params){const sns=new _clientSns.SNS;return await sns.createTopic(params)}(params)};exports.default=SNSUtil;
156
+ /***/},
157
+ /***/394(module){module.exports=require("dayjs/plugin/isSameOrBefore");
158
+ /***/},
159
+ /***/515(module){module.exports=require("@aws-sdk/lib-dynamodb");
160
+ /***/},
161
+ /***/564(module){module.exports=require("bluebird");
162
+ /***/},
163
+ /***/673(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.accessRightsUtils=accessRightsUtils,exports.checkIsSuper=
164
+ /**
165
+ * Throws unauthorized error if the user is not a super user.
166
+ * Mirrors the behavior and style of checkModule but focused on SUPER role.
167
+ *
168
+ * @param {object} event - The lambda event passed in by a validated api request.
308
169
  */
309
- function isPartnerUser(event) {
310
- const partnerId = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:PID') ||
311
- _lodash.default.get(event, 'requestContext.authorizer.custom:PID') ||
312
- '';
313
- return partnerId || false;
314
- }
315
-
316
- /**
317
- * Get the partner ID from custom:BPID if the user's business belongs to a partner.
318
- *
319
- * @param {object} event - The lambda event passed in by a validated api request.
320
- * @returns {string|false} The partner ID or false if not associated with a partner.
170
+ function checkIsSuper(event){
171
+ // Super or System users are always allowed
172
+ if(isSuperUser(event))return;if(isSystemUser(event))return;
173
+ // In local builds allow bypass to ease development and tests
174
+ if("local"===process.env.BUILD_ENV)return;throw _errorCodes.errorList.unauthorized}
175
+ /**
176
+ * Get the allowed businessIds for a user from the lambda event, compare it to businessIds, return what user has access to.
177
+ *
178
+ * @param {object} event - The lambda event passed in by a validated api request.
179
+ * @param {{useCognitoBid:boolean}} [options] - An object with options, useCognitoBid prefers the businessId set in cognito if set and does not return the local bid of 1 if a bid is in the claim.
180
+ * @returns {array} A list of businessIds that have been requested and are allowed to for some user.
181
+ */,exports.checkModule=
182
+ /**
183
+ * Get the modules listed in custom:MOD.
184
+ *
185
+ * @param {string} moduleName - A sting name for a module.
186
+ * @param {object} event - The lambda event passed in by a validated api request.
187
+ * @returns {array} The Module access list
321
188
  */
322
- function getBelongsToPartnerId(event) {
323
- const partnerId = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:BPID') ||
324
- _lodash.default.get(event, 'requestContext.authorizer.custom:BPID') ||
325
- '';
326
- return partnerId || false;
327
- }
328
-
329
- /**
330
- * Get the effective partner ID from either custom:PID or custom:BPID.
331
- *
332
- * @param {object} event - The lambda event passed in by a validated api request.
333
- * @returns {string|false} The partner ID or false.
189
+ function checkModule(moduleName,event){const moduleRights=getModuleInfo(event);let allowAccess=_lodash.default.get(moduleRights,moduleName,!1);if(isSuperUser(event))return;if(isSystemUser(event))return;if("local"===process.env.BUILD_ENV)return;if(!allowAccess)throw _errorCodes.errorList.unauthorized},exports.checkWriteAccess=
190
+ /**
191
+ * @param {{body: string}} event
192
+ * @param {{useCognitoBid:boolean}} [options] - An object with options, useCognitoBid prefers the businessId set in cognito if set and does not return the local bid of 1 if a bid is in the claim.
193
+ * @returns {string} businessId
334
194
  */
335
- function getEffectivePartnerId(event) {
336
- return isPartnerUser(event) || getBelongsToPartnerId(event);
337
- }
338
-
339
- /**
340
- * Enrich the event's custom:AR with partner business IDs in-memory.
341
- * Call this BEFORE accessRightsUtils() or getBusinessesInfo() so that
342
- * partner admins (custom:PID) get access to their partner's merchants.
343
- *
344
- * This keeps accessRightsUtils synchronous the DB lookup is done by the caller.
345
- *
346
- * @param {object} event - The lambda event passed in by a validated api request.
347
- * @param {string[]} partnerBusinessIds - Array of business IDs from the partner record.
348
- * @param {string} [role='R'] - Access role to assign (default: Read).
195
+ function checkWriteAccess(event,options){const eventBody=(0,_requestResponse.parseBody)(event),businessId=(accessRightsUtils(event,options)||[]).find(id=>id===eventBody.businessId),userRight=getBusinessesInfo(event)[businessId];if(isSuperUser(event))return eventBody.businessId;if(isSystemUser(event))return eventBody.businessId;if("local"===process.env.BUILD_ENV)return eventBody.businessId;if(userRight!==userRoles.admin&&userRight!==userRoles.write||!userRight)throw _errorCodes.errorList.unauthorized;return businessId}
196
+ /**
197
+ * Get the company-level cached settings from custom:SET.
198
+ *
199
+ * @param {object} event - The lambda event passed in by a validated api request.
200
+ * @returns {object} The company settings object (e.g. { auditEnabled: true })
201
+ */,exports.enrichEventWithPartnerAccess=
202
+ /**
203
+ * Enrich the event's custom:AR with partner business IDs in-memory.
204
+ * Call this BEFORE accessRightsUtils() or getBusinessesInfo() so that
205
+ * partner admins (custom:PID) get access to their partner's merchants.
206
+ *
207
+ * This keeps accessRightsUtils synchronous the DB lookup is done by the caller.
208
+ *
209
+ * @param {object} event - The lambda event passed in by a validated api request.
210
+ * @param {string[]} partnerBusinessIds - Array of business IDs from the partner record.
211
+ * @param {string} [role='R'] - Access role to assign (default: Read).
349
212
  */
350
- function enrichEventWithPartnerAccess(event, partnerBusinessIds, role = 'R') {
351
- if (!partnerBusinessIds || partnerBusinessIds.length === 0) return;
352
-
353
- const arPath = event?.requestContext?.authorizer?.claims ?
354
- 'requestContext.authorizer.claims.custom:AR' :
355
- 'requestContext.authorizer.custom:AR';
356
-
357
- const json = _lodash.default.get(event, arPath) || '{}';
358
- const accessRights = JSON.parse(json);
359
- const businessIds = accessRights.businessIds || {};
360
-
361
- for (const bid of partnerBusinessIds) {
362
- if (!businessIds[bid]) {
363
- businessIds[bid] = role;
364
- }
365
- }
366
-
367
- accessRights.businessIds = businessIds;
368
- _lodash.default.set(event, arPath, JSON.stringify(accessRights));
369
- }
370
-
371
- /**
372
- * @param {{body: string}} event
373
- * @param {{useCognitoBid:boolean}} [options] - An object with options, useCognitoBid prefers the businessId set in cognito if set and does not return the local bid of 1 if a bid is in the claim.
374
- * @returns {string} businessId
213
+ function enrichEventWithPartnerAccess(event,partnerBusinessIds,role="R"){if(!partnerBusinessIds||0===partnerBusinessIds.length)return;const arPath=event?.requestContext?.authorizer?.claims?"requestContext.authorizer.claims.custom:AR":"requestContext.authorizer.custom:AR",json=_lodash.default.get(event,arPath)||"{}",accessRights=JSON.parse(json),businessIds=accessRights.businessIds||{};for(const bid of partnerBusinessIds)businessIds[bid]||(businessIds[bid]=role);accessRights.businessIds=businessIds,_lodash.default.set(event,arPath,JSON.stringify(accessRights))},exports.getAccessRightsInfo=function getAccessRightsInfo(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:AR")||_lodash.default.get(event,"requestContext.authorizer.custom:AR")||"{}";const accessRights=JSON.parse(jsonToParse);return _lodash.default.get(accessRights,"businessIds",{})},exports.getBelongsToPartnerId=getBelongsToPartnerId,exports.getBusinessesInfo=getBusinessesInfo,exports.getCompanySettings=function getCompanySettings(event){const jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:SET")||_lodash.default.get(event,"requestContext.authorizer.custom:SET")||"{}";try{return JSON.parse(jsonToParse)}catch(e){return{}}}
214
+ /***/,exports.getDefaultBusinessIDInfo=function getDefaultBusinessIDInfo(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:DBI")||_lodash.default.get(event,"requestContext.authorizer.custom:DBI")||"{}";const dbi=JSON.parse(jsonToParse);return _lodash.default.get(dbi,"defaultBid","1")},exports.getEffectivePartnerId=
215
+ /**
216
+ * Get the effective partner ID from either custom:PID or custom:BPID.
217
+ *
218
+ * @param {object} event - The lambda event passed in by a validated api request.
219
+ * @returns {string|false} The partner ID or false.
375
220
  */
376
- function checkWriteAccess(event, options) {
377
- const eventBody = (0, _requestResponse.parseBody)(event);
378
- const businessIds = accessRightsUtils(event, options) || [];
379
- const businessId = businessIds.find((id) => id === eventBody.businessId);
380
- const raw = getBusinessesInfo(event);
381
- const userRight = raw[businessId];
382
-
383
- if (isSuperUser(event)) {
384
- return eventBody.businessId;
385
- }
386
-
387
- if (isSystemUser(event)) {
388
- return eventBody.businessId;
389
- }
390
-
391
- if (process.env.BUILD_ENV === 'local') {
392
- return eventBody.businessId;
393
- }
394
-
395
- if (userRight !== userRoles.admin && userRight !== userRoles.write || !userRight) {
396
- throw _errorCodes.errorList.unauthorized;
397
- }
398
- return businessId;
399
- }
400
-
401
- /**
402
- * Get the company-level cached settings from custom:SET.
403
- *
404
- * @param {object} event - The lambda event passed in by a validated api request.
405
- * @returns {object} The company settings object (e.g. { auditEnabled: true })
221
+ function getEffectivePartnerId(event){return isPartnerUser(event)||getBelongsToPartnerId(event)},exports.getModuleInfo=getModuleInfo,exports.getRequestedBusinessIds=getRequestedBusinessIds,exports.isPartnerUser=isPartnerUser,exports.isSuperUser=isSuperUser,exports.isSystemUser=isSystemUser,exports.userDefaultBid=
222
+ /**
223
+ * Get the businessID set in cognito as custom:DBI.
224
+ *
225
+ * @param {object} event - The lambda event passed in by a validated api request.
226
+ * @returns {string} The businessID set in cognito as custom:DBI
406
227
  */
407
- function getCompanySettings(event) {
408
- const jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:SET') ||
409
- _lodash.default.get(event, 'requestContext.authorizer.custom:SET') ||
410
- '{}';
411
- try {
412
- return JSON.parse(jsonToParse);
413
- } catch (e) {
414
- return {};
415
- }
416
- }
417
-
418
- /***/ },
419
-
420
- /***/ "./src/database/dbUtils/queryStringUtils/createFilters.js"
421
- /*!****************************************************************!*\
422
- !*** ./src/database/dbUtils/queryStringUtils/createFilters.js ***!
423
- \****************************************************************/
424
- (__unused_webpack_module, exports, __webpack_require__) {
425
-
426
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.createFilters = void 0;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
427
- var _sequelize = _interopRequireDefault(__webpack_require__(/*! sequelize */ "sequelize"));
428
- var _dayjs = _interopRequireDefault(__webpack_require__(/*! dayjs */ "dayjs"));
429
- var _utc = _interopRequireDefault(__webpack_require__(/*! dayjs/plugin/utc.js */ "dayjs/plugin/utc.js"));
430
- var _errorCodes = __webpack_require__(/*! ../../../requestResponse/errorCodes.js */ "./src/requestResponse/errorCodes.js");
431
- var _accessRightsUtils = __webpack_require__(/*! ./accessRightsUtils.js */ "./src/database/dbUtils/queryStringUtils/accessRightsUtils.js");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
432
-
433
- _dayjs.default.extend(_utc.default);
434
-
228
+ function userDefaultBid(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:DBI")||_lodash.default.get(event,"requestContext.authorizer.custom:DBI")||"{}";const dbi=JSON.parse(jsonToParse);return _lodash.default.get(dbi,"defaultBid","")||"1"}
435
229
  /**
436
- * Create sequelize where clause from query string parameters and default sort object
230
+ * Get requested businessIds from the query string.
437
231
  *
438
- * Translates URL query string parameters into a Sequelize-compatible WHERE object
439
- * by matching each param against a filter definition (objectFilters).
232
+ * @param {object} event - The lambda event passed in by a validated api request.
233
+ * @returns {array} The businessID requested by the query string
234
+ */,exports.userRoles=void 0;var _lodash=function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap,n=new WeakMap;return function(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(i.get||i.set)?o(f,t,i):f[t]=e[t]);return f}(e,t)}(__webpack_require__(825)),_errorCodes=__webpack_require__(953),_requestResponse=__webpack_require__(859);function isSystemUser(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:SYSTEM")||_lodash.default.get(event,"requestContext.authorizer.custom:SYSTEM")||"false",isSys=!1;try{return isSys=JSON.parse(jsonToParse),isSys}catch(e){return console.error("error with system user:",e),!1}}function isSuperUser(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:SUPER")||_lodash.default.get(event,"requestContext.authorizer.custom:SUPER")||"false",isSys=!1;try{return isSys=JSON.parse(jsonToParse),isSys}catch(e){return!1}}function accessRightsUtils(event,options){const useCognitoBid=_lodash.default.get(options,"useCognitoBid",!1),requestedBusinessIds=getRequestedBusinessIds(event),allowedBusinessIds=
235
+ /**
236
+ * Get the allowed businessIds for a user from cognito custom:AR property.
440
237
  *
441
- * Filter definitions come from defaultFilters() which maps schema data types to operators:
442
- * STRING / CHAR / TEXT -> Op.iLike (case-insensitive LIKE)
443
- * INTEGER / DECIMAL -> Op.or (positive or negative match)
444
- * BOOLEAN -> Op.eq (exact match with string-to-boolean coercion)
445
- * JSONB -> case-insensitive search via jsonb_extract_path_text
446
- * DATE -> Op.between
238
+ * @param {object} event - The lambda event passed in by a validated api request.
239
+ * @param useCognitoBid
240
+ * @returns {array} The businessID requested by the query string
241
+ */
242
+ function getAllowedBusinessIds(event,useCognitoBid){const businesses=getBusinessesInfo(event,useCognitoBid);return Object.keys(businesses)}(event,useCognitoBid);if(isSuperUser(event)){let v=requestedBusinessIds;return _lodash.default.isEmpty(requestedBusinessIds)&&(v=allowedBusinessIds),v}return isSystemUser(event)?requestedBusinessIds:0===requestedBusinessIds.length?allowedBusinessIds:_lodash.default.intersection(requestedBusinessIds,allowedBusinessIds)}function getRequestedBusinessIds(event){let requestedBusinessIds=_lodash.default.get(event,"queryStringParameters.businessIds",null);const body=(0,_requestResponse.parseBody)(event),bodyBid=body?.businessId;return requestedBusinessIds?requestedBusinessIds?requestedBusinessIds.split(","):[]:bodyBid?[bodyBid]:[]}function getBusinessesInfo(event,useCognitoBid=!1){const json=_lodash.default.get(event,"requestContext.authorizer.claims.custom:AR")||_lodash.default.get(event,"requestContext.authorizer.custom:AR")||"{}";let businessIds=_lodash.default.get(JSON.parse(json),"businessIds",{});
243
+ // Local environment tweaks
244
+ if("local"===process.env.BUILD_ENV){let b;try{b=JSON.parse(event?.body)}catch(e){}const bodyBid=b?.businessId;
245
+ // Always inject the default local BID “1” unless the caller explicitly wants
246
+ // what Cognito says **and** Cognito actually returned something.
247
+ useCognitoBid||(businessIds={...businessIds,1:"A"}),
248
+ // If Cognito gave no BIDs at all, fall back to the local default.
249
+ (0,_lodash.isEmpty)(businessIds)&&(businessIds={1:"A"}),
250
+ // a businessId is found on the body for local allow it
251
+ bodyBid&&(businessIds[bodyBid]="A")}return businessIds}
252
+ /**
253
+ * Get the modules listed in custom:MOD.
447
254
  *
448
- * Three convenience params are handled automatically:
449
- * - searchString: searches a single value across all iLike and eq fields using OR
450
- * - startDate + endDate: filters createdAt with a BETWEEN range
255
+ * @param {object} event - The lambda event passed in by a validated api request.
256
+ * @returns {array} The Module access list
257
+ */function getModuleInfo(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:MOD")||_lodash.default.get(event,"requestContext.authorizer.custom:MOD")||_lodash.default.get(event,"requestContext.authorizer.claims.custom:AR")||_lodash.default.get(event,"requestContext.authorizer.custom:AR")||"{}";const moduleRights=JSON.parse(jsonToParse);return _lodash.default.get(moduleRights,"module",{})}const userRoles=exports.userRoles={admin:"A",read:"R",write:"W"};
258
+ /**
259
+ * Get the partner ID from custom:PID if the user is a partner admin.
451
260
  *
452
- * @param {object} event - the Lambda event containing queryStringParameters
453
- * @param {object} objectFilters - filter definitions created by defaultFilters()
454
- * @returns {object} A Sequelize where clause object
455
- */
456
- const createFilters = function (event, objectFilters) {
457
- let query = _lodash.default.get(event, 'queryStringParameters', {}) || {};
458
-
459
- // Extract the three convenience params before iterating.
460
- // These are handled separately from the per-field filter logic below.
461
- const searchString = _lodash.default.get(query, 'searchString');
462
- const startDate = _lodash.default.get(query, 'startDate');
463
- const endDate = _lodash.default.get(query, 'endDate');
464
-
465
- // ──────────────────────────────────────────────────────────────────────
466
- // STEP 1 — Build per-field WHERE conditions
467
- //
468
- // Each query param is looked up in objectFilters. If a matching filter
469
- // definition exists, we create the appropriate Sequelize condition.
470
- //
471
- // String-type fields (Op.iLike) are collected into a separate array
472
- // because they use DB.where(DB.fn('LOWER', DB.col(...))) which cannot
473
- // be expressed as a simple { column: { operator: value } } key.
474
- // Instead they are merged into WHERE via Op.and after the reduce.
475
- //
476
- // This approach replaces the Postgres-only Op.iLike with
477
- // LOWER(column) LIKE '%lowered_value%' which works across all
478
- // database dialects (Postgres, MySQL, MSSQL, SQLite).
479
- // ──────────────────────────────────────────────────────────────────────
480
- const caseInsensitiveConditions = [];
481
- const where = Object.keys(query).reduce((acc, item) => {
482
- const val = _lodash.default.get(objectFilters, item, null);
483
-
484
- if (val) {
485
- // JSONB fields are handled entirely in Step 4 below.
486
- // Skip them here so they don't fall into the catch-all else branch.
487
- if (val.type === 'jsonb') {
488
- return acc;
489
- }
490
-
491
- // Dot-notation keys (e.g. "snowman.snowmanType") reference columns
492
- // on joined/included models. Sequelize requires these to be wrapped
493
- // in $...$ syntax in the WHERE object so it can resolve them.
494
- const itemName = item.includes('.') ?
495
- `$${item}$` :
496
- item;
497
-
498
- // STRING / CHAR / TEXT fields — case-insensitive partial match
499
- // Generates: WHERE LOWER("column") LIKE '%lowered_value%'
500
- if (val.filterType === _sequelize.default.Op.iLike) {
501
- caseInsensitiveConditions.push(
502
- _sequelize.default.where(
503
- _sequelize.default.fn('LOWER', _sequelize.default.col(item)),
504
- { [_sequelize.default.Op.like]: `%${query[item]?.toLowerCase()}%` }
505
- )
506
- );
507
-
508
- // INTEGER / DECIMAL fields — match positive or negative value
509
- // Generates: WHERE "column" IN (-value, value)
510
- // Useful for fields like amounts where sign may vary.
511
- } else if (val.filterType === _sequelize.default.Op.or) {
512
- acc[itemName] = {};
513
- acc[itemName][val.filterType] = [-1 * +query[item], +query[item]];
514
-
515
- // ENUM / multi-value fields — match any value in a comma-separated list
516
- // Query: ?status=open,closed -> WHERE "status" IN ('open','closed')
517
- } else if (val.filterType === _sequelize.default.Op.in) {
518
- acc[itemName] = {};
519
- acc[itemName][val.filterType] = query[item].split(',');
520
-
521
- // Catch-all for other operators (Op.eq, Op.contains, Op.between, etc.)
522
- // Attempts JSON.parse first so structured values (objects, arrays, numbers)
523
- // are passed as their parsed type rather than raw strings.
524
- } else {
525
- acc[itemName] = {};
526
- let parsedJson;
527
- try {
528
- parsedJson = JSON.parse(query[item]);
529
- } catch (e) {
530
- parsedJson = query[item];
531
- }
532
- acc[itemName][val.filterType] = parsedJson;
533
- }
534
-
535
- // BOOLEAN override — runs after the block above so it can replace
536
- // the value set by the catch-all. Query strings are always strings
537
- // ("true", "false", "null"), so we coerce them to actual booleans/null.
538
- if (val.type === _sequelize.default.BOOLEAN) {
539
- const queryValue = _lodash.default.get(query, item, '').toLowerCase();
540
-
541
- const booleanMap = {
542
- 'false': false,
543
- 'null': null,
544
- 'true': true
545
- };
546
-
547
- acc[itemName][val.filterType] = booleanMap[queryValue];
548
- }
549
- }
550
-
551
- return acc;
552
- }, {});
553
-
554
- // Merge the case-insensitive string conditions into WHERE using Op.and.
555
- // This keeps them alongside the key-based conditions built above.
556
- // Example result: WHERE decimal = 100 AND LOWER("name") LIKE '%john%'
557
- if (caseInsensitiveConditions.length) {
558
- where[_sequelize.default.Op.and] = [...(where[_sequelize.default.Op.and] || []), ...caseInsensitiveConditions];
559
- }
560
-
561
- // ──────────────────────────────────────────────────────────────────────
562
- // STEP 2 — Apply automatic filters (active flag, businessId, dates)
563
- //
564
- // These are appended to every query regardless of what the caller sent.
565
- // ──────────────────────────────────────────────────────────────────────
566
-
567
- // If the model has an "active" column and the caller did not explicitly
568
- // filter by it, default to only returning active records.
569
- if (objectFilters?.active && !where?.active) {
570
- where.active = true;
571
- }
572
-
573
- // Scope every query to the caller's authorized business IDs.
574
- // accessRightsUtils extracts them from the JWT claims on the event.
575
- const businessIds = (0, _accessRightsUtils.accessRightsUtils)(event);
576
- const filterAdds = {
577
- businessId: businessIds
578
- };
579
-
580
- // Date range filter — when both startDate and endDate are provided,
581
- // automatically filter createdAt with a BETWEEN clause.
582
- // Generates: WHERE "createdAt" BETWEEN '2024-01-01' AND '2024-12-31'
583
- if (startDate && endDate) {
584
- const s = _dayjs.default.utc(startDate);
585
- const e = _dayjs.default.utc(endDate);
586
- const dates = {
587
- [_sequelize.default.Op.between]: [s.toDate(), e.toDate()]
588
- };
589
- if (!s.isValid()) {
590
- throw { ..._errorCodes.errorList.invalidStartDate };
591
- }
592
-
593
- if (!e.isValid()) {
594
- throw { ..._errorCodes.errorList.invalidEndDate };
595
- }
596
-
597
- filterAdds.createdAt = dates;
598
- }
599
-
600
- // ──────────────────────────────────────────────────────────────────────
601
- // STEP 3 — searchString: search one value across many fields with OR
602
- //
603
- // When ?searchString=john is provided, we build an OR array that checks
604
- // every filterable field for a match. This lets a single search box
605
- // query across name, title, email, etc. simultaneously.
606
- //
607
- // String fields (Op.iLike) get a case-insensitive LOWER + LIKE condition.
608
- // Numeric fields (Op.eq) get an exact match, but only when the search
609
- // value is a valid number (and the field is not a boolean).
610
- //
611
- // Generates: WHERE (LOWER("name") LIKE '%john%'
612
- // OR LOWER("title") LIKE '%john%'
613
- // OR "id" = 123)
614
- // ──────────────────────────────────────────────────────────────────────
615
- if (searchString) {
616
- const adds = Object.keys(objectFilters).reduce((acc, item) => {
617
- const type = objectFilters[item].filterType;
618
- const dataType = objectFilters[item].type;
619
-
620
- // String fields — case-insensitive partial match via LOWER + LIKE
621
- if (type === _sequelize.default.Op.iLike) {
622
- acc.push(
623
- _sequelize.default.where(
624
- _sequelize.default.fn('LOWER', _sequelize.default.col(item)),
625
- { [_sequelize.default.Op.like]: `%${query['searchString'].toLowerCase()}%` }
626
- )
627
- );
628
- }
629
-
630
- // Numeric fields — exact match only when the search value is numeric.
631
- // Booleans are excluded because a search for "1" should not match
632
- // boolean true.
633
- if (!_lodash.default.isNaN(Number(query['searchString'])) && !(dataType instanceof _sequelize.default.BOOLEAN)) {
634
-
635
- if (type === _sequelize.default.Op.eq) {
636
- const newOr = {};
637
- const itemName = item.includes('.') ? `$${item}$` : item;
638
- newOr[itemName] = {
639
- [_sequelize.default.Op.eq]: `${query['searchString']}`
640
- };
641
- acc.push(newOr);
642
- }
643
- }
644
-
645
- return acc;
646
- }, []);
647
-
648
- filterAdds[_sequelize.default.Op.or] = adds;
649
- }
650
-
651
- // Merge the automatic filters (businessId, createdAt, searchString OR)
652
- // into the where object built in Step 1.
653
- const withDate = Object.assign(where, filterAdds);
654
-
655
- // ──────────────────────────────────────────────────────────────────────
656
- // STEP 4 — JSONB field filters: case-insensitive search inside JSON columns
657
- //
658
- // JSONB columns store structured data (e.g. a "token" column containing
659
- // { cardType: "mastercard", cardHolderName: "GREGORY HERBERT" }).
660
- //
661
- // Query params use dot-notation to target nested keys:
662
- // ?token.cardHolderName=gregory
663
- // ?paymentProviderData.payment.result.message=approved
664
- //
665
- // For each matching param we:
666
- // 1. Split the path after the column prefix into individual key segments
667
- // 2. Use jsonb_extract_path_text(column, key1, key2, ...) to pull the
668
- // value out of the JSON as plain text
669
- // 3. Wrap it in LOWER() and compare with Op.like for case-insensitive match
670
- //
671
- // Generates: WHERE LOWER(jsonb_extract_path_text("token", 'cardHolderName'))
672
- // LIKE '%gregory%'
673
- //
674
- // jsonb_extract_path_text is used via DB.fn() so Sequelize parameterizes
675
- // the path arguments, keeping it safe from SQL injection.
676
- // ──────────────────────────────────────────────────────────────────────
677
- Object.keys(objectFilters || {}).forEach((k) => {
678
- const def = objectFilters[k];
679
- if (def && def.type === 'jsonb' && def.field) {
680
- const prefix = `${def.field}.`;
681
-
682
- Object.keys(query).forEach((qKey) => {
683
- if (qKey.startsWith(prefix)) {
684
- // Dot-notation: ?token.cardHolderName=gregory
685
- // e.g. "token.cardHolderName" -> pathParts = ["cardHolderName"]
686
- // e.g. "data.payment.result.message" -> pathParts = ["payment","result","message"]
687
- const pathParts = qKey.substring(prefix.length).split('.');
688
- const value = query[qKey];
689
-
690
- if (!withDate[_sequelize.default.Op.and]) {
691
- withDate[_sequelize.default.Op.and] = [];
692
- }
693
- withDate[_sequelize.default.Op.and].push(
694
- _sequelize.default.where(
695
- _sequelize.default.fn('LOWER', _sequelize.default.fn('jsonb_extract_path_text', _sequelize.default.col(def.field), ...pathParts)),
696
- { [_sequelize.default.Op.like]: `%${value?.toLowerCase()}%` }
697
- )
698
- );
699
- } else if (qKey === def.field) {
700
- // JSON-object-as-value: ?token={"cardHolderName":"Test"}
701
- // Parse the JSON and create a condition for each key-value pair.
702
- // Nested objects are flattened recursively into deeper path segments.
703
- let parsed;
704
- try {
705
- parsed = JSON.parse(query[qKey]);
706
- } catch (e) {
707
- return;
708
- }
709
- if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
710
- const addJsonbConditions = (obj, pathParts) => {
711
- Object.entries(obj).forEach(([key, value]) => {
712
- const currentPath = [...pathParts, key];
713
- if (value && typeof value === 'object' && !Array.isArray(value)) {
714
- addJsonbConditions(value, currentPath);
715
- } else if (value !== null && !Array.isArray(value)) {
716
- if (!withDate[_sequelize.default.Op.and]) {
717
- withDate[_sequelize.default.Op.and] = [];
718
- }
719
- withDate[_sequelize.default.Op.and].push(
720
- _sequelize.default.where(
721
- _sequelize.default.fn('LOWER', _sequelize.default.fn('jsonb_extract_path_text', _sequelize.default.col(def.field), ...currentPath)),
722
- { [_sequelize.default.Op.like]: `%${String(value)?.toLowerCase()}%` }
723
- )
724
- );
725
- }
726
- });
727
- };
728
- addJsonbConditions(parsed, []);
729
- }
730
- }
731
- });
732
- }
733
- });
734
-
735
- return withDate;
736
- };exports.createFilters = createFilters;
737
-
738
- /***/ },
739
-
740
- /***/ "./src/database/dbUtils/queryStringUtils/createIncludes.js"
741
- /*!*****************************************************************!*\
742
- !*** ./src/database/dbUtils/queryStringUtils/createIncludes.js ***!
743
- \*****************************************************************/
744
- (__unused_webpack_module, exports, __webpack_require__) {
745
-
746
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.createIncludes = createIncludes;exports.includeSubItem = includeSubItem;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
747
-
261
+ * @param {object} event - The lambda event passed in by a validated api request.
262
+ * @returns {string|false} The partner ID or false if not a partner user.
263
+ */function isPartnerUser(event){return _lodash.default.get(event,"requestContext.authorizer.claims.custom:PID")||_lodash.default.get(event,"requestContext.authorizer.custom:PID")||""||!1}
748
264
  /**
749
- * Create sequelize includes array from query string parameters and default sequelize model
265
+ * Get the partner ID from custom:BPID if the user's business belongs to a partner.
750
266
  *
751
- * @param {object} event - the query parameters from the event passed by lambda
752
- * @param {object} objectFilters - the default filters object created by createDefaultFilters
753
- * @returns {object} A sequelize includes array
754
- */
755
-
756
- function createIncludes(event, objectFilters) {
757
- const query = _lodash.default.get(event, 'queryStringParameters', {}) || {};
758
-
759
- const keys = Object.keys(objectFilters);
760
-
761
- const canBeIncluded = keys.reduce((acc, item) => {
762
- acc = includeSubItem(item, acc);
763
-
764
- return acc;
765
- }, []);
766
-
767
- const askedForInQuery = Object.keys(query).reduce((acc, item) => {
768
- if (item === 'sort') {
769
- query[item].split(',').forEach((sortItem) => {
770
- sortItem = sortItem.indexOf('-') === 0 ? sortItem.substr(1) : sortItem;
771
- acc = includeSubItem(sortItem, acc);
772
- });
773
- }
774
-
775
- acc = includeSubItem(item, acc);
776
-
777
- return acc;
778
- }, []);
779
-
780
- return _lodash.default.intersection(canBeIncluded, askedForInQuery);
781
- }
782
-
783
- function includeSubItem(queryStringItem, acc = []) {
784
- const dot = queryStringItem.indexOf('.');
785
- if (dot > 0) {
786
- acc.push(queryStringItem.substring(0, dot));
787
- }
788
-
789
- return acc;
790
- }
791
-
792
- /***/ },
793
-
794
- /***/ "./src/database/dbUtils/queryStringUtils/createSort.js"
795
- /*!*************************************************************!*\
796
- !*** ./src/database/dbUtils/queryStringUtils/createSort.js ***!
797
- \*************************************************************/
798
- (__unused_webpack_module, exports, __webpack_require__) {
799
-
800
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.createSort = void 0;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
801
-
267
+ * @param {object} event - The lambda event passed in by a validated api request.
268
+ * @returns {string|false} The partner ID or false if not associated with a partner.
269
+ */function getBelongsToPartnerId(event){return _lodash.default.get(event,"requestContext.authorizer.claims.custom:BPID")||_lodash.default.get(event,"requestContext.authorizer.custom:BPID")||""||!1}},
270
+ /***/793(module){module.exports=require("@aws-sdk/client-sns");
271
+ /***/},
272
+ /***/825(module){module.exports=require("lodash");
273
+ /***/},
274
+ /***/835(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.createSort=void 0;var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
802
275
  /**
803
276
  * Create sequelize order clause from query string parameters and default sort object
804
277
  *
805
278
  * @param {object} event - the event created AWS lambda, it will contain queryStringParameters with sort property a comma seperated list of sortable fields * @param {object} objectFilters - the default filters object created by createDefaultFilters
806
279
  * @param {object} defaultFilter - A default filter object as built by createDefault Filters, if items are not on the schema they will not be in the order by
807
280
  * @returns {object} An sequelize order by object
808
- */
809
- const createSort = function (event, defaultFilter) {
810
- let copyOfDefaultFilter = _lodash.default.clone(defaultFilter);
811
- let query = _lodash.default.get(event, 'queryStringParameters', {}) || {};
812
- let sort = _lodash.default.get(query, 'sort', '-updatedAt') || '-updatedAt';
813
-
814
- return sort.split(',').reduce((acc, item) => {
815
-
816
- const testItem = item.indexOf('-') === 0 ? item.substr(1) : item;
817
-
818
- if (_lodash.default.get(copyOfDefaultFilter, testItem, null)) {
819
- const sortItem = [];
820
-
821
- testItem.split('.').forEach((parentChildList) => {
822
- sortItem.push(parentChildList);
823
- });
824
-
825
- if (item.indexOf('-') === 0) {
826
- sortItem.push('DESC');
827
- } else {
828
- sortItem.push('ASC');
829
- }
830
- acc.push(sortItem);
831
- }
832
-
833
- return acc;
834
- }, []);
835
- };exports.createSort = createSort;
836
-
837
- /***/ },
838
-
839
- /***/ "./src/database/dbUtils/queryStringUtils/defaultFilters.js"
840
- /*!*****************************************************************!*\
841
- !*** ./src/database/dbUtils/queryStringUtils/defaultFilters.js ***!
842
- \*****************************************************************/
843
- (__unused_webpack_module, exports, __webpack_require__) {
844
-
845
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.addFiltersFromSchema = addFiltersFromSchema;exports.defaultFilters = defaultFilters;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
846
- var _sequelize = _interopRequireDefault(__webpack_require__(/*! sequelize */ "sequelize"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
847
-
281
+ */(__webpack_require__(825));exports.createSort=function(event,defaultFilter){let copyOfDefaultFilter=_lodash.default.clone(defaultFilter),query=_lodash.default.get(event,"queryStringParameters",{})||{};return(_lodash.default.get(query,"sort","-updatedAt")||"-updatedAt").split(",").reduce((acc,item)=>{const testItem=0===item.indexOf("-")?item.substr(1):item;if(_lodash.default.get(copyOfDefaultFilter,testItem,null)){const sortItem=[];testItem.split(".").forEach(parentChildList=>{sortItem.push(parentChildList)}),0===item.indexOf("-")?sortItem.push("DESC"):sortItem.push("ASC"),acc.push(sortItem)}return acc},[])}},
282
+ /***/859(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.detectDynamooseError=
848
283
  /**
849
- * Create an object with default filters for a given sequeliaze Schema Object, and set of sub schemas
284
+ * Parse the body of a Dynamoose error response.
285
+ * Attempts to extract a human-readable error message from Dynamoose errors.
286
+ * This is a fallback for unknown database errors.
850
287
  *
851
- * @param {object} schema - type is sequelize data type
852
- * @param {object} subSchemas - An object with alias as the key and sequelize schema as the value http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-method-define
853
- * sub schema can be {location: locationSchema} or {location: {as: "asAlias", schema: schema}}
854
- * @returns {object} An Object with a default filter for each dataType CHAR and TEXT will get a $like operator, INTEGER, DECIMAL and BOOLEAN will get a $eq.
288
+ * @param {object} body - Part of a body response containing error details.
289
+ * @returns {object} - Error message object { message: string }
290
+ */
291
+ function detectDynamooseError(body){const errorBody={};
292
+ // Start with an empty message string.
293
+ let dynamooseError="";
294
+ // If the error body contains an array of errors, concatenate their messages.
295
+ Array.isArray(body.errors)&&(dynamooseError+=body.errors.reduce((acc,err)=>acc+" "+(err.message||""),""));
296
+ // If there's a top-level message, add it.
297
+ body.message&&(dynamooseError+=" "+body.message);
298
+ // If there is any additional detail provided, append it.
299
+ body.detail&&(dynamooseError+=" "+body.detail);
300
+ // Trim the message to remove extra spaces.
301
+ return errorBody.message=dynamooseError.trim(),errorBody}
302
+ /***/,exports.detectJoyError=detectJoyError,exports.detectSequelizeError=detectSequelizeError,exports.failure=
303
+ /**
304
+ * Create a failure response
305
+ *
306
+ * @param body {Object} an event object
307
+ * @param options {Object} an options object
308
+ * @returns {{statusCode:number, headers:object, body:string}} a response object
855
309
  */
856
- function defaultFilters(schema, subSchemas = {}) {
857
- schema = _lodash.default.clone(schema);
858
-
859
- const filters = {};
860
-
861
- addFiltersFromSchema(schema, filters);
862
- Object.keys(subSchemas).forEach((key) => {
863
- addFiltersFromSchema(subSchemas[key], filters, key);
864
- });
865
-
866
- return filters;
867
- }
868
-
869
- function addFiltersFromSchema(schema, filters, keyPrefix = '') {
870
- const asLinkAlias = _lodash.default.get(schema, 'as', null);
871
- schema = _lodash.default.get(schema, 'schema') || schema;
872
-
873
- return Object.keys(schema).reduce((acc, item) => {
874
- let key = item;
875
-
876
- if (asLinkAlias) {
877
- acc[asLinkAlias] = { type: _sequelize.default.STRING, filterType: _sequelize.default.Op.eq };
878
- }
879
-
880
- if (keyPrefix) {
881
- key = `${keyPrefix}.${item}`;
882
- }
883
-
884
- if (schema[item].filterType) {
885
- acc[key] = { filterType: schema[item].filterType };
886
-
887
- return acc;
888
- }
889
-
890
- const itemType = schema[item].type;
891
-
892
- //new sequelize uses class symbols instead of objects
893
- if (itemType instanceof _sequelize.default.STRING) {
894
- acc[key] = { filterType: _sequelize.default.Op.iLike };
895
- } else if (itemType instanceof _sequelize.default.CHAR) {
896
- acc[key] = { filterType: _sequelize.default.Op.iLike };
897
- } else if (itemType instanceof _sequelize.default.TEXT) {
898
- acc[key] = { filterType: _sequelize.default.Op.iLike };
899
- } else if (itemType instanceof _sequelize.default.DECIMAL) {
900
- acc[key] = { filterType: _sequelize.default.Op.or };
901
- } else if (itemType instanceof _sequelize.default.INTEGER) {
902
- acc[key] = { filterType: _sequelize.default.Op.or };
903
- } else if (itemType instanceof _sequelize.default.BIGINT) {
904
- acc[key] = { filterType: _sequelize.default.Op.or };
905
- } else if (itemType instanceof _sequelize.default.BOOLEAN) {
906
- acc[key] = { type: _sequelize.default.BOOLEAN, filterType: _sequelize.default.Op.eq };
907
- } else if (itemType instanceof _sequelize.default.JSONB || itemType === _sequelize.default.JSONB) {
908
- acc[key] = { type: 'jsonb', field: item };
909
- } else if (itemType instanceof _sequelize.default.DATE) {
910
- acc[key] = { filterType: _sequelize.default.Op.between };
911
- } else if (itemType instanceof _sequelize.default.DATEONLY) {
912
- acc[key] = { filterType: _sequelize.default.Op.eq };
913
- }
914
-
915
- //these are automatically part of the models, so add them always
916
- acc['createdAt'] = { type: _sequelize.default.DATE, filterType: _sequelize.default.Op.between };
917
- acc['updatedAt'] = { type: _sequelize.default.DATE, filterType: _sequelize.default.Op.between };
918
- acc['id'] = { type: _sequelize.default.INTEGER, filterType: _sequelize.default.Op.eq };
919
-
920
- return acc;
921
- }, filters);
922
- }
923
-
924
- /***/ },
925
-
926
- /***/ "./src/database/dbUtils/queryStringUtils/findAll.js"
927
- /*!**********************************************************!*\
928
- !*** ./src/database/dbUtils/queryStringUtils/findAll.js ***!
929
- \**********************************************************/
930
- (__unused_webpack_module, exports) {
931
-
932
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;exports.findAll = findAll;exports.getPaginationFromFindAll = getPaginationFromFindAll; /**
933
- * create pagination object from Sequelize findAll
934
- * @param {object} result - sequelize result
935
- * @param {number} limit - max number of results to return
936
- * @param {number} offset - page offset
310
+ function failure(body={},options){let cleanedErrorBody;_lodash.default.get(options,"dbClose",_lodash.default.noop)(),("LOG_ALL"===process.env.UTIL_LOG||"test"===process.env.BUILD_ENV)&&_lodash.default.isObject(body)&&console.error("-------\x3eALL UTIL ERROR:",JSON.stringify(body,null,2));cleanedErrorBody=body,_lodash.default.isUndefined(body.details)?(_lodash.default.isUndefined(body.errorCode)||_lodash.default.isUndefined(body.statusCode))&&(cleanedErrorBody=detectSequelizeError(body)):cleanedErrorBody=detectJoyError(body);if(_lodash.default.get(body,"response.data.message")){const err=_lodash.default.get(body,"response.data.message");_lodash.default.isObject(body)&&("LOG_ALL"!==process.env.UTIL_LOG&&"test"!==process.env.BUILD_ENV||console.error("-------\x3eMSG UTIL ERROR:",JSON.stringify(err,null,2)))}const newBody=_lodash.default.merge({statusCode:500,errorCode:"5XX",message:"INTERNAL UTIL ERROR"},cleanedErrorBody);return buildResponse(newBody.statusCode,newBody)}
311
+ /**
312
+ * Create a failure response object
313
+ *
314
+ * @param statusCode {Number} a status code
315
+ * @param body {Object} an event object
316
+ * @returns {{statusCode:number, headers:object, body:string}} a response object
317
+ */,exports.getCurrentUser=
318
+ /**
319
+ * Get the user information from the event object
320
+ *
321
+ * @param event {Object} an event object
322
+ * @returns {{username: string, id: number}}
937
323
  */
938
- function getPaginationFromFindAll(result, limit, offset) {
939
- result = result || [];
940
- limit = limit || 0;
941
- offset = offset || 0;
942
-
943
- const hasMore = result.length > limit;
944
- if (hasMore) {
945
- result.splice(-1, 1);
946
- }
947
- const pageObject = {
948
- offset: offset,
949
- limit: limit,
950
- rows: result,
951
- hasMore: hasMore
952
- };
953
-
954
- return pageObject;
955
- }
956
-
324
+ function getCurrentUser(event){let jsonToParse=_lodash.default.get(event,"requestContext.authorizer.claims.custom:UID")||_lodash.default.get(event,"requestContext.authorizer.custom:UID")||"0";const id=JSON.parse(jsonToParse);return{username:_lodash.default.get(event,"requestContext.authorizer.claims.email")||_lodash.default.get(event,"requestContext.authorizer.email")||"localtestuser@gexample.com",id}},exports.getCurrentUserNameFromCognitoEvent=
957
325
  /**
958
- * wrapper for Sequelize findAll
959
- * @param {object} model - instance of Sequelize (must be initialized)
960
- * @param {*&{include: [{model: *}], where: {businessId: Array}, order: [string[]]}} options - instance of Sequelize (must be initialized)
326
+ * @param {string} event
327
+ * @returns string
961
328
  */
962
- async function findAll(model, options) {
963
-
964
- const limit = options.limit || 0;
965
- const includes = options.includes || { all: true, nested: true };
966
- const findArgs = Object.assign({ include: includes }, options, { limit: limit + 1 });
967
- const results = await model.findAll(findArgs);
968
- return getPaginationFromFindAll(results, limit, options.offset);
969
- }
970
-
971
- const findUtils = {
972
- findAll
973
- };var _default = exports["default"] =
974
- findUtils;
975
-
976
- /***/ },
977
-
978
- /***/ "./src/dynamo/dynamoUtils.js"
979
- /*!***********************************!*\
980
- !*** ./src/dynamo/dynamoUtils.js ***!
981
- \***********************************/
982
- (__unused_webpack_module, exports, __webpack_require__) {
983
-
984
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _libDynamodb = __webpack_require__(/*! @aws-sdk/lib-dynamodb */ "@aws-sdk/lib-dynamodb");
985
- var _clientDynamodb = __webpack_require__(/*! @aws-sdk/client-dynamodb */ "@aws-sdk/client-dynamodb");
986
-
987
- const dynamoUtil = {
988
- get: (params) => get(params)
989
- };
990
-
329
+ function getCurrentUserNameFromCognitoEvent(event){const attributes=_lodash.default.get(event,"request.userAttributes");return attributes["cognito:email_alias"]||attributes.email||"UNKNOWN USER"},exports.parseBody=
991
330
  /**
992
- * @param {{TableName:string, Key:{key:string}}} params
331
+ * parse the body of the event object
332
+ *
333
+ * @param requestEvent {{body:string}} an event object
334
+ * @returns event {*} the json object of the body
993
335
  */
994
- async function get(params) {
995
- const dynamoDb = _libDynamodb.DynamoDBDocument.from(new _clientDynamodb.DynamoDB());
996
- return dynamoDb.get(params);
997
- }var _default = exports["default"] =
998
-
999
- dynamoUtil;
1000
-
1001
- /***/ },
1002
-
1003
- /***/ "./src/eventManager/handleEvents.js"
1004
- /*!******************************************!*\
1005
- !*** ./src/eventManager/handleEvents.js ***!
1006
- \******************************************/
1007
- (__unused_webpack_module, exports, __webpack_require__) {
1008
-
1009
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.handleDirectS3WriteEvent = handleDirectS3WriteEvent;exports.handleEvents = handleEvents;var _handleFile = __webpack_require__(/*! ./handleFile.js */ "./src/eventManager/handleFile.js");
1010
- var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
1011
- var _bluebird = _interopRequireDefault(__webpack_require__(/*! bluebird */ "bluebird"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
1012
-
1013
- function handleEvents(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {
1014
- if (!event || !event.Records) {
1015
- return _bluebird.default.resolve();
1016
- }
1017
-
1018
- let hasErrors = false;
1019
-
1020
- return _bluebird.default.map(event.Records, (record) => {
1021
- const snsInfo = JSON.parse(_lodash.default.get(record, 'Sns.Message', '{}'));
1022
- const s3Bucket = snsInfo.bucket;
1023
- const files = snsInfo.files || [];
1024
-
1025
- return _bluebird.default.map(files, (file) => {
1026
- let path = decodeURIComponent(file);
1027
- if (path) {
1028
- return (0, _handleFile.handleFile)(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {
1029
- if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {
1030
- console.error('HANDLE-FILE-CATCH: ', err);
1031
- hasErrors = true;
1032
- }
1033
- });
1034
- }
1035
- });
1036
- }).then(() => {
1037
- if (hasErrors) {
1038
- throw new Error('ERROR: HANDLE-FILE');
1039
- }
1040
- });
1041
- }
1042
-
1043
- function handleDirectS3WriteEvent(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {
1044
- if (!event || !event.Records) {
1045
- return _bluebird.default.resolve();
1046
- }
1047
-
1048
- let hasErrors = false;
1049
-
1050
- return _bluebird.default.map(event.Records, (record) => {
1051
- const s3Bucket = record.s3.bucket.name;
1052
- const file = record.s3.object.key || [];
1053
-
1054
- let path = decodeURIComponent(file);
1055
- if (path) {
1056
- return (0, _handleFile.handleFile)(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {
1057
- if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {
1058
- console.error('HANDLE-FILE-CATCH:', err);
1059
- hasErrors = true;
1060
- }
1061
- });
1062
- }
1063
-
1064
- }).then(() => {
1065
- if (hasErrors) {
1066
- throw new Error('ERROR: HANDLE-FILE (DIRECT S3 EVENT)');
1067
- }
1068
- });
1069
- }
1070
-
1071
- /***/ },
1072
-
1073
- /***/ "./src/eventManager/handleFile.js"
1074
- /*!****************************************!*\
1075
- !*** ./src/eventManager/handleFile.js ***!
1076
- \****************************************/
1077
- (__unused_webpack_module, exports, __webpack_require__) {
1078
-
1079
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.containsError = containsError;exports.handleFile = handleFile;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
1080
- var _S3Utils = _interopRequireDefault(__webpack_require__(/*! ../s3/S3Utils/S3Utils.js */ "./src/s3/S3Utils/S3Utils.js"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
1081
-
1082
- async function handleFile(path, s3Bucket, transformer, options) {
1083
- const shouldSkipFailedFolders = _lodash.default.get(options, 'shouldSkipFailedFolders');
1084
- const userImportTypes = _lodash.default.get(options, 'userImportTypes');
1085
- const params = {
1086
- Bucket: s3Bucket,
1087
- Key: path
1088
- };
1089
- let body;
1090
-
1091
- try {
1092
- body = await _S3Utils.default.getObject(params);
1093
- } catch (e) {
1094
- if (e.Code === 'NoSuchKey' || e.code === 'NoSuchKey' || e.name === 'NoSuchKey') {
1095
- return;
1096
- }
1097
- console.error('S3 getObject error:', e);
1098
- throw e;
1099
- }
1100
-
1101
- try {
1102
- // exit early for null/undefined or blank string bodies
1103
- if (_lodash.default.isNil(body) || _lodash.default.isString(body) && _lodash.default.isEmpty(body.trim())) {
1104
- await _S3Utils.default.deleteObject(params);
1105
- return;
1106
- }
1107
-
1108
- const parsedBody = JSON.parse(body);
1109
-
1110
- // exit early for objects like {} or []
1111
- if (_lodash.default.isEmpty(parsedBody)) {
1112
- await _S3Utils.default.deleteObject(params);
1113
- return;
1114
- }
1115
-
1116
- const returnedValue = await transformer(parsedBody);
1117
- await _S3Utils.default.deleteObject(params);
1118
-
1119
- return returnedValue;
1120
- } catch (error) {
1121
- console.error('HANDLE-FILE-ERROR', error);
1122
-
1123
- if (!body) {
1124
- return;
1125
- }
1126
-
1127
- let newPath = '';
1128
-
1129
- if (userImportTypes) {
1130
- console.log('USER IMPORT');
1131
- // look for items in the userImportTypes
1132
- const usersImports = Object.values(userImportTypes);
1133
- const items = path.split('/');
1134
- const fileName = _lodash.default.last(items);
1135
- const folderName = _lodash.default.first(items);
1136
-
1137
- if (usersImports.indexOf(folderName) > -1) {
1138
- if (shouldSkipFailedFolders) {
1139
- newPath = `${folderName}/error/${fileName}`;
1140
- } else if (_lodash.default.startsWith(path, `${folderName}/failed-once/`)) {
1141
- newPath = _lodash.default.replace(path, `${folderName}/failed-once/`, `${folderName}/failed-twice/`);
1142
- } else if (_lodash.default.startsWith(path, `${folderName}/failed-twice/`)) {
1143
- newPath = _lodash.default.replace(path, `${folderName}/failed-twice/`, `${folderName}/error/`);
1144
- } else {
1145
- newPath = `${folderName}/failed-once/${fileName}`;
1146
- }
1147
- } else {
1148
- newPath = `pathAndEventMisMatchError/${path}`;
1149
- }
1150
-
1151
- } else {
1152
- if (shouldSkipFailedFolders) {
1153
- newPath = `error/${path}`;
1154
- } else if (_lodash.default.startsWith(path, 'failed-once/')) {
1155
- newPath = _lodash.default.replace(path, 'failed-once/', 'failed-twice/');
1156
- } else if (_lodash.default.startsWith(path, 'failed-twice/')) {
1157
- newPath = _lodash.default.replace(path, 'failed-twice/', 'error/');
1158
- } else {
1159
- if (_lodash.default.includes(path, 'delayUntil/')) {
1160
- path = _lodash.default.last(path.split('/'));
1161
- }
1162
-
1163
- newPath = `failed-once/${path}`;
1164
- }
1165
- }
1166
-
1167
- const newParams = {
1168
- Bucket: s3Bucket,
1169
- Key: newPath,
1170
- Body: body
1171
- };
1172
-
1173
- if (
1174
- containsError(newPath, 'failed-once') ||
1175
- containsError(newPath, 'failed-twice') ||
1176
- containsError(newPath, 'error'))
1177
- {
1178
- throw new Error('NESTING ERROR');
1179
- }
1180
-
1181
- await _S3Utils.default.putObject(newParams);
1182
- await _S3Utils.default.deleteObject(params);
1183
-
1184
- throw error;
1185
- }
1186
- }
1187
-
1188
- function containsError(str, val) {
1189
- const firstIndex = str.toLowerCase().indexOf(val);
1190
- if (firstIndex === -1) return false;
1191
- const secondIndex = str.toLowerCase().indexOf(val, firstIndex + 1);
1192
- return secondIndex !== -1;
1193
- }
1194
-
1195
- /***/ },
1196
-
1197
- /***/ "./src/eventManager/publishEvents.js"
1198
- /*!*******************************************!*\
1199
- !*** ./src/eventManager/publishEvents.js ***!
1200
- \*******************************************/
1201
- (__unused_webpack_module, exports, __webpack_require__) {
1202
-
1203
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.loop = loop;exports.publishEvents = publishEvents;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
1204
- var _dayjs = _interopRequireDefault(__webpack_require__(/*! dayjs */ "dayjs"));
1205
- var _customParseFormat = _interopRequireDefault(__webpack_require__(/*! dayjs/plugin/customParseFormat */ "dayjs/plugin/customParseFormat"));
1206
- var _isSameOrBefore = _interopRequireDefault(__webpack_require__(/*! dayjs/plugin/isSameOrBefore */ "dayjs/plugin/isSameOrBefore"));
1207
- var _bluebird = _interopRequireDefault(__webpack_require__(/*! bluebird */ "bluebird"));
1208
- var _S3Utils = _interopRequireDefault(__webpack_require__(/*! ../s3/S3Utils/S3Utils.js */ "./src/s3/S3Utils/S3Utils.js"));
1209
- var _SNSUtils = _interopRequireDefault(__webpack_require__(/*! ../sns/SNSUtils.js */ "./src/sns/SNSUtils.js"));
1210
- var _dynamoUtils = _interopRequireDefault(__webpack_require__(/*! ../dynamo/dynamoUtils.js */ "./src/dynamo/dynamoUtils.js"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
1211
-
1212
- _dayjs.default.extend(_customParseFormat.default);
1213
- _dayjs.default.extend(_isSameOrBefore.default);
1214
-
336
+ function parseBody(requestEvent){let eventBody={};if(_lodash.default.isString(requestEvent.body))try{eventBody=JSON.parse(requestEvent.body)}catch(e){
337
+ // Invalid JSON
338
+ throw eventBody=null,_errorCodes.errorList.invalidJson}else _lodash.default.isObject(requestEvent.body)&&(eventBody=requestEvent.body);return eventBody}
1215
339
  /**
1216
- * @param {string} bucket
1217
- * @param {number} maxKeys
1218
- * @param {Object} userImportTypes
340
+ * parse the body of the event object
341
+ *
342
+ * @param requestEvent {string|object} an event object
343
+ * @param [callback] {function} undefined a call back function
344
+ * @returns event {*} the json object of the body
345
+ */,exports.parseEvent=function parseEvent(requestEvent,callback){let event={};if(_lodash.default.isString(requestEvent))try{event=JSON.parse(requestEvent)}catch(e){
346
+ // Invalid JSON
347
+ event=null,callback&&callback(Error(e))}else _lodash.default.isObject(requestEvent)&&(event=requestEvent);return event}
348
+ /**
349
+ * parse the body of the event object
350
+ * look for sequelize errors and return a message
351
+ * ERRORS should not be caught here this is a fallback for unknown database errors
352
+ *
353
+ * @param body {object} part of a body response
354
+ * @returns error message object {message:string}
355
+ */,exports.success=
356
+ /**
357
+ * @param {Object} body
358
+ * @param {{dbClose?:function}} [options]
1219
359
  */
1220
- async function loop(bucket, maxKeys, userImportTypes) {
1221
- let bucketResult = {};
1222
- let fileList = [];
1223
-
1224
- const currentTime = (0, _dayjs.default)();
1225
-
1226
- do {
1227
- bucketResult = await _S3Utils.default.listObjectsV2({
1228
- Bucket: bucket,
1229
- MaxKeys: maxKeys,
1230
- ContinuationToken: _lodash.default.get(bucketResult, 'NextContinuationToken')
1231
- });
1232
-
1233
- let newFiles = _lodash.default.filter(bucketResult.Contents, (file) => {
1234
- if (_lodash.default.startsWith(_lodash.default.get(file, 'Key'), 'delayUntil/')) {
1235
- const fileDelayTime = _lodash.default.get(file, 'Key').split('/')[1];
1236
- return (0, _dayjs.default)(fileDelayTime, 'YYYYMMDDHHmm').isSameOrBefore(currentTime);
1237
- }
1238
- if (userImportTypes) {
1239
- // look for items in the userImportTypes
1240
- const usersImports = Object.values(userImportTypes);
1241
- const items = file.Key.split('/');
1242
- const fileName = _lodash.default.last(items);
1243
- const folderName = _lodash.default.first(items);
1244
- if (_lodash.default.isEmpty(fileName)) {
1245
- return false;
1246
-
1247
- } else if (usersImports.indexOf(folderName) === -1) {
1248
- return false;
1249
- }
1250
-
1251
- return !_lodash.default.startsWith(file.Key, `${folderName}/error`);
1252
- }
1253
- return !_lodash.default.startsWith(file.Key, 'error');
1254
- });
1255
-
1256
- fileList = _lodash.default.concat(fileList, newFiles);
1257
- } while (bucketResult.IsTruncated && bucketResult.NextContinuationToken && fileList.length < maxKeys);
1258
-
1259
- return fileList;
1260
- }
1261
-
360
+ function success(body,options){return _lodash.default.get(options,"dbClose",_lodash.default.noop)(),buildResponse(200,body)}
361
+ /**
362
+ * @param {string} html
363
+ * @param {{dbClose:function|undefined}} options
364
+ */,exports.successHtml=function successHtml(html,options){return _lodash.default.get(options,"dbClose",_lodash.default.noop)(),{statusCode:200,headers:{"Content-Type":"text/html","Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0,...htmlSecurityHeaders},body:html}};var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825)),_errorCodes=__webpack_require__(953);const securityHeaders={"Strict-Transport-Security":"max-age=31536000; includeSubDomains","X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"camera=(), microphone=(), geolocation=()","Cache-Control":"no-store","Content-Security-Policy":"default-src 'none'; frame-ancestors 'none'"},htmlSecurityHeaders={"Strict-Transport-Security":"max-age=31536000; includeSubDomains","X-Content-Type-Options":"nosniff","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"camera=(), microphone=(), geolocation=(), payment=*","Cache-Control":"no-store","Content-Security-Policy":["default-src 'self'","script-src 'self' 'unsafe-inline' https://browser.sentry-cdn.com https://test-htp.tokenex.com https://htp.tokenex.com https://sandbox.nmi.com https://secure.nmi.com https://applepay.cdn-apple.com","style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://sandbox.nmi.com https://secure.nmi.com","font-src 'self' https://fonts.gstatic.com","frame-src https:","connect-src 'self' https://*.tokenex.com https://*.sentry.io https://*.nmi.com https://*.apple.com","img-src 'self' data:","frame-ancestors *"].join("; ")};function buildResponse(statusCode,body){return{statusCode,headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0,...securityHeaders},body:JSON.stringify(body)}}function detectSequelizeError(body){const errorBody={},errorName=_lodash.default.get(body,"name","");if("SequelizeForeignKeyConstraintError"===errorName)return errorBody.message="You cannot UPDATE or DELETE this item as it is in use",errorBody.statusCode=409,errorBody.errorCode="4090",errorBody;if("SequelizeUniqueConstraintError"===errorName){const fields=_lodash.default.get(body,"errors",[]).map(err=>_lodash.default.get(err,"path")).filter(Boolean);return errorBody.message=fields.length?"A record with this "+fields.join(", ")+" already exists":"A record with this value already exists",errorBody.statusCode=409,errorBody.errorCode="4091",errorBody}if("SequelizeValidationError"===errorName){const messages=_lodash.default.get(body,"errors",[]).map(err=>_lodash.default.get(err,"message")).filter(Boolean);return errorBody.message=messages.length?messages.join(", "):"Validation error",errorBody.statusCode=400,errorBody.errorCode="4001",errorBody}let sequelizeError=_lodash.default.get(body,"errors",[]).reduce((acc,err)=>acc=acc+" "+_lodash.default.get(err,"message"),"");const parentError=_lodash.default.get(body,"parent","");return sequelizeError=sequelizeError+_lodash.default.get(body,"original.detail","")+_lodash.default.get(body,"TypeError","")+parentError,errorBody.message=sequelizeError.trim(),errorBody}function detectJoyError(body){const errorBody={},joyError=_lodash.default.get(body,"details[0]",{}),v=(_lodash.default.get(body,"details[0].context.details")||[]).reduce((acc,contextItem)=>acc=acc+" "+contextItem?.message||"","");console.error("USER VALIDATION ERROR:",body);const msg=(joyError?.message||"")+v;return msg&&(errorBody.message=_lodash.default.trim(msg)),errorBody.statusCode=400,errorBody.errorCode="4000",errorBody}},
365
+ /***/864(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.loop=loop,exports.publishEvents=
1262
366
  /**
1263
367
  * Published SNS events at a steady pace for data in a particular bucket. Should be executed via a cloud watch cron job as a part of a micro service
1264
368
  *
@@ -1268,857 +372,98 @@ async function loop(bucket, maxKeys, userImportTypes) {
1268
372
  * @param {string} snsTopic - The name of the snsEvent to publish
1269
373
  * @param {object} userImportTypes - import types to filter on
1270
374
  */
1271
- async function publishEvents(configTable, tableKey, bucket, snsTopic, userImportTypes) {
1272
- let result;
1273
- try {
1274
- result = await _dynamoUtils.default.get({
1275
- TableName: configTable,
1276
- Key: { key: tableKey }
1277
- });
1278
- } catch (e) {
1279
- console.error(`Cannot get config for key: ${tableKey} table: ${configTable} falling back to defaults of 2 and 10`, e);
1280
- }
1281
- let chunkSize = _lodash.default.get(result, 'Item.snsChunkSize', 2);
1282
- let maxMessages = _lodash.default.get(result, 'Item.snsMaxMessages', 10);
1283
-
1284
- const snsCreateTopicResponse = await _SNSUtils.default.createTopic({ Name: snsTopic });
1285
- const topicArn = snsCreateTopicResponse.TopicArn;
1286
- const maxKeys = chunkSize * maxMessages;
1287
-
1288
- const fileList = await loop(bucket, maxKeys, userImportTypes);
1289
-
1290
- const messageList = _lodash.default.chain(fileList).
1291
- map('Key').
1292
- chunk(chunkSize).
1293
- slice(0, maxMessages).
1294
- value();
1295
-
1296
-
1297
- return _bluebird.default.map(messageList, (files) => {
1298
- return _SNSUtils.default.publish({
1299
- Message: JSON.stringify({
1300
- bucket: bucket,
1301
- files: files
1302
- }),
1303
- TopicArn: topicArn
1304
- });
1305
- });
1306
- }
1307
-
1308
- /***/ },
1309
-
1310
- /***/ "./src/eventManager/watchBucket.js"
1311
- /*!*****************************************!*\
1312
- !*** ./src/eventManager/watchBucket.js ***!
1313
- \*****************************************/
1314
- (__unused_webpack_module, exports, __webpack_require__) {
1315
-
1316
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.watchBucket = watchBucket;var _publishEvents = __webpack_require__(/*! ./publishEvents.js */ "./src/eventManager/publishEvents.js");
1317
- var _handleEvents = __webpack_require__(/*! ./handleEvents.js */ "./src/eventManager/handleEvents.js");
1318
- var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
1319
-
375
+ async function publishEvents(configTable,tableKey,bucket,snsTopic,userImportTypes){let result;try{result=await _dynamoUtils.default.get({TableName:configTable,Key:{key:tableKey}})}catch(e){console.error(`Cannot get config for key: ${tableKey} table: ${configTable} falling back to defaults of 2 and 10`,e)}let chunkSize=_lodash.default.get(result,"Item.snsChunkSize",2),maxMessages=_lodash.default.get(result,"Item.snsMaxMessages",10);const topicArn=(await _SNSUtils.default.createTopic({Name:snsTopic})).TopicArn,maxKeys=chunkSize*maxMessages,fileList=await loop(bucket,maxKeys,userImportTypes),messageList=_lodash.default.chain(fileList).map("Key").chunk(chunkSize).slice(0,maxMessages).value();return _bluebird.default.map(messageList,files=>_SNSUtils.default.publish({Message:JSON.stringify({bucket,files}),TopicArn:topicArn}))}
376
+ /***/;var _lodash=_interopRequireDefault(__webpack_require__(825)),_dayjs=_interopRequireDefault(__webpack_require__(293)),_customParseFormat=_interopRequireDefault(__webpack_require__(59)),_isSameOrBefore=_interopRequireDefault(__webpack_require__(394)),_bluebird=_interopRequireDefault(__webpack_require__(564)),_S3Utils=_interopRequireDefault(__webpack_require__(908)),_SNSUtils=_interopRequireDefault(__webpack_require__(306)),_dynamoUtils=_interopRequireDefault(__webpack_require__(64));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
1320
377
  /**
1321
- * bucket watcher watches a s3 bucket and publishes events to a sns topic, this allows you to process files in s3 with a some transformer function
1322
- * prefix objects with DIRECT to listen to direct s3 events
1323
- *
1324
- * @param {object} params - The parameters for watchBucket, see below
1325
- * @param {object} params.event - The event of the lambda
1326
- * @param {string} params.dynamoConfigTable - The Dynamo DB table where to get the chunkSize and maxMessage size
1327
- * @param {string} params.dynamoConfigKey - The key to the item in the Dynamo DB table that holds the chunkSize and maxMessage size
1328
- * @param {string} params.s3Bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created
1329
- * @param {string} params.snsTopic - The name of the snsEvent to publish
1330
- * @param {function} params.transformer - the function to run on each file
1331
- * @param {function} [params.errorHandlerPerFile] - the function to run on as a catch on each file
1332
- * @param {boolean} [params.shouldSkipFailedFolders] - whether to use the failed-once, failed-twice, error or just error folders
1333
- * @param {object} [params.userImportTypes] - user import subdirectories object map
1334
- */
1335
- function watchBucket({
1336
- event,
1337
- dynamoConfigTable,
1338
- dynamoConfigKey,
1339
- s3Bucket,
1340
- snsTopic,
1341
- transformer,
1342
- errorHandlerPerFile = _lodash.default.noop,
1343
- shouldSkipFailedFolders = false,
1344
- userImportTypes
1345
- }) {
1346
- if (!event || !dynamoConfigTable || !dynamoConfigKey || !s3Bucket || !snsTopic || !transformer) {
1347
- throw new Error('Missing required parameters. Need event, dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, transformer');
1348
- }
1349
-
1350
- const EventSource = _lodash.default.get(event, 'Records[0].eventSource') || _lodash.default.get(event, 'Records[0].EventSource');
1351
-
1352
- if (_lodash.default.isEqual(EventSource, 'aws:sns')) {
1353
- return (0, _handleEvents.handleEvents)(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);
1354
- } else if (_lodash.default.isEqual(EventSource, 'aws:s3')) {
1355
- const failedOnce = 'failed-once';
1356
- const failedTwice = 'failed-twice';
1357
- const error = 'error';
1358
- const direct = 'DIRECT';
1359
- const key = _lodash.default.get(event, 'Records[0].s3.object.key') || '';
1360
- const startsWithDirect = _lodash.default.startsWith(key, direct);
1361
- if (key.includes(failedOnce) || key.includes(failedTwice) || key.includes(error)) {
1362
- // this used to throw, but the throw raised useless alarms, I believed turing throw in to a return was ok
1363
- return;
1364
- }
1365
-
1366
- if (startsWithDirect) {
1367
- console.log('------->DIRECT WRITE FIRE');
1368
- return (0, _handleEvents.handleDirectS3WriteEvent)(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);
1369
- }
1370
-
1371
- } else {
1372
- // the function is being run from the cron job so publish SNS events
1373
- return (0, _publishEvents.publishEvents)(dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, userImportTypes);
1374
- }
1375
- }
1376
-
1377
- /***/ },
1378
-
1379
- /***/ "./src/requestResponse/errorCodes.js"
1380
- /*!*******************************************!*\
1381
- !*** ./src/requestResponse/errorCodes.js ***!
1382
- \*******************************************/
1383
- (__unused_webpack_module, exports) {
1384
-
1385
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.errorList = void 0;const errorList = exports.errorList = {
1386
- invalidInventoryReleaseRequest: {
1387
- message: 'NOT ENOUGH INVENTORY TO FULFILL RELEASE',
1388
- errorCode: '4010',
1389
- statusCode: 400
1390
- },
1391
- alreadyReleased: {
1392
- message: 'ALREADY RELEASED',
1393
- errorCode: '4011',
1394
- statusCode: 400
1395
- },
1396
- alreadyReceived: {
1397
- message: 'RECEIVABLE ALREADY RECEIVED',
1398
- errorCode: '4012',
1399
- statusCode: 400
1400
- },
1401
- invalidItemsRequest: {
1402
- message: 'VALID ITEMS MUST BE INCLUDED',
1403
- errorCode: '4013',
1404
- statusCode: 400
1405
- },
1406
- invalidID: {
1407
- message: 'ID is invalid',
1408
- errorCode: '4014',
1409
- statusCode: 400
1410
- },
1411
- invalidReceivable: {
1412
- message: 'MUST CONTAIN AT LEAST ONE RECEIVABLE',
1413
- errorCode: '4015',
1414
- statusCode: 400
1415
- },
1416
- invalidRequest: {
1417
- message: 'INVALID REQUEST DATA',
1418
- errorCode: '4016',
1419
- statusCode: 400
1420
- },
1421
- invalidAPIKey: {
1422
- message: 'INVALID REQUEST - API MAY KEY INVALID',
1423
- errorCode: '4017',
1424
- statusCode: 400
1425
- },
1426
- qbCreationError: {
1427
- message: 'QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS',
1428
- errorCode: '4018',
1429
- statusCode: 400
1430
- },
1431
- cannotReopen: {
1432
- message: 'CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED',
1433
- errorCode: '4018',
1434
- statusCode: 400
1435
- },
1436
- invalidDateFormat: {
1437
- message: 'INVALID DATE FORMAT',
1438
- errorCode: '4019',
1439
- statusCode: 400
1440
- },
1441
- invalidStartDate: {
1442
- message: 'INVALID START DATE',
1443
- errorCode: '4020',
1444
- statusCode: 400
1445
- },
1446
- invalidEndDate: {
1447
- message: 'INVALID END DATE',
1448
- errorCode: '4021',
1449
- statusCode: 400
1450
- },
1451
- invalidOrderStatus: {
1452
- message: 'UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS',
1453
- errorCode: '4022',
1454
- statusCode: 400
1455
- },
1456
- invalidPaymentStatus: {
1457
- message: 'UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN',
1458
- errorCode: '4023',
1459
- statusCode: 400
1460
- },
1461
- invalidReleaseStatus: {
1462
- message: 'UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN',
1463
- errorCode: '4024',
1464
- statusCode: 400
1465
- },
1466
- invalidReceivableStatus: {
1467
- message: 'UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN',
1468
- errorCode: '40025',
1469
- statusCode: 400
1470
- },
1471
- invalidJson: {
1472
- message: 'INVALID JSON',
1473
- errorCode: '4005',
1474
- statusCode: 400
1475
- },
1476
- invalidFilter: {
1477
- message: 'INVALID FILTER',
1478
- errorCode: '4026',
1479
- statusCode: 400
1480
- },
1481
- invalidUserNameUpdate: {
1482
- message: 'UNABLE TO UPDATE USERNAME',
1483
- errorCode: '4027',
1484
- statusCode: 400
1485
- },
1486
- imageSizeLimit: {
1487
- message: 'IMAGE SIZE LIMIT 100KB EXCEEDED',
1488
- errorCode: '4028',
1489
- statusCode: 400
1490
- },
1491
- unauthorized: {
1492
- message: 'UNAUTHORIZED',
1493
- errorCode: '4111',
1494
- statusCode: 401
1495
- },
1496
- notFound: {
1497
- message: 'ITEM NOT FOUND',
1498
- errorCode: '4004',
1499
- statusCode: 404
1500
- },
1501
- emailRequired: {
1502
- message: 'NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL',
1503
- errorCode: '4004',
1504
- statusCode: 404
1505
- },
1506
- mobilePhoneRequired: {
1507
- message: 'NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS',
1508
- errorCode: '4004',
1509
- statusCode: 404
1510
- },
1511
- invalidCadenceType: {
1512
- message: 'INVALID CADENCE TYPE',
1513
- errorCode: '5001',
1514
- statusCode: 500
1515
- }
1516
- };
1517
-
1518
- /***/ },
1519
-
1520
- /***/ "./src/requestResponse/requestResponse.js"
1521
- /*!************************************************!*\
1522
- !*** ./src/requestResponse/requestResponse.js ***!
1523
- \************************************************/
1524
- (__unused_webpack_module, exports, __webpack_require__) {
1525
-
1526
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.detectDynamooseError = detectDynamooseError;exports.detectJoyError = detectJoyError;exports.detectSequelizeError = detectSequelizeError;exports.failure = failure;exports.getCurrentUser = getCurrentUser;exports.getCurrentUserNameFromCognitoEvent = getCurrentUserNameFromCognitoEvent;exports.parseBody = parseBody;exports.parseEvent = parseEvent;exports.success = success;exports.successHtml = successHtml;var _lodash = _interopRequireDefault(__webpack_require__(/*! lodash */ "lodash"));
1527
- var _errorCodes = __webpack_require__(/*! ./errorCodes.js */ "./src/requestResponse/errorCodes.js");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
1528
-
1529
- const securityHeaders = {
1530
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
1531
- 'X-Content-Type-Options': 'nosniff',
1532
- 'X-Frame-Options': 'DENY',
1533
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
1534
- 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
1535
- 'Cache-Control': 'no-store',
1536
- 'Content-Security-Policy': "default-src 'none'; frame-ancestors 'none'"
1537
- };
1538
-
1539
- const htmlSecurityHeaders = {
1540
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
1541
- 'X-Content-Type-Options': 'nosniff',
1542
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
1543
- 'Permissions-Policy': 'camera=(), microphone=(), geolocation=(), payment=*',
1544
- 'Cache-Control': 'no-store',
1545
- 'Content-Security-Policy': [
1546
- "default-src 'self'",
1547
- "script-src 'self' 'unsafe-inline' https://browser.sentry-cdn.com https://test-htp.tokenex.com https://htp.tokenex.com https://sandbox.nmi.com https://secure.nmi.com https://applepay.cdn-apple.com",
1548
- "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://sandbox.nmi.com https://secure.nmi.com",
1549
- "font-src 'self' https://fonts.gstatic.com",
1550
- "frame-src https:",
1551
- "connect-src 'self' https://*.tokenex.com https://*.sentry.io https://*.nmi.com https://*.apple.com",
1552
- "img-src 'self' data:",
1553
- "frame-ancestors *"].
1554
- join('; ')
1555
- };
1556
-
1557
- /**
1558
- * @param {Object} body
1559
- * @param {{dbClose?:function}} [options]
1560
- */
1561
- function success(body, options) {
1562
- const dbClose = _lodash.default.get(options, 'dbClose', _lodash.default.noop);
1563
- dbClose();
1564
-
1565
- return buildResponse(200, body);
1566
- }
1567
-
1568
- /**
1569
- * @param {string} html
1570
- * @param {{dbClose:function|undefined}} options
1571
- */
1572
- function successHtml(html, options) {
1573
- const dbClose = _lodash.default.get(options, 'dbClose', _lodash.default.noop);
1574
-
1575
- dbClose();
1576
- return {
1577
- statusCode: 200,
1578
- headers: {
1579
- 'Content-Type': 'text/html',
1580
- 'Access-Control-Allow-Origin': '*',
1581
- 'Access-Control-Allow-Credentials': true,
1582
- ...htmlSecurityHeaders
1583
- },
1584
- body: html
1585
- };
1586
- }
1587
-
1588
- /**
1589
- * @param {string} event
1590
- * @returns string
1591
- */
1592
- function getCurrentUserNameFromCognitoEvent(event) {
1593
- const attributes = _lodash.default.get(event, 'request.userAttributes');
1594
-
1595
- return attributes['cognito:email_alias'] || attributes['email'] || 'UNKNOWN USER';
1596
- }
1597
-
1598
- /**
1599
- * Get the user information from the event object
1600
- *
1601
- * @param event {Object} an event object
1602
- * @returns {{username: string, id: number}}
1603
- */
1604
- function getCurrentUser(event) {
1605
- let jsonToParse = _lodash.default.get(event, 'requestContext.authorizer.claims.custom:UID') ||
1606
- _lodash.default.get(event, 'requestContext.authorizer.custom:UID') ||
1607
- '0';
1608
-
1609
- const id = JSON.parse(jsonToParse);
1610
-
1611
- const username = _lodash.default.get(event, 'requestContext.authorizer.claims.email') || _lodash.default.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';
1612
-
1613
- return {
1614
- username,
1615
- id
1616
- };
1617
- }
1618
-
1619
- /**
1620
- * Create a failure response
1621
- *
1622
- * @param body {Object} an event object
1623
- * @param options {Object} an options object
1624
- * @returns {{statusCode:number, headers:object, body:string}} a response object
1625
- */
1626
- function failure(body = {}, options) {
1627
- const dbClose = _lodash.default.get(options, 'dbClose', _lodash.default.noop);
1628
- dbClose();
1629
- let cleanedErrorBody;
1630
-
1631
- if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {
1632
- if (_lodash.default.isObject(body)) {
1633
- console.error('------->ALL UTIL ERROR:', JSON.stringify(body, null, 2));
1634
- }
1635
- }
1636
-
1637
- const NORMAL_ERROR = { statusCode: 500, errorCode: '5XX', message: 'INTERNAL UTIL ERROR' };
1638
- cleanedErrorBody = body;
1639
- if (!_lodash.default.isUndefined(body.details)) {
1640
- cleanedErrorBody = detectJoyError(body);
1641
- } else if (_lodash.default.isUndefined(body.errorCode) || _lodash.default.isUndefined(body.statusCode)) {
1642
- cleanedErrorBody = detectSequelizeError(body);
1643
- }
1644
- if (_lodash.default.get(body, 'response.data.message')) {
1645
- const err = _lodash.default.get(body, 'response.data.message');
1646
- if (_lodash.default.isObject(body)) {
1647
- if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {
1648
- console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));
1649
- }
1650
- }
1651
- }
1652
- const newBody = _lodash.default.merge(NORMAL_ERROR, cleanedErrorBody);
1653
-
1654
- return buildResponse(newBody.statusCode, newBody);
1655
- }
1656
-
1657
- /**
1658
- * Create a failure response object
1659
- *
1660
- * @param statusCode {Number} a status code
1661
- * @param body {Object} an event object
1662
- * @returns {{statusCode:number, headers:object, body:string}} a response object
1663
- */
1664
- function buildResponse(statusCode, body) {
1665
- return {
1666
- statusCode: statusCode,
1667
- headers: {
1668
- 'Access-Control-Allow-Origin': '*',
1669
- 'Access-Control-Allow-Credentials': true,
1670
- ...securityHeaders
1671
- },
1672
- body: JSON.stringify(body)
1673
- };
1674
- }
1675
-
1676
- /**
1677
- * parse the body of the event object
1678
- *
1679
- * @param requestEvent {{body:string}} an event object
1680
- * @returns event {*} the json object of the body
378
+ * @param {string} bucket
379
+ * @param {number} maxKeys
380
+ * @param {Object} userImportTypes
1681
381
  */
1682
- function parseBody(requestEvent) {
1683
-
1684
- let eventBody = {};
1685
- if (_lodash.default.isString(requestEvent.body)) {
1686
- try {
1687
- eventBody = JSON.parse(requestEvent.body);
1688
- } catch (e) {
1689
- // Invalid JSON
1690
- eventBody = null;
1691
-
1692
- throw _errorCodes.errorList.invalidJson;
1693
- }
1694
- } else if (_lodash.default.isObject(requestEvent.body)) {
1695
- eventBody = requestEvent.body;
1696
- }
1697
-
1698
- return eventBody;
1699
- }
1700
-
1701
- /**
1702
- * parse the body of the event object
1703
- *
1704
- * @param requestEvent {string|object} an event object
1705
- * @param [callback] {function} undefined a call back function
1706
- * @returns event {*} the json object of the body
382
+ async function loop(bucket,maxKeys,userImportTypes){let bucketResult={},fileList=[];const currentTime=(0,_dayjs.default)();do{bucketResult=await _S3Utils.default.listObjectsV2({Bucket:bucket,MaxKeys:maxKeys,ContinuationToken:_lodash.default.get(bucketResult,"NextContinuationToken")});let newFiles=_lodash.default.filter(bucketResult.Contents,file=>{if(_lodash.default.startsWith(_lodash.default.get(file,"Key"),"delayUntil/")){const fileDelayTime=_lodash.default.get(file,"Key").split("/")[1];return(0,_dayjs.default)(fileDelayTime,"YYYYMMDDHHmm").isSameOrBefore(currentTime)}if(userImportTypes){
383
+ // look for items in the userImportTypes
384
+ const usersImports=Object.values(userImportTypes),items=file.Key.split("/"),fileName=_lodash.default.last(items),folderName=_lodash.default.first(items);return!_lodash.default.isEmpty(fileName)&&(-1!==usersImports.indexOf(folderName)&&!_lodash.default.startsWith(file.Key,`${folderName}/error`))}return!_lodash.default.startsWith(file.Key,"error")});fileList=_lodash.default.concat(fileList,newFiles)}while(bucketResult.IsTruncated&&bucketResult.NextContinuationToken&&fileList.length<maxKeys);return fileList}_dayjs.default.extend(_customParseFormat.default),_dayjs.default.extend(_isSameOrBefore.default)},
385
+ /***/871(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.runMigrations=
386
+ /**
387
+ * Execute database migrations
388
+ * @param {string} databaseName - name of database to create (or verify existence)
389
+ * @param {object} sequelizeInstance - instance of Sequelize (must be initialized)
390
+ * @param {function} initializeModels - function to run to sync Sequelize models with database
391
+ * @param {string} pathToMigrationFolder - pass in the path if using windows. windows and linux PWD will be different
1707
392
  */
1708
- function parseEvent(requestEvent, callback) {
1709
- let event = {};
1710
- if (_lodash.default.isString(requestEvent)) {
1711
- try {
1712
- event = JSON.parse(requestEvent);
1713
- } catch (e) {
1714
- // Invalid JSON
1715
- event = null;
1716
-
1717
- if (callback) {
1718
- callback(Error(e));
1719
- }
1720
- }
1721
- } else if (_lodash.default.isObject(requestEvent)) {
1722
- event = requestEvent;
1723
- }
1724
-
1725
- return event;
1726
- }
1727
-
1728
- /**
1729
- * parse the body of the event object
1730
- * look for sequelize errors and return a message
1731
- * ERRORS should not be caught here this is a fallback for unknown database errors
1732
- *
1733
- * @param body {object} part of a body response
1734
- * @returns error message object {message:string}
393
+ async function runMigrations(databaseName,sequelizeInstance,initializeModels,pathToMigrationFolder=`${process.env.PWD}/migrations/*.js`){const umzug=new _umzug.Umzug({migrations:{glob:pathToMigrationFolder},context:sequelizeInstance.getQueryInterface(),storage:new _umzug.SequelizeStorage({sequelize:sequelizeInstance}),logger:console}),pendingMigrations=await umzug.pending();console.log("-------\x3eUTIL Pending Migrations:",pendingMigrations,pathToMigrationFolder),await umzug.up().catch(upError=>(console.error("Migration Error: ",upError),umzug.down({migrations:_lodash.default.chain(pendingMigrations).map("file").reverse().value()}).then(()=>{const msg="UTIL Error: Error with migrating up:"+upError;throw console.error(msg),new Error(msg)},downError=>{const msg="UTIL Error: Error with migrating down:"+downError;throw console.error(msg),new Error(msg)}))),
394
+ // The following line is needed to sync (create) tables, but not to database updates
395
+ // in the past it worked to leave it in, but now the tags module causes foreign key problems
396
+ // The tables are still initiated by being passed in to run migrations
397
+ await initializeModels()}
398
+ /***/;var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825)),_umzug=__webpack_require__(920)},
399
+ /***/876(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.containsError=containsError,exports.handleFile=async function handleFile(path,s3Bucket,transformer,options){const shouldSkipFailedFolders=_lodash.default.get(options,"shouldSkipFailedFolders"),userImportTypes=_lodash.default.get(options,"userImportTypes"),params={Bucket:s3Bucket,Key:path};let body;try{body=await _S3Utils.default.getObject(params)}catch(e){if("NoSuchKey"===e.Code||"NoSuchKey"===e.code||"NoSuchKey"===e.name)return;throw console.error("S3 getObject error:",e),e}try{
400
+ // exit early for null/undefined or blank string bodies
401
+ if(_lodash.default.isNil(body)||_lodash.default.isString(body)&&_lodash.default.isEmpty(body.trim()))return void await _S3Utils.default.deleteObject(params);const parsedBody=JSON.parse(body);
402
+ // exit early for objects like {} or []
403
+ if(_lodash.default.isEmpty(parsedBody))return void await _S3Utils.default.deleteObject(params);const returnedValue=await transformer(parsedBody);return await _S3Utils.default.deleteObject(params),returnedValue}catch(error){if(console.error("HANDLE-FILE-ERROR",error),!body)return;let newPath="";if(userImportTypes){console.log("USER IMPORT");
404
+ // look for items in the userImportTypes
405
+ const usersImports=Object.values(userImportTypes),items=path.split("/"),fileName=_lodash.default.last(items),folderName=_lodash.default.first(items);newPath=usersImports.indexOf(folderName)>-1?shouldSkipFailedFolders?`${folderName}/error/${fileName}`:_lodash.default.startsWith(path,`${folderName}/failed-once/`)?_lodash.default.replace(path,`${folderName}/failed-once/`,`${folderName}/failed-twice/`):_lodash.default.startsWith(path,`${folderName}/failed-twice/`)?_lodash.default.replace(path,`${folderName}/failed-twice/`,`${folderName}/error/`):`${folderName}/failed-once/${fileName}`:`pathAndEventMisMatchError/${path}`}else shouldSkipFailedFolders?newPath=`error/${path}`:_lodash.default.startsWith(path,"failed-once/")?newPath=_lodash.default.replace(path,"failed-once/","failed-twice/"):_lodash.default.startsWith(path,"failed-twice/")?newPath=_lodash.default.replace(path,"failed-twice/","error/"):(_lodash.default.includes(path,"delayUntil/")&&(path=_lodash.default.last(path.split("/"))),newPath=`failed-once/${path}`);const newParams={Bucket:s3Bucket,Key:newPath,Body:body};if(containsError(newPath,"failed-once")||containsError(newPath,"failed-twice")||containsError(newPath,"error"))throw new Error("NESTING ERROR");throw await _S3Utils.default.putObject(newParams),await _S3Utils.default.deleteObject(params),error}};var _lodash=_interopRequireDefault(__webpack_require__(825)),_S3Utils=_interopRequireDefault(__webpack_require__(908));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function containsError(str,val){const firstIndex=str.toLowerCase().indexOf(val);if(-1===firstIndex)return!1;return-1!==str.toLowerCase().indexOf(val,firstIndex+1)}
406
+ /***/},
407
+ /***/908(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0,exports.s3Utils=s3Utils;var _clientS=__webpack_require__(43);function s3Utils(action,params){return(new _clientS.S3)[action](params)}const S3Util={getObject:params=>async function getS3(params){const s3=new _clientS.S3,response=await s3.getObject(params);return response?.Body.transformToString("utf-8")}
408
+ /***/(params),deleteObject:params=>s3Utils("deleteObject",params),putObject:params=>s3Utils("putObject",params),listObjectsV2:params=>s3Utils("listObjectsV2",params)};exports.default=S3Util},
409
+ /***/920(module){module.exports=require("umzug");
410
+ /***/},
411
+ /***/929(module){module.exports=require("@aws-sdk/client-dynamodb");
412
+ /***/},
413
+ /***/953(__unused_webpack_module,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorList=void 0;exports.errorList={invalidInventoryReleaseRequest:{message:"NOT ENOUGH INVENTORY TO FULFILL RELEASE",errorCode:"4010",statusCode:400},alreadyReleased:{message:"ALREADY RELEASED",errorCode:"4011",statusCode:400},alreadyReceived:{message:"RECEIVABLE ALREADY RECEIVED",errorCode:"4012",statusCode:400},invalidItemsRequest:{message:"VALID ITEMS MUST BE INCLUDED",errorCode:"4013",statusCode:400},invalidID:{message:"ID is invalid",errorCode:"4014",statusCode:400},invalidReceivable:{message:"MUST CONTAIN AT LEAST ONE RECEIVABLE",errorCode:"4015",statusCode:400},invalidRequest:{message:"INVALID REQUEST DATA",errorCode:"4016",statusCode:400},invalidAPIKey:{message:"INVALID REQUEST - API MAY KEY INVALID",errorCode:"4017",statusCode:400},qbCreationError:{message:"QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS",errorCode:"4018",statusCode:400},cannotReopen:{message:"CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED",errorCode:"4018",statusCode:400},invalidDateFormat:{message:"INVALID DATE FORMAT",errorCode:"4019",statusCode:400},invalidStartDate:{message:"INVALID START DATE",errorCode:"4020",statusCode:400},invalidEndDate:{message:"INVALID END DATE",errorCode:"4021",statusCode:400},invalidOrderStatus:{message:"UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS",errorCode:"4022",statusCode:400},invalidPaymentStatus:{message:"UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN",errorCode:"4023",statusCode:400},invalidReleaseStatus:{message:"UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN",errorCode:"4024",statusCode:400},invalidReceivableStatus:{message:"UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN",errorCode:"40025",statusCode:400},invalidJson:{message:"INVALID JSON",errorCode:"4005",statusCode:400},invalidFilter:{message:"INVALID FILTER",errorCode:"4026",statusCode:400},invalidUserNameUpdate:{message:"UNABLE TO UPDATE USERNAME",errorCode:"4027",statusCode:400},imageSizeLimit:{message:"IMAGE SIZE LIMIT 100KB EXCEEDED",errorCode:"4028",statusCode:400},unauthorized:{message:"UNAUTHORIZED",errorCode:"4111",statusCode:401},notFound:{message:"ITEM NOT FOUND",errorCode:"4004",statusCode:404},emailRequired:{message:"NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL",errorCode:"4004",statusCode:404},mobilePhoneRequired:{message:"NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS",errorCode:"4004",statusCode:404},invalidCadenceType:{message:"INVALID CADENCE TYPE",errorCode:"5001",statusCode:500}};
414
+ /***/},
415
+ /***/981(__unused_webpack_module,exports){
416
+ /**
417
+ * create pagination object from Sequelize findAll
418
+ * @param {object} result - sequelize result
419
+ * @param {number} limit - max number of results to return
420
+ * @param {number} offset - page offset
1735
421
  */
1736
- function detectSequelizeError(body) {
1737
- const errorBody = {};
1738
- const errorName = _lodash.default.get(body, 'name', '');
1739
-
1740
- if (errorName === 'SequelizeForeignKeyConstraintError') {
1741
- errorBody.message = 'You cannot delete this item as it is in use';
1742
- errorBody.statusCode = 409;
1743
- errorBody.errorCode = '4090';
1744
- return errorBody;
1745
- }
1746
-
1747
- if (errorName === 'SequelizeUniqueConstraintError') {
1748
- const fields = _lodash.default.get(body, 'errors', []).map((err) => _lodash.default.get(err, 'path')).filter(Boolean);
1749
- errorBody.message = fields.length ?
1750
- 'A record with this ' + fields.join(', ') + ' already exists' :
1751
- 'A record with this value already exists';
1752
- errorBody.statusCode = 409;
1753
- errorBody.errorCode = '4091';
1754
- return errorBody;
1755
- }
1756
-
1757
- if (errorName === 'SequelizeValidationError') {
1758
- const messages = _lodash.default.get(body, 'errors', []).map((err) => _lodash.default.get(err, 'message')).filter(Boolean);
1759
- errorBody.message = messages.length ? messages.join(', ') : 'Validation error';
1760
- errorBody.statusCode = 400;
1761
- errorBody.errorCode = '4001';
1762
- return errorBody;
1763
- }
1764
-
1765
- let sequelizeError = _lodash.default.get(body, 'errors', []).reduce((acc, err) => {
1766
- acc = acc + ' ' + _lodash.default.get(err, 'message');
1767
- return acc;
1768
- }, '');
1769
- const parentError = _lodash.default.get(body, 'parent', '');
1770
-
1771
- sequelizeError = sequelizeError + _lodash.default.get(body, 'original.detail', '') + _lodash.default.get(body, 'TypeError', '') + parentError;
1772
- errorBody.message = sequelizeError.trim();
1773
- return errorBody;
1774
- }
1775
-
1776
- function detectJoyError(body) {
1777
- const errorBody = {};
1778
- const joyError = _lodash.default.get(body, 'details[0]', {});
1779
- const additionalMessages = _lodash.default.get(body, 'details[0].context.details') || [];
1780
-
1781
- const v = additionalMessages.reduce((acc, contextItem) => {
1782
- acc = acc + ' ' + contextItem?.message || '';
1783
- return acc;
1784
- }, '');
1785
-
1786
- console.error('USER VALIDATION ERROR:', body);
1787
- const msg = (joyError?.message || '') + v;
1788
-
1789
- if (msg) {
1790
- errorBody.message = _lodash.default.trim(msg);
1791
- }
1792
-
1793
- errorBody.statusCode = 400;
1794
- errorBody.errorCode = '4000';
1795
- return errorBody;
1796
- }
1797
-
1798
- /**
1799
- * Parse the body of a Dynamoose error response.
1800
- * Attempts to extract a human-readable error message from Dynamoose errors.
1801
- * This is a fallback for unknown database errors.
1802
- *
1803
- * @param {object} body - Part of a body response containing error details.
1804
- * @returns {object} - Error message object { message: string }
422
+ function getPaginationFromFindAll(result,limit,offset){limit=limit||0,offset=offset||0;const hasMore=(result=result||[]).length>limit;hasMore&&result.splice(-1,1);return{offset,limit,rows:result,hasMore}}
423
+ /**
424
+ * wrapper for Sequelize findAll
425
+ * @param {object} model - instance of Sequelize (must be initialized)
426
+ * @param {*&{include: [{model: *}], where: {businessId: Array}, order: [string[]]}} options - instance of Sequelize (must be initialized)
427
+ */async function findAll(model,options){const limit=options.limit||0,includes=options.includes||{all:!0,nested:!0},findArgs=Object.assign({include:includes},options,{limit:limit+1});return getPaginationFromFindAll(await model.findAll(findArgs),limit,options.offset)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0,exports.findAll=findAll,exports.getPaginationFromFindAll=getPaginationFromFindAll;const findUtils={findAll};exports.default=findUtils;
428
+ /***/},
429
+ /***/982(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.createIncludes=
430
+ /**
431
+ * Create sequelize includes array from query string parameters and default sequelize model
432
+ *
433
+ * @param {object} event - the query parameters from the event passed by lambda
434
+ * @param {object} objectFilters - the default filters object created by createDefaultFilters
435
+ * @returns {object} A sequelize includes array
1805
436
  */
1806
- function detectDynamooseError(body) {
1807
- const errorBody = {};
1808
-
1809
- // Start with an empty message string.
1810
- let dynamooseError = '';
1811
-
1812
- // If the error body contains an array of errors, concatenate their messages.
1813
- if (Array.isArray(body.errors)) {
1814
- dynamooseError += body.errors.reduce((acc, err) => {
1815
- return acc + ' ' + (err.message || '');
1816
- }, '');
1817
- }
1818
-
1819
- // If there's a top-level message, add it.
1820
- if (body.message) {
1821
- dynamooseError += ' ' + body.message;
1822
- }
1823
-
1824
- // If there is any additional detail provided, append it.
1825
- if (body.detail) {
1826
- dynamooseError += ' ' + body.detail;
1827
- }
1828
-
1829
- // Trim the message to remove extra spaces.
1830
- errorBody.message = dynamooseError.trim();
1831
-
1832
- return errorBody;
1833
- }
1834
-
1835
- /***/ },
1836
-
1837
- /***/ "./src/s3/S3Utils/S3Utils.js"
1838
- /*!***********************************!*\
1839
- !*** ./src/s3/S3Utils/S3Utils.js ***!
1840
- \***********************************/
1841
- (__unused_webpack_module, exports, __webpack_require__) {
1842
-
1843
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;exports.s3Utils = s3Utils;var _clientS = __webpack_require__(/*! @aws-sdk/client-s3 */ "@aws-sdk/client-s3");
1844
-
1845
- function s3Utils(action, params) {
1846
- const s3 = new _clientS.S3();
1847
- return s3[action](params);
1848
- }
1849
-
1850
- const S3Util = {
1851
- getObject: (params) => getS3(params),
1852
- deleteObject: (params) => s3Utils('deleteObject', params),
1853
- putObject: (params) => s3Utils('putObject', params),
1854
- listObjectsV2: (params) => s3Utils('listObjectsV2', params)
1855
- };var _default = exports["default"] =
1856
- S3Util;
1857
-
1858
- async function getS3(params) {
1859
- const s3 = new _clientS.S3();
1860
- const response = await s3.getObject(params);
1861
- return response?.Body.transformToString('utf-8');
1862
- }
1863
-
1864
- /***/ },
1865
-
1866
- /***/ "./src/sns/SNSUtils.js"
1867
- /*!*****************************!*\
1868
- !*** ./src/sns/SNSUtils.js ***!
1869
- \*****************************/
1870
- (__unused_webpack_module, exports, __webpack_require__) {
1871
-
1872
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports["default"] = void 0;var _clientSns = __webpack_require__(/*! @aws-sdk/client-sns */ "@aws-sdk/client-sns");
1873
-
1874
- const SNSUtil = {
1875
- publish: (params) => publish(params),
1876
- createTopic: (params) => createTopic(params)
1877
- };
1878
-
1879
- async function publish(params) {
1880
- const sns = new _clientSns.SNS();
1881
- return await sns.publish(params);
1882
- }
1883
-
1884
- async function createTopic(params) {
1885
- const sns = new _clientSns.SNS();
1886
- return await sns.createTopic(params);
1887
- }var _default = exports["default"] =
1888
-
1889
- SNSUtil;
1890
-
1891
- /***/ },
1892
-
1893
- /***/ "@aws-sdk/client-dynamodb"
1894
- /*!*******************************************!*\
1895
- !*** external "@aws-sdk/client-dynamodb" ***!
1896
- \*******************************************/
1897
- (module) {
1898
-
1899
- module.exports = require("@aws-sdk/client-dynamodb");
1900
-
1901
- /***/ },
1902
-
1903
- /***/ "@aws-sdk/client-s3"
1904
- /*!*************************************!*\
1905
- !*** external "@aws-sdk/client-s3" ***!
1906
- \*************************************/
1907
- (module) {
1908
-
1909
- module.exports = require("@aws-sdk/client-s3");
1910
-
1911
- /***/ },
1912
-
1913
- /***/ "@aws-sdk/client-sns"
1914
- /*!**************************************!*\
1915
- !*** external "@aws-sdk/client-sns" ***!
1916
- \**************************************/
1917
- (module) {
1918
-
1919
- module.exports = require("@aws-sdk/client-sns");
1920
-
1921
- /***/ },
1922
-
1923
- /***/ "@aws-sdk/lib-dynamodb"
1924
- /*!****************************************!*\
1925
- !*** external "@aws-sdk/lib-dynamodb" ***!
1926
- \****************************************/
1927
- (module) {
1928
-
1929
- module.exports = require("@aws-sdk/lib-dynamodb");
1930
-
1931
- /***/ },
1932
-
1933
- /***/ "bluebird"
1934
- /*!***************************!*\
1935
- !*** external "bluebird" ***!
1936
- \***************************/
1937
- (module) {
1938
-
1939
- module.exports = require("bluebird");
1940
-
1941
- /***/ },
1942
-
1943
- /***/ "dayjs"
1944
- /*!************************!*\
1945
- !*** external "dayjs" ***!
1946
- \************************/
1947
- (module) {
1948
-
1949
- module.exports = require("dayjs");
1950
-
1951
- /***/ },
1952
-
1953
- /***/ "dayjs/plugin/customParseFormat"
1954
- /*!*************************************************!*\
1955
- !*** external "dayjs/plugin/customParseFormat" ***!
1956
- \*************************************************/
1957
- (module) {
1958
-
1959
- module.exports = require("dayjs/plugin/customParseFormat");
1960
-
1961
- /***/ },
1962
-
1963
- /***/ "dayjs/plugin/isSameOrBefore"
1964
- /*!**********************************************!*\
1965
- !*** external "dayjs/plugin/isSameOrBefore" ***!
1966
- \**********************************************/
1967
- (module) {
1968
-
1969
- module.exports = require("dayjs/plugin/isSameOrBefore");
1970
-
1971
- /***/ },
1972
-
1973
- /***/ "dayjs/plugin/utc.js"
1974
- /*!**************************************!*\
1975
- !*** external "dayjs/plugin/utc.js" ***!
1976
- \**************************************/
1977
- (module) {
1978
-
1979
- module.exports = require("dayjs/plugin/utc.js");
1980
-
1981
- /***/ },
1982
-
1983
- /***/ "lodash"
1984
- /*!*************************!*\
1985
- !*** external "lodash" ***!
1986
- \*************************/
1987
- (module) {
1988
-
1989
- module.exports = require("lodash");
1990
-
1991
- /***/ },
1992
-
1993
- /***/ "sequelize"
1994
- /*!****************************!*\
1995
- !*** external "sequelize" ***!
1996
- \****************************/
1997
- (module) {
1998
-
1999
- module.exports = require("sequelize");
2000
-
2001
- /***/ },
2002
-
2003
- /***/ "umzug"
2004
- /*!************************!*\
2005
- !*** external "umzug" ***!
2006
- \************************/
2007
- (module) {
2008
-
2009
- module.exports = require("umzug");
2010
-
2011
- /***/ }
2012
-
2013
- /******/ });
2014
- /************************************************************************/
2015
- /******/ // The module cache
2016
- /******/ var __webpack_module_cache__ = {};
2017
- /******/
2018
- /******/ // The require function
2019
- /******/ function __webpack_require__(moduleId) {
2020
- /******/ // Check if module is in cache
2021
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
2022
- /******/ if (cachedModule !== undefined) {
2023
- /******/ return cachedModule.exports;
2024
- /******/ }
2025
- /******/ // Check if module exists (development only)
2026
- /******/ if (__webpack_modules__[moduleId] === undefined) {
2027
- /******/ var e = new Error("Cannot find module '" + moduleId + "'");
2028
- /******/ e.code = 'MODULE_NOT_FOUND';
2029
- /******/ throw e;
2030
- /******/ }
2031
- /******/ // Create a new module (and put it into the cache)
2032
- /******/ var module = __webpack_module_cache__[moduleId] = {
2033
- /******/ // no module.id needed
2034
- /******/ // no module.loaded needed
2035
- /******/ exports: {}
2036
- /******/ };
2037
- /******/
2038
- /******/ // Execute the module function
2039
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
2040
- /******/
2041
- /******/ // Return the exports of the module
2042
- /******/ return module.exports;
2043
- /******/ }
2044
- /******/
437
+ function createIncludes(event,objectFilters){const query=_lodash.default.get(event,"queryStringParameters",{})||{},canBeIncluded=Object.keys(objectFilters).reduce((acc,item)=>acc=includeSubItem(item,acc),[]),askedForInQuery=Object.keys(query).reduce((acc,item)=>("sort"===item&&query[item].split(",").forEach(sortItem=>{sortItem=0===sortItem.indexOf("-")?sortItem.substr(1):sortItem,acc=includeSubItem(sortItem,acc)}),acc=includeSubItem(item,acc)),[]);return _lodash.default.intersection(canBeIncluded,askedForInQuery)},exports.includeSubItem=includeSubItem;var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825));function includeSubItem(queryStringItem,acc=[]){const dot=queryStringItem.indexOf(".");return dot>0&&acc.push(queryStringItem.substring(0,dot)),acc}
438
+ /***/}
439
+ /******/},__webpack_module_cache__={};
2045
440
  /************************************************************************/
2046
- var __webpack_exports__ = {};
2047
- // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
2048
- (() => {
2049
- var exports = __webpack_exports__;
2050
- /*!**********************!*\
2051
- !*** ./src/index.js ***!
2052
- \**********************/
2053
- Object.defineProperty(exports, "__esModule", ({ value: true }));exports.watchBucket = exports.userDefaultBid = exports.successHtml = exports.success = exports.runMigrations = exports.publishEvents = exports.parseEvent = exports.parseBody = exports.isSystemUser = exports.isSuperUser = exports.isPartnerUser = exports.handleFile = exports.getModuleInfo = exports.getEffectivePartnerId = exports.getDefaultBusinessIDInfo = exports.getCurrentUserNameFromCognitoEvent = exports.getCurrentUser = exports.getCompanySettings = exports.getBusinessesInfo = exports.getBelongsToPartnerId = exports.getAccessRightsInfo = exports.findAll = exports.failure = exports.enrichEventWithPartnerAccess = exports.defaultFilters = exports.createSort = exports.createIncludes = exports.createFilters = exports.checkWriteAccess = exports.checkModule = exports.checkIsSuper = exports.accessRightsUtils = void 0;var _handleFile = __webpack_require__(/*! ./eventManager/handleFile.js */ "./src/eventManager/handleFile.js");
2054
- var _watchBucket = __webpack_require__(/*! ./eventManager/watchBucket.js */ "./src/eventManager/watchBucket.js");
2055
- var _publishEvents = __webpack_require__(/*! ./eventManager/publishEvents.js */ "./src/eventManager/publishEvents.js");
2056
- var _createIncludes = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/createIncludes.js */ "./src/database/dbUtils/queryStringUtils/createIncludes.js");
2057
- var _createFilters = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/createFilters.js */ "./src/database/dbUtils/queryStringUtils/createFilters.js");
2058
- var _createSort = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/createSort.js */ "./src/database/dbUtils/queryStringUtils/createSort.js");
2059
- var _findAll = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/findAll.js */ "./src/database/dbUtils/queryStringUtils/findAll.js");
2060
- var _accessRightsUtils = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/accessRightsUtils.js */ "./src/database/dbUtils/queryStringUtils/accessRightsUtils.js");
2061
-
2062
-
2063
-
2064
-
2065
- var _requestResponse = __webpack_require__(/*! ./requestResponse/requestResponse.js */ "./src/requestResponse/requestResponse.js");
2066
- var _migrations = __webpack_require__(/*! ./database/dbSetup/migrations.js */ "./src/database/dbSetup/migrations.js");
2067
-
2068
-
2069
-
2070
- var _defaultFilters = __webpack_require__(/*! ./database/dbUtils/queryStringUtils/defaultFilters.js */ "./src/database/dbUtils/queryStringUtils/defaultFilters.js");
2071
-
2072
-
2073
-
2074
-
2075
-
2076
-
2077
-
2078
-
2079
-
2080
-
2081
-
2082
-
2083
-
2084
-
2085
- const handleFile = exports.handleFile = _handleFile.handleFile;
2086
- const watchBucket = exports.watchBucket = _watchBucket.watchBucket;
2087
- const publishEvents = exports.publishEvents = _publishEvents.publishEvents;
2088
- const createFilters = exports.createFilters = _createFilters.createFilters;
2089
- const createIncludes = exports.createIncludes = _createIncludes.createIncludes;
2090
- const createSort = exports.createSort = _createSort.createSort;
2091
- const findAll = exports.findAll = _findAll.findAll;
2092
- const checkModule = exports.checkModule = _accessRightsUtils.checkModule;
2093
- const checkIsSuper = exports.checkIsSuper = _accessRightsUtils.checkIsSuper;
2094
- const getAccessRightsInfo = exports.getAccessRightsInfo = _accessRightsUtils.getAccessRightsInfo;
2095
- const getDefaultBusinessIDInfo = exports.getDefaultBusinessIDInfo = _accessRightsUtils.getDefaultBusinessIDInfo;
2096
- const getModuleInfo = exports.getModuleInfo = _accessRightsUtils.getModuleInfo;
2097
- const failure = exports.failure = _requestResponse.failure;
2098
- const success = exports.success = _requestResponse.success;
2099
- const runMigrations = exports.runMigrations = _migrations.runMigrations;
2100
- const getCurrentUser = exports.getCurrentUser = _requestResponse.getCurrentUser;
2101
- const successHtml = exports.successHtml = _requestResponse.successHtml;
2102
- const getCurrentUserNameFromCognitoEvent = exports.getCurrentUserNameFromCognitoEvent = _requestResponse.getCurrentUserNameFromCognitoEvent;
2103
- const defaultFilters = exports.defaultFilters = _defaultFilters.defaultFilters;
2104
- const accessRightsUtils = exports.accessRightsUtils = _accessRightsUtils.accessRightsUtils;
2105
- const parseBody = exports.parseBody = _requestResponse.parseBody;
2106
- const parseEvent = exports.parseEvent = _requestResponse.parseEvent;
2107
- const getBusinessesInfo = exports.getBusinessesInfo = _accessRightsUtils.getBusinessesInfo;
2108
- const userDefaultBid = exports.userDefaultBid = _accessRightsUtils.userDefaultBid;
2109
- const checkWriteAccess = exports.checkWriteAccess = _accessRightsUtils.checkWriteAccess;
2110
- const isSystemUser = exports.isSystemUser = _accessRightsUtils.isSystemUser;
2111
- const isSuperUser = exports.isSuperUser = _accessRightsUtils.isSuperUser;
2112
- const isPartnerUser = exports.isPartnerUser = _accessRightsUtils.isPartnerUser;
2113
- const getBelongsToPartnerId = exports.getBelongsToPartnerId = _accessRightsUtils.getBelongsToPartnerId;
2114
- const getEffectivePartnerId = exports.getEffectivePartnerId = _accessRightsUtils.getEffectivePartnerId;
2115
- const enrichEventWithPartnerAccess = exports.enrichEventWithPartnerAccess = _accessRightsUtils.enrichEventWithPartnerAccess;
2116
- const getCompanySettings = exports.getCompanySettings = _accessRightsUtils.getCompanySettings;
2117
- })();
2118
-
2119
- var __webpack_export_target__ = exports;
2120
- for(var __webpack_i__ in __webpack_exports__) __webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
2121
- if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });
2122
- /******/ })()
2123
- ;
441
+ /******/ // The module cache
442
+ /******/
443
+ /******/
444
+ /******/ // The require function
445
+ /******/function __webpack_require__(moduleId){
446
+ /******/ // Check if module is in cache
447
+ /******/var cachedModule=__webpack_module_cache__[moduleId];
448
+ /******/if(void 0!==cachedModule)
449
+ /******/return cachedModule.exports;
450
+ /******/
451
+ /******/ // Create a new module (and put it into the cache)
452
+ /******/var module=__webpack_module_cache__[moduleId]={
453
+ /******/ // no module.id needed
454
+ /******/ // no module.loaded needed
455
+ /******/exports:{}
456
+ /******/};
457
+ /******/
458
+ /******/ // Execute the module function
459
+ /******/
460
+ /******/
461
+ /******/ // Return the exports of the module
462
+ /******/return __webpack_modules__[moduleId](module,module.exports,__webpack_require__),module.exports;
463
+ /******/}
464
+ /******/
465
+ /************************************************************************/var __webpack_exports__={};
466
+ // This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
467
+ (()=>{var exports=__webpack_exports__;Object.defineProperty(exports,"__esModule",{value:!0}),exports.watchBucket=exports.userDefaultBid=exports.successHtml=exports.success=exports.runMigrations=exports.publishEvents=exports.parseEvent=exports.parseBody=exports.isSystemUser=exports.isSuperUser=exports.isPartnerUser=exports.handleFile=exports.getModuleInfo=exports.getEffectivePartnerId=exports.getDefaultBusinessIDInfo=exports.getCurrentUserNameFromCognitoEvent=exports.getCurrentUser=exports.getCompanySettings=exports.getBusinessesInfo=exports.getBelongsToPartnerId=exports.getAccessRightsInfo=exports.findAll=exports.failure=exports.enrichEventWithPartnerAccess=exports.defaultFilters=exports.createSort=exports.createIncludes=exports.createFilters=exports.checkWriteAccess=exports.checkModule=exports.checkIsSuper=exports.accessRightsUtils=void 0;var _handleFile=__webpack_require__(876),_watchBucket=__webpack_require__(183),_publishEvents=__webpack_require__(864),_createIncludes=__webpack_require__(982),_createFilters=__webpack_require__(288),_createSort=__webpack_require__(835),_findAll=__webpack_require__(981),_accessRightsUtils=__webpack_require__(673),_requestResponse=__webpack_require__(859),_migrations=__webpack_require__(871),_defaultFilters=__webpack_require__(207);exports.handleFile=_handleFile.handleFile,exports.watchBucket=_watchBucket.watchBucket,exports.publishEvents=_publishEvents.publishEvents,exports.createFilters=_createFilters.createFilters,exports.createIncludes=_createIncludes.createIncludes,exports.createSort=_createSort.createSort,exports.findAll=_findAll.findAll,exports.checkModule=_accessRightsUtils.checkModule,exports.checkIsSuper=_accessRightsUtils.checkIsSuper,exports.getAccessRightsInfo=_accessRightsUtils.getAccessRightsInfo,exports.getDefaultBusinessIDInfo=_accessRightsUtils.getDefaultBusinessIDInfo,exports.getModuleInfo=_accessRightsUtils.getModuleInfo,exports.failure=_requestResponse.failure,exports.success=_requestResponse.success,exports.runMigrations=_migrations.runMigrations,exports.getCurrentUser=_requestResponse.getCurrentUser,exports.successHtml=_requestResponse.successHtml,exports.getCurrentUserNameFromCognitoEvent=_requestResponse.getCurrentUserNameFromCognitoEvent,exports.defaultFilters=_defaultFilters.defaultFilters,exports.accessRightsUtils=_accessRightsUtils.accessRightsUtils,exports.parseBody=_requestResponse.parseBody,exports.parseEvent=_requestResponse.parseEvent,exports.getBusinessesInfo=_accessRightsUtils.getBusinessesInfo,exports.userDefaultBid=_accessRightsUtils.userDefaultBid,exports.checkWriteAccess=_accessRightsUtils.checkWriteAccess,exports.isSystemUser=_accessRightsUtils.isSystemUser,exports.isSuperUser=_accessRightsUtils.isSuperUser,exports.isPartnerUser=_accessRightsUtils.isPartnerUser,exports.getBelongsToPartnerId=_accessRightsUtils.getBelongsToPartnerId,exports.getEffectivePartnerId=_accessRightsUtils.getEffectivePartnerId,exports.enrichEventWithPartnerAccess=_accessRightsUtils.enrichEventWithPartnerAccess,exports.getCompanySettings=_accessRightsUtils.getCompanySettings})();var __webpack_export_target__=exports;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0})
468
+ /******/})();
2124
469
  //# sourceMappingURL=main.js.map