piper-utils 1.1.54 → 1.1.56

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/WHITE_LABEL.md ADDED
@@ -0,0 +1,60 @@
1
+ # White Label Partner System — piper-utils
2
+
3
+ ## Overview
4
+
5
+ This repo provides shared utility functions for identifying partner users and enriching their access rights. These functions are used by piper (ERP) and can be used by any service that processes Lambda events with JWT claims.
6
+
7
+ ## Files
8
+
9
+ | File | Purpose |
10
+ |------|---------|
11
+ | `src/database/dbUtils/queryStringUtils/accessRightsUtils.js` | Added 4 partner functions |
12
+ | `src/index.js` | Exports the new functions |
13
+
14
+ ## JWT Claims
15
+
16
+ Two Cognito custom attributes drive the partner system:
17
+
18
+ | Claim | Meaning | Set on |
19
+ |-------|---------|--------|
20
+ | `custom:PID` | User is a partner admin | Partner admin users |
21
+ | `custom:BPID` | User's business belongs to a partner | Merchant users managed by a partner |
22
+
23
+ ## Functions
24
+
25
+ ### `isPartnerUser(event)`
26
+ Returns the partner ID from `custom:PID` if present, otherwise `false`. Use this to identify partner admin users who manage multiple businesses.
27
+
28
+ ### `getBelongsToPartnerId(event)`
29
+ Returns the partner ID from `custom:BPID` if present, otherwise `false`. Use this to identify merchant users whose business is managed by a partner (branding only, no extra access).
30
+
31
+ ### `getEffectivePartnerId(event)`
32
+ Returns whichever partner ID exists — checks `custom:PID` first, falls back to `custom:BPID`. Used by the whoAmI endpoint to look up branding regardless of user type.
33
+
34
+ ### `enrichEventWithPartnerAccess(event, partnerBusinessIds, role = 'R')`
35
+ Mutates the event's `custom:AR` claim in-memory to include the partner's business IDs. This is the "enrichment pattern" — the caller does the DB lookup to get the business IDs, then calls this function before calling any existing access control functions like `accessRightsUtils()` or `checkWriteAccess()`.
36
+
37
+ **Why mutate instead of making accessRightsUtils async?** The access rights functions are synchronous and used across every service. Making them async would be a massive breaking change. The enrichment pattern keeps them synchronous — the caller does the async DB work, enriches the event, then the existing sync functions work as-is.
38
+
39
+ ## Example Usage
40
+
41
+ ```javascript
42
+ import { isPartnerUser, enrichEventWithPartnerAccess } from 'piper-utils';
43
+
44
+ // In a route handler:
45
+ const partnerId = isPartnerUser(event);
46
+ if (partnerId) {
47
+ // Fetch partner's business IDs from DynamoDB
48
+ const partner = await getPartnerById(partnerId);
49
+ // Enrich the event so accessRightsUtils sees the partner's businesses
50
+ enrichEventWithPartnerAccess(event, partner.businessIds, 'R');
51
+ }
52
+
53
+ // Now existing access control works as normal
54
+ const businessIds = accessRightsUtils(event);
55
+ // businessIds now includes the partner's businesses with 'R' access
56
+ ```
57
+
58
+ ## Build
59
+
60
+ After modifying source files, rebuild with `npm run build`. The compiled output goes to `bin/main.js`. Other repos consume piper-utils via npm, so they need `npm install` or `npm link` to pick up changes.
package/bin/main.js CHANGED
@@ -193,7 +193,26 @@ function checkModule(moduleName,event){const moduleRights=getModuleInfo(event);l
193
193
  * @returns {string} businessId
194
194
  */
195
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
- /***/,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.getBusinessesInfo=getBusinessesInfo,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.getModuleInfo=getModuleInfo,exports.getRequestedBusinessIds=getRequestedBusinessIds,exports.isSuperUser=isSuperUser,exports.isSystemUser=isSystemUser,exports.userDefaultBid=
196
+ /***/,exports.enrichEventWithPartnerAccess=
197
+ /**
198
+ * Enrich the event's custom:AR with partner business IDs in-memory.
199
+ * Call this BEFORE accessRightsUtils() or getBusinessesInfo() so that
200
+ * partner admins (custom:PID) get access to their partner's merchants.
201
+ *
202
+ * This keeps accessRightsUtils synchronous — the DB lookup is done by the caller.
203
+ *
204
+ * @param {object} event - The lambda event passed in by a validated api request.
205
+ * @param {string[]} partnerBusinessIds - Array of business IDs from the partner record.
206
+ * @param {string} [role='R'] - Access role to assign (default: Read).
207
+ */
208
+ 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.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=
209
+ /**
210
+ * Get the effective partner ID from either custom:PID or custom:BPID.
211
+ *
212
+ * @param {object} event - The lambda event passed in by a validated api request.
213
+ * @returns {string|false} The partner ID or false.
214
+ */
215
+ 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=
197
216
  /**
198
217
  * Get the businessID set in cognito as custom:DBI.
199
218
  *
@@ -229,7 +248,19 @@ bodyBid&&(businessIds[bodyBid]="A")}return businessIds}
229
248
  *
230
249
  * @param {object} event - The lambda event passed in by a validated api request.
231
250
  * @returns {array} The Module access list
232
- */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"}},
251
+ */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"};
252
+ /**
253
+ * Get the partner ID from custom:PID if the user is a partner admin.
254
+ *
255
+ * @param {object} event - The lambda event passed in by a validated api request.
256
+ * @returns {string|false} The partner ID or false if not a partner user.
257
+ */function isPartnerUser(event){return _lodash.default.get(event,"requestContext.authorizer.claims.custom:PID")||_lodash.default.get(event,"requestContext.authorizer.custom:PID")||""||!1}
258
+ /**
259
+ * Get the partner ID from custom:BPID if the user's business belongs to a partner.
260
+ *
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 associated with a partner.
263
+ */function getBelongsToPartnerId(event){return _lodash.default.get(event,"requestContext.authorizer.claims.custom:BPID")||_lodash.default.get(event,"requestContext.authorizer.custom:BPID")||""||!1}},
233
264
  /***/793(module){module.exports=require("@aws-sdk/client-sns");
234
265
  /***/},
235
266
  /***/825(module){module.exports=require("lodash");
@@ -270,7 +301,7 @@ return errorBody.message=dynamooseError.trim(),errorBody}
270
301
  * @param options {Object} an options object
271
302
  * @returns {{statusCode:number, headers:object, body:string}} a response object
272
303
  */
273
- 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)&&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)}
304
+ 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)}
274
305
  /**
275
306
  * Create a failure response object
276
307
  *
@@ -324,7 +355,7 @@ function success(body,options){return _lodash.default.get(options,"dbClose",_lod
324
355
  /**
325
356
  * @param {string} html
326
357
  * @param {{dbClose:function|undefined}} options
327
- */,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},body:html}};var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825)),_errorCodes=__webpack_require__(953);function buildResponse(statusCode,body){return{statusCode,headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Credentials":!0},body:JSON.stringify(body)}}function detectSequelizeError(body){const errorBody={},errorName=_lodash.default.get(body,"name","");if("SequelizeForeignKeyConstraintError"===errorName)return errorBody.message="You cannot 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}},
358
+ */,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","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 '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","style-src 'self' 'unsafe-inline' https://fonts.googleapis.com","font-src 'self' https://fonts.gstatic.com","frame-src https:","connect-src 'self' https://*.tokenex.com https://*.sentry.io https://*.nmi.com","img-src 'self' data:","frame-ancestors 'none'"].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 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}},
328
359
  /***/864(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.loop=loop,exports.publishEvents=
329
360
  /**
330
361
  * 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
@@ -427,6 +458,6 @@ function createIncludes(event,objectFilters){const query=_lodash.default.get(eve
427
458
  /******/
428
459
  /************************************************************************/var __webpack_exports__={};
429
460
  // This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
430
- (()=>{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.handleFile=exports.getModuleInfo=exports.getDefaultBusinessIDInfo=exports.getCurrentUserNameFromCognitoEvent=exports.getCurrentUser=exports.getBusinessesInfo=exports.getAccessRightsInfo=exports.findAll=exports.failure=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})();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})
461
+ (()=>{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.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})();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})
431
462
  /******/})();
432
463
  //# sourceMappingURL=main.js.map
