piper-utils 1.1.62 → 1.1.64

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.
@@ -81,9 +81,8 @@ export function getCurrentUser(event) {
81
81
  _.get(event, 'requestContext.authorizer.custom:UID') ||
82
82
  '0';
83
83
 
84
- const id = JSON.parse(jsonToParse);
85
-
86
84
  const username = _.get(event, 'requestContext.authorizer.claims.email') || _.get(event, 'requestContext.authorizer.email') || 'localtestuser@gexample.com';
85
+ const id = process.env.BUILD_ENV === 'local' ? 1 : JSON.parse(jsonToParse);
87
86
 
88
87
  return {
89
88
  username,
@@ -213,7 +212,16 @@ export function detectSequelizeError(body) {
213
212
  const errorName = _.get(body, 'name', '');
214
213
 
215
214
  if (errorName === 'SequelizeForeignKeyConstraintError') {
216
- errorBody.message = 'You cannot UPDATE or DELETE this item as it is in use';
215
+ const detail = _.get(body, 'parent.detail') || _.get(body, 'original.detail') || '';
216
+ const notPresent = detail.match(/Key \((\w+)\)=\((.+?)\) is not present in table "(\w+)"/);
217
+ const stillReferenced = detail.match(/Key \((\w+)\)=\((.+?)\) is still referenced from table "(\w+)"/);
218
+ if (notPresent) {
219
+ errorBody.message = 'The referenced ' + notPresent[3] + ' does not exist (' + notPresent[1] + ': ' + notPresent[2] + ')';
220
+ } else if (stillReferenced) {
221
+ errorBody.message = 'This item cannot be removed because it is referenced by ' + stillReferenced[3];
222
+ } else {
223
+ errorBody.message = 'A referenced item does not exist or is still in use';
224
+ }
217
225
  errorBody.statusCode = 409;
218
226
  errorBody.errorCode = '4090';
219
227
  return errorBody;
@@ -230,7 +230,22 @@ describe('requestResponse', () => {
230
230
  expect(res).toEqual({ message: 'Ilikegreeneggs' });
231
231
  });
232
232
 
233
- it('should return a friendly message for foreign key constraint errors', () => {
233
+ it('should return user-friendly message when referenced record does not exist', () => {
234
+ const body = {
235
+ name: 'SequelizeForeignKeyConstraintError',
236
+ parent: { detail: 'Key (partId)=(54) is not present in table "part".' },
237
+ original: { detail: 'Key (partId)=(54) is not present in table "part".' }
238
+ };
239
+
240
+ const res = detectSequelizeError(body);
241
+ expect(res).toEqual({
242
+ message: 'The referenced part does not exist (partId: 54)',
243
+ statusCode: 409,
244
+ errorCode: '4090'
245
+ });
246
+ });
247
+
248
+ it('should return user-friendly message when record is still referenced', () => {
234
249
  const body = {
235
250
  name: 'SequelizeForeignKeyConstraintError',
236
251
  parent: { detail: 'Key (id)=(5) is still referenced from table "orders".' },
@@ -239,7 +254,20 @@ describe('requestResponse', () => {
239
254
 
240
255
  const res = detectSequelizeError(body);
241
256
  expect(res).toEqual({
242
- message: 'You cannot delete this item as it is in use',
257
+ message: 'This item cannot be removed because it is referenced by orders',
258
+ statusCode: 409,
259
+ errorCode: '4090'
260
+ });
261
+ });
262
+
263
+ it('should return generic message for foreign key constraint errors with no detail', () => {
264
+ const body = {
265
+ name: 'SequelizeForeignKeyConstraintError'
266
+ };
267
+
268
+ const res = detectSequelizeError(body);
269
+ expect(res).toEqual({
270
+ message: 'A referenced item does not exist or is still in use',
243
271
  statusCode: 409,
244
272
  errorCode: '4090'
245
273
  });
package/WHITE_LABEL.md DELETED
@@ -1,60 +0,0 @@
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.