piper-utils 1.1.65 → 1.1.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/main.js +414 -2
- package/bin/main.js.map +1 -1
- package/package.json +1 -1
- package/src/audit/audit.js +422 -0
- package/src/audit/audit.test.js +313 -0
- package/src/database/dbUtils/partnerAccess/accessContext.js +70 -0
- package/src/database/dbUtils/partnerAccess/accessGates.js +34 -0
- package/src/database/dbUtils/partnerAccess/accessScope.js +99 -0
- package/src/database/dbUtils/partnerAccess/accessWrites.js +128 -0
- package/src/database/dbUtils/partnerAccess/createAccessHelpers.js +38 -0
- package/src/index.js +98 -64
- package/src/requestResponse/errorCodes.js +5 -0
package/bin/main.js
CHANGED
|
@@ -7,6 +7,35 @@
|
|
|
7
7
|
/***/},
|
|
8
8
|
/***/59(module){module.exports=require("dayjs/plugin/customParseFormat");
|
|
9
9
|
/***/},
|
|
10
|
+
/***/62(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.ensurePartnerScope=
|
|
11
|
+
/**
|
|
12
|
+
* Lazy-load partner scope from Dynamo. Populates partnerBusinessId and
|
|
13
|
+
* businessIds on the access object, then caches for the request lifetime.
|
|
14
|
+
*
|
|
15
|
+
* No-op for non-partner access objects or if already loaded.
|
|
16
|
+
*
|
|
17
|
+
* @param {object} access - Access object from resolveAccess.
|
|
18
|
+
* @param {{ getPartnerById: Function }} deps - Injected so piper-utils stays DB-agnostic.
|
|
19
|
+
* @returns {object} The same access object, now populated.
|
|
20
|
+
*/
|
|
21
|
+
async function ensurePartnerScope(access,{getPartnerById}){if(!access||"partner"!==access.level)return access;if(null!==access.businessIds&&void 0!==access.businessIds)return access;try{const partner=await getPartnerById(access.partnerId);access.businessIds=partner?.businessIds||[],access.partnerBusinessId=partner?.partnerBusinessId||null}catch(err){console.error("partnerAccess: failed to load partner for scoping:",err),access.businessIds=[],access.partnerBusinessId=null}return access}
|
|
22
|
+
/***/,exports.resolveAccess=
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the caller's access level from the Lambda event.
|
|
25
|
+
* Synchronous — reads JWT claims only, no Dynamo lookups.
|
|
26
|
+
*
|
|
27
|
+
* Returns an access object:
|
|
28
|
+
* { level: 'global' } — super user or local/test env
|
|
29
|
+
* { level: 'partner', partnerId, partnerBusinessId: null, businessIds: null }
|
|
30
|
+
* { level: 'standard', businessIds: string[] }
|
|
31
|
+
*
|
|
32
|
+
* Partner fields (partnerBusinessId, businessIds) start null and are
|
|
33
|
+
* lazy-loaded by ensurePartnerScope on first use.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} event - Lambda event with Cognito authorizer claims.
|
|
36
|
+
* @returns {object} Access object.
|
|
37
|
+
*/
|
|
38
|
+
function resolveAccess(event){if((0,_accessRightsUtils.isSuperUser)(event))return{level:"global"};const env=process.env.BUILD_ENV;if("local"===env||"test"===env)return{level:"global"};const partnerId=(0,_accessRightsUtils.isPartnerUser)(event);if(partnerId)return{level:"partner",partnerId,partnerBusinessId:null,businessIds:null};const arBusinessIds=(0,_accessRightsUtils.getAccessRightsInfo)(event),businessIds=Object.keys(arBusinessIds);if(businessIds.length>0)return{level:"standard",businessIds};throw _errorCodes.errorList.unauthorized};var _accessRightsUtils=__webpack_require__(673),_errorCodes=__webpack_require__(953)},
|
|
10
39
|
/***/64(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _libDynamodb=__webpack_require__(515),_clientDynamodb=__webpack_require__(929);const dynamoUtil={get:params=>
|
|
11
40
|
/**
|
|
12
41
|
* @param {{TableName:string, Key:{key:string}}} params
|
|
@@ -17,6 +46,307 @@ async function get(params){return _libDynamodb.DynamoDBDocument.from(new _client
|
|
|
17
46
|
/***/,exports.handleEvents=function handleEvents(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders=!1,userImportTypes){if(!event||!event.Records)return _bluebird.default.resolve();let hasErrors=!1;return _bluebird.default.map(event.Records,record=>{const snsInfo=JSON.parse(_lodash.default.get(record,"Sns.Message","{}")),s3Bucket=snsInfo.bucket,files=snsInfo.files||[];return _bluebird.default.map(files,file=>{let path=decodeURIComponent(file);if(path)return(0,_handleFile.handleFile)(path,s3Bucket,transformer,{shouldSkipFailedFolders,userImportTypes}).catch(err=>{errorHandlerPerFile&&!errorHandlerPerFile(err,path)&&(console.error("HANDLE-FILE-CATCH: ",err),hasErrors=!0)})})}).then(()=>{if(hasErrors)throw new Error("ERROR: HANDLE-FILE")})};var _handleFile=__webpack_require__(876),_lodash=_interopRequireDefault(__webpack_require__(825)),_bluebird=_interopRequireDefault(__webpack_require__(564));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},
|
|
18
47
|
/***/137(module){module.exports=require("dayjs/plugin/utc.js");
|
|
19
48
|
/***/},
|
|
49
|
+
/***/165(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.assertCanWriteBookBusiness=
|
|
50
|
+
/**
|
|
51
|
+
* Assert the caller can write to a business in their portfolio.
|
|
52
|
+
* For partner: businessId must be in the businessIds array.
|
|
53
|
+
*
|
|
54
|
+
* global → allow
|
|
55
|
+
* standard → allow (handled elsewhere via checkWriteAccess)
|
|
56
|
+
* partner → businessId must be in portfolio; throws if not
|
|
57
|
+
*
|
|
58
|
+
* @param {object} access - Access object from resolveAccess.
|
|
59
|
+
* @param {string} businessId - The businessId being written to.
|
|
60
|
+
* @param {{ getPartnerById: Function }} deps
|
|
61
|
+
*/
|
|
62
|
+
async function assertCanWriteBookBusiness(access,businessId,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return;if("standard"===access.level)return;if("partner"===access.level){if(!businessId)throw{..._errorCodes.errorList.invalidRequest,message:"businessId is required"};if(await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById}),!(access.businessIds||[]).includes(businessId))throw _errorCodes.errorList.unauthorized;return}throw _errorCodes.errorList.unauthorized}
|
|
63
|
+
/**
|
|
64
|
+
* Assert the caller can write to a business in the union of own + portfolio.
|
|
65
|
+
* For partner: businessId must be partnerBusinessId OR in businessIds[].
|
|
66
|
+
* Used by ticket write paths.
|
|
67
|
+
*
|
|
68
|
+
* global → allow
|
|
69
|
+
* standard → allow (handled elsewhere via checkWriteAccess)
|
|
70
|
+
* partner → businessId must be in [partnerBusinessId, ...businessIds]
|
|
71
|
+
*
|
|
72
|
+
* @param {object} access - Access object from resolveAccess.
|
|
73
|
+
* @param {string} businessId - The businessId being written to.
|
|
74
|
+
* @param {{ getPartnerById: Function }} deps
|
|
75
|
+
*/,exports.assertCanWriteBookUnionOwn=async function assertCanWriteBookUnionOwn(access,businessId,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return;if("standard"===access.level)return;if("partner"===access.level){if(!businessId)throw{..._errorCodes.errorList.invalidRequest,message:"businessId is required"};await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById});if(!_lodash.default.uniq([access.partnerBusinessId,...access.businessIds||[]].filter(Boolean)).includes(businessId))throw _errorCodes.errorList.unauthorized;return}throw _errorCodes.errorList.unauthorized}
|
|
76
|
+
/**
|
|
77
|
+
* Auto-stamp body.businessId from the partner's own business if missing.
|
|
78
|
+
* No-op for non-partner users or if body.businessId is already set.
|
|
79
|
+
*
|
|
80
|
+
* @param {object} access - Access object from resolveAccess.
|
|
81
|
+
* @param {object} body - Request body to mutate.
|
|
82
|
+
* @param {{ getPartnerById: Function }} deps
|
|
83
|
+
*/,exports.assertCanWriteOwnBusiness=
|
|
84
|
+
/**
|
|
85
|
+
* Assert the caller can write to their own business.
|
|
86
|
+
* For partner: businessId must equal partnerBusinessId.
|
|
87
|
+
*
|
|
88
|
+
* global → allow
|
|
89
|
+
* partner → businessId must equal partnerBusinessId; throws if not
|
|
90
|
+
* standard → throws (CRM routes gate standard users before reaching this)
|
|
91
|
+
*
|
|
92
|
+
* @param {object} access - Access object from resolveAccess.
|
|
93
|
+
* @param {string} businessId - The businessId being written to.
|
|
94
|
+
* @param {{ getPartnerById: Function }} deps
|
|
95
|
+
*/
|
|
96
|
+
async function assertCanWriteOwnBusiness(access,businessId,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return;if("partner"===access.level){if(await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById}),!access.partnerBusinessId)throw{..._errorCodes.errorList.partnerNotConfigured};if(businessId!==access.partnerBusinessId)throw _errorCodes.errorList.unauthorized;return}throw _errorCodes.errorList.unauthorized},exports.stampOwnBusinessId=async function stampOwnBusinessId(access,body,{getPartnerById}={}){if(!access||"partner"!==access.level)return;if(body.businessId)return;await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById}),body.businessId=access.partnerBusinessId}
|
|
97
|
+
/***/;var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825)),_accessContext=__webpack_require__(62),_errorCodes=__webpack_require__(953)},
|
|
98
|
+
/***/179(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.attachAudit=
|
|
99
|
+
/**
|
|
100
|
+
* Define a sibling `<ModelName>Audit` table for the given Sequelize model and
|
|
101
|
+
* wire the four lifecycle hooks (`afterCreate`, `afterUpsert`, `afterUpdate`,
|
|
102
|
+
* `afterDestroy`) that record changes into it.
|
|
103
|
+
*
|
|
104
|
+
* Call this **once per model at boot time** from inside the model's
|
|
105
|
+
* `dbSetup()` function. It is idempotent — calling it again for a model that
|
|
106
|
+
* already has an audit table attached is a no-op.
|
|
107
|
+
*
|
|
108
|
+
* The audit table has no foreign key into any user table; the username of the
|
|
109
|
+
* person who made the change is stamped onto each row from the JWT (set by
|
|
110
|
+
* {@link bindAuditRequest}). This keeps the audit util portable across domain
|
|
111
|
+
* services that own different user models.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // src/customer/customer.js
|
|
115
|
+
* Customer.dbSetup = async function () {
|
|
116
|
+
* await attachAudit(Customer);
|
|
117
|
+
* };
|
|
118
|
+
*
|
|
119
|
+
* @param {import('sequelize').ModelStatic<any>} model the Sequelize model to audit
|
|
120
|
+
* @returns {Promise<void>} resolves when the audit table's `sync()` completes
|
|
121
|
+
* @see {@link bindAuditRequest} - per-request setup that turns audit on
|
|
122
|
+
* @see {@link getAuditModel} - retrieve the audit model from the parent
|
|
123
|
+
* @see {@link getAuditFilter} - build a filter for an audit history query
|
|
124
|
+
*/
|
|
125
|
+
async function attachAudit(model){if(auditModels[model.name])return;const auditModel=model.sequelize.define(model.name+"Audit",function getAuditSchema(model){const DataTypes=model.sequelize.Sequelize;return{field:{type:DataTypes.STRING,allowNull:!1},type:DataTypes.STRING,valueOld:DataTypes.STRING,valueNew:DataTypes.STRING,changedByUser:{type:DataTypes.STRING,allowNull:!1},businessId:{type:DataTypes.STRING,allowNull:!1}}}
|
|
126
|
+
/**
|
|
127
|
+
* Internal hook factory. Returns the async function that Sequelize invokes on
|
|
128
|
+
* each create/upsert/update/destroy. Reads its per-request state from
|
|
129
|
+
* {@link modelOptions}; emits zero rows when audit is disabled for the model.
|
|
130
|
+
*
|
|
131
|
+
* Sensitive fields inside JSON values (token, password, secret, key,
|
|
132
|
+
* credential, auth, securityCode, cvv, pin, ssn) are masked as
|
|
133
|
+
* `***************` before being persisted. String values longer than 255
|
|
134
|
+
* characters are truncated.
|
|
135
|
+
*
|
|
136
|
+
* Exported only so tests can drive the hook directly. Application code should
|
|
137
|
+
* never call this — use {@link attachAudit}.
|
|
138
|
+
*
|
|
139
|
+
* @param {string} modelName name of the parent Sequelize model
|
|
140
|
+
* @returns {(modelInfo: any, options: { type?: string, transaction?: import('sequelize').Transaction }) => Promise<void>}
|
|
141
|
+
* the hook function Sequelize will call on each lifecycle event
|
|
142
|
+
*/(model),{updatedAt:!1,freezeTableName:!0});return auditModel.belongsTo(model,{foreignKey:{allowNull:!0},onDelete:"SET NULL"}),auditModels[model.name]=auditModel,model.addHook("afterCreate",auditMe(model.name)),model.addHook("afterUpsert",auditMe(model.name)),model.addHook("afterUpdate",auditMe(model.name)),model.addHook("afterDestroy",auditMe(model.name)),auditModel.sync()}
|
|
143
|
+
/**
|
|
144
|
+
* Bind per-request audit context for one or more models. Call this **once at
|
|
145
|
+
* the top of each route handler** that mutates an audited model.
|
|
146
|
+
*
|
|
147
|
+
* Resolves the acting user from the JWT claims on the event
|
|
148
|
+
* (via {@link getCurrentUser}) and reads the company `auditEnabled` flag from
|
|
149
|
+
* the `custom:SET` claim (via {@link getCompanySettings}). If the company has
|
|
150
|
+
* `auditEnabled: false` then no rows will be written for the bound models on
|
|
151
|
+
* this request.
|
|
152
|
+
*
|
|
153
|
+
* Audit is **off by default** for any model that has not been bound this
|
|
154
|
+
* request — a route that omits this call writes no audit rows.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* // src/customer/customerRoutes.js
|
|
158
|
+
* export async function updateCustomer(event) {
|
|
159
|
+
* checkModule('customer', event);
|
|
160
|
+
* const businessId = checkWriteAccess(event);
|
|
161
|
+
* bindAuditRequest(event, businessId, [Customer]);
|
|
162
|
+
* // ...mutate Customer here; rows are written automatically by hooks
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* // Bind several models in one call when a handler touches more than one
|
|
167
|
+
* bindAuditRequest(event, businessId, [Order, Payment, Receivable]);
|
|
168
|
+
*
|
|
169
|
+
* @param {import('aws-lambda').APIGatewayProxyEvent} event API Gateway event
|
|
170
|
+
* with `requestContext.authorizer.claims` (must include `email` and
|
|
171
|
+
* optionally `custom:UID`, `custom:SET`)
|
|
172
|
+
* @param {string|number} businessId business id this request acts on; stamped
|
|
173
|
+
* onto every audit row written for the bound models
|
|
174
|
+
* @param {Array<import('sequelize').ModelStatic<any>>} models Sequelize models
|
|
175
|
+
* to enable audit on for the duration of this request
|
|
176
|
+
* @returns {void}
|
|
177
|
+
* @see {@link bindAuditRequestForUser} - the equivalent for non-JWT contexts
|
|
178
|
+
* (webhooks, integration crons, Cognito triggers)
|
|
179
|
+
* @see {@link attachAudit} - one-time setup that creates the audit table
|
|
180
|
+
*/,exports.auditMe=auditMe,exports.auditModels=void 0,exports.bindAuditRequest=function bindAuditRequest(event,businessId,models){const user=(0,_requestResponse.getCurrentUser)(event),auditEnabled=!!((0,_accessRightsUtils.getCompanySettings)(event)||{}).auditEnabled;_lodash.default.forEach(models,model=>{modelOptions[model.name]={user,businessId,auditEnabled}})}
|
|
181
|
+
/**
|
|
182
|
+
* Bind per-request audit context for **system-driven flows** that do not carry
|
|
183
|
+
* an API Gateway JWT — for example, payment-gateway webhooks, integration
|
|
184
|
+
* crons (QuickBooks/Inbox/etc.), Cognito triggers, or batch jobs.
|
|
185
|
+
*
|
|
186
|
+
* Use {@link bindAuditRequest} instead whenever you have a JWT-authenticated
|
|
187
|
+
* API event; that path automatically resolves the user and the company's
|
|
188
|
+
* `auditEnabled` flag from claims.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* // payment webhook from the gateway — no JWT, but we still want audit
|
|
192
|
+
* import { systemUser } from '../user/user.js';
|
|
193
|
+
*
|
|
194
|
+
* export async function webhook(event) {
|
|
195
|
+
* const businessId = event.queryStringParameters.businessId;
|
|
196
|
+
* bindAuditRequestForUser(systemUser, businessId, [Order, Payment]);
|
|
197
|
+
* // ...mutate Order/Payment; audit rows are written by hooks
|
|
198
|
+
* }
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* // turn audit OFF explicitly for a system flow that should not be audited
|
|
202
|
+
* bindAuditRequestForUser(systemUser, businessId, [Order], { auditEnabled: false });
|
|
203
|
+
*
|
|
204
|
+
* @param {{ username: string, id?: number }} user identity stamped onto each
|
|
205
|
+
* audit row's `changedByUser` field. Conventionally the `systemUser`
|
|
206
|
+
* constant exported from your service's user model
|
|
207
|
+
* @param {string|number} businessId business id this flow is acting on
|
|
208
|
+
* @param {Array<import('sequelize').ModelStatic<any>>} models Sequelize models
|
|
209
|
+
* to enable audit on
|
|
210
|
+
* @param {{ auditEnabled?: boolean }} [opts] when `auditEnabled` is `false`,
|
|
211
|
+
* binds context but suppresses writes; defaults to `true`
|
|
212
|
+
* @returns {void}
|
|
213
|
+
* @see {@link bindAuditRequest} - the JWT-driven equivalent for API handlers
|
|
214
|
+
*/,exports.bindAuditRequestForUser=function bindAuditRequestForUser(user,businessId,models,opts={}){const auditEnabled=!1!==opts.auditEnabled;_lodash.default.forEach(models,model=>{modelOptions[model.name]={user,businessId,auditEnabled}})}
|
|
215
|
+
/**
|
|
216
|
+
* Get the `<ModelName>Audit` Sequelize model that {@link attachAudit} created
|
|
217
|
+
* for a parent model. Returns `undefined` if audit was never attached.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* const audits = await findAll(getAuditModel(Customer), filter);
|
|
221
|
+
*
|
|
222
|
+
* @param {import('sequelize').ModelStatic<any>} model parent Sequelize model
|
|
223
|
+
* @returns {import('sequelize').ModelStatic<any> | undefined} the audit model,
|
|
224
|
+
* or `undefined` if {@link attachAudit} has not been called for this model
|
|
225
|
+
* @see {@link getAuditFilter} - companion filter builder for history queries
|
|
226
|
+
*/,exports.decrementWithAudit=
|
|
227
|
+
/**
|
|
228
|
+
* Decrement an integer field on a Sequelize instance and write a matching
|
|
229
|
+
* audit row in the same call. Useful for inventory adjustments and other
|
|
230
|
+
* counter-style fields where Sequelize's plain `model.decrement()` would
|
|
231
|
+
* bypass the `afterUpdate` hook.
|
|
232
|
+
*
|
|
233
|
+
* The acting user and businessId come from whatever
|
|
234
|
+
* {@link bindAuditRequest} / {@link bindAuditRequestForUser} was called for
|
|
235
|
+
* this request. If audit is disabled for the model, the decrement still
|
|
236
|
+
* happens but no audit row is written.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* // release inventory on order release
|
|
240
|
+
* await decrementWithAudit('inventory', inventoryEntry, 'quantity', {
|
|
241
|
+
* by: item.quantity,
|
|
242
|
+
* transaction: t
|
|
243
|
+
* });
|
|
244
|
+
*
|
|
245
|
+
* @param {string} modelName name of the parent model (e.g. `'inventory'`)
|
|
246
|
+
* @param {import('sequelize').Model} model the Sequelize instance to mutate
|
|
247
|
+
* @param {string} field the integer/decimal field to decrement
|
|
248
|
+
* @param {{ by?: number, transaction?: import('sequelize').Transaction }} args
|
|
249
|
+
* passed straight through to Sequelize's `decrement()`; transaction is also
|
|
250
|
+
* propagated to the audit write
|
|
251
|
+
* @returns {Promise<import('sequelize').Model>} the updated instance (with
|
|
252
|
+
* `_changed` set on it so internal hooks can observe the change)
|
|
253
|
+
* @see {@link incrementWithAudit} - the +1 counterpart
|
|
254
|
+
*/
|
|
255
|
+
async function decrementWithAudit(modelName,model,field,args){const r=await model.decrement(field,args);r._changed=[field];const options={};args.transaction&&(options.transaction=args.transaction);return await auditMe(modelName)(r,options),r}
|
|
256
|
+
/**
|
|
257
|
+
* Increment an integer field on a Sequelize instance and write a matching
|
|
258
|
+
* audit row in the same call. The mirror of {@link decrementWithAudit}.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* // restock from a receivable
|
|
262
|
+
* await incrementWithAudit('inventory', inventoryEntry, 'quantity', {
|
|
263
|
+
* by: item.quantity,
|
|
264
|
+
* transaction: t
|
|
265
|
+
* });
|
|
266
|
+
*
|
|
267
|
+
* @param {string} modelName name of the parent model (e.g. `'inventory'`)
|
|
268
|
+
* @param {import('sequelize').Model} model the Sequelize instance to mutate
|
|
269
|
+
* @param {string} field the integer/decimal field to increment
|
|
270
|
+
* @param {{ by?: number, transaction?: import('sequelize').Transaction }} args
|
|
271
|
+
* passed straight through to Sequelize's `increment()`; transaction is also
|
|
272
|
+
* propagated to the audit write
|
|
273
|
+
* @returns {Promise<import('sequelize').Model>} the updated instance
|
|
274
|
+
* @see {@link decrementWithAudit} - the -1 counterpart
|
|
275
|
+
*/,exports.getAuditFilter=
|
|
276
|
+
/**
|
|
277
|
+
* Build a Sequelize `findAll`-style filter for an audit-history query, scoped
|
|
278
|
+
* to the businesses the caller is allowed to read (resolved from
|
|
279
|
+
* {@link accessRightsUtils}).
|
|
280
|
+
*
|
|
281
|
+
* The returned filter joins the parent model so callers can render `oldValue`
|
|
282
|
+
* → `newValue` rows in the UI alongside the parent record.
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* // GET /customer/{id}/audit
|
|
286
|
+
* export async function getCustomerAudit(event) {
|
|
287
|
+
* bindAuditRequest(event, userDefaultBid(event), [Customer]);
|
|
288
|
+
* const filter = getAuditFilter(Customer, event.pathParameters.id, {
|
|
289
|
+
* event,
|
|
290
|
+
* offset: 0,
|
|
291
|
+
* limit: 10
|
|
292
|
+
* });
|
|
293
|
+
* const audits = await findAll(getAuditModel(Customer), filter);
|
|
294
|
+
* return success(audits);
|
|
295
|
+
* }
|
|
296
|
+
*
|
|
297
|
+
* @param {import('sequelize').ModelStatic<any>} modelToFilter the parent model
|
|
298
|
+
* whose history is being fetched
|
|
299
|
+
* @param {string|number} id parent record id
|
|
300
|
+
* @param {{ event: import('aws-lambda').APIGatewayProxyEvent, offset?: number, limit?: number }} options
|
|
301
|
+
* `event` is required (drives business-id scoping); `offset` and `limit`
|
|
302
|
+
* are pagination passthroughs
|
|
303
|
+
* @returns {{ where: Object, include: Array<{ model: Object }>, order: Array, offset?: number, limit?: number }}
|
|
304
|
+
* a Sequelize `findAll`-compatible filter
|
|
305
|
+
* @see {@link getAuditModel} - call to get the audit model to query against
|
|
306
|
+
*/
|
|
307
|
+
function getAuditFilter(modelToFilter,id,options){const filter={where:{businessId:(0,_accessRightsUtils.accessRightsUtils)(options.event)},include:[{model:modelToFilter}],order:[["createdAt","DESC"]]};return filter.where[modelToFilter.name+"Id"]=id,{...filter,...options}},exports.getAuditModel=function getAuditModel(model){return auditModels[model.name]},exports.incrementWithAudit=async function incrementWithAudit(modelName,model,field,args){const r=await model.increment(field,args);r._changed=[field];const options={};args.transaction&&(options.transaction=args.transaction);return await auditMe(modelName)(r,options),r}
|
|
308
|
+
/***/,exports.modelOptions=void 0;var _lodash=_interopRequireDefault(__webpack_require__(825)),_bluebird=_interopRequireDefault(__webpack_require__(564)),_requestResponse=__webpack_require__(859),_accessRightsUtils=__webpack_require__(673);function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
|
|
309
|
+
/**
|
|
310
|
+
* @file Audit logging for Sequelize models. Each parent model gets a sibling
|
|
311
|
+
* `<ModelName>Audit` table that records every field-level change made through
|
|
312
|
+
* Sequelize hooks (afterCreate / afterUpsert / afterUpdate / afterDestroy).
|
|
313
|
+
*
|
|
314
|
+
* Typical wiring in a domain service:
|
|
315
|
+
*
|
|
316
|
+
* 1. At model `dbSetup` (one-time, at boot):
|
|
317
|
+
* `await attachAudit(MyModel);`
|
|
318
|
+
*
|
|
319
|
+
* 2. At the top of each route handler that mutates the model:
|
|
320
|
+
* `bindAuditRequest(event, businessId, [MyModel]);`
|
|
321
|
+
*
|
|
322
|
+
* 3. To list audit history for a record:
|
|
323
|
+
* `const filter = getAuditFilter(MyModel, id, { event, offset, limit });`
|
|
324
|
+
* `const audits = await findAll(getAuditModel(MyModel), filter);`
|
|
325
|
+
*
|
|
326
|
+
* Audit is **off by default** for any model whose request hasn't been bound —
|
|
327
|
+
* so cron lambdas, untouched endpoints, and unit tests will not write audit
|
|
328
|
+
* rows unless they explicitly opt in. The on/off switch comes from the
|
|
329
|
+
* `custom:SET.auditEnabled` JWT claim resolved by {@link getCompanySettings}.
|
|
330
|
+
*
|
|
331
|
+
* The user identity stamped on each row is read from the JWT via
|
|
332
|
+
* {@link getCurrentUser}; `changedByUser` stores `claims.email`. There is
|
|
333
|
+
* intentionally no foreign key back to a User table — domain services must
|
|
334
|
+
* not read across other services' databases.
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* Registry of `<ModelName>Audit` Sequelize models, keyed by parent model name.
|
|
338
|
+
* Populated by {@link attachAudit}. Exported for tests; do not mutate from app code.
|
|
339
|
+
*
|
|
340
|
+
* @type {Object<string, import('sequelize').ModelStatic<any>>}
|
|
341
|
+
*/const auditModels=exports.auditModels={},modelOptions=exports.modelOptions={},SENSITIVE_FIELDS_PATTERN=/"(token|password|secret|key|credential|auth|securityCode|cvv|pin|ssn)":\s*"[^"]*"/gi;
|
|
342
|
+
/**
|
|
343
|
+
* Per-model per-request audit context, keyed by parent model name. Populated by
|
|
344
|
+
* {@link bindAuditRequest} or {@link bindAuditRequestForUser}. A model with no
|
|
345
|
+
* entry here (or with `auditEnabled === false`) will not write any audit rows.
|
|
346
|
+
* Exported for tests; do not mutate from app code.
|
|
347
|
+
*
|
|
348
|
+
* @type {Object<string, { user: { username: string, id?: number }, businessId: string|number, auditEnabled: boolean }>}
|
|
349
|
+
*/function auditMe(modelName){return async(modelInfo,options)=>{_lodash.default.isArray(modelInfo)&&(modelInfo=modelInfo[0]);const opts=modelOptions[modelName];if(!opts||!opts.auditEnabled)return;const auditModel=auditModels[modelName],writeAuditRow=async(field,type,valueOld,valueNew)=>{const data={field,type,valueOld:String(valueOld).substring(0,255),valueNew:String(valueNew).substring(0,255),businessId:opts.businessId,changedByUser:opts.user.username};data[modelName+"Id"]=modelInfo.dataValues.id;const newOptions={};return options.transaction&&(newOptions.transaction=options.transaction),auditModel.create(data,newOptions)},checkAudit=async(field,type="INITIAL",valueOld,valueNew)=>{if(!_lodash.default.isEqual(valueOld,valueNew)){if(_lodash.default.isString(valueOld)&&_lodash.default.isString(valueNew)&&(type="INSERT"),_lodash.default.isArray(valueOld)||_lodash.default.isArray(valueNew)){let oldString=JSON.stringify(valueOld||[]),newString=JSON.stringify(valueNew||[]);return oldString=oldString.replace(SENSITIVE_FIELDS_PATTERN,'"$1":"***************"').substring(0,255),newString=newString.replace(SENSITIVE_FIELDS_PATTERN,'"$1":"***************"').substring(0,255),writeAuditRow(field,"UPDATE",oldString,newString)}return _lodash.default.isObject(valueOld)||_lodash.default.isObject(valueNew)?(_lodash.default.forEach(valueOld,(valueSub,keySub)=>{checkAudit(field+" "+keySub,"DELETED",valueSub||"",(valueNew||{})[keySub]||"")}),void _lodash.default.forEach(valueNew,(valueSub,keySub)=>{checkAudit(field+" "+keySub,"INSERT",(valueOld||{})[keySub]||"",valueSub||"")})):writeAuditRow(field,type,valueOld,valueNew)}};return _bluebird.default.map([...modelInfo._changed],async field=>{const valueOld=modelInfo._previousDataValues[field]||"",valueNew=modelInfo.dataValues[field]||"";await checkAudit(field,options.type,valueOld,valueNew)})}}},
|
|
20
350
|
/***/183(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.watchBucket=
|
|
21
351
|
/**
|
|
22
352
|
* 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
|
|
@@ -39,6 +369,22 @@ return(0,_publishEvents.publishEvents)(dynamoConfigTable,dynamoConfigKey,s3Bucke
|
|
|
39
369
|
// this used to throw, but the throw raised useless alarms, I believed turing throw in to a return was ok
|
|
40
370
|
return;if(startsWithDirect)return console.log("-------\x3eDIRECT WRITE FIRE"),(0,_handleEvents.handleDirectS3WriteEvent)(event,transformer,errorHandlerPerFile,shouldSkipFailedFolders,userImportTypes)}}
|
|
41
371
|
/***/;var _publishEvents=__webpack_require__(864),_handleEvents=__webpack_require__(95),_lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825))},
|
|
372
|
+
/***/189(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.requireCrmAccess=
|
|
373
|
+
/**
|
|
374
|
+
* Gate: CRM routes — rejects standard users. Super and partner pass.
|
|
375
|
+
* @param {object} access - Access object from resolveAccess.
|
|
376
|
+
*/
|
|
377
|
+
function requireCrmAccess(access){if(!access)throw _errorCodes.errorList.unauthorized;if("standard"===access.level)throw _errorCodes.errorList.unauthorized}
|
|
378
|
+
/**
|
|
379
|
+
* Gate: Ticket routes — all three user types pass. Only rejects null access.
|
|
380
|
+
* @param {object} access - Access object from resolveAccess.
|
|
381
|
+
*/,exports.requireSuper=
|
|
382
|
+
/**
|
|
383
|
+
* Gate: Super-only routes — throws unless global.
|
|
384
|
+
* @param {object} access - Access object from resolveAccess.
|
|
385
|
+
*/
|
|
386
|
+
function requireSuper(access){if(!access||"global"!==access.level)throw _errorCodes.errorList.unauthorized}
|
|
387
|
+
/***/,exports.requireTicketAccess=function requireTicketAccess(access){if(!access)throw _errorCodes.errorList.unauthorized};var _errorCodes=__webpack_require__(953)},
|
|
42
388
|
/***/207(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.addFiltersFromSchema=addFiltersFromSchema,exports.defaultFilters=
|
|
43
389
|
/**
|
|
44
390
|
* Create an object with default filters for a given sequeliaze Schema Object, and set of sub schemas
|
|
@@ -156,8 +502,74 @@ let parsed;try{parsed=JSON.parse(query[qKey])}catch(e){return}if(parsed&&"object
|
|
|
156
502
|
/***/},
|
|
157
503
|
/***/394(module){module.exports=require("dayjs/plugin/isSameOrBefore");
|
|
158
504
|
/***/},
|
|
505
|
+
/***/513(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.scopeToBookUnionOwn=
|
|
506
|
+
/**
|
|
507
|
+
* Scope to the union of partnerBusinessId + businessIds.
|
|
508
|
+
* Use for tickets — partner sees own tickets + portfolio merchants' tickets.
|
|
509
|
+
*
|
|
510
|
+
* global → deletes where.businessId
|
|
511
|
+
* partner → sets where.businessId = [partnerBusinessId, ...businessIds]
|
|
512
|
+
* standard → sets where.businessId = access.businessIds
|
|
513
|
+
* (explicitly handled here because ticket routes may not call
|
|
514
|
+
* createFilters before scoping, e.g. delete/resolve handlers)
|
|
515
|
+
*
|
|
516
|
+
* @param {object} where - Sequelize WHERE clause to mutate.
|
|
517
|
+
* @param {object} access - Access object from resolveAccess.
|
|
518
|
+
* @param {{ getPartnerById: Function }} deps
|
|
519
|
+
*/
|
|
520
|
+
async function scopeToBookUnionOwn(where,access,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return void delete where.businessId;if("partner"===access.level){await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById});const ids=_lodash.default.uniq([access.partnerBusinessId,...access.businessIds||[]].filter(Boolean));return void(where.businessId=ids)}if("standard"===access.level)return void(where.businessId=access.businessIds)}
|
|
521
|
+
/***/,exports.scopeToOwnBusiness=
|
|
522
|
+
/**
|
|
523
|
+
* Scope a WHERE clause to the partner's own business (partnerBusinessId).
|
|
524
|
+
* Use for "mine" resources: deal, activity, application, template.
|
|
525
|
+
*
|
|
526
|
+
* global → deletes where.businessId (super sees everything)
|
|
527
|
+
* partner → sets where.businessId = partnerBusinessId
|
|
528
|
+
* throws partnerNotConfigured if partnerBusinessId is missing
|
|
529
|
+
* standard → no-op (createFilters already handled)
|
|
530
|
+
*
|
|
531
|
+
* @param {object} where - Sequelize WHERE clause to mutate.
|
|
532
|
+
* @param {object} access - Access object from resolveAccess.
|
|
533
|
+
* @param {{ getPartnerById: Function }} deps
|
|
534
|
+
*/
|
|
535
|
+
async function scopeToOwnBusiness(where,access,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return void delete where.businessId;if("partner"===access.level){if(await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById}),!access.partnerBusinessId)throw _errorCodes.errorList.partnerNotConfigured;return void(where.businessId=access.partnerBusinessId)}
|
|
536
|
+
// standard → no-op (createFilters already injected from JWT)
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Scope a WHERE clause to the partner's portfolio (businessIds array).
|
|
540
|
+
* Use for "book" resources (future transaction lists, merchant inbox views).
|
|
541
|
+
*
|
|
542
|
+
* global → deletes where.businessId
|
|
543
|
+
* partner → sets where.businessId = businessIds[]
|
|
544
|
+
* standard → no-op
|
|
545
|
+
*
|
|
546
|
+
* @param {object} where - Sequelize WHERE clause to mutate.
|
|
547
|
+
* @param {object} access - Access object from resolveAccess.
|
|
548
|
+
* @param {{ getPartnerById: Function }} deps
|
|
549
|
+
*/,exports.scopeToPartnerBook=async function scopeToPartnerBook(where,access,{getPartnerById}={}){if(!access)throw _errorCodes.errorList.unauthorized;if("global"===access.level)return void delete where.businessId;if("partner"===access.level)return await(0,_accessContext.ensurePartnerScope)(access,{getPartnerById}),void(where.businessId=access.businessIds||[]);
|
|
550
|
+
// standard → no-op
|
|
551
|
+
};var _lodash=function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}(__webpack_require__(825)),_accessContext=__webpack_require__(62),_errorCodes=__webpack_require__(953)},
|
|
159
552
|
/***/515(module){module.exports=require("@aws-sdk/lib-dynamodb");
|
|
160
553
|
/***/},
|
|
554
|
+
/***/539(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.createAccessHelpers=
|
|
555
|
+
/**
|
|
556
|
+
* Factory that pre-binds getPartnerById into all scope/assert/stamp helpers.
|
|
557
|
+
* Bind once at module level, then call without repeating the injection:
|
|
558
|
+
*
|
|
559
|
+
* import { createAccessHelpers } from 'piper-utils';
|
|
560
|
+
* import { getPartnerById } from '../partner/partner.js';
|
|
561
|
+
*
|
|
562
|
+
* const {
|
|
563
|
+
* scopeToOwnBusiness,
|
|
564
|
+
* stampOwnBusinessId,
|
|
565
|
+
* assertCanWriteOwnBusiness
|
|
566
|
+
* } = createAccessHelpers({ getPartnerById });
|
|
567
|
+
*
|
|
568
|
+
* @param {{ getPartnerById: Function }} deps
|
|
569
|
+
* @returns {object} Pre-bound helpers.
|
|
570
|
+
*/
|
|
571
|
+
function createAccessHelpers({getPartnerById}){const deps={getPartnerById};return{ensurePartnerScope:access=>(0,_accessContext.ensurePartnerScope)(access,deps),scopeToOwnBusiness:(where,access)=>(0,_accessScope.scopeToOwnBusiness)(where,access,deps),scopeToPartnerBook:(where,access)=>(0,_accessScope.scopeToPartnerBook)(where,access,deps),scopeToBookUnionOwn:(where,access)=>(0,_accessScope.scopeToBookUnionOwn)(where,access,deps),assertCanWriteOwnBusiness:(access,businessId)=>(0,_accessWrites.assertCanWriteOwnBusiness)(access,businessId,deps),assertCanWriteBookBusiness:(access,businessId)=>(0,_accessWrites.assertCanWriteBookBusiness)(access,businessId,deps),assertCanWriteBookUnionOwn:(access,businessId)=>(0,_accessWrites.assertCanWriteBookUnionOwn)(access,businessId,deps),stampOwnBusinessId:(access,body)=>(0,_accessWrites.stampOwnBusinessId)(access,body,deps)}}
|
|
572
|
+
/***/;var _accessContext=__webpack_require__(62),_accessScope=__webpack_require__(513),_accessWrites=__webpack_require__(165)},
|
|
161
573
|
/***/564(module){module.exports=require("bluebird");
|
|
162
574
|
/***/},
|
|
163
575
|
/***/673(__unused_webpack_module,exports,__webpack_require__){Object.defineProperty(exports,"__esModule",{value:!0}),exports.accessRightsUtils=accessRightsUtils,exports.checkIsSuper=
|
|
@@ -410,7 +822,7 @@ const usersImports=Object.values(userImportTypes),items=path.split("/"),fileName
|
|
|
410
822
|
/***/},
|
|
411
823
|
/***/929(module){module.exports=require("@aws-sdk/client-dynamodb");
|
|
412
824
|
/***/},
|
|
413
|
-
/***/953(__unused_webpack_module,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorList=void 0;exports.errorList={invalidInventoryReleaseRequest:{message:"NOT ENOUGH INVENTORY TO FULFILL RELEASE",errorCode:"4010",statusCode:400},alreadyReleased:{message:"ALREADY RELEASED",errorCode:"4011",statusCode:400},alreadyReceived:{message:"RECEIVABLE ALREADY RECEIVED",errorCode:"4012",statusCode:400},invalidItemsRequest:{message:"VALID ITEMS MUST BE INCLUDED",errorCode:"4013",statusCode:400},invalidID:{message:"ID is invalid",errorCode:"4014",statusCode:400},invalidReceivable:{message:"MUST CONTAIN AT LEAST ONE RECEIVABLE",errorCode:"4015",statusCode:400},invalidRequest:{message:"INVALID REQUEST DATA",errorCode:"4016",statusCode:400},invalidAPIKey:{message:"INVALID REQUEST - API MAY KEY INVALID",errorCode:"4017",statusCode:400},qbCreationError:{message:"QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS",errorCode:"4018",statusCode:400},cannotReopen:{message:"CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED",errorCode:"4018",statusCode:400},invalidDateFormat:{message:"INVALID DATE FORMAT",errorCode:"4019",statusCode:400},invalidStartDate:{message:"INVALID START DATE",errorCode:"4020",statusCode:400},invalidEndDate:{message:"INVALID END DATE",errorCode:"4021",statusCode:400},invalidOrderStatus:{message:"UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS",errorCode:"4022",statusCode:400},invalidPaymentStatus:{message:"UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN",errorCode:"4023",statusCode:400},invalidReleaseStatus:{message:"UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN",errorCode:"4024",statusCode:400},invalidReceivableStatus:{message:"UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN",errorCode:"40025",statusCode:400},invalidJson:{message:"INVALID JSON",errorCode:"4005",statusCode:400},invalidFilter:{message:"INVALID FILTER",errorCode:"4026",statusCode:400},invalidUserNameUpdate:{message:"UNABLE TO UPDATE USERNAME",errorCode:"4027",statusCode:400},imageSizeLimit:{message:"IMAGE SIZE LIMIT 100KB EXCEEDED",errorCode:"4028",statusCode:400},unauthorized:{message:"UNAUTHORIZED",errorCode:"4111",statusCode:401},notFound:{message:"ITEM NOT FOUND",errorCode:"4004",statusCode:404},emailRequired:{message:"NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL",errorCode:"4004",statusCode:404},mobilePhoneRequired:{message:"NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS",errorCode:"4004",statusCode:404},invalidCadenceType:{message:"INVALID CADENCE TYPE",errorCode:"5001",statusCode:500}};
|
|
825
|
+
/***/953(__unused_webpack_module,exports){Object.defineProperty(exports,"__esModule",{value:!0}),exports.errorList=void 0;exports.errorList={invalidInventoryReleaseRequest:{message:"NOT ENOUGH INVENTORY TO FULFILL RELEASE",errorCode:"4010",statusCode:400},alreadyReleased:{message:"ALREADY RELEASED",errorCode:"4011",statusCode:400},alreadyReceived:{message:"RECEIVABLE ALREADY RECEIVED",errorCode:"4012",statusCode:400},invalidItemsRequest:{message:"VALID ITEMS MUST BE INCLUDED",errorCode:"4013",statusCode:400},invalidID:{message:"ID is invalid",errorCode:"4014",statusCode:400},invalidReceivable:{message:"MUST CONTAIN AT LEAST ONE RECEIVABLE",errorCode:"4015",statusCode:400},invalidRequest:{message:"INVALID REQUEST DATA",errorCode:"4016",statusCode:400},invalidAPIKey:{message:"INVALID REQUEST - API MAY KEY INVALID",errorCode:"4017",statusCode:400},qbCreationError:{message:"QUICKBOOKS ERROR - ERROR CREATING OBJECT IN QUICKBOOKS",errorCode:"4018",statusCode:400},cannotReopen:{message:"CANNOT REOPEN - THE ORDER HAS ALREADY BEEN OPENED",errorCode:"4018",statusCode:400},invalidDateFormat:{message:"INVALID DATE FORMAT",errorCode:"4019",statusCode:400},invalidStartDate:{message:"INVALID START DATE",errorCode:"4020",statusCode:400},invalidEndDate:{message:"INVALID END DATE",errorCode:"4021",statusCode:400},invalidOrderStatus:{message:"UNABLE TO EDIT ORDER ITEMS UNLESS THE ORDER IS IN ESTIMATE STATUS",errorCode:"4022",statusCode:400},invalidPaymentStatus:{message:"UNABLE TO UPDATE PAYMENT STATUS PAYMENT MUST BE OPEN",errorCode:"4023",statusCode:400},invalidReleaseStatus:{message:"UNABLE TO UPDATE RELEASE, STATUS RELEASE MUST BE OPEN",errorCode:"4024",statusCode:400},invalidReceivableStatus:{message:"UNABLE TO UPDATE RECEIVABLE, STATUS RECEIVABLE MUST BE OPEN",errorCode:"40025",statusCode:400},invalidJson:{message:"INVALID JSON",errorCode:"4005",statusCode:400},invalidFilter:{message:"INVALID FILTER",errorCode:"4026",statusCode:400},invalidUserNameUpdate:{message:"UNABLE TO UPDATE USERNAME",errorCode:"4027",statusCode:400},imageSizeLimit:{message:"IMAGE SIZE LIMIT 100KB EXCEEDED",errorCode:"4028",statusCode:400},unauthorized:{message:"UNAUTHORIZED",errorCode:"4111",statusCode:401},notFound:{message:"ITEM NOT FOUND",errorCode:"4004",statusCode:404},emailRequired:{message:"NO EMAIL PROVIDED, CHECK CUSTOMER EMAIL",errorCode:"4004",statusCode:404},mobilePhoneRequired:{message:"NO MOBILE PHONE PROVIDED, CHECK CUSTOMER CONTACTS",errorCode:"4004",statusCode:404},invalidCadenceType:{message:"INVALID CADENCE TYPE",errorCode:"5001",statusCode:500},partnerNotConfigured:{message:"Partner has no partnerBusinessId configured. Contact support.",errorCode:"4310",statusCode:400}};
|
|
414
826
|
/***/},
|
|
415
827
|
/***/981(__unused_webpack_module,exports){
|
|
416
828
|
/**
|
|
@@ -464,6 +876,6 @@ function createIncludes(event,objectFilters){const query=_lodash.default.get(eve
|
|
|
464
876
|
/******/
|
|
465
877
|
/************************************************************************/var __webpack_exports__={};
|
|
466
878
|
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
|
467
|
-
(()=>{var exports=__webpack_exports__;Object.defineProperty(exports,"__esModule",{value:!0}),exports.watchBucket=exports.userDefaultBid=exports.successHtml=exports.success=exports.runMigrations=exports.publishEvents=exports.parseEvent=exports.parseBody=exports.isSystemUser=exports.isSuperUser=exports.isPartnerUser=exports.handleFile=exports.getModuleInfo=exports.getEffectivePartnerId=exports.getDefaultBusinessIDInfo=exports.getCurrentUserNameFromCognitoEvent=exports.getCurrentUser=exports.getCompanySettings=exports.getBusinessesInfo=exports.getBelongsToPartnerId=exports.getAccessRightsInfo=exports.findAll=exports.failure=exports.enrichEventWithPartnerAccess=exports.defaultFilters=exports.createSort=exports.createIncludes=exports.createFilters=exports.checkWriteAccess=exports.checkModule=exports.checkIsSuper=exports.accessRightsUtils=void 0;var _handleFile=__webpack_require__(876),_watchBucket=__webpack_require__(183),_publishEvents=__webpack_require__(864),_createIncludes=__webpack_require__(982),_createFilters=__webpack_require__(288),_createSort=__webpack_require__(835),_findAll=__webpack_require__(981),_accessRightsUtils=__webpack_require__(673),_requestResponse=__webpack_require__(859),_migrations=__webpack_require__(871),_defaultFilters=__webpack_require__(207);exports.handleFile=_handleFile.handleFile,exports.watchBucket=_watchBucket.watchBucket,exports.publishEvents=_publishEvents.publishEvents,exports.createFilters=_createFilters.createFilters,exports.createIncludes=_createIncludes.createIncludes,exports.createSort=_createSort.createSort,exports.findAll=_findAll.findAll,exports.checkModule=_accessRightsUtils.checkModule,exports.checkIsSuper=_accessRightsUtils.checkIsSuper,exports.getAccessRightsInfo=_accessRightsUtils.getAccessRightsInfo,exports.getDefaultBusinessIDInfo=_accessRightsUtils.getDefaultBusinessIDInfo,exports.getModuleInfo=_accessRightsUtils.getModuleInfo,exports.failure=_requestResponse.failure,exports.success=_requestResponse.success,exports.runMigrations=_migrations.runMigrations,exports.getCurrentUser=_requestResponse.getCurrentUser,exports.successHtml=_requestResponse.successHtml,exports.getCurrentUserNameFromCognitoEvent=_requestResponse.getCurrentUserNameFromCognitoEvent,exports.defaultFilters=_defaultFilters.defaultFilters,exports.accessRightsUtils=_accessRightsUtils.accessRightsUtils,exports.parseBody=_requestResponse.parseBody,exports.parseEvent=_requestResponse.parseEvent,exports.getBusinessesInfo=_accessRightsUtils.getBusinessesInfo,exports.userDefaultBid=_accessRightsUtils.userDefaultBid,exports.checkWriteAccess=_accessRightsUtils.checkWriteAccess,exports.isSystemUser=_accessRightsUtils.isSystemUser,exports.isSuperUser=_accessRightsUtils.isSuperUser,exports.isPartnerUser=_accessRightsUtils.isPartnerUser,exports.getBelongsToPartnerId=_accessRightsUtils.getBelongsToPartnerId,exports.getEffectivePartnerId=_accessRightsUtils.getEffectivePartnerId,exports.enrichEventWithPartnerAccess=_accessRightsUtils.enrichEventWithPartnerAccess,exports.getCompanySettings=_accessRightsUtils.getCompanySettings})();var __webpack_export_target__=exports;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0})
|
|
879
|
+
(()=>{var exports=__webpack_exports__;Object.defineProperty(exports,"__esModule",{value:!0}),exports.watchBucket=exports.userDefaultBid=exports.successHtml=exports.success=exports.stampOwnBusinessId=exports.scopeToPartnerBook=exports.scopeToOwnBusiness=exports.scopeToBookUnionOwn=exports.runMigrations=exports.resolveAccess=exports.requireTicketAccess=exports.requireSuper=exports.requireCrmAccess=exports.publishEvents=exports.parseEvent=exports.parseBody=exports.isSystemUser=exports.isSuperUser=exports.isPartnerUser=exports.incrementWithAudit=exports.handleFile=exports.getModuleInfo=exports.getEffectivePartnerId=exports.getDefaultBusinessIDInfo=exports.getCurrentUserNameFromCognitoEvent=exports.getCurrentUser=exports.getCompanySettings=exports.getBusinessesInfo=exports.getBelongsToPartnerId=exports.getAuditModel=exports.getAuditFilter=exports.getAccessRightsInfo=exports.findAll=exports.failure=exports.ensurePartnerScope=exports.enrichEventWithPartnerAccess=exports.defaultFilters=exports.decrementWithAudit=exports.createSort=exports.createIncludes=exports.createFilters=exports.createAccessHelpers=exports.checkWriteAccess=exports.checkModule=exports.checkIsSuper=exports.bindAuditRequestForUser=exports.bindAuditRequest=exports.attachAudit=exports.assertCanWriteOwnBusiness=exports.assertCanWriteBookUnionOwn=exports.assertCanWriteBookBusiness=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),_accessContext=__webpack_require__(62),_accessGates=__webpack_require__(189),_accessScope=__webpack_require__(513),_accessWrites=__webpack_require__(165),_createAccessHelpers=__webpack_require__(539),_audit=__webpack_require__(179);exports.handleFile=_handleFile.handleFile,exports.watchBucket=_watchBucket.watchBucket,exports.publishEvents=_publishEvents.publishEvents,exports.createFilters=_createFilters.createFilters,exports.createIncludes=_createIncludes.createIncludes,exports.createSort=_createSort.createSort,exports.findAll=_findAll.findAll,exports.checkModule=_accessRightsUtils.checkModule,exports.checkIsSuper=_accessRightsUtils.checkIsSuper,exports.getAccessRightsInfo=_accessRightsUtils.getAccessRightsInfo,exports.getDefaultBusinessIDInfo=_accessRightsUtils.getDefaultBusinessIDInfo,exports.getModuleInfo=_accessRightsUtils.getModuleInfo,exports.failure=_requestResponse.failure,exports.success=_requestResponse.success,exports.runMigrations=_migrations.runMigrations,exports.getCurrentUser=_requestResponse.getCurrentUser,exports.successHtml=_requestResponse.successHtml,exports.getCurrentUserNameFromCognitoEvent=_requestResponse.getCurrentUserNameFromCognitoEvent,exports.defaultFilters=_defaultFilters.defaultFilters,exports.accessRightsUtils=_accessRightsUtils.accessRightsUtils,exports.parseBody=_requestResponse.parseBody,exports.parseEvent=_requestResponse.parseEvent,exports.getBusinessesInfo=_accessRightsUtils.getBusinessesInfo,exports.userDefaultBid=_accessRightsUtils.userDefaultBid,exports.checkWriteAccess=_accessRightsUtils.checkWriteAccess,exports.isSystemUser=_accessRightsUtils.isSystemUser,exports.isSuperUser=_accessRightsUtils.isSuperUser,exports.isPartnerUser=_accessRightsUtils.isPartnerUser,exports.getBelongsToPartnerId=_accessRightsUtils.getBelongsToPartnerId,exports.getEffectivePartnerId=_accessRightsUtils.getEffectivePartnerId,exports.enrichEventWithPartnerAccess=_accessRightsUtils.enrichEventWithPartnerAccess,exports.getCompanySettings=_accessRightsUtils.getCompanySettings,exports.resolveAccess=_accessContext.resolveAccess,exports.ensurePartnerScope=_accessContext.ensurePartnerScope,exports.requireCrmAccess=_accessGates.requireCrmAccess,exports.requireTicketAccess=_accessGates.requireTicketAccess,exports.requireSuper=_accessGates.requireSuper,exports.scopeToOwnBusiness=_accessScope.scopeToOwnBusiness,exports.scopeToPartnerBook=_accessScope.scopeToPartnerBook,exports.scopeToBookUnionOwn=_accessScope.scopeToBookUnionOwn,exports.assertCanWriteOwnBusiness=_accessWrites.assertCanWriteOwnBusiness,exports.assertCanWriteBookBusiness=_accessWrites.assertCanWriteBookBusiness,exports.assertCanWriteBookUnionOwn=_accessWrites.assertCanWriteBookUnionOwn,exports.stampOwnBusinessId=_accessWrites.stampOwnBusinessId,exports.createAccessHelpers=_createAccessHelpers.createAccessHelpers,exports.attachAudit=_audit.attachAudit,exports.bindAuditRequest=_audit.bindAuditRequest,exports.bindAuditRequestForUser=_audit.bindAuditRequestForUser,exports.decrementWithAudit=_audit.decrementWithAudit,exports.getAuditFilter=_audit.getAuditFilter,exports.getAuditModel=_audit.getAuditModel,exports.incrementWithAudit=_audit.incrementWithAudit})();var __webpack_export_target__=exports;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0})
|
|
468
880
|
/******/})();
|
|
469
881
|
//# sourceMappingURL=main.js.map
|