package/bin/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","mappings":"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","sources":["webpack://piper-utils/external commonjs \"sequelize\"","webpack://piper-utils/external commonjs \"@aws-sdk/client-s3\"","webpack://piper-utils/external commonjs \"dayjs/plugin/customParseFormat\"","webpack://piper-utils/./src/dynamo/dynamoUtils.js","webpack://piper-utils/./src/eventManager/handleEvents.js","webpack://piper-utils/external commonjs \"dayjs/plugin/utc.js\"","webpack://piper-utils/./src/eventManager/watchBucket.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/defaultFilters.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createFilters.js","webpack://piper-utils/external commonjs \"dayjs\"","webpack://piper-utils/./src/sns/SNSUtils.js","webpack://piper-utils/external commonjs \"dayjs/plugin/isSameOrBefore\"","webpack://piper-utils/external commonjs \"@aws-sdk/lib-dynamodb\"","webpack://piper-utils/external commonjs \"bluebird\"","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/accessRightsUtils.js","webpack://piper-utils/external commonjs \"@aws-sdk/client-sns\"","webpack://piper-utils/external commonjs \"lodash\"","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createSort.js","webpack://piper-utils/./src/requestResponse/requestResponse.js","webpack://piper-utils/./src/eventManager/publishEvents.js","webpack://piper-utils/./src/database/dbSetup/migrations.js","webpack://piper-utils/./src/eventManager/handleFile.js","webpack://piper-utils/./src/s3/S3Utils/S3Utils.js","webpack://piper-utils/external commonjs \"umzug\"","webpack://piper-utils/external commonjs \"@aws-sdk/client-dynamodb\"","webpack://piper-utils/./src/requestResponse/errorCodes.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/findAll.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createIncludes.js","webpack://piper-utils/webpack/bootstrap","webpack://piper-utils/./src/index.js"],"sourcesContent":["module.exports = require(\"sequelize\");","module.exports = require(\"@aws-sdk/client-s3\");","module.exports = require(\"dayjs/plugin/customParseFormat\");","import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';\nimport { DynamoDB } from '@aws-sdk/client-dynamodb';\n\nconst dynamoUtil = {\n get: (params) => get(params)\n};\n\n/**\n * @param {{TableName:string, Key:{key:string}}} params\n */\nasync function get(params) {\n const dynamoDb = DynamoDBDocument.from(new DynamoDB());\n return dynamoDb.get(params);\n}\n\nexport default dynamoUtil;","import { handleFile } from './handleFile.js';\nimport _ from 'lodash';\nimport Promise from 'bluebird';\n\nexport function handleEvents(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {\n if (!event || !event.Records) {\n return Promise.resolve();\n }\n\n let hasErrors = false;\n\n return Promise.map(event.Records, (record) => {\n const snsInfo = JSON.parse(_.get(record, 'Sns.Message', '{}'));\n const s3Bucket = snsInfo.bucket;\n const files = snsInfo.files || [];\n\n return Promise.map(files, (file) => {\n let path = decodeURIComponent(file);\n if (path) {\n return handleFile(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {\n if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {\n console.error('HANDLE-FILE-CATCH: ', err);\n hasErrors = true;\n }\n });\n }\n });\n }).then(() => {\n if (hasErrors) {\n throw new Error('ERROR: HANDLE-FILE');\n }\n });\n}\n\nexport function handleDirectS3WriteEvent(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {\n if (!event || !event.Records) {\n return Promise.resolve();\n }\n\n let hasErrors = false;\n\n return Promise.map(event.Records, (record) => {\n const s3Bucket = record.s3.bucket.name;\n const file = record.s3.object.key || [];\n\n let path = decodeURIComponent(file);\n if (path) {\n return handleFile(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {\n if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {\n console.error('HANDLE-FILE-CATCH:', err);\n hasErrors = true;\n }\n });\n }\n\n }).then(() => {\n if (hasErrors) {\n throw new Error('ERROR: HANDLE-FILE (DIRECT S3 EVENT)');\n }\n });\n}\n","module.exports = require(\"dayjs/plugin/utc.js\");","import { publishEvents } from './publishEvents.js';\nimport { handleEvents, handleDirectS3WriteEvent } from './handleEvents.js';\nimport _ from 'lodash';\n\n/**\n * 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\n * prefix objects with DIRECT to listen to direct s3 events\n *\n * @param {object} params - The parameters for watchBucket, see below\n * @param {object} params.event - The event of the lambda\n * @param {string} params.dynamoConfigTable - The Dynamo DB table where to get the chunkSize and maxMessage size\n * @param {string} params.dynamoConfigKey - The key to the item in the Dynamo DB table that holds the chunkSize and maxMessage size\n * @param {string} params.s3Bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created\n * @param {string} params.snsTopic - The name of the snsEvent to publish\n * @param {function} params.transformer - the function to run on each file\n * @param {function} [params.errorHandlerPerFile] - the function to run on as a catch on each file\n * @param {boolean} [params.shouldSkipFailedFolders] - whether to use the failed-once, failed-twice, error or just error folders\n * @param {object} [params.userImportTypes] - user import subdirectories object map\n */\nexport function watchBucket({\n event,\n dynamoConfigTable,\n dynamoConfigKey,\n s3Bucket,\n snsTopic,\n transformer,\n errorHandlerPerFile = _.noop,\n shouldSkipFailedFolders = false,\n userImportTypes\n }) {\n if (!event || !dynamoConfigTable || !dynamoConfigKey || !s3Bucket || !snsTopic || !transformer) {\n throw new Error('Missing required parameters. Need event, dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, transformer');\n }\n\n const EventSource = _.get(event, 'Records[0].eventSource') || _.get(event, 'Records[0].EventSource');\n\n if (_.isEqual(EventSource, 'aws:sns')) {\n return handleEvents(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);\n } else if (_.isEqual(EventSource, 'aws:s3')) {\n const failedOnce = 'failed-once';\n const failedTwice = 'failed-twice';\n const error = 'error';\n const direct = 'DIRECT';\n const key = _.get(event, 'Records[0].s3.object.key') || '';\n const startsWithDirect = _.startsWith(key, direct);\n if (key.includes(failedOnce) || key.includes(failedTwice) || key.includes(error)) {\n // this used to throw, but the throw raised useless alarms, I believed turing throw in to a return was ok\n return;\n }\n\n if (startsWithDirect) {\n console.log('------->DIRECT WRITE FIRE');\n return handleDirectS3WriteEvent(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);\n }\n\n } else {\n // the function is being run from the cron job so publish SNS events\n return publishEvents(dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, userImportTypes);\n }\n}\n","import _ from 'lodash';\nimport DB from 'sequelize';\n\n/**\n * Create an object with default filters for a given sequeliaze Schema Object, and set of sub schemas\n *\n * @param {object} schema - type is sequelize data type\n * @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\n * sub schema can be {location: locationSchema} or {location: {as: \"asAlias\", schema: schema}}\n * @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.\n */\nexport function defaultFilters(schema, subSchemas = {}) {\n schema = _.clone(schema);\n\n const filters = {};\n\n addFiltersFromSchema(schema, filters);\n Object.keys(subSchemas).forEach((key) => {\n addFiltersFromSchema(subSchemas[key], filters, key);\n });\n\n return filters;\n}\n\nexport function addFiltersFromSchema(schema, filters, keyPrefix = '') {\n const asLinkAlias = _.get(schema, 'as', null);\n schema = _.get(schema, 'schema') || schema;\n\n return Object.keys(schema).reduce((acc, item) => {\n let key = item;\n\n if (asLinkAlias) {\n acc[asLinkAlias] = { type: DB.STRING, filterType: DB.Op.eq };\n }\n\n if (keyPrefix) {\n key = `${keyPrefix}.${item}`;\n }\n\n if (schema[item].filterType) {\n acc[key] = { filterType: schema[item].filterType };\n\n return acc;\n }\n\n const itemType = schema[item].type;\n\n //new sequelize uses class symbols instead of objects\n if (itemType instanceof DB.STRING) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.CHAR) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.TEXT) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.DECIMAL) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.INTEGER) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.BIGINT) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.BOOLEAN) {\n acc[key] = { type: DB.BOOLEAN, filterType: DB.Op.eq };\n } else if (itemType instanceof DB.JSONB || itemType === DB.JSONB) {\n acc[key] = { type: 'jsonb', field: item };\n } else if (itemType instanceof DB.DATE) {\n acc[key] = { filterType: DB.Op.between };\n } else if (itemType instanceof DB.DATEONLY) {\n acc[key] = { filterType: DB.Op.eq };\n }\n\n //these are automatically part of the models, so add them always\n acc['createdAt'] = { type: DB.DATE, filterType: DB.Op.between };\n acc['updatedAt'] = { type: DB.DATE, filterType: DB.Op.between };\n acc['id'] = { type: DB.INTEGER, filterType: DB.Op.eq };\n\n return acc;\n }, filters);\n}\n","import _ from 'lodash';\nimport DB from 'sequelize';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport { errorList } from '../../../requestResponse/errorCodes.js';\nimport { accessRightsUtils } from './accessRightsUtils.js';\n\ndayjs.extend(utc);\n\n/**\n * Create sequelize where clause from query string parameters and default sort object\n *\n * Translates URL query string parameters into a Sequelize-compatible WHERE object\n * by matching each param against a filter definition (objectFilters).\n *\n * Filter definitions come from defaultFilters() which maps schema data types to operators:\n * STRING / CHAR / TEXT -> Op.iLike (case-insensitive LIKE)\n * INTEGER / DECIMAL -> Op.or (positive or negative match)\n * BOOLEAN -> Op.eq (exact match with string-to-boolean coercion)\n * JSONB -> case-insensitive search via jsonb_extract_path_text\n * DATE -> Op.between\n *\n * Three convenience params are handled automatically:\n * - searchString: searches a single value across all iLike and eq fields using OR\n * - startDate + endDate: filters createdAt with a BETWEEN range\n *\n * @param {object} event - the Lambda event containing queryStringParameters\n * @param {object} objectFilters - filter definitions created by defaultFilters()\n * @returns {object} A Sequelize where clause object\n */\nexport const createFilters = function (event, objectFilters) {\n let query = _.get(event, 'queryStringParameters', {}) || {};\n\n // Extract the three convenience params before iterating.\n // These are handled separately from the per-field filter logic below.\n const searchString = _.get(query, 'searchString');\n const startDate = _.get(query, 'startDate');\n const endDate = _.get(query, 'endDate');\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 1 — Build per-field WHERE conditions\n //\n // Each query param is looked up in objectFilters. If a matching filter\n // definition exists, we create the appropriate Sequelize condition.\n //\n // String-type fields (Op.iLike) are collected into a separate array\n // because they use DB.where(DB.fn('LOWER', DB.col(...))) which cannot\n // be expressed as a simple { column: { operator: value } } key.\n // Instead they are merged into WHERE via Op.and after the reduce.\n //\n // This approach replaces the Postgres-only Op.iLike with\n // LOWER(column) LIKE '%lowered_value%' which works across all\n // database dialects (Postgres, MySQL, MSSQL, SQLite).\n // ──────────────────────────────────────────────────────────────────────\n const caseInsensitiveConditions = [];\n const where = Object.keys(query).reduce((acc, item) => {\n const val = _.get(objectFilters, item, null);\n\n if (val) {\n // JSONB fields are handled entirely in Step 4 below.\n // Skip them here so they don't fall into the catch-all else branch.\n if (val.type === 'jsonb') {\n return acc;\n }\n\n // Dot-notation keys (e.g. \"snowman.snowmanType\") reference columns\n // on joined/included models. Sequelize requires these to be wrapped\n // in $...$ syntax in the WHERE object so it can resolve them.\n const itemName = item.includes('.')\n ? `$${item}$`\n : item;\n\n // STRING / CHAR / TEXT fields — case-insensitive partial match\n // Generates: WHERE LOWER(\"column\") LIKE '%lowered_value%'\n if (val.filterType === DB.Op.iLike) {\n caseInsensitiveConditions.push(\n DB.where(\n DB.fn('LOWER', DB.col(item)),\n { [DB.Op.like]: `%${query[item]?.toLowerCase()}%` }\n )\n );\n\n // INTEGER / DECIMAL fields — match positive or negative value\n // Generates: WHERE \"column\" IN (-value, value)\n // Useful for fields like amounts where sign may vary.\n } else if (val.filterType === DB.Op.or) {\n acc[itemName] = {};\n acc[itemName][val.filterType] = [ -1 * +query[item], +query[item] ];\n\n // ENUM / multi-value fields — match any value in a comma-separated list\n // Query: ?status=open,closed -> WHERE \"status\" IN ('open','closed')\n } else if (val.filterType === DB.Op.in) {\n acc[itemName] = {};\n acc[itemName][val.filterType] = query[item].split(',');\n\n // Catch-all for other operators (Op.eq, Op.contains, Op.between, etc.)\n // Attempts JSON.parse first so structured values (objects, arrays, numbers)\n // are passed as their parsed type rather than raw strings.\n } else {\n acc[itemName] = {};\n let parsedJson;\n try {\n parsedJson = JSON.parse(query[item]);\n } catch (e) {\n parsedJson = query[item];\n }\n acc[itemName][val.filterType] = parsedJson;\n }\n\n // BOOLEAN override — runs after the block above so it can replace\n // the value set by the catch-all. Query strings are always strings\n // (\"true\", \"false\", \"null\"), so we coerce them to actual booleans/null.\n if (val.type === DB.BOOLEAN) {\n const queryValue = _.get(query, item, '').toLowerCase();\n\n const booleanMap = {\n 'false': false,\n 'null': null,\n 'true': true\n };\n\n acc[itemName][val.filterType] = booleanMap[queryValue];\n }\n }\n\n return acc;\n }, {});\n\n // Merge the case-insensitive string conditions into WHERE using Op.and.\n // This keeps them alongside the key-based conditions built above.\n // Example result: WHERE decimal = 100 AND LOWER(\"name\") LIKE '%john%'\n if (caseInsensitiveConditions.length) {\n where[DB.Op.and] = [ ...(where[DB.Op.and] || []), ...caseInsensitiveConditions ];\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 2 — Apply automatic filters (active flag, businessId, dates)\n //\n // These are appended to every query regardless of what the caller sent.\n // ──────────────────────────────────────────────────────────────────────\n\n // If the model has an \"active\" column and the caller did not explicitly\n // filter by it, default to only returning active records.\n if (objectFilters?.active && !where?.active) {\n where.active = true;\n }\n\n // Scope every query to the caller's authorized business IDs.\n // accessRightsUtils extracts them from the JWT claims on the event.\n const businessIds = accessRightsUtils(event);\n const filterAdds = {\n businessId: businessIds\n };\n\n // Date range filter — when both startDate and endDate are provided,\n // automatically filter createdAt with a BETWEEN clause.\n // Generates: WHERE \"createdAt\" BETWEEN '2024-01-01' AND '2024-12-31'\n if (startDate && endDate) {\n const s = dayjs.utc(startDate);\n const e = dayjs.utc(endDate);\n const dates = {\n [DB.Op.between]: [ s.toDate(), e.toDate() ]\n };\n if (!s.isValid()) {\n throw { ...errorList.invalidStartDate };\n }\n\n if (!e.isValid()) {\n throw { ...errorList.invalidEndDate };\n }\n\n filterAdds.createdAt = dates;\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 3 — searchString: search one value across many fields with OR\n //\n // When ?searchString=john is provided, we build an OR array that checks\n // every filterable field for a match. This lets a single search box\n // query across name, title, email, etc. simultaneously.\n //\n // String fields (Op.iLike) get a case-insensitive LOWER + LIKE condition.\n // Numeric fields (Op.eq) get an exact match, but only when the search\n // value is a valid number (and the field is not a boolean).\n //\n // Generates: WHERE (LOWER(\"name\") LIKE '%john%'\n // OR LOWER(\"title\") LIKE '%john%'\n // OR \"id\" = 123)\n // ──────────────────────────────────────────────────────────────────────\n if (searchString) {\n const adds = Object.keys(objectFilters).reduce((acc, item) => {\n const type = objectFilters[item].filterType;\n const dataType = objectFilters[item].type;\n\n // String fields — case-insensitive partial match via LOWER + LIKE\n if (type === DB.Op.iLike) {\n acc.push(\n DB.where(\n DB.fn('LOWER', DB.col(item)),\n { [DB.Op.like]: `%${query['searchString'].toLowerCase()}%` }\n )\n );\n }\n\n // Numeric fields — exact match only when the search value is numeric.\n // Booleans are excluded because a search for \"1\" should not match\n // boolean true.\n if (!_.isNaN(Number(query['searchString'])) && !(dataType instanceof DB.BOOLEAN)) {\n\n if (type === DB.Op.eq) {\n const newOr = {};\n const itemName = item.includes('.') ? `$${item}$` : item;\n newOr[itemName] = {\n [DB.Op.eq]: `${query['searchString']}`\n };\n acc.push(newOr);\n }\n }\n\n return acc;\n }, []);\n\n filterAdds[DB.Op.or] = adds;\n }\n\n // Merge the automatic filters (businessId, createdAt, searchString OR)\n // into the where object built in Step 1.\n const withDate = Object.assign(where, filterAdds);\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 4 — JSONB field filters: case-insensitive search inside JSON columns\n //\n // JSONB columns store structured data (e.g. a \"token\" column containing\n // { cardType: \"mastercard\", cardHolderName: \"GREGORY HERBERT\" }).\n //\n // Query params use dot-notation to target nested keys:\n // ?token.cardHolderName=gregory\n // ?paymentProviderData.payment.result.message=approved\n //\n // For each matching param we:\n // 1. Split the path after the column prefix into individual key segments\n // 2. Use jsonb_extract_path_text(column, key1, key2, ...) to pull the\n // value out of the JSON as plain text\n // 3. Wrap it in LOWER() and compare with Op.like for case-insensitive match\n //\n // Generates: WHERE LOWER(jsonb_extract_path_text(\"token\", 'cardHolderName'))\n // LIKE '%gregory%'\n //\n // jsonb_extract_path_text is used via DB.fn() so Sequelize parameterizes\n // the path arguments, keeping it safe from SQL injection.\n // ──────────────────────────────────────────────────────────────────────\n Object.keys(objectFilters || {}).forEach((k) => {\n const def = objectFilters[k];\n if (def && def.type === 'jsonb' && def.field) {\n const prefix = `${def.field}.`;\n\n Object.keys(query).forEach((qKey) => {\n if (qKey.startsWith(prefix)) {\n // Dot-notation: ?token.cardHolderName=gregory\n // e.g. \"token.cardHolderName\" -> pathParts = [\"cardHolderName\"]\n // e.g. \"data.payment.result.message\" -> pathParts = [\"payment\",\"result\",\"message\"]\n const pathParts = qKey.substring(prefix.length).split('.');\n const value = query[qKey];\n\n if (!withDate[DB.Op.and]) {\n withDate[DB.Op.and] = [];\n }\n withDate[DB.Op.and].push(\n DB.where(\n DB.fn('LOWER', DB.fn('jsonb_extract_path_text', DB.col(def.field), ...pathParts)),\n { [DB.Op.like]: `%${value?.toLowerCase()}%` }\n )\n );\n } else if (qKey === def.field) {\n // JSON-object-as-value: ?token={\"cardHolderName\":\"Test\"}\n // Parse the JSON and create a condition for each key-value pair.\n // Nested objects are flattened recursively into deeper path segments.\n let parsed;\n try {\n parsed = JSON.parse(query[qKey]);\n } catch (e) {\n return;\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n const addJsonbConditions = (obj, pathParts) => {\n Object.entries(obj).forEach(([key, value]) => {\n const currentPath = [...pathParts, key];\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n addJsonbConditions(value, currentPath);\n } else if (value !== null && !Array.isArray(value)) {\n if (!withDate[DB.Op.and]) {\n withDate[DB.Op.and] = [];\n }\n withDate[DB.Op.and].push(\n DB.where(\n DB.fn('LOWER', DB.fn('jsonb_extract_path_text', DB.col(def.field), ...currentPath)),\n { [DB.Op.like]: `%${String(value)?.toLowerCase()}%` }\n )\n );\n }\n });\n };\n addJsonbConditions(parsed, []);\n }\n }\n });\n }\n });\n\n return withDate;\n};\n","module.exports = require(\"dayjs\");","import { SNS } from '@aws-sdk/client-sns';\n\nconst SNSUtil = {\n publish: (params) => publish(params),\n createTopic: (params) => createTopic(params)\n};\n\nasync function publish(params) {\n const sns = new SNS();\n return await sns.publish(params);\n}\n\nasync function createTopic(params) {\n const sns = new SNS();\n return await sns.createTopic(params);\n}\n\nexport default SNSUtil;\n","module.exports = require(\"dayjs/plugin/isSameOrBefore\");","module.exports = require(\"@aws-sdk/lib-dynamodb\");","module.exports = require(\"bluebird\");","import _, { isEmpty } from 'lodash';\r\nimport { errorList } from '../../../requestResponse/errorCodes.js';\r\nimport { parseBody } from '../../../requestResponse/requestResponse.js';\r\n\r\nexport function isSystemUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:SYSTEM') ||\r\n _.get(event, 'requestContext.authorizer.custom:SYSTEM') ||\r\n 'false';\r\n let isSys = false;\r\n try {\r\n isSys = JSON.parse(jsonToParse);\r\n return isSys;\r\n } catch (e) {\r\n console.error('error with system user:', e);\r\n\r\n return false;\r\n }\r\n}\r\n\r\nexport function isSuperUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:SUPER') ||\r\n _.get(event, 'requestContext.authorizer.custom:SUPER') ||\r\n 'false';\r\n let isSys = false;\r\n\r\n try {\r\n isSys = JSON.parse(jsonToParse);\r\n\r\n return isSys;\r\n } catch (e) {\r\n\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Throws unauthorized error if the user is not a super user.\r\n * Mirrors the behavior and style of checkModule but focused on SUPER role.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n */\r\nexport function checkIsSuper(event) {\r\n // Super or System users are always allowed\r\n if (isSuperUser(event)) {\r\n return;\r\n }\r\n if (isSystemUser(event)) {\r\n return;\r\n }\r\n\r\n // In local builds allow bypass to ease development and tests\r\n if (process.env.BUILD_ENV === 'local') {\r\n return;\r\n }\r\n\r\n throw errorList.unauthorized;\r\n}\r\n\r\n/**\r\n * Get the allowed businessIds for a user from the lambda event, compare it to businessIds, return what user has access to.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @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.\r\n * @returns {array} A list of businessIds that have been requested and are allowed to for some user.\r\n */\r\nexport function accessRightsUtils(event, options) {\r\n const useCognitoBid = _.get(options, 'useCognitoBid', false);\r\n const requestedBusinessIds = getRequestedBusinessIds(event);\r\n const allowedBusinessIds = getAllowedBusinessIds(event, useCognitoBid);\r\n\r\n if (isSuperUser(event)) {\r\n let v = requestedBusinessIds;\r\n if (_.isEmpty(requestedBusinessIds)) {\r\n v = allowedBusinessIds;\r\n }\r\n\r\n return v;\r\n }\r\n if (isSystemUser(event)) {\r\n return requestedBusinessIds;\r\n }\r\n\r\n if (requestedBusinessIds.length === 0) {\r\n return allowedBusinessIds;\r\n }\r\n\r\n return _.intersection(requestedBusinessIds, allowedBusinessIds);\r\n}\r\n\r\n/**\r\n * Get the businessID set in cognito as custom:DBI.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {string} The businessID set in cognito as custom:DBI\r\n */\r\nexport function userDefaultBid(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:DBI') ||\r\n _.get(event, 'requestContext.authorizer.custom:DBI') ||\r\n '{}';\r\n\r\n const dbi = JSON.parse(jsonToParse);\r\n return _.get(dbi, 'defaultBid', '') || '1';\r\n}\r\n\r\n/**\r\n * Get requested businessIds from the query string.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The businessID requested by the query string\r\n */\r\nexport function getRequestedBusinessIds(event) {\r\n let requestedBusinessIds = _.get(event, 'queryStringParameters.businessIds', null);\r\n const body = parseBody(event);\r\n const bodyBid = body?.businessId;\r\n if (requestedBusinessIds) {\r\n return requestedBusinessIds ? requestedBusinessIds.split(',') : [];\r\n } else if (bodyBid) {\r\n return [ bodyBid ];\r\n } else {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get the allowed businessIds for a user from cognito custom:AR property.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @param useCognitoBid\r\n * @returns {array} The businessID requested by the query string\r\n */\r\nfunction getAllowedBusinessIds(event, useCognitoBid) {\r\n const businesses = getBusinessesInfo(event, useCognitoBid);\r\n return Object.keys(businesses);\r\n}\r\n\r\nexport function getAccessRightsInfo(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n '{}';\r\n const accessRights = JSON.parse(jsonToParse);\r\n return _.get(accessRights, 'businessIds', {});\r\n}\r\n\r\nexport function getDefaultBusinessIDInfo(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:DBI') ||\r\n _.get(event, 'requestContext.authorizer.custom:DBI') ||\r\n '{}';\r\n const dbi = JSON.parse(jsonToParse);\r\n\r\n return _.get(dbi, 'defaultBid', '1');\r\n}\r\n\r\nexport function getBusinessesInfo(event, useCognitoBid = false) {\r\n const json = _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n '{}';\r\n\r\n let businessIds = _.get(JSON.parse(json), 'businessIds', {});\r\n\r\n // Local environment tweaks\r\n if (process.env.BUILD_ENV === 'local') {\r\n let b;\r\n try {\r\n b = JSON.parse(event?.body);\r\n } catch (e) {\r\n }\r\n const bodyBid = b?.businessId;\r\n // Always inject the default local BID “1” unless the caller explicitly wants\r\n // what Cognito says **and** Cognito actually returned something.\r\n if (!useCognitoBid) {\r\n businessIds = { ...businessIds, '1': 'A' };\r\n }\r\n\r\n // If Cognito gave no BIDs at all, fall back to the local default.\r\n if (isEmpty(businessIds)) {\r\n businessIds = { '1': 'A' };\r\n }\r\n // a businessId is found on the body for local allow it\r\n if (bodyBid) {\r\n businessIds[bodyBid] = 'A';\r\n }\r\n }\r\n\r\n return businessIds;\r\n}\r\n\r\n/**\r\n * Get the modules listed in custom:MOD.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The Module access list\r\n */\r\nexport function getModuleInfo(event) {\r\n let jsonToParse =\r\n _.get(event, 'requestContext.authorizer.claims.custom:MOD') ||\r\n _.get(event, 'requestContext.authorizer.custom:MOD') ||\r\n _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n\r\n '{}';\r\n\r\n const moduleRights = JSON.parse(jsonToParse);\r\n return _.get(moduleRights, 'module', {});\r\n}\r\n\r\n/**\r\n * Get the modules listed in custom:MOD.\r\n *\r\n * @param {string} moduleName - A sting name for a module.\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The Module access list\r\n */\r\nexport function checkModule(moduleName, event) {\r\n const moduleRights = getModuleInfo(event);\r\n let allowAccess = _.get(moduleRights, moduleName, false);\r\n\r\n if (isSuperUser(event)) {\r\n return;\r\n }\r\n if (isSystemUser(event)) {\r\n return;\r\n }\r\n\r\n if (process.env.BUILD_ENV === 'local') {\r\n return;\r\n }\r\n if (!allowAccess) {\r\n throw errorList.unauthorized;\r\n }\r\n}\r\n\r\nexport const userRoles = {\r\n admin: 'A',\r\n read: 'R',\r\n write: 'W'\r\n};\r\n\r\n/**\r\n * @param {{body: string}} event\r\n * @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.\r\n * @returns {string} businessId\r\n */\r\nexport function checkWriteAccess(event, options) {\r\n const eventBody = parseBody(event);\r\n const businessIds = accessRightsUtils(event, options) || [];\r\n const businessId = businessIds.find((id) => id === eventBody.businessId);\r\n const raw = getBusinessesInfo(event);\r\n const userRight = raw[businessId];\r\n\r\n if (isSuperUser(event)) {\r\n return eventBody.businessId;\r\n }\r\n\r\n if (isSystemUser(event)) {\r\n return eventBody.businessId;\r\n }\r\n\r\n if (process.env.BUILD_ENV === 'local') {\r\n return eventBody.businessId;\r\n }\r\n\r\n if ((userRight !== userRoles.admin && userRight !== userRoles.write) || (!userRight)) {\r\n throw errorList.unauthorized;\r\n }\r\n return businessId;\r\n}\r\n\r\n","module.exports = require(\"@aws-sdk/client-sns\");","module.exports = require(\"lodash\");","import _ from 'lodash';\n\n/**\n * Create sequelize order clause from query string parameters and default sort object\n *\n * @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\n * @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\n * @returns {object} An sequelize order by object\n */\nexport const createSort = function (event, defaultFilter) {\n let copyOfDefaultFilter = _.clone(defaultFilter);\n let query = _.get(event, 'queryStringParameters', {}) || {};\n let sort = _.get(query, 'sort', '-updatedAt') || '-updatedAt';\n\n return sort.split(',').reduce((acc, item) => {\n\n const testItem = item.indexOf('-') === 0 ? item.substr(1) : item;\n\n if (_.get(copyOfDefaultFilter, testItem, null)) {\n const sortItem = [];\n\n testItem.split('.').forEach((parentChildList) => {\n sortItem.push(parentChildList);\n });\n\n if (item.indexOf('-') === 0) {\n sortItem.push('DESC');\n } else {\n sortItem.push('ASC');\n }\n acc.push(sortItem);\n }\n\n return acc;\n }, []);\n};\n","import _ from 'lodash';\r\nimport { errorList } from './errorCodes.js';\r\n\r\n/**\r\n * @param {Object} body\r\n * @param {{dbClose?:function}} [options]\r\n */\r\nexport function success(body, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n dbClose();\r\n\r\n return buildResponse(200, body);\r\n}\r\n\r\n/**\r\n * @param {string} html\r\n * @param {{dbClose:function|undefined}} options\r\n */\r\nexport function successHtml(html, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n\r\n dbClose();\r\n return {\r\n statusCode: 200,\r\n headers: {\r\n 'Content-Type': 'text/html',\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Credentials': true\r\n },\r\n body: html\r\n };\r\n}\r\n\r\n/**\r\n * @param {string} event\r\n * @returns string\r\n */\r\nexport function getCurrentUserNameFromCognitoEvent(event) {\r\n const attributes = _.get(event, 'request.userAttributes');\r\n\r\n return attributes['cognito:email_alias'] || attributes['email'] || 'UNKNOWN USER';\r\n}\r\n\r\n/**\r\n * Get the user information from the event object\r\n *\r\n * @param event {Object} an event object\r\n * @returns {{username: string, id: number}}\r\n */\r\nexport function getCurrentUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:UID') ||\r\n _.get(event, 'requestContext.authorizer.custom:UID') ||\r\n '0';\r\n\r\n const id = JSON.parse(jsonToParse);\r\n\r\n const username = _.get(event, 'requestContext.authorizer.claims.email') || _.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';\r\n\r\n return {\r\n username,\r\n id\r\n };\r\n}\r\n\r\n/**\r\n * Create a failure response\r\n *\r\n * @param body {Object} an event object\r\n * @param options {Object} an options object\r\n * @returns {{statusCode:number, headers:object, body:string}} a response object\r\n */\r\nexport function failure(body = {}, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n dbClose();\r\n let cleanedErrorBody;\r\n\r\n if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {\r\n if (_.isObject(body)) {\r\n console.error('------->ALL UTIL ERROR:', JSON.stringify(body, null, 2));\r\n }\r\n }\r\n\r\n const NORMAL_ERROR = { statusCode: 500, errorCode: '5XX', message: 'INTERNAL UTIL ERROR' };\r\n cleanedErrorBody = body;\r\n if (!_.isUndefined(body.details)) {\r\n cleanedErrorBody = detectJoyError(body);\r\n } else if (_.isUndefined(body.errorCode) || _.isUndefined(body.statusCode)) {\r\n cleanedErrorBody = detectSequelizeError(body);\r\n }\r\n if (_.get(body, 'response.data.message')) {\r\n const err = _.get(body, 'response.data.message');\r\n if (_.isObject(body)) {\r\n console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));\r\n }\r\n }\r\n const newBody = _.merge(NORMAL_ERROR, cleanedErrorBody);\r\n\r\n return buildResponse(newBody.statusCode, newBody);\r\n}\r\n\r\n/**\r\n * Create a failure response object\r\n *\r\n * @param statusCode {Number} a status code\r\n * @param body {Object} an event object\r\n * @returns {{statusCode:number, headers:object, body:string}} a response object\r\n */\r\nfunction buildResponse(statusCode, body) {\r\n return {\r\n statusCode: statusCode,\r\n headers: {\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Credentials': true\r\n },\r\n body: JSON.stringify(body)\r\n };\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n *\r\n * @param requestEvent {{body:string}} an event object\r\n * @returns event {*} the json object of the body\r\n */\r\nexport function parseBody(requestEvent) {\r\n\r\n let eventBody = {};\r\n if (_.isString(requestEvent.body)) {\r\n try {\r\n eventBody = JSON.parse(requestEvent.body);\r\n } catch (e) {\r\n // Invalid JSON\r\n eventBody = null;\r\n\r\n throw errorList.invalidJson;\r\n }\r\n } else if (_.isObject(requestEvent.body)) {\r\n eventBody = requestEvent.body;\r\n }\r\n\r\n return eventBody;\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n *\r\n * @param requestEvent {string|object} an event object\r\n * @param [callback] {function} undefined a call back function\r\n * @returns event {*} the json object of the body\r\n */\r\nexport function parseEvent(requestEvent, callback) {\r\n let event = {};\r\n if (_.isString(requestEvent)) {\r\n try {\r\n event = JSON.parse(requestEvent);\r\n } catch (e) {\r\n // Invalid JSON\r\n event = null;\r\n\r\n if (callback) {\r\n callback(Error(e));\r\n }\r\n }\r\n } else if (_.isObject(requestEvent)) {\r\n event = requestEvent;\r\n }\r\n\r\n return event;\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n * look for sequelize errors and return a message\r\n * ERRORS should not be caught here this is a fallback for unknown database errors\r\n *\r\n * @param body {object} part of a body response\r\n * @returns error message object {message:string}\r\n */\r\nexport function detectSequelizeError(body) {\r\n const errorBody = {};\r\n const errorName = _.get(body, 'name', '');\r\n\r\n if (errorName === 'SequelizeForeignKeyConstraintError') {\r\n errorBody.message = 'You cannot delete this item as it is in use';\r\n errorBody.statusCode = 409;\r\n errorBody.errorCode = '4090';\r\n return errorBody;\r\n }\r\n\r\n if (errorName === 'SequelizeUniqueConstraintError') {\r\n const fields = _.get(body, 'errors', []).map(err => _.get(err, 'path')).filter(Boolean);\r\n errorBody.message = fields.length\r\n ? 'A record with this ' + fields.join(', ') + ' already exists'\r\n : 'A record with this value already exists';\r\n errorBody.statusCode = 409;\r\n errorBody.errorCode = '4091';\r\n return errorBody;\r\n }\r\n\r\n if (errorName === 'SequelizeValidationError') {\r\n const messages = _.get(body, 'errors', []).map(err => _.get(err, 'message')).filter(Boolean);\r\n errorBody.message = messages.length ? messages.join(', ') : 'Validation error';\r\n errorBody.statusCode = 400;\r\n errorBody.errorCode = '4001';\r\n return errorBody;\r\n }\r\n\r\n let sequelizeError = _.get(body, 'errors', []).reduce((acc, err) => {\r\n acc = acc + ' ' + _.get(err, 'message');\r\n return acc;\r\n }, '');\r\n const parentError = _.get(body, 'parent', '');\r\n\r\n sequelizeError = sequelizeError + _.get(body, 'original.detail', '') + _.get(body, 'TypeError', '') + parentError;\r\n errorBody.message = sequelizeError.trim();\r\n return errorBody;\r\n}\r\n\r\nexport function detectJoyError(body) {\r\n const errorBody = {};\r\n const joyError = _.get(body, 'details[0]', {});\r\n const additionalMessages = _.get(body, 'details[0].context.details') || [];\r\n\r\n const v = additionalMessages.reduce((acc, contextItem) => {\r\n acc = acc + ' ' + contextItem?.message || '';\r\n return acc;\r\n }, '');\r\n\r\n console.error('USER VALIDATION ERROR:', body);\r\n const msg = (joyError?.message || '') + v;\r\n\r\n if (msg) {\r\n errorBody.message = _.trim(msg);\r\n }\r\n\r\n errorBody.statusCode = 400;\r\n errorBody.errorCode = '4000';\r\n return errorBody;\r\n}\r\n\r\n/**\r\n * Parse the body of a Dynamoose error response.\r\n * Attempts to extract a human-readable error message from Dynamoose errors.\r\n * This is a fallback for unknown database errors.\r\n *\r\n * @param {object} body - Part of a body response containing error details.\r\n * @returns {object} - Error message object { message: string }\r\n */\r\nexport function detectDynamooseError(body) {\r\n const errorBody = {};\r\n\r\n // Start with an empty message string.\r\n let dynamooseError = '';\r\n\r\n // If the error body contains an array of errors, concatenate their messages.\r\n if (Array.isArray(body.errors)) {\r\n dynamooseError += body.errors.reduce((acc, err) => {\r\n return acc + ' ' + (err.message || '');\r\n }, '');\r\n }\r\n\r\n // If there's a top-level message, add it.\r\n if (body.message) {\r\n dynamooseError += ' ' + body.message;\r\n }\r\n\r\n // If there is any additional detail provided, append it.\r\n if (body.detail) {\r\n dynamooseError += ' ' + body.detail;\r\n }\r\n\r\n // Trim the message to remove extra spaces.\r\n errorBody.message = dynamooseError.trim();\r\n\r\n return errorBody;\r\n}","import _ from 'lodash';\nimport dayjs from 'dayjs';\nimport customParseFormat from 'dayjs/plugin/customParseFormat';\nimport isSameOrBefore from 'dayjs/plugin/isSameOrBefore';\nimport Promise from 'bluebird';\nimport S3Utils from '../s3/S3Utils/S3Utils.js';\nimport SNSUtil from '../sns/SNSUtils.js';\nimport dynamoUtil from '../dynamo/dynamoUtils.js';\n\ndayjs.extend(customParseFormat);\ndayjs.extend(isSameOrBefore);\n\n/**\n * @param {string} bucket\n * @param {number} maxKeys\n * @param {Object} userImportTypes\n */\nexport async function loop(bucket, maxKeys, userImportTypes) {\n let bucketResult = {};\n let fileList = [];\n\n const currentTime = dayjs();\n\n do {\n bucketResult = await S3Utils.listObjectsV2({\n Bucket: bucket,\n MaxKeys: maxKeys,\n ContinuationToken: _.get(bucketResult, 'NextContinuationToken')\n });\n\n let newFiles = _.filter(bucketResult.Contents, (file) => {\n if (_.startsWith(_.get(file, 'Key'), 'delayUntil/')) {\n const fileDelayTime = _.get(file, 'Key').split('/')[1];\n return dayjs(fileDelayTime, 'YYYYMMDDHHmm').isSameOrBefore(currentTime);\n }\n if (userImportTypes) {\n // look for items in the userImportTypes\n const usersImports = Object.values(userImportTypes);\n const items = file.Key.split('/');\n const fileName = _.last(items);\n const folderName = _.first(items);\n if (_.isEmpty(fileName)) {\n return false;\n\n } else if (usersImports.indexOf(folderName) === -1) {\n return false;\n }\n\n return !_.startsWith(file.Key, `${folderName}/error`);\n }\n return !_.startsWith(file.Key, 'error');\n });\n\n fileList = _.concat(fileList, newFiles);\n } while (bucketResult.IsTruncated && bucketResult.NextContinuationToken && fileList.length < maxKeys);\n\n return fileList;\n}\n\n/**\n * 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\n *\n * @param {string} configTable - The Dynamo DB table where to get the chunk-size and maxMessage size\n * @param {string} tableKey - The key to the item in the Dynamo DB table that holds the chunk-size and maxMessage size\n * @param {string} bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created\n * @param {string} snsTopic - The name of the snsEvent to publish\n * @param {object} userImportTypes - import types to filter on\n */\nexport async function publishEvents(configTable, tableKey, bucket, snsTopic, userImportTypes) {\n let result;\n try {\n result = await dynamoUtil.get({\n TableName: configTable,\n Key: { key: tableKey }\n });\n } catch (e) {\n console.error(`Cannot get config for key: ${tableKey} table: ${configTable} falling back to defaults of 2 and 10`, e);\n }\n let chunkSize = _.get(result, 'Item.snsChunkSize', 2);\n let maxMessages = _.get(result, 'Item.snsMaxMessages', 10);\n\n const snsCreateTopicResponse = await SNSUtil.createTopic({ Name: snsTopic });\n const topicArn = snsCreateTopicResponse.TopicArn;\n const maxKeys = chunkSize * maxMessages;\n\n const fileList = await loop(bucket, maxKeys, userImportTypes);\n\n const messageList = _.chain(fileList)\n .map('Key')\n .chunk(chunkSize)\n .slice(0, maxMessages)\n .value()\n ;\n\n return Promise.map(messageList, (files) => {\n return SNSUtil.publish({\n Message: JSON.stringify({\n bucket: bucket,\n files: files\n }),\n TopicArn: topicArn\n });\n });\n}","import _ from 'lodash';\nimport { SequelizeStorage, Umzug } from 'umzug';\n\n/**\n * Execute database migrations\n * @param {string} databaseName - name of database to create (or verify existence)\n * @param {object} sequelizeInstance - instance of Sequelize (must be initialized)\n * @param {function} initializeModels - function to run to sync Sequelize models with database\n * @param {string} pathToMigrationFolder - pass in the path if using windows. windows and linux PWD will be different\n */\nexport async function runMigrations(databaseName,\n sequelizeInstance,\n initializeModels,\n pathToMigrationFolder = `${process.env.PWD}/migrations/*.js`) {\n const umzug = new Umzug({\n migrations: { glob: pathToMigrationFolder },\n context: sequelizeInstance.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize: sequelizeInstance }),\n logger: console\n });\n\n const pendingMigrations = await umzug.pending();\n console.log('------->UTIL Pending Migrations:', pendingMigrations, pathToMigrationFolder);\n await umzug.up().catch((upError) => {\n console.error('Migration Error: ', upError);\n return umzug.down({\n migrations: _.chain(pendingMigrations)\n .map('file')\n .reverse()\n .value()\n }).then(() => {\n const msg = 'UTIL Error: Error with migrating up:' + upError;\n console.error(msg);\n throw new Error(msg);\n }, (downError) => {\n const msg = 'UTIL Error: Error with migrating down:' + downError;\n console.error(msg);\n throw new Error(msg);\n });\n });\n\n // The following line is needed to sync (create) tables, but not to database updates\n // in the past it worked to leave it in, but now the tags module causes foreign key problems\n // The tables are still initiated by being passed in to run migrations\n await initializeModels();\n}","import _ from 'lodash';\nimport S3Util from '../s3/S3Utils/S3Utils.js';\n\nexport async function handleFile(path, s3Bucket, transformer, options) {\n const shouldSkipFailedFolders = _.get(options, 'shouldSkipFailedFolders');\n const userImportTypes = _.get(options, 'userImportTypes');\n const params = {\n Bucket: s3Bucket,\n Key: path\n };\n let body;\n\n try {\n body = await S3Util.getObject(params);\n } catch (e) {\n if (e.Code === 'NoSuchKey' || e.code === 'NoSuchKey' || e.name === 'NoSuchKey') {\n return;\n }\n console.error('S3 getObject error:', e);\n throw e;\n }\n\n try {\n // exit early for null/undefined or blank string bodies\n if (_.isNil(body) || (_.isString(body) && _.isEmpty(body.trim()))) {\n await S3Util.deleteObject(params);\n return;\n }\n\n const parsedBody = JSON.parse(body);\n\n // exit early for objects like {} or []\n if (_.isEmpty(parsedBody)) {\n await S3Util.deleteObject(params);\n return;\n }\n\n const returnedValue = await transformer(parsedBody);\n await S3Util.deleteObject(params);\n\n return returnedValue;\n } catch (error) {\n console.error('HANDLE-FILE-ERROR', error);\n\n if (!body) {\n return;\n }\n\n let newPath = '';\n\n if (userImportTypes) {\n console.log('USER IMPORT');\n // look for items in the userImportTypes\n const usersImports = Object.values(userImportTypes);\n const items = path.split('/');\n const fileName = _.last(items);\n const folderName = _.first(items);\n\n if (usersImports.indexOf(folderName) > -1) {\n if (shouldSkipFailedFolders) {\n newPath = `${folderName}/error/${fileName}`;\n } else if (_.startsWith(path, `${folderName}/failed-once/`)) {\n newPath = _.replace(path, `${folderName}/failed-once/`, `${folderName}/failed-twice/`);\n } else if (_.startsWith(path, `${folderName}/failed-twice/`)) {\n newPath = _.replace(path, `${folderName}/failed-twice/`, `${folderName}/error/`);\n } else {\n newPath = `${folderName}/failed-once/${fileName}`;\n }\n } else {\n newPath = `pathAndEventMisMatchError/${path}`;\n }\n\n } else {\n if (shouldSkipFailedFolders) {\n newPath = `error/${path}`;\n } else if (_.startsWith(path, 'failed-once/')) {\n newPath = _.replace(path, 'failed-once/', 'failed-twice/');\n } else if (_.startsWith(path, 'failed-twice/')) {\n newPath = _.replace(path, 'failed-twice/', 'error/');\n } else {\n if (_.includes(path, 'delayUntil/')) {\n path = _.last(path.split('/'));\n }\n\n newPath = `failed-once/${path}`;\n }\n }\n\n const newParams = {\n Bucket: s3Bucket,\n Key: newPath,\n Body: body\n };\n\n if (\n containsError(newPath, 'failed-once') ||\n containsError(newPath, 'failed-twice') ||\n containsError(newPath, 'error')\n ) {\n throw new Error('NESTING ERROR');\n }\n\n await S3Util.putObject(newParams);\n await S3Util.deleteObject(params);\n\n throw error;\n }\n}\n\nexport function containsError(str, val) {\n const firstIndex = str.toLowerCase().indexOf(val);\n if (firstIndex === -1) return false;\n const secondIndex = str.toLowerCase().indexOf(val, firstIndex + 1);\n return secondIndex !== -1;\n}\n","import { S3 } from '@aws-sdk/client-s3';\n\nexport function s3Utils(action, params) {\n const s3 = new S3();\n return s3[action](params);\n}\n\nconst S3Util = {\n getObject: (params) => getS3(params),\n deleteObject: (params) => s3Utils('deleteObject', params),\n putObject: (params) => s3Utils('putObject', params),\n listObjectsV2: (params) => s3Utils('listObjectsV2', params)\n};\nexport default S3Util;\n\nasync function getS3(params) {\n const s3 = new S3();\n const response = await s3.getObject(params);\n return response?.Body.transformToString('utf-8');\n}","module.exports = require(\"umzug\");","module.exports = require(\"@aws-sdk/client-dynamodb\");","export const errorList = {\n invalidInventoryReleaseRequest: {\n message: 'NOT ENOUGH INVENTORY TO FULFILL RELEASE',\n errorCode: '4010',\n statusCode: 400\n },\n alreadyReleased: {\n message: 'ALREADY RELEASED',\n errorCode: '4011',\n statusCode: 400\n },\n alreadyReceived: {\n message: 'RECEIVABLE ALREADY RECEIVED',\n errorCode: '4012',\n statusCode: 400\n },\n invalidItemsRequest: {\n message: 'VALID ITEMS MUST BE INCLUDED',\n errorCode: '4013',\n statusCode: 400\n },\n invalidID: {\n message: 'ID is invalid',\n errorCode: '4014',\n statusCode: 400\n },\n invalidReceivable: {\n message: 'MUST CONTAIN AT LEAST ONE RECEIVABLE',\n errorCode: '4015',\n statusCode: 400\n },\n invalidRequest: {\n message: 'INVALID REQUEST DATA',\n errorCode: '4016',\n statusCode: 400\n },\n invalidAPIKey: {\n message: 'INVALID REQUEST - API MAY KEY INVALID',\n errorCode: '4017',\n statusCode: 400\n },\n qbCreationError: {\n message: 'QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS',\n errorCode: '4018',\n statusCode: 400\n },\n cannotReopen: {\n message: 'CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED',\n errorCode: '4018',\n statusCode: 400\n },\n invalidDateFormat: {\n message: 'INVALID DATE FORMAT',\n errorCode: '4019',\n statusCode: 400\n },\n invalidStartDate: {\n message: 'INVALID START DATE',\n errorCode: '4020',\n statusCode: 400\n },\n invalidEndDate: {\n message: 'INVALID END DATE',\n errorCode: '4021',\n statusCode: 400\n },\n invalidOrderStatus: {\n message: 'UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS',\n errorCode: '4022',\n statusCode: 400\n },\n invalidPaymentStatus: {\n message: 'UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN',\n errorCode: '4023',\n statusCode: 400\n },\n invalidReleaseStatus: {\n message: 'UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN',\n errorCode: '4024',\n statusCode: 400\n },\n invalidReceivableStatus: {\n message: 'UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN',\n errorCode: '40025',\n statusCode: 400\n },\n invalidJson:{\n message: 'INVALID JSON',\n errorCode: '4005',\n statusCode: 400\n },\n invalidFilter:{\n message: 'INVALID FILTER',\n errorCode: '4026',\n statusCode: 400\n },\n invalidUserNameUpdate:{\n message: 'UNABLE TO UPDATE USERNAME',\n errorCode: '4027',\n statusCode: 400\n },\n imageSizeLimit:{\n message: 'IMAGE SIZE LIMIT 100KB EXCEEDED',\n errorCode: '4028',\n statusCode: 400\n },\n unauthorized:{\n message: 'UNAUTHORIZED',\n errorCode: '4111',\n statusCode: 401\n },\n notFound:{\n message: 'ITEM NOT FOUND',\n errorCode: '4004',\n statusCode: 404\n },\n emailRequired:{\n message: 'NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL',\n errorCode: '4004',\n statusCode: 404\n },\n mobilePhoneRequired:{\n message: 'NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS',\n errorCode: '4004',\n statusCode: 404\n },\n invalidCadenceType: {\n message: 'INVALID CADENCE TYPE',\n errorCode: '5001',\n statusCode: 500\n },\n};","/**\n * create pagination object from Sequelize findAll\n * @param {object} result - sequelize result\n * @param {number} limit - max number of results to return\n * @param {number} offset - page offset\n */\nexport function getPaginationFromFindAll(result, limit, offset) {\n result = result || [];\n limit = limit || 0;\n offset = offset || 0;\n\n const hasMore = result.length > limit;\n if (hasMore) {\n result.splice(-1, 1);\n }\n const pageObject = {\n offset: offset,\n limit: limit,\n rows: result,\n hasMore: hasMore\n };\n\n return pageObject;\n}\n\n/**\n * wrapper for Sequelize findAll\n * @param {object} model - instance of Sequelize (must be initialized)\n * @param {*&{include: [{model: *}], where: {businessId: Array}, order: [string[]]}} options - instance of Sequelize (must be initialized)\n */\nexport async function findAll(model, options) {\n\n const limit = options.limit || 0;\n const includes = options.includes || { all: true, nested: true };\n const findArgs = Object.assign({include: includes}, options, { limit: limit + 1 });\n const results = await model.findAll(findArgs);\n return getPaginationFromFindAll(results, limit, options.offset);\n}\n\nconst findUtils = {\n findAll\n};\nexport default findUtils;","import _ from 'lodash';\n\n/**\n * Create sequelize includes array from query string parameters and default sequelize model\n *\n * @param {object} event - the query parameters from the event passed by lambda\n * @param {object} objectFilters - the default filters object created by createDefaultFilters\n * @returns {object} A sequelize includes array\n */\n\nexport function createIncludes(event, objectFilters) {\n const query = _.get(event, 'queryStringParameters', {}) || {};\n\n const keys = Object.keys(objectFilters);\n\n const canBeIncluded = keys.reduce((acc, item) => {\n acc = includeSubItem(item, acc);\n\n return acc;\n }, []);\n\n const askedForInQuery = Object.keys(query).reduce((acc, item) => {\n if (item === 'sort') {\n query[item].split(',').forEach((sortItem) => {\n sortItem = sortItem.indexOf('-') === 0 ? sortItem.substr(1) : sortItem;\n acc = includeSubItem(sortItem, acc);\n });\n }\n\n acc = includeSubItem(item, acc);\n\n return acc;\n }, []);\n\n return _.intersection(canBeIncluded, askedForInQuery);\n}\n\nexport function includeSubItem(queryStringItem, acc = []) {\n const dot = queryStringItem.indexOf('.');\n if (dot > 0) {\n acc.push(queryStringItem.substring(0, dot));\n }\n\n return acc;\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import { handleFile as handleFileImport } from './eventManager/handleFile.js';\nimport { watchBucket as watchBucketImport } from './eventManager/watchBucket.js';\nimport { publishEvents as publishEventsImport } from './eventManager/publishEvents.js';\nimport { createIncludes as createIncludesImport } from './database/dbUtils/queryStringUtils/createIncludes.js';\nimport { createFilters as createFiltersImport } from './database/dbUtils/queryStringUtils/createFilters.js';\nimport { createSort as createSortImport } from './database/dbUtils/queryStringUtils/createSort.js';\nimport { findAll as findAllImport } from './database/dbUtils/queryStringUtils/findAll.js';\nimport { checkModule as checkModuleImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { checkIsSuper as checkIsSuperImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getModuleInfo as getModuleInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getAccessRightsInfo as getAccessRightsInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getDefaultBusinessIDInfo as getDefaultBusinessIDInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { failure as failureImport, success as successImport } from './requestResponse/requestResponse.js';\nimport { runMigrations as runMigrationsImport } from './database/dbSetup/migrations.js';\nimport { getCurrentUser as getCurrentUserImport } from './requestResponse/requestResponse.js';\nimport { successHtml as successHtmlImport } from './requestResponse/requestResponse.js';\nimport { getCurrentUserNameFromCognitoEvent as getCurrentUserNameFromCognitoEventImport } from './requestResponse/requestResponse.js';\nimport { defaultFilters as defaultFiltersImport } from './database/dbUtils/queryStringUtils/defaultFilters.js';\nimport { accessRightsUtils as accessRightsUtilsImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { parseBody as parseBodyImport } from './requestResponse/requestResponse.js';\nimport { parseEvent as parseEventImport } from './requestResponse/requestResponse.js';\nimport { getBusinessesInfo as getBusinessesInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { userDefaultBid as userDefaultBidImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { checkWriteAccess as checkWriteAccessImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { isSystemUser as isSystemUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { isSuperUser as isSuperUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\n\nexport const handleFile = handleFileImport;\nexport const watchBucket = watchBucketImport;\nexport const publishEvents = publishEventsImport;\nexport const createFilters = createFiltersImport;\nexport const createIncludes = createIncludesImport;\nexport const createSort = createSortImport;\nexport const findAll = findAllImport;\nexport const checkModule = checkModuleImport;\nexport const checkIsSuper = checkIsSuperImport;\nexport const getAccessRightsInfo = getAccessRightsInfoImport;\nexport const getDefaultBusinessIDInfo = getDefaultBusinessIDInfoImport;\nexport const getModuleInfo = getModuleInfoImport;\nexport const failure = failureImport;\nexport const success = successImport;\nexport const runMigrations = runMigrationsImport;\nexport const getCurrentUser = getCurrentUserImport;\nexport const successHtml = successHtmlImport;\nexport const getCurrentUserNameFromCognitoEvent = getCurrentUserNameFromCognitoEventImport;\nexport const defaultFilters = defaultFiltersImport;\nexport const accessRightsUtils = accessRightsUtilsImport;\nexport const parseBody = parseBodyImport;\nexport const parseEvent = parseEventImport;\nexport const getBusinessesInfo = getBusinessesInfoImport;\nexport const userDefaultBid = userDefaultBidImport;\nexport const checkWriteAccess = checkWriteAccessImport;\nexport const isSystemUser = isSystemUserImport;\nexport const isSuperUser = isSuperUserImport;\n"],"names":["module","exports","require","_libDynamodb","_clientDynamodb","dynamoUtil","get","params","async","DynamoDBDocument","from","DynamoDB","handleDirectS3WriteEvent","event","transformer","errorHandlerPerFile","shouldSkipFailedFolders","userImportTypes","Records","Promise","resolve","hasErrors","map","record","s3Bucket","s3","bucket","name","file","object","key","path","decodeURIComponent","handleFile","catch","err","console","error","then","Error","handleEvents","snsInfo","JSON","parse","_","files","_handleFile","_lodash","_interopRequireDefault","_bluebird","e","__esModule","default","watchBucket","noop","dynamoConfigTable","dynamoConfigKey","snsTopic","EventSource","isEqual","publishEvents","failedOnce","failedTwice","direct","startsWithDirect","startsWith","includes","log","_publishEvents","_handleEvents","defaultFilters","schema","subSchemas","clone","filters","addFiltersFromSchema","Object","keys","forEach","_sequelize","keyPrefix","asLinkAlias","reduce","acc","item","type","DB","STRING","filterType","Op","eq","itemType","CHAR","TEXT","iLike","DECIMAL","INTEGER","BIGINT","or","BOOLEAN","JSONB","field","DATE","between","DATEONLY","_dayjs","_utc","_errorCodes","_accessRightsUtils","dayjs","extend","utc","objectFilters","query","searchString","startDate","endDate","caseInsensitiveConditions","where","val","itemName","push","fn","col","like","toLowerCase","in","split","parsedJson","queryValue","booleanMap","length","and","active","filterAdds","businessId","accessRightsUtils","s","dates","toDate","isValid","errorList","invalidStartDate","invalidEndDate","createdAt","adds","dataType","isNaN","Number","newOr","withDate","assign","k","def","prefix","qKey","pathParts","substring","value","parsed","Array","isArray","addJsonbConditions","obj","entries","currentPath","String","_clientSns","SNSUtil","publish","sns","SNS","createTopic","checkIsSuper","isSuperUser","isSystemUser","process","env","BUILD_ENV","unauthorized","checkModule","moduleName","moduleRights","getModuleInfo","allowAccess","checkWriteAccess","options","eventBody","parseBody","find","id","userRight","getBusinessesInfo","userRoles","admin","write","getAccessRightsInfo","jsonToParse","accessRights","getDefaultBusinessIDInfo","dbi","userDefaultBid","_interopRequireWildcard","t","WeakMap","r","n","o","i","f","__proto__","has","set","hasOwnProperty","call","defineProperty","getOwnPropertyDescriptor","_requestResponse","isSys","useCognitoBid","requestedBusinessIds","getRequestedBusinessIds","allowedBusinessIds","getAllowedBusinessIds","businesses","v","isEmpty","intersection","body","bodyBid","json","businessIds","b","read","defaultFilter","copyOfDefaultFilter","testItem","indexOf","substr","sortItem","parentChildList","detectDynamooseError","errorBody","dynamooseError","errors","message","detail","trim","failure","cleanedErrorBody","dbClose","UTIL_LOG","isObject","stringify","isUndefined","details","errorCode","statusCode","detectSequelizeError","detectJoyError","newBody","merge","buildResponse","getCurrentUser","username","getCurrentUserNameFromCognitoEvent","attributes","requestEvent","isString","invalidJson","parseEvent","callback","success","successHtml","html","headers","errorName","fields","filter","Boolean","join","messages","sequelizeError","parentError","joyError","contextItem","msg","configTable","tableKey","result","TableName","Key","chunkSize","maxMessages","topicArn","Name","TopicArn","maxKeys","fileList","loop","messageList","chain","chunk","slice","Message","_customParseFormat","_isSameOrBefore","_S3Utils","_SNSUtils","_dynamoUtils","bucketResult","currentTime","S3Utils","listObjectsV2","Bucket","MaxKeys","ContinuationToken","newFiles","Contents","fileDelayTime","isSameOrBefore","usersImports","values","items","fileName","last","folderName","first","concat","IsTruncated","NextContinuationToken","customParseFormat","runMigrations","databaseName","sequelizeInstance","initializeModels","pathToMigrationFolder","PWD","umzug","Umzug","migrations","glob","context","getQueryInterface","storage","SequelizeStorage","sequelize","logger","pendingMigrations","pending","up","upError","down","reverse","downError","_umzug","S3Util","getObject","Code","code","isNil","deleteObject","parsedBody","returnedValue","newPath","replace","newParams","Body","containsError","putObject","str","firstIndex","_clientS","s3Utils","action","S3","getS3","response","transformToString","invalidInventoryReleaseRequest","alreadyReleased","alreadyReceived","invalidItemsRequest","invalidID","invalidReceivable","invalidRequest","invalidAPIKey","qbCreationError","cannotReopen","invalidDateFormat","invalidOrderStatus","invalidPaymentStatus","invalidReleaseStatus","invalidReceivableStatus","invalidFilter","invalidUserNameUpdate","imageSizeLimit","notFound","emailRequired","mobilePhoneRequired","invalidCadenceType","getPaginationFromFindAll","limit","offset","hasMore","splice","rows","findAll","model","all","nested","findArgs","include","findUtils","createIncludes","canBeIncluded","includeSubItem","askedForInQuery","queryStringItem","dot","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","_watchBucket","_createIncludes","_createFilters","_createSort","_findAll","_migrations","_defaultFilters","handleFileImport","watchBucketImport","publishEventsImport","createFiltersImport","createIncludesImport","createSortImport","findAllImport","checkModuleImport","checkIsSuperImport","getAccessRightsInfoImport","getDefaultBusinessIDInfoImport","getModuleInfoImport","failureImport","successImport","runMigrationsImport","getCurrentUserImport","successHtmlImport","getCurrentUserNameFromCognitoEventImport","defaultFiltersImport","accessRightsUtilsImport","parseBodyImport","parseEventImport","getBusinessesInfoImport","userDefaultBidImport","checkWriteAccessImport","isSystemUserImport","isSuperUserImport"],"ignoreList":[],"sourceRoot":""}
1
+ {"version":3,"file":"main.js","mappings":"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","sources":["webpack://piper-utils/external commonjs \"sequelize\"","webpack://piper-utils/external commonjs \"@aws-sdk/client-s3\"","webpack://piper-utils/external commonjs \"dayjs/plugin/customParseFormat\"","webpack://piper-utils/./src/dynamo/dynamoUtils.js","webpack://piper-utils/./src/eventManager/handleEvents.js","webpack://piper-utils/external commonjs \"dayjs/plugin/utc.js\"","webpack://piper-utils/./src/eventManager/watchBucket.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/defaultFilters.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createFilters.js","webpack://piper-utils/external commonjs \"dayjs\"","webpack://piper-utils/./src/sns/SNSUtils.js","webpack://piper-utils/external commonjs \"dayjs/plugin/isSameOrBefore\"","webpack://piper-utils/external commonjs \"@aws-sdk/lib-dynamodb\"","webpack://piper-utils/external commonjs \"bluebird\"","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/accessRightsUtils.js","webpack://piper-utils/external commonjs \"@aws-sdk/client-sns\"","webpack://piper-utils/external commonjs \"lodash\"","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createSort.js","webpack://piper-utils/./src/requestResponse/requestResponse.js","webpack://piper-utils/./src/eventManager/publishEvents.js","webpack://piper-utils/./src/database/dbSetup/migrations.js","webpack://piper-utils/./src/eventManager/handleFile.js","webpack://piper-utils/./src/s3/S3Utils/S3Utils.js","webpack://piper-utils/external commonjs \"umzug\"","webpack://piper-utils/external commonjs \"@aws-sdk/client-dynamodb\"","webpack://piper-utils/./src/requestResponse/errorCodes.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/findAll.js","webpack://piper-utils/./src/database/dbUtils/queryStringUtils/createIncludes.js","webpack://piper-utils/webpack/bootstrap","webpack://piper-utils/./src/index.js"],"sourcesContent":["module.exports = require(\"sequelize\");","module.exports = require(\"@aws-sdk/client-s3\");","module.exports = require(\"dayjs/plugin/customParseFormat\");","import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';\nimport { DynamoDB } from '@aws-sdk/client-dynamodb';\n\nconst dynamoUtil = {\n get: (params) => get(params)\n};\n\n/**\n * @param {{TableName:string, Key:{key:string}}} params\n */\nasync function get(params) {\n const dynamoDb = DynamoDBDocument.from(new DynamoDB());\n return dynamoDb.get(params);\n}\n\nexport default dynamoUtil;","import { handleFile } from './handleFile.js';\nimport _ from 'lodash';\nimport Promise from 'bluebird';\n\nexport function handleEvents(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {\n if (!event || !event.Records) {\n return Promise.resolve();\n }\n\n let hasErrors = false;\n\n return Promise.map(event.Records, (record) => {\n const snsInfo = JSON.parse(_.get(record, 'Sns.Message', '{}'));\n const s3Bucket = snsInfo.bucket;\n const files = snsInfo.files || [];\n\n return Promise.map(files, (file) => {\n let path = decodeURIComponent(file);\n if (path) {\n return handleFile(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {\n if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {\n console.error('HANDLE-FILE-CATCH: ', err);\n hasErrors = true;\n }\n });\n }\n });\n }).then(() => {\n if (hasErrors) {\n throw new Error('ERROR: HANDLE-FILE');\n }\n });\n}\n\nexport function handleDirectS3WriteEvent(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders = false, userImportTypes) {\n if (!event || !event.Records) {\n return Promise.resolve();\n }\n\n let hasErrors = false;\n\n return Promise.map(event.Records, (record) => {\n const s3Bucket = record.s3.bucket.name;\n const file = record.s3.object.key || [];\n\n let path = decodeURIComponent(file);\n if (path) {\n return handleFile(path, s3Bucket, transformer, { shouldSkipFailedFolders, userImportTypes }).catch((err) => {\n if (errorHandlerPerFile && !errorHandlerPerFile(err, path)) {\n console.error('HANDLE-FILE-CATCH:', err);\n hasErrors = true;\n }\n });\n }\n\n }).then(() => {\n if (hasErrors) {\n throw new Error('ERROR: HANDLE-FILE (DIRECT S3 EVENT)');\n }\n });\n}\n","module.exports = require(\"dayjs/plugin/utc.js\");","import { publishEvents } from './publishEvents.js';\nimport { handleEvents, handleDirectS3WriteEvent } from './handleEvents.js';\nimport _ from 'lodash';\n\n/**\n * 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\n * prefix objects with DIRECT to listen to direct s3 events\n *\n * @param {object} params - The parameters for watchBucket, see below\n * @param {object} params.event - The event of the lambda\n * @param {string} params.dynamoConfigTable - The Dynamo DB table where to get the chunkSize and maxMessage size\n * @param {string} params.dynamoConfigKey - The key to the item in the Dynamo DB table that holds the chunkSize and maxMessage size\n * @param {string} params.s3Bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created\n * @param {string} params.snsTopic - The name of the snsEvent to publish\n * @param {function} params.transformer - the function to run on each file\n * @param {function} [params.errorHandlerPerFile] - the function to run on as a catch on each file\n * @param {boolean} [params.shouldSkipFailedFolders] - whether to use the failed-once, failed-twice, error or just error folders\n * @param {object} [params.userImportTypes] - user import subdirectories object map\n */\nexport function watchBucket({\n event,\n dynamoConfigTable,\n dynamoConfigKey,\n s3Bucket,\n snsTopic,\n transformer,\n errorHandlerPerFile = _.noop,\n shouldSkipFailedFolders = false,\n userImportTypes\n }) {\n if (!event || !dynamoConfigTable || !dynamoConfigKey || !s3Bucket || !snsTopic || !transformer) {\n throw new Error('Missing required parameters. Need event, dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, transformer');\n }\n\n const EventSource = _.get(event, 'Records[0].eventSource') || _.get(event, 'Records[0].EventSource');\n\n if (_.isEqual(EventSource, 'aws:sns')) {\n return handleEvents(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);\n } else if (_.isEqual(EventSource, 'aws:s3')) {\n const failedOnce = 'failed-once';\n const failedTwice = 'failed-twice';\n const error = 'error';\n const direct = 'DIRECT';\n const key = _.get(event, 'Records[0].s3.object.key') || '';\n const startsWithDirect = _.startsWith(key, direct);\n if (key.includes(failedOnce) || key.includes(failedTwice) || key.includes(error)) {\n // this used to throw, but the throw raised useless alarms, I believed turing throw in to a return was ok\n return;\n }\n\n if (startsWithDirect) {\n console.log('------->DIRECT WRITE FIRE');\n return handleDirectS3WriteEvent(event, transformer, errorHandlerPerFile, shouldSkipFailedFolders, userImportTypes);\n }\n\n } else {\n // the function is being run from the cron job so publish SNS events\n return publishEvents(dynamoConfigTable, dynamoConfigKey, s3Bucket, snsTopic, userImportTypes);\n }\n}\n","import _ from 'lodash';\nimport DB from 'sequelize';\n\n/**\n * Create an object with default filters for a given sequeliaze Schema Object, and set of sub schemas\n *\n * @param {object} schema - type is sequelize data type\n * @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\n * sub schema can be {location: locationSchema} or {location: {as: \"asAlias\", schema: schema}}\n * @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.\n */\nexport function defaultFilters(schema, subSchemas = {}) {\n schema = _.clone(schema);\n\n const filters = {};\n\n addFiltersFromSchema(schema, filters);\n Object.keys(subSchemas).forEach((key) => {\n addFiltersFromSchema(subSchemas[key], filters, key);\n });\n\n return filters;\n}\n\nexport function addFiltersFromSchema(schema, filters, keyPrefix = '') {\n const asLinkAlias = _.get(schema, 'as', null);\n schema = _.get(schema, 'schema') || schema;\n\n return Object.keys(schema).reduce((acc, item) => {\n let key = item;\n\n if (asLinkAlias) {\n acc[asLinkAlias] = { type: DB.STRING, filterType: DB.Op.eq };\n }\n\n if (keyPrefix) {\n key = `${keyPrefix}.${item}`;\n }\n\n if (schema[item].filterType) {\n acc[key] = { filterType: schema[item].filterType };\n\n return acc;\n }\n\n const itemType = schema[item].type;\n\n //new sequelize uses class symbols instead of objects\n if (itemType instanceof DB.STRING) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.CHAR) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.TEXT) {\n acc[key] = { filterType: DB.Op.iLike };\n } else if (itemType instanceof DB.DECIMAL) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.INTEGER) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.BIGINT) {\n acc[key] = { filterType: DB.Op.or };\n } else if (itemType instanceof DB.BOOLEAN) {\n acc[key] = { type: DB.BOOLEAN, filterType: DB.Op.eq };\n } else if (itemType instanceof DB.JSONB || itemType === DB.JSONB) {\n acc[key] = { type: 'jsonb', field: item };\n } else if (itemType instanceof DB.DATE) {\n acc[key] = { filterType: DB.Op.between };\n } else if (itemType instanceof DB.DATEONLY) {\n acc[key] = { filterType: DB.Op.eq };\n }\n\n //these are automatically part of the models, so add them always\n acc['createdAt'] = { type: DB.DATE, filterType: DB.Op.between };\n acc['updatedAt'] = { type: DB.DATE, filterType: DB.Op.between };\n acc['id'] = { type: DB.INTEGER, filterType: DB.Op.eq };\n\n return acc;\n }, filters);\n}\n","import _ from 'lodash';\nimport DB from 'sequelize';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc.js';\nimport { errorList } from '../../../requestResponse/errorCodes.js';\nimport { accessRightsUtils } from './accessRightsUtils.js';\n\ndayjs.extend(utc);\n\n/**\n * Create sequelize where clause from query string parameters and default sort object\n *\n * Translates URL query string parameters into a Sequelize-compatible WHERE object\n * by matching each param against a filter definition (objectFilters).\n *\n * Filter definitions come from defaultFilters() which maps schema data types to operators:\n * STRING / CHAR / TEXT -> Op.iLike (case-insensitive LIKE)\n * INTEGER / DECIMAL -> Op.or (positive or negative match)\n * BOOLEAN -> Op.eq (exact match with string-to-boolean coercion)\n * JSONB -> case-insensitive search via jsonb_extract_path_text\n * DATE -> Op.between\n *\n * Three convenience params are handled automatically:\n * - searchString: searches a single value across all iLike and eq fields using OR\n * - startDate + endDate: filters createdAt with a BETWEEN range\n *\n * @param {object} event - the Lambda event containing queryStringParameters\n * @param {object} objectFilters - filter definitions created by defaultFilters()\n * @returns {object} A Sequelize where clause object\n */\nexport const createFilters = function (event, objectFilters) {\n let query = _.get(event, 'queryStringParameters', {}) || {};\n\n // Extract the three convenience params before iterating.\n // These are handled separately from the per-field filter logic below.\n const searchString = _.get(query, 'searchString');\n const startDate = _.get(query, 'startDate');\n const endDate = _.get(query, 'endDate');\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 1 — Build per-field WHERE conditions\n //\n // Each query param is looked up in objectFilters. If a matching filter\n // definition exists, we create the appropriate Sequelize condition.\n //\n // String-type fields (Op.iLike) are collected into a separate array\n // because they use DB.where(DB.fn('LOWER', DB.col(...))) which cannot\n // be expressed as a simple { column: { operator: value } } key.\n // Instead they are merged into WHERE via Op.and after the reduce.\n //\n // This approach replaces the Postgres-only Op.iLike with\n // LOWER(column) LIKE '%lowered_value%' which works across all\n // database dialects (Postgres, MySQL, MSSQL, SQLite).\n // ──────────────────────────────────────────────────────────────────────\n const caseInsensitiveConditions = [];\n const where = Object.keys(query).reduce((acc, item) => {\n const val = _.get(objectFilters, item, null);\n\n if (val) {\n // JSONB fields are handled entirely in Step 4 below.\n // Skip them here so they don't fall into the catch-all else branch.\n if (val.type === 'jsonb') {\n return acc;\n }\n\n // Dot-notation keys (e.g. \"snowman.snowmanType\") reference columns\n // on joined/included models. Sequelize requires these to be wrapped\n // in $...$ syntax in the WHERE object so it can resolve them.\n const itemName = item.includes('.')\n ? `$${item}$`\n : item;\n\n // STRING / CHAR / TEXT fields — case-insensitive partial match\n // Generates: WHERE LOWER(\"column\") LIKE '%lowered_value%'\n if (val.filterType === DB.Op.iLike) {\n caseInsensitiveConditions.push(\n DB.where(\n DB.fn('LOWER', DB.col(item)),\n { [DB.Op.like]: `%${query[item]?.toLowerCase()}%` }\n )\n );\n\n // INTEGER / DECIMAL fields — match positive or negative value\n // Generates: WHERE \"column\" IN (-value, value)\n // Useful for fields like amounts where sign may vary.\n } else if (val.filterType === DB.Op.or) {\n acc[itemName] = {};\n acc[itemName][val.filterType] = [ -1 * +query[item], +query[item] ];\n\n // ENUM / multi-value fields — match any value in a comma-separated list\n // Query: ?status=open,closed -> WHERE \"status\" IN ('open','closed')\n } else if (val.filterType === DB.Op.in) {\n acc[itemName] = {};\n acc[itemName][val.filterType] = query[item].split(',');\n\n // Catch-all for other operators (Op.eq, Op.contains, Op.between, etc.)\n // Attempts JSON.parse first so structured values (objects, arrays, numbers)\n // are passed as their parsed type rather than raw strings.\n } else {\n acc[itemName] = {};\n let parsedJson;\n try {\n parsedJson = JSON.parse(query[item]);\n } catch (e) {\n parsedJson = query[item];\n }\n acc[itemName][val.filterType] = parsedJson;\n }\n\n // BOOLEAN override — runs after the block above so it can replace\n // the value set by the catch-all. Query strings are always strings\n // (\"true\", \"false\", \"null\"), so we coerce them to actual booleans/null.\n if (val.type === DB.BOOLEAN) {\n const queryValue = _.get(query, item, '').toLowerCase();\n\n const booleanMap = {\n 'false': false,\n 'null': null,\n 'true': true\n };\n\n acc[itemName][val.filterType] = booleanMap[queryValue];\n }\n }\n\n return acc;\n }, {});\n\n // Merge the case-insensitive string conditions into WHERE using Op.and.\n // This keeps them alongside the key-based conditions built above.\n // Example result: WHERE decimal = 100 AND LOWER(\"name\") LIKE '%john%'\n if (caseInsensitiveConditions.length) {\n where[DB.Op.and] = [ ...(where[DB.Op.and] || []), ...caseInsensitiveConditions ];\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 2 — Apply automatic filters (active flag, businessId, dates)\n //\n // These are appended to every query regardless of what the caller sent.\n // ──────────────────────────────────────────────────────────────────────\n\n // If the model has an \"active\" column and the caller did not explicitly\n // filter by it, default to only returning active records.\n if (objectFilters?.active && !where?.active) {\n where.active = true;\n }\n\n // Scope every query to the caller's authorized business IDs.\n // accessRightsUtils extracts them from the JWT claims on the event.\n const businessIds = accessRightsUtils(event);\n const filterAdds = {\n businessId: businessIds\n };\n\n // Date range filter — when both startDate and endDate are provided,\n // automatically filter createdAt with a BETWEEN clause.\n // Generates: WHERE \"createdAt\" BETWEEN '2024-01-01' AND '2024-12-31'\n if (startDate && endDate) {\n const s = dayjs.utc(startDate);\n const e = dayjs.utc(endDate);\n const dates = {\n [DB.Op.between]: [ s.toDate(), e.toDate() ]\n };\n if (!s.isValid()) {\n throw { ...errorList.invalidStartDate };\n }\n\n if (!e.isValid()) {\n throw { ...errorList.invalidEndDate };\n }\n\n filterAdds.createdAt = dates;\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 3 — searchString: search one value across many fields with OR\n //\n // When ?searchString=john is provided, we build an OR array that checks\n // every filterable field for a match. This lets a single search box\n // query across name, title, email, etc. simultaneously.\n //\n // String fields (Op.iLike) get a case-insensitive LOWER + LIKE condition.\n // Numeric fields (Op.eq) get an exact match, but only when the search\n // value is a valid number (and the field is not a boolean).\n //\n // Generates: WHERE (LOWER(\"name\") LIKE '%john%'\n // OR LOWER(\"title\") LIKE '%john%'\n // OR \"id\" = 123)\n // ──────────────────────────────────────────────────────────────────────\n if (searchString) {\n const adds = Object.keys(objectFilters).reduce((acc, item) => {\n const type = objectFilters[item].filterType;\n const dataType = objectFilters[item].type;\n\n // String fields — case-insensitive partial match via LOWER + LIKE\n if (type === DB.Op.iLike) {\n acc.push(\n DB.where(\n DB.fn('LOWER', DB.col(item)),\n { [DB.Op.like]: `%${query['searchString'].toLowerCase()}%` }\n )\n );\n }\n\n // Numeric fields — exact match only when the search value is numeric.\n // Booleans are excluded because a search for \"1\" should not match\n // boolean true.\n if (!_.isNaN(Number(query['searchString'])) && !(dataType instanceof DB.BOOLEAN)) {\n\n if (type === DB.Op.eq) {\n const newOr = {};\n const itemName = item.includes('.') ? `$${item}$` : item;\n newOr[itemName] = {\n [DB.Op.eq]: `${query['searchString']}`\n };\n acc.push(newOr);\n }\n }\n\n return acc;\n }, []);\n\n filterAdds[DB.Op.or] = adds;\n }\n\n // Merge the automatic filters (businessId, createdAt, searchString OR)\n // into the where object built in Step 1.\n const withDate = Object.assign(where, filterAdds);\n\n // ──────────────────────────────────────────────────────────────────────\n // STEP 4 — JSONB field filters: case-insensitive search inside JSON columns\n //\n // JSONB columns store structured data (e.g. a \"token\" column containing\n // { cardType: \"mastercard\", cardHolderName: \"GREGORY HERBERT\" }).\n //\n // Query params use dot-notation to target nested keys:\n // ?token.cardHolderName=gregory\n // ?paymentProviderData.payment.result.message=approved\n //\n // For each matching param we:\n // 1. Split the path after the column prefix into individual key segments\n // 2. Use jsonb_extract_path_text(column, key1, key2, ...) to pull the\n // value out of the JSON as plain text\n // 3. Wrap it in LOWER() and compare with Op.like for case-insensitive match\n //\n // Generates: WHERE LOWER(jsonb_extract_path_text(\"token\", 'cardHolderName'))\n // LIKE '%gregory%'\n //\n // jsonb_extract_path_text is used via DB.fn() so Sequelize parameterizes\n // the path arguments, keeping it safe from SQL injection.\n // ──────────────────────────────────────────────────────────────────────\n Object.keys(objectFilters || {}).forEach((k) => {\n const def = objectFilters[k];\n if (def && def.type === 'jsonb' && def.field) {\n const prefix = `${def.field}.`;\n\n Object.keys(query).forEach((qKey) => {\n if (qKey.startsWith(prefix)) {\n // Dot-notation: ?token.cardHolderName=gregory\n // e.g. \"token.cardHolderName\" -> pathParts = [\"cardHolderName\"]\n // e.g. \"data.payment.result.message\" -> pathParts = [\"payment\",\"result\",\"message\"]\n const pathParts = qKey.substring(prefix.length).split('.');\n const value = query[qKey];\n\n if (!withDate[DB.Op.and]) {\n withDate[DB.Op.and] = [];\n }\n withDate[DB.Op.and].push(\n DB.where(\n DB.fn('LOWER', DB.fn('jsonb_extract_path_text', DB.col(def.field), ...pathParts)),\n { [DB.Op.like]: `%${value?.toLowerCase()}%` }\n )\n );\n } else if (qKey === def.field) {\n // JSON-object-as-value: ?token={\"cardHolderName\":\"Test\"}\n // Parse the JSON and create a condition for each key-value pair.\n // Nested objects are flattened recursively into deeper path segments.\n let parsed;\n try {\n parsed = JSON.parse(query[qKey]);\n } catch (e) {\n return;\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n const addJsonbConditions = (obj, pathParts) => {\n Object.entries(obj).forEach(([key, value]) => {\n const currentPath = [...pathParts, key];\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n addJsonbConditions(value, currentPath);\n } else if (value !== null && !Array.isArray(value)) {\n if (!withDate[DB.Op.and]) {\n withDate[DB.Op.and] = [];\n }\n withDate[DB.Op.and].push(\n DB.where(\n DB.fn('LOWER', DB.fn('jsonb_extract_path_text', DB.col(def.field), ...currentPath)),\n { [DB.Op.like]: `%${String(value)?.toLowerCase()}%` }\n )\n );\n }\n });\n };\n addJsonbConditions(parsed, []);\n }\n }\n });\n }\n });\n\n return withDate;\n};\n","module.exports = require(\"dayjs\");","import { SNS } from '@aws-sdk/client-sns';\n\nconst SNSUtil = {\n publish: (params) => publish(params),\n createTopic: (params) => createTopic(params)\n};\n\nasync function publish(params) {\n const sns = new SNS();\n return await sns.publish(params);\n}\n\nasync function createTopic(params) {\n const sns = new SNS();\n return await sns.createTopic(params);\n}\n\nexport default SNSUtil;\n","module.exports = require(\"dayjs/plugin/isSameOrBefore\");","module.exports = require(\"@aws-sdk/lib-dynamodb\");","module.exports = require(\"bluebird\");","import _, { isEmpty } from 'lodash';\r\nimport { errorList } from '../../../requestResponse/errorCodes.js';\r\nimport { parseBody } from '../../../requestResponse/requestResponse.js';\r\n\r\nexport function isSystemUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:SYSTEM') ||\r\n _.get(event, 'requestContext.authorizer.custom:SYSTEM') ||\r\n 'false';\r\n let isSys = false;\r\n try {\r\n isSys = JSON.parse(jsonToParse);\r\n return isSys;\r\n } catch (e) {\r\n console.error('error with system user:', e);\r\n\r\n return false;\r\n }\r\n}\r\n\r\nexport function isSuperUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:SUPER') ||\r\n _.get(event, 'requestContext.authorizer.custom:SUPER') ||\r\n 'false';\r\n let isSys = false;\r\n\r\n try {\r\n isSys = JSON.parse(jsonToParse);\r\n\r\n return isSys;\r\n } catch (e) {\r\n\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Throws unauthorized error if the user is not a super user.\r\n * Mirrors the behavior and style of checkModule but focused on SUPER role.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n */\r\nexport function checkIsSuper(event) {\r\n // Super or System users are always allowed\r\n if (isSuperUser(event)) {\r\n return;\r\n }\r\n if (isSystemUser(event)) {\r\n return;\r\n }\r\n\r\n // In local builds allow bypass to ease development and tests\r\n if (process.env.BUILD_ENV === 'local') {\r\n return;\r\n }\r\n\r\n throw errorList.unauthorized;\r\n}\r\n\r\n/**\r\n * Get the allowed businessIds for a user from the lambda event, compare it to businessIds, return what user has access to.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @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.\r\n * @returns {array} A list of businessIds that have been requested and are allowed to for some user.\r\n */\r\nexport function accessRightsUtils(event, options) {\r\n const useCognitoBid = _.get(options, 'useCognitoBid', false);\r\n const requestedBusinessIds = getRequestedBusinessIds(event);\r\n const allowedBusinessIds = getAllowedBusinessIds(event, useCognitoBid);\r\n\r\n if (isSuperUser(event)) {\r\n let v = requestedBusinessIds;\r\n if (_.isEmpty(requestedBusinessIds)) {\r\n v = allowedBusinessIds;\r\n }\r\n\r\n return v;\r\n }\r\n if (isSystemUser(event)) {\r\n return requestedBusinessIds;\r\n }\r\n\r\n if (requestedBusinessIds.length === 0) {\r\n return allowedBusinessIds;\r\n }\r\n\r\n return _.intersection(requestedBusinessIds, allowedBusinessIds);\r\n}\r\n\r\n/**\r\n * Get the businessID set in cognito as custom:DBI.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {string} The businessID set in cognito as custom:DBI\r\n */\r\nexport function userDefaultBid(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:DBI') ||\r\n _.get(event, 'requestContext.authorizer.custom:DBI') ||\r\n '{}';\r\n\r\n const dbi = JSON.parse(jsonToParse);\r\n return _.get(dbi, 'defaultBid', '') || '1';\r\n}\r\n\r\n/**\r\n * Get requested businessIds from the query string.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The businessID requested by the query string\r\n */\r\nexport function getRequestedBusinessIds(event) {\r\n let requestedBusinessIds = _.get(event, 'queryStringParameters.businessIds', null);\r\n const body = parseBody(event);\r\n const bodyBid = body?.businessId;\r\n if (requestedBusinessIds) {\r\n return requestedBusinessIds ? requestedBusinessIds.split(',') : [];\r\n } else if (bodyBid) {\r\n return [ bodyBid ];\r\n } else {\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get the allowed businessIds for a user from cognito custom:AR property.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @param useCognitoBid\r\n * @returns {array} The businessID requested by the query string\r\n */\r\nfunction getAllowedBusinessIds(event, useCognitoBid) {\r\n const businesses = getBusinessesInfo(event, useCognitoBid);\r\n return Object.keys(businesses);\r\n}\r\n\r\nexport function getAccessRightsInfo(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n '{}';\r\n const accessRights = JSON.parse(jsonToParse);\r\n return _.get(accessRights, 'businessIds', {});\r\n}\r\n\r\nexport function getDefaultBusinessIDInfo(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:DBI') ||\r\n _.get(event, 'requestContext.authorizer.custom:DBI') ||\r\n '{}';\r\n const dbi = JSON.parse(jsonToParse);\r\n\r\n return _.get(dbi, 'defaultBid', '1');\r\n}\r\n\r\nexport function getBusinessesInfo(event, useCognitoBid = false) {\r\n const json = _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n '{}';\r\n\r\n let businessIds = _.get(JSON.parse(json), 'businessIds', {});\r\n\r\n // Local environment tweaks\r\n if (process.env.BUILD_ENV === 'local') {\r\n let b;\r\n try {\r\n b = JSON.parse(event?.body);\r\n } catch (e) {\r\n }\r\n const bodyBid = b?.businessId;\r\n // Always inject the default local BID “1” unless the caller explicitly wants\r\n // what Cognito says **and** Cognito actually returned something.\r\n if (!useCognitoBid) {\r\n businessIds = { ...businessIds, '1': 'A' };\r\n }\r\n\r\n // If Cognito gave no BIDs at all, fall back to the local default.\r\n if (isEmpty(businessIds)) {\r\n businessIds = { '1': 'A' };\r\n }\r\n // a businessId is found on the body for local allow it\r\n if (bodyBid) {\r\n businessIds[bodyBid] = 'A';\r\n }\r\n }\r\n\r\n return businessIds;\r\n}\r\n\r\n/**\r\n * Get the modules listed in custom:MOD.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The Module access list\r\n */\r\nexport function getModuleInfo(event) {\r\n let jsonToParse =\r\n _.get(event, 'requestContext.authorizer.claims.custom:MOD') ||\r\n _.get(event, 'requestContext.authorizer.custom:MOD') ||\r\n _.get(event, 'requestContext.authorizer.claims.custom:AR') ||\r\n _.get(event, 'requestContext.authorizer.custom:AR') ||\r\n\r\n '{}';\r\n\r\n const moduleRights = JSON.parse(jsonToParse);\r\n return _.get(moduleRights, 'module', {});\r\n}\r\n\r\n/**\r\n * Get the modules listed in custom:MOD.\r\n *\r\n * @param {string} moduleName - A sting name for a module.\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {array} The Module access list\r\n */\r\nexport function checkModule(moduleName, event) {\r\n const moduleRights = getModuleInfo(event);\r\n let allowAccess = _.get(moduleRights, moduleName, false);\r\n\r\n if (isSuperUser(event)) {\r\n return;\r\n }\r\n if (isSystemUser(event)) {\r\n return;\r\n }\r\n\r\n if (process.env.BUILD_ENV === 'local') {\r\n return;\r\n }\r\n if (!allowAccess) {\r\n throw errorList.unauthorized;\r\n }\r\n}\r\n\r\nexport const userRoles = {\r\n admin: 'A',\r\n read: 'R',\r\n write: 'W'\r\n};\r\n\r\n/**\r\n * Get the partner ID from custom:PID if the user is a partner admin.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {string|false} The partner ID or false if not a partner user.\r\n */\r\nexport function isPartnerUser(event) {\r\n const partnerId = _.get(event, 'requestContext.authorizer.claims.custom:PID') ||\r\n _.get(event, 'requestContext.authorizer.custom:PID') ||\r\n '';\r\n return partnerId || false;\r\n}\r\n\r\n/**\r\n * Get the partner ID from custom:BPID if the user's business belongs to a partner.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {string|false} The partner ID or false if not associated with a partner.\r\n */\r\nexport function getBelongsToPartnerId(event) {\r\n const partnerId = _.get(event, 'requestContext.authorizer.claims.custom:BPID') ||\r\n _.get(event, 'requestContext.authorizer.custom:BPID') ||\r\n '';\r\n return partnerId || false;\r\n}\r\n\r\n/**\r\n * Get the effective partner ID from either custom:PID or custom:BPID.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @returns {string|false} The partner ID or false.\r\n */\r\nexport function getEffectivePartnerId(event) {\r\n return isPartnerUser(event) || getBelongsToPartnerId(event);\r\n}\r\n\r\n/**\r\n * Enrich the event's custom:AR with partner business IDs in-memory.\r\n * Call this BEFORE accessRightsUtils() or getBusinessesInfo() so that\r\n * partner admins (custom:PID) get access to their partner's merchants.\r\n *\r\n * This keeps accessRightsUtils synchronous — the DB lookup is done by the caller.\r\n *\r\n * @param {object} event - The lambda event passed in by a validated api request.\r\n * @param {string[]} partnerBusinessIds - Array of business IDs from the partner record.\r\n * @param {string} [role='R'] - Access role to assign (default: Read).\r\n */\r\nexport function enrichEventWithPartnerAccess(event, partnerBusinessIds, role = 'R') {\r\n if (!partnerBusinessIds || partnerBusinessIds.length === 0) return;\r\n\r\n const arPath = event?.requestContext?.authorizer?.claims\r\n ? 'requestContext.authorizer.claims.custom:AR'\r\n : 'requestContext.authorizer.custom:AR';\r\n\r\n const json = _.get(event, arPath) || '{}';\r\n const accessRights = JSON.parse(json);\r\n const businessIds = accessRights.businessIds || {};\r\n\r\n for (const bid of partnerBusinessIds) {\r\n if (!businessIds[bid]) {\r\n businessIds[bid] = role;\r\n }\r\n }\r\n\r\n accessRights.businessIds = businessIds;\r\n _.set(event, arPath, JSON.stringify(accessRights));\r\n}\r\n\r\n/**\r\n * @param {{body: string}} event\r\n * @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.\r\n * @returns {string} businessId\r\n */\r\nexport function checkWriteAccess(event, options) {\r\n const eventBody = parseBody(event);\r\n const businessIds = accessRightsUtils(event, options) || [];\r\n const businessId = businessIds.find((id) => id === eventBody.businessId);\r\n const raw = getBusinessesInfo(event);\r\n const userRight = raw[businessId];\r\n\r\n if (isSuperUser(event)) {\r\n return eventBody.businessId;\r\n }\r\n\r\n if (isSystemUser(event)) {\r\n return eventBody.businessId;\r\n }\r\n\r\n if (process.env.BUILD_ENV === 'local') {\r\n return eventBody.businessId;\r\n }\r\n\r\n if ((userRight !== userRoles.admin && userRight !== userRoles.write) || (!userRight)) {\r\n throw errorList.unauthorized;\r\n }\r\n return businessId;\r\n}\r\n\r\n","module.exports = require(\"@aws-sdk/client-sns\");","module.exports = require(\"lodash\");","import _ from 'lodash';\n\n/**\n * Create sequelize order clause from query string parameters and default sort object\n *\n * @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\n * @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\n * @returns {object} An sequelize order by object\n */\nexport const createSort = function (event, defaultFilter) {\n let copyOfDefaultFilter = _.clone(defaultFilter);\n let query = _.get(event, 'queryStringParameters', {}) || {};\n let sort = _.get(query, 'sort', '-updatedAt') || '-updatedAt';\n\n return sort.split(',').reduce((acc, item) => {\n\n const testItem = item.indexOf('-') === 0 ? item.substr(1) : item;\n\n if (_.get(copyOfDefaultFilter, testItem, null)) {\n const sortItem = [];\n\n testItem.split('.').forEach((parentChildList) => {\n sortItem.push(parentChildList);\n });\n\n if (item.indexOf('-') === 0) {\n sortItem.push('DESC');\n } else {\n sortItem.push('ASC');\n }\n acc.push(sortItem);\n }\n\n return acc;\n }, []);\n};\n","import _ from 'lodash';\r\nimport { errorList } from './errorCodes.js';\r\n\r\nconst securityHeaders = {\r\n 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',\r\n 'X-Content-Type-Options': 'nosniff',\r\n 'X-Frame-Options': 'DENY',\r\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\r\n 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',\r\n 'Cache-Control': 'no-store',\r\n 'Content-Security-Policy': \"default-src 'none'; frame-ancestors 'none'\"\r\n};\r\n\r\nconst htmlSecurityHeaders = {\r\n 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',\r\n 'X-Content-Type-Options': 'nosniff',\r\n 'X-Frame-Options': 'DENY',\r\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\r\n 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',\r\n 'Cache-Control': 'no-store',\r\n 'Content-Security-Policy': [\r\n \"default-src 'self'\",\r\n \"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\",\r\n \"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com\",\r\n \"font-src 'self' https://fonts.gstatic.com\",\r\n \"frame-src https:\",\r\n \"connect-src 'self' https://*.tokenex.com https://*.sentry.io https://*.nmi.com\",\r\n \"img-src 'self' data:\",\r\n \"frame-ancestors 'none'\"\r\n ].join('; ')\r\n};\r\n\r\n/**\r\n * @param {Object} body\r\n * @param {{dbClose?:function}} [options]\r\n */\r\nexport function success(body, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n dbClose();\r\n\r\n return buildResponse(200, body);\r\n}\r\n\r\n/**\r\n * @param {string} html\r\n * @param {{dbClose:function|undefined}} options\r\n */\r\nexport function successHtml(html, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n\r\n dbClose();\r\n return {\r\n statusCode: 200,\r\n headers: {\r\n 'Content-Type': 'text/html',\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Credentials': true,\r\n ...htmlSecurityHeaders\r\n },\r\n body: html\r\n };\r\n}\r\n\r\n/**\r\n * @param {string} event\r\n * @returns string\r\n */\r\nexport function getCurrentUserNameFromCognitoEvent(event) {\r\n const attributes = _.get(event, 'request.userAttributes');\r\n\r\n return attributes['cognito:email_alias'] || attributes['email'] || 'UNKNOWN USER';\r\n}\r\n\r\n/**\r\n * Get the user information from the event object\r\n *\r\n * @param event {Object} an event object\r\n * @returns {{username: string, id: number}}\r\n */\r\nexport function getCurrentUser(event) {\r\n let jsonToParse = _.get(event, 'requestContext.authorizer.claims.custom:UID') ||\r\n _.get(event, 'requestContext.authorizer.custom:UID') ||\r\n '0';\r\n\r\n const id = JSON.parse(jsonToParse);\r\n\r\n const username = _.get(event, 'requestContext.authorizer.claims.email') || _.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';\r\n\r\n return {\r\n username,\r\n id\r\n };\r\n}\r\n\r\n/**\r\n * Create a failure response\r\n *\r\n * @param body {Object} an event object\r\n * @param options {Object} an options object\r\n * @returns {{statusCode:number, headers:object, body:string}} a response object\r\n */\r\nexport function failure(body = {}, options) {\r\n const dbClose = _.get(options, 'dbClose', _.noop);\r\n dbClose();\r\n let cleanedErrorBody;\r\n\r\n if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {\r\n if (_.isObject(body)) {\r\n console.error('------->ALL UTIL ERROR:', JSON.stringify(body, null, 2));\r\n }\r\n }\r\n\r\n const NORMAL_ERROR = { statusCode: 500, errorCode: '5XX', message: 'INTERNAL UTIL ERROR' };\r\n cleanedErrorBody = body;\r\n if (!_.isUndefined(body.details)) {\r\n cleanedErrorBody = detectJoyError(body);\r\n } else if (_.isUndefined(body.errorCode) || _.isUndefined(body.statusCode)) {\r\n cleanedErrorBody = detectSequelizeError(body);\r\n }\r\n if (_.get(body, 'response.data.message')) {\r\n const err = _.get(body, 'response.data.message');\r\n if (_.isObject(body)) {\r\n if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {\r\n console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));\r\n }\r\n }\r\n }\r\n const newBody = _.merge(NORMAL_ERROR, cleanedErrorBody);\r\n\r\n return buildResponse(newBody.statusCode, newBody);\r\n}\r\n\r\n/**\r\n * Create a failure response object\r\n *\r\n * @param statusCode {Number} a status code\r\n * @param body {Object} an event object\r\n * @returns {{statusCode:number, headers:object, body:string}} a response object\r\n */\r\nfunction buildResponse(statusCode, body) {\r\n return {\r\n statusCode: statusCode,\r\n headers: {\r\n 'Access-Control-Allow-Origin': '*',\r\n 'Access-Control-Allow-Credentials': true,\r\n ...securityHeaders\r\n },\r\n body: JSON.stringify(body)\r\n };\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n *\r\n * @param requestEvent {{body:string}} an event object\r\n * @returns event {*} the json object of the body\r\n */\r\nexport function parseBody(requestEvent) {\r\n\r\n let eventBody = {};\r\n if (_.isString(requestEvent.body)) {\r\n try {\r\n eventBody = JSON.parse(requestEvent.body);\r\n } catch (e) {\r\n // Invalid JSON\r\n eventBody = null;\r\n\r\n throw errorList.invalidJson;\r\n }\r\n } else if (_.isObject(requestEvent.body)) {\r\n eventBody = requestEvent.body;\r\n }\r\n\r\n return eventBody;\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n *\r\n * @param requestEvent {string|object} an event object\r\n * @param [callback] {function} undefined a call back function\r\n * @returns event {*} the json object of the body\r\n */\r\nexport function parseEvent(requestEvent, callback) {\r\n let event = {};\r\n if (_.isString(requestEvent)) {\r\n try {\r\n event = JSON.parse(requestEvent);\r\n } catch (e) {\r\n // Invalid JSON\r\n event = null;\r\n\r\n if (callback) {\r\n callback(Error(e));\r\n }\r\n }\r\n } else if (_.isObject(requestEvent)) {\r\n event = requestEvent;\r\n }\r\n\r\n return event;\r\n}\r\n\r\n/**\r\n * parse the body of the event object\r\n * look for sequelize errors and return a message\r\n * ERRORS should not be caught here this is a fallback for unknown database errors\r\n *\r\n * @param body {object} part of a body response\r\n * @returns error message object {message:string}\r\n */\r\nexport function detectSequelizeError(body) {\r\n const errorBody = {};\r\n const errorName = _.get(body, 'name', '');\r\n\r\n if (errorName === 'SequelizeForeignKeyConstraintError') {\r\n errorBody.message = 'You cannot delete this item as it is in use';\r\n errorBody.statusCode = 409;\r\n errorBody.errorCode = '4090';\r\n return errorBody;\r\n }\r\n\r\n if (errorName === 'SequelizeUniqueConstraintError') {\r\n const fields = _.get(body, 'errors', []).map(err => _.get(err, 'path')).filter(Boolean);\r\n errorBody.message = fields.length\r\n ? 'A record with this ' + fields.join(', ') + ' already exists'\r\n : 'A record with this value already exists';\r\n errorBody.statusCode = 409;\r\n errorBody.errorCode = '4091';\r\n return errorBody;\r\n }\r\n\r\n if (errorName === 'SequelizeValidationError') {\r\n const messages = _.get(body, 'errors', []).map(err => _.get(err, 'message')).filter(Boolean);\r\n errorBody.message = messages.length ? messages.join(', ') : 'Validation error';\r\n errorBody.statusCode = 400;\r\n errorBody.errorCode = '4001';\r\n return errorBody;\r\n }\r\n\r\n let sequelizeError = _.get(body, 'errors', []).reduce((acc, err) => {\r\n acc = acc + ' ' + _.get(err, 'message');\r\n return acc;\r\n }, '');\r\n const parentError = _.get(body, 'parent', '');\r\n\r\n sequelizeError = sequelizeError + _.get(body, 'original.detail', '') + _.get(body, 'TypeError', '') + parentError;\r\n errorBody.message = sequelizeError.trim();\r\n return errorBody;\r\n}\r\n\r\nexport function detectJoyError(body) {\r\n const errorBody = {};\r\n const joyError = _.get(body, 'details[0]', {});\r\n const additionalMessages = _.get(body, 'details[0].context.details') || [];\r\n\r\n const v = additionalMessages.reduce((acc, contextItem) => {\r\n acc = acc + ' ' + contextItem?.message || '';\r\n return acc;\r\n }, '');\r\n\r\n console.error('USER VALIDATION ERROR:', body);\r\n const msg = (joyError?.message || '') + v;\r\n\r\n if (msg) {\r\n errorBody.message = _.trim(msg);\r\n }\r\n\r\n errorBody.statusCode = 400;\r\n errorBody.errorCode = '4000';\r\n return errorBody;\r\n}\r\n\r\n/**\r\n * Parse the body of a Dynamoose error response.\r\n * Attempts to extract a human-readable error message from Dynamoose errors.\r\n * This is a fallback for unknown database errors.\r\n *\r\n * @param {object} body - Part of a body response containing error details.\r\n * @returns {object} - Error message object { message: string }\r\n */\r\nexport function detectDynamooseError(body) {\r\n const errorBody = {};\r\n\r\n // Start with an empty message string.\r\n let dynamooseError = '';\r\n\r\n // If the error body contains an array of errors, concatenate their messages.\r\n if (Array.isArray(body.errors)) {\r\n dynamooseError += body.errors.reduce((acc, err) => {\r\n return acc + ' ' + (err.message || '');\r\n }, '');\r\n }\r\n\r\n // If there's a top-level message, add it.\r\n if (body.message) {\r\n dynamooseError += ' ' + body.message;\r\n }\r\n\r\n // If there is any additional detail provided, append it.\r\n if (body.detail) {\r\n dynamooseError += ' ' + body.detail;\r\n }\r\n\r\n // Trim the message to remove extra spaces.\r\n errorBody.message = dynamooseError.trim();\r\n\r\n return errorBody;\r\n}","import _ from 'lodash';\nimport dayjs from 'dayjs';\nimport customParseFormat from 'dayjs/plugin/customParseFormat';\nimport isSameOrBefore from 'dayjs/plugin/isSameOrBefore';\nimport Promise from 'bluebird';\nimport S3Utils from '../s3/S3Utils/S3Utils.js';\nimport SNSUtil from '../sns/SNSUtils.js';\nimport dynamoUtil from '../dynamo/dynamoUtils.js';\n\ndayjs.extend(customParseFormat);\ndayjs.extend(isSameOrBefore);\n\n/**\n * @param {string} bucket\n * @param {number} maxKeys\n * @param {Object} userImportTypes\n */\nexport async function loop(bucket, maxKeys, userImportTypes) {\n let bucketResult = {};\n let fileList = [];\n\n const currentTime = dayjs();\n\n do {\n bucketResult = await S3Utils.listObjectsV2({\n Bucket: bucket,\n MaxKeys: maxKeys,\n ContinuationToken: _.get(bucketResult, 'NextContinuationToken')\n });\n\n let newFiles = _.filter(bucketResult.Contents, (file) => {\n if (_.startsWith(_.get(file, 'Key'), 'delayUntil/')) {\n const fileDelayTime = _.get(file, 'Key').split('/')[1];\n return dayjs(fileDelayTime, 'YYYYMMDDHHmm').isSameOrBefore(currentTime);\n }\n if (userImportTypes) {\n // look for items in the userImportTypes\n const usersImports = Object.values(userImportTypes);\n const items = file.Key.split('/');\n const fileName = _.last(items);\n const folderName = _.first(items);\n if (_.isEmpty(fileName)) {\n return false;\n\n } else if (usersImports.indexOf(folderName) === -1) {\n return false;\n }\n\n return !_.startsWith(file.Key, `${folderName}/error`);\n }\n return !_.startsWith(file.Key, 'error');\n });\n\n fileList = _.concat(fileList, newFiles);\n } while (bucketResult.IsTruncated && bucketResult.NextContinuationToken && fileList.length < maxKeys);\n\n return fileList;\n}\n\n/**\n * 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\n *\n * @param {string} configTable - The Dynamo DB table where to get the chunk-size and maxMessage size\n * @param {string} tableKey - The key to the item in the Dynamo DB table that holds the chunk-size and maxMessage size\n * @param {string} bucket - The name of the s3 bucket to watch, when you drop items into this table events will be created\n * @param {string} snsTopic - The name of the snsEvent to publish\n * @param {object} userImportTypes - import types to filter on\n */\nexport async function publishEvents(configTable, tableKey, bucket, snsTopic, userImportTypes) {\n let result;\n try {\n result = await dynamoUtil.get({\n TableName: configTable,\n Key: { key: tableKey }\n });\n } catch (e) {\n console.error(`Cannot get config for key: ${tableKey} table: ${configTable} falling back to defaults of 2 and 10`, e);\n }\n let chunkSize = _.get(result, 'Item.snsChunkSize', 2);\n let maxMessages = _.get(result, 'Item.snsMaxMessages', 10);\n\n const snsCreateTopicResponse = await SNSUtil.createTopic({ Name: snsTopic });\n const topicArn = snsCreateTopicResponse.TopicArn;\n const maxKeys = chunkSize * maxMessages;\n\n const fileList = await loop(bucket, maxKeys, userImportTypes);\n\n const messageList = _.chain(fileList)\n .map('Key')\n .chunk(chunkSize)\n .slice(0, maxMessages)\n .value()\n ;\n\n return Promise.map(messageList, (files) => {\n return SNSUtil.publish({\n Message: JSON.stringify({\n bucket: bucket,\n files: files\n }),\n TopicArn: topicArn\n });\n });\n}","import _ from 'lodash';\nimport { SequelizeStorage, Umzug } from 'umzug';\n\n/**\n * Execute database migrations\n * @param {string} databaseName - name of database to create (or verify existence)\n * @param {object} sequelizeInstance - instance of Sequelize (must be initialized)\n * @param {function} initializeModels - function to run to sync Sequelize models with database\n * @param {string} pathToMigrationFolder - pass in the path if using windows. windows and linux PWD will be different\n */\nexport async function runMigrations(databaseName,\n sequelizeInstance,\n initializeModels,\n pathToMigrationFolder = `${process.env.PWD}/migrations/*.js`) {\n const umzug = new Umzug({\n migrations: { glob: pathToMigrationFolder },\n context: sequelizeInstance.getQueryInterface(),\n storage: new SequelizeStorage({ sequelize: sequelizeInstance }),\n logger: console\n });\n\n const pendingMigrations = await umzug.pending();\n console.log('------->UTIL Pending Migrations:', pendingMigrations, pathToMigrationFolder);\n await umzug.up().catch((upError) => {\n console.error('Migration Error: ', upError);\n return umzug.down({\n migrations: _.chain(pendingMigrations)\n .map('file')\n .reverse()\n .value()\n }).then(() => {\n const msg = 'UTIL Error: Error with migrating up:' + upError;\n console.error(msg);\n throw new Error(msg);\n }, (downError) => {\n const msg = 'UTIL Error: Error with migrating down:' + downError;\n console.error(msg);\n throw new Error(msg);\n });\n });\n\n // The following line is needed to sync (create) tables, but not to database updates\n // in the past it worked to leave it in, but now the tags module causes foreign key problems\n // The tables are still initiated by being passed in to run migrations\n await initializeModels();\n}","import _ from 'lodash';\nimport S3Util from '../s3/S3Utils/S3Utils.js';\n\nexport async function handleFile(path, s3Bucket, transformer, options) {\n const shouldSkipFailedFolders = _.get(options, 'shouldSkipFailedFolders');\n const userImportTypes = _.get(options, 'userImportTypes');\n const params = {\n Bucket: s3Bucket,\n Key: path\n };\n let body;\n\n try {\n body = await S3Util.getObject(params);\n } catch (e) {\n if (e.Code === 'NoSuchKey' || e.code === 'NoSuchKey' || e.name === 'NoSuchKey') {\n return;\n }\n console.error('S3 getObject error:', e);\n throw e;\n }\n\n try {\n // exit early for null/undefined or blank string bodies\n if (_.isNil(body) || (_.isString(body) && _.isEmpty(body.trim()))) {\n await S3Util.deleteObject(params);\n return;\n }\n\n const parsedBody = JSON.parse(body);\n\n // exit early for objects like {} or []\n if (_.isEmpty(parsedBody)) {\n await S3Util.deleteObject(params);\n return;\n }\n\n const returnedValue = await transformer(parsedBody);\n await S3Util.deleteObject(params);\n\n return returnedValue;\n } catch (error) {\n console.error('HANDLE-FILE-ERROR', error);\n\n if (!body) {\n return;\n }\n\n let newPath = '';\n\n if (userImportTypes) {\n console.log('USER IMPORT');\n // look for items in the userImportTypes\n const usersImports = Object.values(userImportTypes);\n const items = path.split('/');\n const fileName = _.last(items);\n const folderName = _.first(items);\n\n if (usersImports.indexOf(folderName) > -1) {\n if (shouldSkipFailedFolders) {\n newPath = `${folderName}/error/${fileName}`;\n } else if (_.startsWith(path, `${folderName}/failed-once/`)) {\n newPath = _.replace(path, `${folderName}/failed-once/`, `${folderName}/failed-twice/`);\n } else if (_.startsWith(path, `${folderName}/failed-twice/`)) {\n newPath = _.replace(path, `${folderName}/failed-twice/`, `${folderName}/error/`);\n } else {\n newPath = `${folderName}/failed-once/${fileName}`;\n }\n } else {\n newPath = `pathAndEventMisMatchError/${path}`;\n }\n\n } else {\n if (shouldSkipFailedFolders) {\n newPath = `error/${path}`;\n } else if (_.startsWith(path, 'failed-once/')) {\n newPath = _.replace(path, 'failed-once/', 'failed-twice/');\n } else if (_.startsWith(path, 'failed-twice/')) {\n newPath = _.replace(path, 'failed-twice/', 'error/');\n } else {\n if (_.includes(path, 'delayUntil/')) {\n path = _.last(path.split('/'));\n }\n\n newPath = `failed-once/${path}`;\n }\n }\n\n const newParams = {\n Bucket: s3Bucket,\n Key: newPath,\n Body: body\n };\n\n if (\n containsError(newPath, 'failed-once') ||\n containsError(newPath, 'failed-twice') ||\n containsError(newPath, 'error')\n ) {\n throw new Error('NESTING ERROR');\n }\n\n await S3Util.putObject(newParams);\n await S3Util.deleteObject(params);\n\n throw error;\n }\n}\n\nexport function containsError(str, val) {\n const firstIndex = str.toLowerCase().indexOf(val);\n if (firstIndex === -1) return false;\n const secondIndex = str.toLowerCase().indexOf(val, firstIndex + 1);\n return secondIndex !== -1;\n}\n","import { S3 } from '@aws-sdk/client-s3';\n\nexport function s3Utils(action, params) {\n const s3 = new S3();\n return s3[action](params);\n}\n\nconst S3Util = {\n getObject: (params) => getS3(params),\n deleteObject: (params) => s3Utils('deleteObject', params),\n putObject: (params) => s3Utils('putObject', params),\n listObjectsV2: (params) => s3Utils('listObjectsV2', params)\n};\nexport default S3Util;\n\nasync function getS3(params) {\n const s3 = new S3();\n const response = await s3.getObject(params);\n return response?.Body.transformToString('utf-8');\n}","module.exports = require(\"umzug\");","module.exports = require(\"@aws-sdk/client-dynamodb\");","export const errorList = {\n invalidInventoryReleaseRequest: {\n message: 'NOT ENOUGH INVENTORY TO FULFILL RELEASE',\n errorCode: '4010',\n statusCode: 400\n },\n alreadyReleased: {\n message: 'ALREADY RELEASED',\n errorCode: '4011',\n statusCode: 400\n },\n alreadyReceived: {\n message: 'RECEIVABLE ALREADY RECEIVED',\n errorCode: '4012',\n statusCode: 400\n },\n invalidItemsRequest: {\n message: 'VALID ITEMS MUST BE INCLUDED',\n errorCode: '4013',\n statusCode: 400\n },\n invalidID: {\n message: 'ID is invalid',\n errorCode: '4014',\n statusCode: 400\n },\n invalidReceivable: {\n message: 'MUST CONTAIN AT LEAST ONE RECEIVABLE',\n errorCode: '4015',\n statusCode: 400\n },\n invalidRequest: {\n message: 'INVALID REQUEST DATA',\n errorCode: '4016',\n statusCode: 400\n },\n invalidAPIKey: {\n message: 'INVALID REQUEST - API MAY KEY INVALID',\n errorCode: '4017',\n statusCode: 400\n },\n qbCreationError: {\n message: 'QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS',\n errorCode: '4018',\n statusCode: 400\n },\n cannotReopen: {\n message: 'CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED',\n errorCode: '4018',\n statusCode: 400\n },\n invalidDateFormat: {\n message: 'INVALID DATE FORMAT',\n errorCode: '4019',\n statusCode: 400\n },\n invalidStartDate: {\n message: 'INVALID START DATE',\n errorCode: '4020',\n statusCode: 400\n },\n invalidEndDate: {\n message: 'INVALID END DATE',\n errorCode: '4021',\n statusCode: 400\n },\n invalidOrderStatus: {\n message: 'UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS',\n errorCode: '4022',\n statusCode: 400\n },\n invalidPaymentStatus: {\n message: 'UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN',\n errorCode: '4023',\n statusCode: 400\n },\n invalidReleaseStatus: {\n message: 'UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN',\n errorCode: '4024',\n statusCode: 400\n },\n invalidReceivableStatus: {\n message: 'UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN',\n errorCode: '40025',\n statusCode: 400\n },\n invalidJson:{\n message: 'INVALID JSON',\n errorCode: '4005',\n statusCode: 400\n },\n invalidFilter:{\n message: 'INVALID FILTER',\n errorCode: '4026',\n statusCode: 400\n },\n invalidUserNameUpdate:{\n message: 'UNABLE TO UPDATE USERNAME',\n errorCode: '4027',\n statusCode: 400\n },\n imageSizeLimit:{\n message: 'IMAGE SIZE LIMIT 100KB EXCEEDED',\n errorCode: '4028',\n statusCode: 400\n },\n unauthorized:{\n message: 'UNAUTHORIZED',\n errorCode: '4111',\n statusCode: 401\n },\n notFound:{\n message: 'ITEM NOT FOUND',\n errorCode: '4004',\n statusCode: 404\n },\n emailRequired:{\n message: 'NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL',\n errorCode: '4004',\n statusCode: 404\n },\n mobilePhoneRequired:{\n message: 'NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS',\n errorCode: '4004',\n statusCode: 404\n },\n invalidCadenceType: {\n message: 'INVALID CADENCE TYPE',\n errorCode: '5001',\n statusCode: 500\n },\n};","/**\n * create pagination object from Sequelize findAll\n * @param {object} result - sequelize result\n * @param {number} limit - max number of results to return\n * @param {number} offset - page offset\n */\nexport function getPaginationFromFindAll(result, limit, offset) {\n result = result || [];\n limit = limit || 0;\n offset = offset || 0;\n\n const hasMore = result.length > limit;\n if (hasMore) {\n result.splice(-1, 1);\n }\n const pageObject = {\n offset: offset,\n limit: limit,\n rows: result,\n hasMore: hasMore\n };\n\n return pageObject;\n}\n\n/**\n * wrapper for Sequelize findAll\n * @param {object} model - instance of Sequelize (must be initialized)\n * @param {*&{include: [{model: *}], where: {businessId: Array}, order: [string[]]}} options - instance of Sequelize (must be initialized)\n */\nexport async function findAll(model, options) {\n\n const limit = options.limit || 0;\n const includes = options.includes || { all: true, nested: true };\n const findArgs = Object.assign({include: includes}, options, { limit: limit + 1 });\n const results = await model.findAll(findArgs);\n return getPaginationFromFindAll(results, limit, options.offset);\n}\n\nconst findUtils = {\n findAll\n};\nexport default findUtils;","import _ from 'lodash';\n\n/**\n * Create sequelize includes array from query string parameters and default sequelize model\n *\n * @param {object} event - the query parameters from the event passed by lambda\n * @param {object} objectFilters - the default filters object created by createDefaultFilters\n * @returns {object} A sequelize includes array\n */\n\nexport function createIncludes(event, objectFilters) {\n const query = _.get(event, 'queryStringParameters', {}) || {};\n\n const keys = Object.keys(objectFilters);\n\n const canBeIncluded = keys.reduce((acc, item) => {\n acc = includeSubItem(item, acc);\n\n return acc;\n }, []);\n\n const askedForInQuery = Object.keys(query).reduce((acc, item) => {\n if (item === 'sort') {\n query[item].split(',').forEach((sortItem) => {\n sortItem = sortItem.indexOf('-') === 0 ? sortItem.substr(1) : sortItem;\n acc = includeSubItem(sortItem, acc);\n });\n }\n\n acc = includeSubItem(item, acc);\n\n return acc;\n }, []);\n\n return _.intersection(canBeIncluded, askedForInQuery);\n}\n\nexport function includeSubItem(queryStringItem, acc = []) {\n const dot = queryStringItem.indexOf('.');\n if (dot > 0) {\n acc.push(queryStringItem.substring(0, dot));\n }\n\n return acc;\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import { handleFile as handleFileImport } from './eventManager/handleFile.js';\nimport { watchBucket as watchBucketImport } from './eventManager/watchBucket.js';\nimport { publishEvents as publishEventsImport } from './eventManager/publishEvents.js';\nimport { createIncludes as createIncludesImport } from './database/dbUtils/queryStringUtils/createIncludes.js';\nimport { createFilters as createFiltersImport } from './database/dbUtils/queryStringUtils/createFilters.js';\nimport { createSort as createSortImport } from './database/dbUtils/queryStringUtils/createSort.js';\nimport { findAll as findAllImport } from './database/dbUtils/queryStringUtils/findAll.js';\nimport { checkModule as checkModuleImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { checkIsSuper as checkIsSuperImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getModuleInfo as getModuleInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getAccessRightsInfo as getAccessRightsInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getDefaultBusinessIDInfo as getDefaultBusinessIDInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { failure as failureImport, success as successImport } from './requestResponse/requestResponse.js';\nimport { runMigrations as runMigrationsImport } from './database/dbSetup/migrations.js';\nimport { getCurrentUser as getCurrentUserImport } from './requestResponse/requestResponse.js';\nimport { successHtml as successHtmlImport } from './requestResponse/requestResponse.js';\nimport { getCurrentUserNameFromCognitoEvent as getCurrentUserNameFromCognitoEventImport } from './requestResponse/requestResponse.js';\nimport { defaultFilters as defaultFiltersImport } from './database/dbUtils/queryStringUtils/defaultFilters.js';\nimport { accessRightsUtils as accessRightsUtilsImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { parseBody as parseBodyImport } from './requestResponse/requestResponse.js';\nimport { parseEvent as parseEventImport } from './requestResponse/requestResponse.js';\nimport { getBusinessesInfo as getBusinessesInfoImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { userDefaultBid as userDefaultBidImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { checkWriteAccess as checkWriteAccessImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { isSystemUser as isSystemUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { isSuperUser as isSuperUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { isPartnerUser as isPartnerUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getBelongsToPartnerId as getBelongsToPartnerIdImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { getEffectivePartnerId as getEffectivePartnerIdImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\nimport { enrichEventWithPartnerAccess as enrichEventWithPartnerAccessImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';\n\nexport const handleFile = handleFileImport;\nexport const watchBucket = watchBucketImport;\nexport const publishEvents = publishEventsImport;\nexport const createFilters = createFiltersImport;\nexport const createIncludes = createIncludesImport;\nexport const createSort = createSortImport;\nexport const findAll = findAllImport;\nexport const checkModule = checkModuleImport;\nexport const checkIsSuper = checkIsSuperImport;\nexport const getAccessRightsInfo = getAccessRightsInfoImport;\nexport const getDefaultBusinessIDInfo = getDefaultBusinessIDInfoImport;\nexport const getModuleInfo = getModuleInfoImport;\nexport const failure = failureImport;\nexport const success = successImport;\nexport const runMigrations = runMigrationsImport;\nexport const getCurrentUser = getCurrentUserImport;\nexport const successHtml = successHtmlImport;\nexport const getCurrentUserNameFromCognitoEvent = getCurrentUserNameFromCognitoEventImport;\nexport const defaultFilters = defaultFiltersImport;\nexport const accessRightsUtils = accessRightsUtilsImport;\nexport const parseBody = parseBodyImport;\nexport const parseEvent = parseEventImport;\nexport const getBusinessesInfo = getBusinessesInfoImport;\nexport const userDefaultBid = userDefaultBidImport;\nexport const checkWriteAccess = checkWriteAccessImport;\nexport const isSystemUser = isSystemUserImport;\nexport const isSuperUser = isSuperUserImport;\nexport const isPartnerUser = isPartnerUserImport;\nexport const getBelongsToPartnerId = getBelongsToPartnerIdImport;\nexport const getEffectivePartnerId = getEffectivePartnerIdImport;\nexport const enrichEventWithPartnerAccess = enrichEventWithPartnerAccessImport;\n"],"names":["module","exports","require","_libDynamodb","_clientDynamodb","dynamoUtil","get","params","async","DynamoDBDocument","from","DynamoDB","handleDirectS3WriteEvent","event","transformer","errorHandlerPerFile","shouldSkipFailedFolders","userImportTypes","Records","Promise","resolve","hasErrors","map","record","s3Bucket","s3","bucket","name","file","object","key","path","decodeURIComponent","handleFile","catch","err","console","error","then","Error","handleEvents","snsInfo","JSON","parse","_","files","_handleFile","_lodash","_interopRequireDefault","_bluebird","e","__esModule","default","watchBucket","noop","dynamoConfigTable","dynamoConfigKey","snsTopic","EventSource","isEqual","publishEvents","failedOnce","failedTwice","direct","startsWithDirect","startsWith","includes","log","_publishEvents","_handleEvents","defaultFilters","schema","subSchemas","clone","filters","addFiltersFromSchema","Object","keys","forEach","_sequelize","keyPrefix","asLinkAlias","reduce","acc","item","type","DB","STRING","filterType","Op","eq","itemType","CHAR","TEXT","iLike","DECIMAL","INTEGER","BIGINT","or","BOOLEAN","JSONB","field","DATE","between","DATEONLY","_dayjs","_utc","_errorCodes","_accessRightsUtils","dayjs","extend","utc","objectFilters","query","searchString","startDate","endDate","caseInsensitiveConditions","where","val","itemName","push","fn","col","like","toLowerCase","in","split","parsedJson","queryValue","booleanMap","length","and","active","filterAdds","businessId","accessRightsUtils","s","dates","toDate","isValid","errorList","invalidStartDate","invalidEndDate","createdAt","adds","dataType","isNaN","Number","newOr","withDate","assign","k","def","prefix","qKey","pathParts","substring","value","parsed","Array","isArray","addJsonbConditions","obj","entries","currentPath","String","_clientSns","SNSUtil","publish","sns","SNS","createTopic","checkIsSuper","isSuperUser","isSystemUser","process","env","BUILD_ENV","unauthorized","checkModule","moduleName","moduleRights","getModuleInfo","allowAccess","checkWriteAccess","options","eventBody","parseBody","find","id","userRight","getBusinessesInfo","userRoles","admin","write","enrichEventWithPartnerAccess","partnerBusinessIds","role","arPath","requestContext","authorizer","claims","json","accessRights","businessIds","bid","set","stringify","getAccessRightsInfo","jsonToParse","getDefaultBusinessIDInfo","dbi","getEffectivePartnerId","isPartnerUser","getBelongsToPartnerId","userDefaultBid","_interopRequireWildcard","t","WeakMap","r","n","o","i","f","__proto__","has","hasOwnProperty","call","defineProperty","getOwnPropertyDescriptor","_requestResponse","isSys","useCognitoBid","requestedBusinessIds","getRequestedBusinessIds","allowedBusinessIds","getAllowedBusinessIds","businesses","v","isEmpty","intersection","body","bodyBid","b","read","defaultFilter","copyOfDefaultFilter","testItem","indexOf","substr","sortItem","parentChildList","detectDynamooseError","errorBody","dynamooseError","errors","message","detail","trim","failure","cleanedErrorBody","dbClose","UTIL_LOG","isObject","isUndefined","details","errorCode","statusCode","detectSequelizeError","detectJoyError","newBody","merge","buildResponse","getCurrentUser","username","getCurrentUserNameFromCognitoEvent","attributes","requestEvent","isString","invalidJson","parseEvent","callback","success","successHtml","html","headers","htmlSecurityHeaders","securityHeaders","join","errorName","fields","filter","Boolean","messages","sequelizeError","parentError","joyError","contextItem","msg","configTable","tableKey","result","TableName","Key","chunkSize","maxMessages","topicArn","Name","TopicArn","maxKeys","fileList","loop","messageList","chain","chunk","slice","Message","_customParseFormat","_isSameOrBefore","_S3Utils","_SNSUtils","_dynamoUtils","bucketResult","currentTime","S3Utils","listObjectsV2","Bucket","MaxKeys","ContinuationToken","newFiles","Contents","fileDelayTime","isSameOrBefore","usersImports","values","items","fileName","last","folderName","first","concat","IsTruncated","NextContinuationToken","customParseFormat","runMigrations","databaseName","sequelizeInstance","initializeModels","pathToMigrationFolder","PWD","umzug","Umzug","migrations","glob","context","getQueryInterface","storage","SequelizeStorage","sequelize","logger","pendingMigrations","pending","up","upError","down","reverse","downError","_umzug","S3Util","getObject","Code","code","isNil","deleteObject","parsedBody","returnedValue","newPath","replace","newParams","Body","containsError","putObject","str","firstIndex","_clientS","s3Utils","action","S3","getS3","response","transformToString","invalidInventoryReleaseRequest","alreadyReleased","alreadyReceived","invalidItemsRequest","invalidID","invalidReceivable","invalidRequest","invalidAPIKey","qbCreationError","cannotReopen","invalidDateFormat","invalidOrderStatus","invalidPaymentStatus","invalidReleaseStatus","invalidReceivableStatus","invalidFilter","invalidUserNameUpdate","imageSizeLimit","notFound","emailRequired","mobilePhoneRequired","invalidCadenceType","getPaginationFromFindAll","limit","offset","hasMore","splice","rows","findAll","model","all","nested","findArgs","include","findUtils","createIncludes","canBeIncluded","includeSubItem","askedForInQuery","queryStringItem","dot","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","_watchBucket","_createIncludes","_createFilters","_createSort","_findAll","_migrations","_defaultFilters","handleFileImport","watchBucketImport","publishEventsImport","createFiltersImport","createIncludesImport","createSortImport","findAllImport","checkModuleImport","checkIsSuperImport","getAccessRightsInfoImport","getDefaultBusinessIDInfoImport","getModuleInfoImport","failureImport","successImport","runMigrationsImport","getCurrentUserImport","successHtmlImport","getCurrentUserNameFromCognitoEventImport","defaultFiltersImport","accessRightsUtilsImport","parseBodyImport","parseEventImport","getBusinessesInfoImport","userDefaultBidImport","checkWriteAccessImport","isSystemUserImport","isSuperUserImport","isPartnerUserImport","getBelongsToPartnerIdImport","getEffectivePartnerIdImport","enrichEventWithPartnerAccessImport"],"ignoreList":[],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "piper-utils",
3
- "version": "1.1.54",
3
+ "version": "1.1.56",
4
4
  "description": "Utility library for Piper",
5
5
  "main": "bin/main.js",
6
6
  "scripts": {
@@ -45,10 +45,6 @@
45
45
  "sequelize": ">=6.6.2",
46
46
  "umzug": ">=3.2.1"
47
47
  },
48
- "peerDependenciesMeta": {
49
- "sequelize": { "optional": true },
50
- "umzug": { "optional": true }
51
- },
52
48
  "nyc": {
53
49
  "require": [
54
50
  "@babel/register"
@@ -235,6 +235,74 @@ export const userRoles = {
235
235
  write: 'W'
236
236
  };
237
237
 
238
+ /**
239
+ * Get the partner ID from custom:PID if the user is a partner admin.
240
+ *
241
+ * @param {object} event - The lambda event passed in by a validated api request.
242
+ * @returns {string|false} The partner ID or false if not a partner user.
243
+ */
244
+ export function isPartnerUser(event) {
245
+ const partnerId = _.get(event, 'requestContext.authorizer.claims.custom:PID') ||
246
+ _.get(event, 'requestContext.authorizer.custom:PID') ||
247
+ '';
248
+ return partnerId || false;
249
+ }
250
+
251
+ /**
252
+ * Get the partner ID from custom:BPID if the user's business belongs to a partner.
253
+ *
254
+ * @param {object} event - The lambda event passed in by a validated api request.
255
+ * @returns {string|false} The partner ID or false if not associated with a partner.
256
+ */
257
+ export function getBelongsToPartnerId(event) {
258
+ const partnerId = _.get(event, 'requestContext.authorizer.claims.custom:BPID') ||
259
+ _.get(event, 'requestContext.authorizer.custom:BPID') ||
260
+ '';
261
+ return partnerId || false;
262
+ }
263
+
264
+ /**
265
+ * Get the effective partner ID from either custom:PID or custom:BPID.
266
+ *
267
+ * @param {object} event - The lambda event passed in by a validated api request.
268
+ * @returns {string|false} The partner ID or false.
269
+ */
270
+ export function getEffectivePartnerId(event) {
271
+ return isPartnerUser(event) || getBelongsToPartnerId(event);
272
+ }
273
+
274
+ /**
275
+ * Enrich the event's custom:AR with partner business IDs in-memory.
276
+ * Call this BEFORE accessRightsUtils() or getBusinessesInfo() so that
277
+ * partner admins (custom:PID) get access to their partner's merchants.
278
+ *
279
+ * This keeps accessRightsUtils synchronous — the DB lookup is done by the caller.
280
+ *
281
+ * @param {object} event - The lambda event passed in by a validated api request.
282
+ * @param {string[]} partnerBusinessIds - Array of business IDs from the partner record.
283
+ * @param {string} [role='R'] - Access role to assign (default: Read).
284
+ */
285
+ export function enrichEventWithPartnerAccess(event, partnerBusinessIds, role = 'R') {
286
+ if (!partnerBusinessIds || partnerBusinessIds.length === 0) return;
287
+
288
+ const arPath = event?.requestContext?.authorizer?.claims
289
+ ? 'requestContext.authorizer.claims.custom:AR'
290
+ : 'requestContext.authorizer.custom:AR';
291
+
292
+ const json = _.get(event, arPath) || '{}';
293
+ const accessRights = JSON.parse(json);
294
+ const businessIds = accessRights.businessIds || {};
295
+
296
+ for (const bid of partnerBusinessIds) {
297
+ if (!businessIds[bid]) {
298
+ businessIds[bid] = role;
299
+ }
300
+ }
301
+
302
+ accessRights.businessIds = businessIds;
303
+ _.set(event, arPath, JSON.stringify(accessRights));
304
+ }
305
+
238
306
  /**
239
307
  * @param {{body: string}} event
240
308
  * @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.
package/src/index.js CHANGED
@@ -24,6 +24,10 @@ import { userDefaultBid as userDefaultBidImport } from './database/dbUtils/query
24
24
  import { checkWriteAccess as checkWriteAccessImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
25
25
  import { isSystemUser as isSystemUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
26
26
  import { isSuperUser as isSuperUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
27
+ import { isPartnerUser as isPartnerUserImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
28
+ import { getBelongsToPartnerId as getBelongsToPartnerIdImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
29
+ import { getEffectivePartnerId as getEffectivePartnerIdImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
30
+ import { enrichEventWithPartnerAccess as enrichEventWithPartnerAccessImport } from './database/dbUtils/queryStringUtils/accessRightsUtils.js';
27
31
 
28
32
  export const handleFile = handleFileImport;
29
33
  export const watchBucket = watchBucketImport;
@@ -52,3 +56,7 @@ export const userDefaultBid = userDefaultBidImport;
52
56
  export const checkWriteAccess = checkWriteAccessImport;
53
57
  export const isSystemUser = isSystemUserImport;
54
58
  export const isSuperUser = isSuperUserImport;
59
+ export const isPartnerUser = isPartnerUserImport;
60
+ export const getBelongsToPartnerId = getBelongsToPartnerIdImport;
61
+ export const getEffectivePartnerId = getEffectivePartnerIdImport;
62
+ export const enrichEventWithPartnerAccess = enrichEventWithPartnerAccessImport;
@@ -1,6 +1,35 @@
1
1
  import _ from 'lodash';
2
2
  import { errorList } from './errorCodes.js';
3
3
 
4
+ const securityHeaders = {
5
+ 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
6
+ 'X-Content-Type-Options': 'nosniff',
7
+ 'X-Frame-Options': 'DENY',
8
+ 'Referrer-Policy': 'strict-origin-when-cross-origin',
9
+ 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
10
+ 'Cache-Control': 'no-store',
11
+ 'Content-Security-Policy': "default-src 'none'; frame-ancestors 'none'"
12
+ };
13
+
14
+ const htmlSecurityHeaders = {
15
+ 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
16
+ 'X-Content-Type-Options': 'nosniff',
17
+ 'X-Frame-Options': 'DENY',
18
+ 'Referrer-Policy': 'strict-origin-when-cross-origin',
19
+ 'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
20
+ 'Cache-Control': 'no-store',
21
+ 'Content-Security-Policy': [
22
+ "default-src 'self'",
23
+ "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",
24
+ "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
25
+ "font-src 'self' https://fonts.gstatic.com",
26
+ "frame-src https:",
27
+ "connect-src 'self' https://*.tokenex.com https://*.sentry.io https://*.nmi.com",
28
+ "img-src 'self' data:",
29
+ "frame-ancestors 'none'"
30
+ ].join('; ')
31
+ };
32
+
4
33
  /**
5
34
  * @param {Object} body
6
35
  * @param {{dbClose?:function}} [options]
@@ -25,7 +54,8 @@ export function successHtml(html, options) {
25
54
  headers: {
26
55
  'Content-Type': 'text/html',
27
56
  'Access-Control-Allow-Origin': '*',
28
- 'Access-Control-Allow-Credentials': true
57
+ 'Access-Control-Allow-Credentials': true,
58
+ ...htmlSecurityHeaders
29
59
  },
30
60
  body: html
31
61
  };
@@ -90,7 +120,9 @@ export function failure(body = {}, options) {
90
120
  if (_.get(body, 'response.data.message')) {
91
121
  const err = _.get(body, 'response.data.message');
92
122
  if (_.isObject(body)) {
93
- console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));
123
+ if (process.env.UTIL_LOG === 'LOG_ALL' || process.env.BUILD_ENV === 'test') {
124
+ console.error('------->MSG UTIL ERROR:', JSON.stringify(err, null, 2));
125
+ }
94
126
  }
95
127
  }
96
128
  const newBody = _.merge(NORMAL_ERROR, cleanedErrorBody);
@@ -110,7 +142,8 @@ function buildResponse(statusCode, body) {
110
142
  statusCode: statusCode,
111
143
  headers: {
112
144
  'Access-Control-Allow-Origin': '*',
113
- 'Access-Control-Allow-Credentials': true
145
+ 'Access-Control-Allow-Credentials': true,
146
+ ...securityHeaders
114
147
  },
115
148
  body: JSON.stringify(body)
116
149
  };
@@ -7,12 +7,14 @@ describe('requestResponse', () => {
7
7
  describe('success', () => {
8
8
  it('should return 200', () => {
9
9
  const res = success({ foo: 'bar' }, {});
10
- expect(res).toEqual({
11
- statusCode: 200, headers: {
12
- 'Access-Control-Allow-Origin': '*',
13
- 'Access-Control-Allow-Credentials': true
14
- }, body: '{"foo":"bar"}'
15
- });
10
+ expect(res.statusCode).toEqual(200);
11
+ expect(res.body).toEqual('{"foo":"bar"}');
12
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
13
+ expect(res.headers['Access-Control-Allow-Credentials']).toEqual(true);
14
+ expect(res.headers['Strict-Transport-Security']).toEqual('max-age=31536000; includeSubDomains');
15
+ expect(res.headers['X-Content-Type-Options']).toEqual('nosniff');
16
+ expect(res.headers['X-Frame-Options']).toEqual('DENY');
17
+ expect(res.headers['Content-Security-Policy']).toBeDefined();
16
18
  });
17
19
  });
18
20
  describe('success', () => {
@@ -30,13 +32,15 @@ describe('requestResponse', () => {
30
32
  describe('successHtml', () => {
31
33
  it('should return 200', () => {
32
34
  const res = successHtml('<html>test</html>', {});
33
- expect(res).toEqual({
34
- statusCode: 200, headers: {
35
- 'Content-Type': 'text/html',
36
- 'Access-Control-Allow-Origin': '*',
37
- 'Access-Control-Allow-Credentials': true
38
- }, body: '<html>test</html>'
39
- });
35
+ expect(res.statusCode).toEqual(200);
36
+ expect(res.body).toEqual('<html>test</html>');
37
+ expect(res.headers['Content-Type']).toEqual('text/html');
38
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
39
+ expect(res.headers['Access-Control-Allow-Credentials']).toEqual(true);
40
+ expect(res.headers['Strict-Transport-Security']).toEqual('max-age=31536000; includeSubDomains');
41
+ expect(res.headers['X-Content-Type-Options']).toEqual('nosniff');
42
+ expect(res.headers['X-Frame-Options']).toEqual('DENY');
43
+ expect(res.headers['Content-Security-Policy']).toContain("script-src");
40
44
  });
41
45
  it('should call dbclose', () => {
42
46
  const options = {
@@ -103,40 +107,32 @@ describe('requestResponse', () => {
103
107
  describe('failure', () => {
104
108
  it('should return an error', () => {
105
109
  const res = failure({ foo: 'bar' }, {});
106
- expect(res).toEqual({
107
- statusCode: 500, headers: {
108
- 'Access-Control-Allow-Origin': '*',
109
- 'Access-Control-Allow-Credentials': true
110
- }, body: '{"statusCode":500,"errorCode":"5XX","message":""}'
111
- });
110
+ expect(res.statusCode).toEqual(500);
111
+ expect(res.body).toEqual('{"statusCode":500,"errorCode":"5XX","message":""}');
112
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
113
+ expect(res.headers['Strict-Transport-Security']).toEqual('max-age=31536000; includeSubDomains');
114
+ expect(res.headers['X-Content-Type-Options']).toEqual('nosniff');
112
115
  });
113
116
  it('should look for errors in details return an error', () => {
114
117
  const res = failure({ details: 'bar' }, {});
115
-
116
- expect(res).toEqual({
117
- statusCode: 400, headers: {
118
- 'Access-Control-Allow-Origin': '*',
119
- 'Access-Control-Allow-Credentials': true
120
- }, body: '{"statusCode":400,"errorCode":"4000","message":"INTERNAL UTIL ERROR"}'
121
- });
118
+ expect(res.statusCode).toEqual(400);
119
+ expect(res.body).toEqual('{"statusCode":400,"errorCode":"4000","message":"INTERNAL UTIL ERROR"}');
120
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
121
+ expect(res.headers['X-Frame-Options']).toEqual('DENY');
122
122
  });
123
123
  it('should deal with error code on body, but no details', () => {
124
124
  const res = failure({ errorCode: 333 }, {});
125
- expect(res).toEqual({
126
- statusCode: 500, headers: {
127
- 'Access-Control-Allow-Origin': '*',
128
- 'Access-Control-Allow-Credentials': true
129
- }, body: '{"statusCode":500,"errorCode":"5XX","message":""}'
130
- });
125
+ expect(res.statusCode).toEqual(500);
126
+ expect(res.body).toEqual('{"statusCode":500,"errorCode":"5XX","message":""}');
127
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
128
+ expect(res.headers['Content-Security-Policy']).toBeDefined();
131
129
  });
132
130
  it('should no details and no codes', () => {
133
131
  const res = failure({ errorCode: 333, statusCode: 222 }, {});
134
- expect(res).toEqual({
135
- statusCode: 222, headers: {
136
- 'Access-Control-Allow-Origin': '*',
137
- 'Access-Control-Allow-Credentials': true
138
- }, body: '{"statusCode":222,"errorCode":333,"message":"INTERNAL UTIL ERROR"}'
139
- });
132
+ expect(res.statusCode).toEqual(222);
133
+ expect(res.body).toEqual('{"statusCode":222,"errorCode":333,"message":"INTERNAL UTIL ERROR"}');
134
+ expect(res.headers['Access-Control-Allow-Origin']).toEqual('*');
135
+ expect(res.headers['Referrer-Policy']).toEqual('strict-origin-when-cross-origin');
140
136
  });
141
137
  });
142
138
  describe('parseBody', () => {