@infuro/cms-core 1.0.41 → 1.0.42
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/README.md +5 -18
- package/dist/admin.cjs +903 -287
- package/dist/admin.d.cts +11 -1
- package/dist/admin.d.ts +11 -1
- package/dist/admin.js +903 -287
- package/dist/api.cjs +35 -35
- package/dist/api.js +3 -3
- package/dist/auth.cjs +51 -51
- package/dist/auth.js +3 -3
- package/dist/{chunk-UXMDSNIG.js → chunk-BLR6H5GL.js} +1 -1
- package/dist/{chunk-P7QCLE5W.js → chunk-DN65KDIA.js} +11 -1
- package/dist/{chunk-QU554KAZ.cjs → chunk-GINYYPXK.cjs} +796 -149
- package/dist/{chunk-4BG7XYSH.js → chunk-I6NH72MO.js} +1 -1
- package/dist/{chunk-ETZN4OQI.cjs → chunk-TAHX46EI.cjs} +6 -6
- package/dist/{chunk-EG4ICILK.js → chunk-W2NL365N.js} +745 -110
- package/dist/{chunk-WMXPKKXU.cjs → chunk-X6UQFV4X.cjs} +11 -1
- package/dist/{chunk-OIGCAGH7.cjs → chunk-ZMRQ72F6.cjs} +7 -7
- package/dist/index.cjs +290 -242
- package/dist/index.d.cts +110 -5
- package/dist/index.d.ts +110 -5
- package/dist/index.js +6 -6
- package/dist/migrations/1781300000000-BrandIsCatalog.ts +61 -0
- package/dist/migrations/1781400000000-ComboEventIdNullable.ts +30 -0
- package/dist/migrations/1781500000000-ProductApprovalWorkflow.ts +30 -0
- package/dist/migrations/1781600000000-ProductApprovalStatusColumn.ts +53 -0
- package/dist/migrations/1781700000000-EventApprovalWorkflow.ts +32 -0
- package/dist/{rbac-debug-db-QWHOENBR.js → rbac-debug-db-2SGNLANF.js} +1 -1
- package/dist/{rbac-debug-db-KHG4FJC3.cjs → rbac-debug-db-4Z6A425H.cjs} +2 -2
- package/package.json +1 -1
|
@@ -7,8 +7,8 @@ var chunkXW5ATPRW_cjs = require('./chunk-XW5ATPRW.cjs');
|
|
|
7
7
|
var chunk3DZRIZOD_cjs = require('./chunk-3DZRIZOD.cjs');
|
|
8
8
|
var chunkSPQFNIYJ_cjs = require('./chunk-SPQFNIYJ.cjs');
|
|
9
9
|
var chunkXQ3QUHWR_cjs = require('./chunk-XQ3QUHWR.cjs');
|
|
10
|
-
var
|
|
11
|
-
var
|
|
10
|
+
var chunkZMRQ72F6_cjs = require('./chunk-ZMRQ72F6.cjs');
|
|
11
|
+
var chunkX6UQFV4X_cjs = require('./chunk-X6UQFV4X.cjs');
|
|
12
12
|
var chunkD5FBNKQM_cjs = require('./chunk-D5FBNKQM.cjs');
|
|
13
13
|
var chunkUPLVMVRX_cjs = require('./chunk-UPLVMVRX.cjs');
|
|
14
14
|
var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
|
|
@@ -87,7 +87,7 @@ async function loadUserVendorContext(dataSource, userId, preferredVendorId) {
|
|
|
87
87
|
`, [
|
|
88
88
|
primary.vendorRoleId
|
|
89
89
|
]);
|
|
90
|
-
vendorEntityPerms =
|
|
90
|
+
vendorEntityPerms = chunkX6UQFV4X_cjs.permissionRowsToRecord(permRows);
|
|
91
91
|
} catch (err) {
|
|
92
92
|
if (!isMissingVendorRoleSchemaError(err)) throw err;
|
|
93
93
|
}
|
|
@@ -104,6 +104,79 @@ async function loadUserVendorContext(dataSource, userId, preferredVendorId) {
|
|
|
104
104
|
}
|
|
105
105
|
chunkUSNT2KNT_cjs.__name(loadUserVendorContext, "loadUserVendorContext");
|
|
106
106
|
|
|
107
|
+
// src/lib/vendor-catalog-create-flags.ts
|
|
108
|
+
var ALL_OFF = {
|
|
109
|
+
categories: false,
|
|
110
|
+
collections: false,
|
|
111
|
+
brands: false
|
|
112
|
+
};
|
|
113
|
+
var cachedFlags = null;
|
|
114
|
+
function invalidateVendorCatalogCreateFlagsCache() {
|
|
115
|
+
cachedFlags = null;
|
|
116
|
+
}
|
|
117
|
+
chunkUSNT2KNT_cjs.__name(invalidateVendorCatalogCreateFlagsCache, "invalidateVendorCatalogCreateFlagsCache");
|
|
118
|
+
function parseTrue(value) {
|
|
119
|
+
return value === "true";
|
|
120
|
+
}
|
|
121
|
+
chunkUSNT2KNT_cjs.__name(parseTrue, "parseTrue");
|
|
122
|
+
async function isMultiVendorEnabled(dataSource) {
|
|
123
|
+
try {
|
|
124
|
+
const rows = await dataSource.query(`
|
|
125
|
+
SELECT value FROM configs
|
|
126
|
+
WHERE settings = 'multi_vendor' AND key = 'enabled' AND deleted = false
|
|
127
|
+
LIMIT 1
|
|
128
|
+
`);
|
|
129
|
+
return rows.length === 0 || rows[0].value !== "false";
|
|
130
|
+
} catch {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
chunkUSNT2KNT_cjs.__name(isMultiVendorEnabled, "isMultiVendorEnabled");
|
|
135
|
+
async function getVendorCatalogCreateFlags(dataSource) {
|
|
136
|
+
if (cachedFlags !== null) return cachedFlags;
|
|
137
|
+
const multiVendorEnabled = await isMultiVendorEnabled(dataSource);
|
|
138
|
+
if (!multiVendorEnabled) {
|
|
139
|
+
cachedFlags = {
|
|
140
|
+
...ALL_OFF
|
|
141
|
+
};
|
|
142
|
+
return cachedFlags;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const rows = await dataSource.query(`
|
|
146
|
+
SELECT key, value FROM configs
|
|
147
|
+
WHERE settings = 'multi_vendor'
|
|
148
|
+
AND key IN (
|
|
149
|
+
'vendorCanCreateCategories',
|
|
150
|
+
'vendorCanCreateCollections',
|
|
151
|
+
'vendorCanCreateBrands'
|
|
152
|
+
)
|
|
153
|
+
AND deleted = false
|
|
154
|
+
`);
|
|
155
|
+
const map = new Map(rows.map((r) => [
|
|
156
|
+
r.key,
|
|
157
|
+
r.value
|
|
158
|
+
]));
|
|
159
|
+
cachedFlags = {
|
|
160
|
+
categories: parseTrue(map.get("vendorCanCreateCategories")),
|
|
161
|
+
collections: parseTrue(map.get("vendorCanCreateCollections")),
|
|
162
|
+
brands: parseTrue(map.get("vendorCanCreateBrands"))
|
|
163
|
+
};
|
|
164
|
+
} catch {
|
|
165
|
+
cachedFlags = {
|
|
166
|
+
...ALL_OFF
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return cachedFlags;
|
|
170
|
+
}
|
|
171
|
+
chunkUSNT2KNT_cjs.__name(getVendorCatalogCreateFlags, "getVendorCatalogCreateFlags");
|
|
172
|
+
function vendorCanCreateResource(resource, flags) {
|
|
173
|
+
if (resource === "product_categories") return flags.categories;
|
|
174
|
+
if (resource === "collections") return flags.collections;
|
|
175
|
+
if (resource === "brands") return flags.brands;
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
chunkUSNT2KNT_cjs.__name(vendorCanCreateResource, "vendorCanCreateResource");
|
|
179
|
+
|
|
107
180
|
// src/lib/hydrate-vendor-session-user.ts
|
|
108
181
|
async function hydrateVendorSessionUser(dataSource, user) {
|
|
109
182
|
if (!user?.email) return user;
|
|
@@ -120,7 +193,7 @@ async function hydrateVendorSessionUser(dataSource, user) {
|
|
|
120
193
|
]);
|
|
121
194
|
const resolvedId = Number(byEmailRows[0]?.id);
|
|
122
195
|
if (!Number.isFinite(resolvedId)) {
|
|
123
|
-
|
|
196
|
+
chunkX6UQFV4X_cjs.logRbac("hydrateVendorSessionUser: unable to resolve numeric user id", {
|
|
124
197
|
email: user.email,
|
|
125
198
|
rawSessionId: user.id ?? null
|
|
126
199
|
});
|
|
@@ -140,7 +213,7 @@ async function hydrateVendorSessionUser(dataSource, user) {
|
|
|
140
213
|
const groupName = rows[0]?.groupName ?? user.groupName ?? null;
|
|
141
214
|
const groupId = rows[0]?.groupId ?? user.groupId ?? void 0;
|
|
142
215
|
const adminAccess = rows[0]?.adminAccess ?? user.adminAccess;
|
|
143
|
-
const isRBACAdmin = user.isRBACAdmin ??
|
|
216
|
+
const isRBACAdmin = user.isRBACAdmin ?? chunkX6UQFV4X_cjs.isSuperAdmin({
|
|
144
217
|
groupId,
|
|
145
218
|
groupName,
|
|
146
219
|
isRBACAdmin: user.isRBACAdmin
|
|
@@ -153,7 +226,7 @@ async function hydrateVendorSessionUser(dataSource, user) {
|
|
|
153
226
|
};
|
|
154
227
|
if (multiVendorEnabled) {
|
|
155
228
|
ctx = await loadUserVendorContext(dataSource, id, user.activeVendorId);
|
|
156
|
-
flags =
|
|
229
|
+
flags = chunkX6UQFV4X_cjs.vendorPortalFlagsFromUser({
|
|
157
230
|
email: user.email,
|
|
158
231
|
isRBACAdmin,
|
|
159
232
|
groupName,
|
|
@@ -188,7 +261,7 @@ async function hydrateVendorSessionUser(dataSource, user) {
|
|
|
188
261
|
isVendorPortal: flags.isVendorPortal,
|
|
189
262
|
isVendorOwner: flags.isVendorOwner
|
|
190
263
|
};
|
|
191
|
-
|
|
264
|
+
chunkX6UQFV4X_cjs.logRbac("hydrateVendorSessionUser", {
|
|
192
265
|
email: user.email,
|
|
193
266
|
userId: id,
|
|
194
267
|
groupName,
|
|
@@ -206,6 +279,7 @@ chunkUSNT2KNT_cjs.__name(hydrateVendorSessionUser, "hydrateVendorSessionUser");
|
|
|
206
279
|
var cachedMultiVendorEnabled = null;
|
|
207
280
|
function invalidateMultiVendorCache() {
|
|
208
281
|
cachedMultiVendorEnabled = null;
|
|
282
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
209
283
|
}
|
|
210
284
|
chunkUSNT2KNT_cjs.__name(invalidateMultiVendorCache, "invalidateMultiVendorCache");
|
|
211
285
|
async function checkMultiVendorEnabled(dataSource) {
|
|
@@ -244,6 +318,279 @@ async function checkEventsEnabled(dataSource) {
|
|
|
244
318
|
}
|
|
245
319
|
chunkUSNT2KNT_cjs.__name(checkEventsEnabled, "checkEventsEnabled");
|
|
246
320
|
|
|
321
|
+
// src/lib/product-approval.ts
|
|
322
|
+
var PRODUCT_APPROVAL_STATUSES = [
|
|
323
|
+
"pending",
|
|
324
|
+
"approved",
|
|
325
|
+
"rejected"
|
|
326
|
+
];
|
|
327
|
+
var APPROVAL_SET = new Set(PRODUCT_APPROVAL_STATUSES);
|
|
328
|
+
var PRODUCT_STATUSES = /* @__PURE__ */ new Set([
|
|
329
|
+
"draft",
|
|
330
|
+
"available",
|
|
331
|
+
"reserved",
|
|
332
|
+
"sold"
|
|
333
|
+
]);
|
|
334
|
+
var cachedRequireApproval = null;
|
|
335
|
+
function invalidateRequireProductApprovalCache() {
|
|
336
|
+
cachedRequireApproval = null;
|
|
337
|
+
}
|
|
338
|
+
chunkUSNT2KNT_cjs.__name(invalidateRequireProductApprovalCache, "invalidateRequireProductApprovalCache");
|
|
339
|
+
function parseTrue2(value) {
|
|
340
|
+
return value === "true";
|
|
341
|
+
}
|
|
342
|
+
chunkUSNT2KNT_cjs.__name(parseTrue2, "parseTrue");
|
|
343
|
+
async function getRequireProductApproval(dataSource) {
|
|
344
|
+
if (cachedRequireApproval !== null) return cachedRequireApproval;
|
|
345
|
+
const multiVendorEnabled = await checkMultiVendorEnabled(dataSource);
|
|
346
|
+
if (!multiVendorEnabled) {
|
|
347
|
+
cachedRequireApproval = false;
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
const rows = await dataSource.query(`
|
|
352
|
+
SELECT value FROM configs
|
|
353
|
+
WHERE settings = 'multi_vendor' AND key = 'requireProductApproval' AND deleted = false
|
|
354
|
+
LIMIT 1
|
|
355
|
+
`);
|
|
356
|
+
cachedRequireApproval = rows.length > 0 && parseTrue2(rows[0].value);
|
|
357
|
+
} catch {
|
|
358
|
+
cachedRequireApproval = false;
|
|
359
|
+
}
|
|
360
|
+
return cachedRequireApproval;
|
|
361
|
+
}
|
|
362
|
+
chunkUSNT2KNT_cjs.__name(getRequireProductApproval, "getRequireProductApproval");
|
|
363
|
+
function applyVendorProductCreateApproval(persistBody, opts) {
|
|
364
|
+
if (!opts.isVendor || !opts.requireApproval) return;
|
|
365
|
+
persistBody.approvalStatus = "pending";
|
|
366
|
+
if (persistBody.status === "available") persistBody.status = "draft";
|
|
367
|
+
persistBody.rejectionReason = null;
|
|
368
|
+
persistBody.rejectedAt = null;
|
|
369
|
+
persistBody.rejectedBy = null;
|
|
370
|
+
}
|
|
371
|
+
chunkUSNT2KNT_cjs.__name(applyVendorProductCreateApproval, "applyVendorProductCreateApproval");
|
|
372
|
+
function assertProductApprovalUpdate(opts) {
|
|
373
|
+
const fromApproval = opts.fromApproval == null || opts.fromApproval === "" ? null : String(opts.fromApproval);
|
|
374
|
+
const toApproval = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
375
|
+
const fromStatus = String(opts.fromStatus || "draft");
|
|
376
|
+
const toStatus = String(opts.toStatus || fromStatus);
|
|
377
|
+
if (opts.statusChanged && !PRODUCT_STATUSES.has(toStatus)) {
|
|
378
|
+
return {
|
|
379
|
+
ok: false,
|
|
380
|
+
error: `Invalid product status: ${toStatus}`
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
if (opts.approvalChanged && toApproval != null && !APPROVAL_SET.has(toApproval)) {
|
|
384
|
+
return {
|
|
385
|
+
ok: false,
|
|
386
|
+
error: `Invalid approval status: ${toApproval}`
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
if (!opts.requireApproval) {
|
|
390
|
+
if (opts.isVendor && opts.approvalChanged) {
|
|
391
|
+
return {
|
|
392
|
+
ok: false,
|
|
393
|
+
error: "Vendors cannot change approval status"
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
ok: true
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
if (opts.isVendor) {
|
|
401
|
+
if (opts.approvalChanged) {
|
|
402
|
+
return {
|
|
403
|
+
ok: false,
|
|
404
|
+
error: "Vendors cannot change approval status"
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
if (opts.statusChanged && toStatus === "available" && fromApproval !== "approved") {
|
|
408
|
+
return {
|
|
409
|
+
ok: false,
|
|
410
|
+
error: "Product must be approved before it can be available"
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if (fromApproval === "rejected" && opts.statusChanged && toStatus === "available") {
|
|
414
|
+
return {
|
|
415
|
+
ok: false,
|
|
416
|
+
error: "Rejected product cannot be made available"
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
ok: true
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
if (opts.approvalChanged && toApproval === "rejected") {
|
|
424
|
+
const reason = String(opts.rejectionReason ?? "").trim();
|
|
425
|
+
if (!reason) return {
|
|
426
|
+
ok: false,
|
|
427
|
+
error: "Rejection reason is required"
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
ok: true
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
chunkUSNT2KNT_cjs.__name(assertProductApprovalUpdate, "assertProductApprovalUpdate");
|
|
435
|
+
function applyApprovalStatusSideEffects(updatePayload, opts) {
|
|
436
|
+
const to = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
437
|
+
if (to == null) return;
|
|
438
|
+
if (to === "approved") {
|
|
439
|
+
updatePayload.approvalStatus = "approved";
|
|
440
|
+
updatePayload.status = "available";
|
|
441
|
+
updatePayload.rejectionReason = null;
|
|
442
|
+
updatePayload.rejectedAt = null;
|
|
443
|
+
updatePayload.rejectedBy = null;
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (to === "rejected") {
|
|
447
|
+
updatePayload.approvalStatus = "rejected";
|
|
448
|
+
updatePayload.rejectionReason = String(opts.rejectionReason ?? "").trim();
|
|
449
|
+
updatePayload.rejectedAt = /* @__PURE__ */ new Date();
|
|
450
|
+
updatePayload.rejectedBy = opts.rejectedBy != null && Number.isFinite(opts.rejectedBy) ? opts.rejectedBy : null;
|
|
451
|
+
const nextStatus = "status" in updatePayload ? String(updatePayload.status) : opts.currentStatus;
|
|
452
|
+
if (nextStatus === "available") updatePayload.status = "draft";
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (to === "pending") {
|
|
456
|
+
updatePayload.approvalStatus = "pending";
|
|
457
|
+
updatePayload.rejectionReason = null;
|
|
458
|
+
updatePayload.rejectedAt = null;
|
|
459
|
+
updatePayload.rejectedBy = null;
|
|
460
|
+
const nextStatus = "status" in updatePayload ? String(updatePayload.status) : opts.currentStatus;
|
|
461
|
+
if (nextStatus === "available") updatePayload.status = "draft";
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
chunkUSNT2KNT_cjs.__name(applyApprovalStatusSideEffects, "applyApprovalStatusSideEffects");
|
|
465
|
+
|
|
466
|
+
// src/lib/event-approval.ts
|
|
467
|
+
var EVENT_APPROVAL_STATUSES = [
|
|
468
|
+
"pending",
|
|
469
|
+
"approved",
|
|
470
|
+
"rejected"
|
|
471
|
+
];
|
|
472
|
+
var APPROVAL_SET2 = new Set(EVENT_APPROVAL_STATUSES);
|
|
473
|
+
var cachedRequireApproval2 = null;
|
|
474
|
+
function invalidateRequireEventApprovalCache() {
|
|
475
|
+
cachedRequireApproval2 = null;
|
|
476
|
+
}
|
|
477
|
+
chunkUSNT2KNT_cjs.__name(invalidateRequireEventApprovalCache, "invalidateRequireEventApprovalCache");
|
|
478
|
+
function parseTrue3(value) {
|
|
479
|
+
return value === "true";
|
|
480
|
+
}
|
|
481
|
+
chunkUSNT2KNT_cjs.__name(parseTrue3, "parseTrue");
|
|
482
|
+
async function getRequireEventApproval(dataSource) {
|
|
483
|
+
if (cachedRequireApproval2 !== null) return cachedRequireApproval2;
|
|
484
|
+
const [eventsOn, multiVendorOn] = await Promise.all([
|
|
485
|
+
checkEventsEnabled(dataSource),
|
|
486
|
+
checkMultiVendorEnabled(dataSource)
|
|
487
|
+
]);
|
|
488
|
+
if (!eventsOn || !multiVendorOn) {
|
|
489
|
+
cachedRequireApproval2 = false;
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
try {
|
|
493
|
+
const rows = await dataSource.query(`
|
|
494
|
+
SELECT value FROM configs
|
|
495
|
+
WHERE settings = 'events' AND key = 'requireEventApproval' AND deleted = false
|
|
496
|
+
LIMIT 1
|
|
497
|
+
`);
|
|
498
|
+
cachedRequireApproval2 = rows.length > 0 && parseTrue3(rows[0].value);
|
|
499
|
+
} catch {
|
|
500
|
+
cachedRequireApproval2 = false;
|
|
501
|
+
}
|
|
502
|
+
return cachedRequireApproval2;
|
|
503
|
+
}
|
|
504
|
+
chunkUSNT2KNT_cjs.__name(getRequireEventApproval, "getRequireEventApproval");
|
|
505
|
+
function applyVendorEventCreateApproval(persistBody, opts) {
|
|
506
|
+
if (!opts.isVendor || !opts.requireApproval) return;
|
|
507
|
+
persistBody.approvalStatus = "pending";
|
|
508
|
+
persistBody.isActive = false;
|
|
509
|
+
persistBody.rejectionReason = null;
|
|
510
|
+
persistBody.rejectedAt = null;
|
|
511
|
+
persistBody.rejectedBy = null;
|
|
512
|
+
}
|
|
513
|
+
chunkUSNT2KNT_cjs.__name(applyVendorEventCreateApproval, "applyVendorEventCreateApproval");
|
|
514
|
+
function assertEventApprovalUpdate(opts) {
|
|
515
|
+
const fromApproval = opts.fromApproval == null || opts.fromApproval === "" ? null : String(opts.fromApproval);
|
|
516
|
+
const toApproval = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
517
|
+
if (opts.approvalChanged && toApproval != null && !APPROVAL_SET2.has(toApproval)) {
|
|
518
|
+
return {
|
|
519
|
+
ok: false,
|
|
520
|
+
error: `Invalid approval status: ${toApproval}`
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
if (!opts.requireApproval) {
|
|
524
|
+
if (opts.isVendor && opts.approvalChanged) {
|
|
525
|
+
return {
|
|
526
|
+
ok: false,
|
|
527
|
+
error: "Vendors cannot change approval status"
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
return {
|
|
531
|
+
ok: true
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (opts.isVendor) {
|
|
535
|
+
if (opts.approvalChanged) {
|
|
536
|
+
return {
|
|
537
|
+
ok: false,
|
|
538
|
+
error: "Vendors cannot change approval status"
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
if (opts.activeChanged && opts.toActive && fromApproval !== "approved") {
|
|
542
|
+
return {
|
|
543
|
+
ok: false,
|
|
544
|
+
error: "Event must be approved before it can be activated"
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
ok: true
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (opts.approvalChanged && toApproval === "rejected") {
|
|
552
|
+
const reason = String(opts.rejectionReason ?? "").trim();
|
|
553
|
+
if (!reason) return {
|
|
554
|
+
ok: false,
|
|
555
|
+
error: "Rejection reason is required"
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
ok: true
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
chunkUSNT2KNT_cjs.__name(assertEventApprovalUpdate, "assertEventApprovalUpdate");
|
|
563
|
+
function applyEventApprovalStatusSideEffects(updatePayload, opts) {
|
|
564
|
+
const to = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
565
|
+
if (to == null) return;
|
|
566
|
+
if (to === "approved") {
|
|
567
|
+
updatePayload.approvalStatus = "approved";
|
|
568
|
+
updatePayload.isActive = true;
|
|
569
|
+
updatePayload.rejectionReason = null;
|
|
570
|
+
updatePayload.rejectedAt = null;
|
|
571
|
+
updatePayload.rejectedBy = null;
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (to === "rejected") {
|
|
575
|
+
updatePayload.approvalStatus = "rejected";
|
|
576
|
+
updatePayload.rejectionReason = String(opts.rejectionReason ?? "").trim();
|
|
577
|
+
updatePayload.rejectedAt = /* @__PURE__ */ new Date();
|
|
578
|
+
updatePayload.rejectedBy = opts.rejectedBy != null && Number.isFinite(opts.rejectedBy) ? opts.rejectedBy : null;
|
|
579
|
+
const nextActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : opts.currentActive;
|
|
580
|
+
if (nextActive) updatePayload.isActive = false;
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
if (to === "pending") {
|
|
584
|
+
updatePayload.approvalStatus = "pending";
|
|
585
|
+
updatePayload.rejectionReason = null;
|
|
586
|
+
updatePayload.rejectedAt = null;
|
|
587
|
+
updatePayload.rejectedBy = null;
|
|
588
|
+
const nextActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : opts.currentActive;
|
|
589
|
+
if (nextActive) updatePayload.isActive = false;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
chunkUSNT2KNT_cjs.__name(applyEventApprovalStatusSideEffects, "applyEventApprovalStatusSideEffects");
|
|
593
|
+
|
|
247
594
|
// src/lib/default-vendor-id.ts
|
|
248
595
|
function getDefaultVendorId() {
|
|
249
596
|
const raw = process.env.DEFAULT_VENDOR_ID;
|
|
@@ -279,17 +626,20 @@ async function assertCatalogCategoryId(dataSource, categoriesEntity, categoryId,
|
|
|
279
626
|
const row = await repo.findOne({
|
|
280
627
|
where: {
|
|
281
628
|
id,
|
|
282
|
-
deleted: false
|
|
283
|
-
isCatalog: true
|
|
629
|
+
deleted: false
|
|
284
630
|
}
|
|
285
631
|
});
|
|
286
632
|
if (!row) {
|
|
287
633
|
return "Invalid catalog category. Choose one of the platform product category types.";
|
|
288
634
|
}
|
|
289
|
-
return null;
|
|
635
|
+
if (row.isCatalog === true) return null;
|
|
636
|
+
if (options?.allowVendorId != null && Number(row.vendorId) === options.allowVendorId && row.isCatalog !== true) {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
return "Invalid catalog category. Choose one of the platform product category types.";
|
|
290
640
|
}
|
|
291
641
|
chunkUSNT2KNT_cjs.__name(assertCatalogCategoryId, "assertCatalogCategoryId");
|
|
292
|
-
async function
|
|
642
|
+
async function assertCollectionForVendorProduct(dataSource, collectionsEntity, collectionId, categoryId, vendorId, options) {
|
|
293
643
|
const cid = Number(collectionId);
|
|
294
644
|
if (!Number.isFinite(cid) || cid <= 0) return null;
|
|
295
645
|
if (!collectionsEntity) return "Collections are not configured";
|
|
@@ -300,11 +650,13 @@ async function assertVendorOwnedCollectionForProduct(dataSource, collectionsEnti
|
|
|
300
650
|
deleted: false
|
|
301
651
|
}
|
|
302
652
|
});
|
|
303
|
-
if (!row
|
|
304
|
-
return "Invalid collection. Choose
|
|
653
|
+
if (!row) {
|
|
654
|
+
return "Invalid collection. Choose a valid collection in this category.";
|
|
305
655
|
}
|
|
306
|
-
|
|
307
|
-
|
|
656
|
+
const isCatalog = row.isCatalog === true;
|
|
657
|
+
const isOwn = Number(row.vendorId) === vendorId && !isCatalog;
|
|
658
|
+
if (!isCatalog && !(options?.allowVendorOwned && isOwn)) {
|
|
659
|
+
return "Invalid collection. Choose one of the platform collections (or your own if allowed).";
|
|
308
660
|
}
|
|
309
661
|
const catId = Number(categoryId);
|
|
310
662
|
if (Number.isFinite(catId) && catId > 0 && Number(row.categoryId) !== catId) {
|
|
@@ -312,7 +664,7 @@ async function assertVendorOwnedCollectionForProduct(dataSource, collectionsEnti
|
|
|
312
664
|
}
|
|
313
665
|
return null;
|
|
314
666
|
}
|
|
315
|
-
chunkUSNT2KNT_cjs.__name(
|
|
667
|
+
chunkUSNT2KNT_cjs.__name(assertCollectionForVendorProduct, "assertCollectionForVendorProduct");
|
|
316
668
|
|
|
317
669
|
// src/lib/catalog-collection.ts
|
|
318
670
|
function isCatalogCollectionRow(row) {
|
|
@@ -326,16 +678,69 @@ function applyPlatformCatalogCollectionFields(persistBody) {
|
|
|
326
678
|
}
|
|
327
679
|
chunkUSNT2KNT_cjs.__name(applyPlatformCatalogCollectionFields, "applyPlatformCatalogCollectionFields");
|
|
328
680
|
|
|
681
|
+
// src/lib/catalog-brand.ts
|
|
682
|
+
function isCatalogBrandRow(row) {
|
|
683
|
+
return row?.isCatalog === true;
|
|
684
|
+
}
|
|
685
|
+
chunkUSNT2KNT_cjs.__name(isCatalogBrandRow, "isCatalogBrandRow");
|
|
686
|
+
function applyPlatformCatalogBrandFields(persistBody) {
|
|
687
|
+
persistBody.isCatalog = true;
|
|
688
|
+
delete persistBody.vendorId;
|
|
689
|
+
persistBody.vendorId = getDefaultVendorId();
|
|
690
|
+
}
|
|
691
|
+
chunkUSNT2KNT_cjs.__name(applyPlatformCatalogBrandFields, "applyPlatformCatalogBrandFields");
|
|
692
|
+
|
|
329
693
|
// src/api/vendor-scope-crud.ts
|
|
694
|
+
var CATALOG_LIST_RESOURCES = /* @__PURE__ */ new Set([
|
|
695
|
+
"product_categories",
|
|
696
|
+
"collections",
|
|
697
|
+
"brands"
|
|
698
|
+
]);
|
|
330
699
|
function repoHasVendorIdColumn(repo) {
|
|
331
700
|
return repo.metadata.columns.some((c) => c.propertyName === "vendorId");
|
|
332
701
|
}
|
|
333
702
|
chunkUSNT2KNT_cjs.__name(repoHasVendorIdColumn, "repoHasVendorIdColumn");
|
|
334
703
|
function resourceUsesVendorScope(resource) {
|
|
335
|
-
return resource === "vendors" ||
|
|
704
|
+
return resource === "vendors" || chunkX6UQFV4X_cjs.VENDOR_SCOPED_STORE_ENTITIES.has(resource);
|
|
336
705
|
}
|
|
337
706
|
chunkUSNT2KNT_cjs.__name(resourceUsesVendorScope, "resourceUsesVendorScope");
|
|
338
|
-
function
|
|
707
|
+
function mergeWhereClause(where, extra) {
|
|
708
|
+
if (Array.isArray(where)) {
|
|
709
|
+
return where.map((w) => ({
|
|
710
|
+
...w,
|
|
711
|
+
...extra
|
|
712
|
+
}));
|
|
713
|
+
}
|
|
714
|
+
if (where && typeof where === "object" && Object.keys(where).length > 0) {
|
|
715
|
+
return {
|
|
716
|
+
...where,
|
|
717
|
+
...extra
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
return extra;
|
|
721
|
+
}
|
|
722
|
+
chunkUSNT2KNT_cjs.__name(mergeWhereClause, "mergeWhereClause");
|
|
723
|
+
function mergeCatalogOrOwnWhere(where, vendorId) {
|
|
724
|
+
const catalog = mergeWhereClause(where, {
|
|
725
|
+
isCatalog: true
|
|
726
|
+
});
|
|
727
|
+
const own = mergeWhereClause(where, {
|
|
728
|
+
vendorId,
|
|
729
|
+
isCatalog: false
|
|
730
|
+
});
|
|
731
|
+
const catalogArr = Array.isArray(catalog) ? catalog : [
|
|
732
|
+
catalog
|
|
733
|
+
];
|
|
734
|
+
const ownArr = Array.isArray(own) ? own : [
|
|
735
|
+
own
|
|
736
|
+
];
|
|
737
|
+
return [
|
|
738
|
+
...catalogArr,
|
|
739
|
+
...ownArr
|
|
740
|
+
];
|
|
741
|
+
}
|
|
742
|
+
chunkUSNT2KNT_cjs.__name(mergeCatalogOrOwnWhere, "mergeCatalogOrOwnWhere");
|
|
743
|
+
function mergeVendorScopeIntoWhere(where, scope, resource, flags) {
|
|
339
744
|
if (scope.type === "all") return where;
|
|
340
745
|
if (scope.type === "deny") {
|
|
341
746
|
if (resource === "vendors") {
|
|
@@ -352,38 +757,20 @@ function mergeVendorScopeIntoWhere(where, scope, resource) {
|
|
|
352
757
|
id: typeorm.In(scope.vendorIds)
|
|
353
758
|
});
|
|
354
759
|
}
|
|
355
|
-
if (resource
|
|
760
|
+
if (CATALOG_LIST_RESOURCES.has(resource) && scope.type === "vendor") {
|
|
761
|
+
const canCreate = flags ? vendorCanCreateResource(resource, flags) : false;
|
|
762
|
+
if (canCreate) {
|
|
763
|
+
return mergeCatalogOrOwnWhere(where, scope.vendorId);
|
|
764
|
+
}
|
|
356
765
|
return mergeWhereClause(where, {
|
|
357
766
|
isCatalog: true
|
|
358
767
|
});
|
|
359
768
|
}
|
|
360
|
-
if (resource === "collections" && scope.type === "vendor") {
|
|
361
|
-
return mergeWhereClause(where, {
|
|
362
|
-
vendorId: scope.vendorId,
|
|
363
|
-
isCatalog: false
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
769
|
return mergeWhereClause(where, {
|
|
367
770
|
vendorId: scope.vendorId
|
|
368
771
|
});
|
|
369
772
|
}
|
|
370
773
|
chunkUSNT2KNT_cjs.__name(mergeVendorScopeIntoWhere, "mergeVendorScopeIntoWhere");
|
|
371
|
-
function mergeWhereClause(where, extra) {
|
|
372
|
-
if (Array.isArray(where)) {
|
|
373
|
-
return where.map((w) => ({
|
|
374
|
-
...w,
|
|
375
|
-
...extra
|
|
376
|
-
}));
|
|
377
|
-
}
|
|
378
|
-
if (where && typeof where === "object" && Object.keys(where).length > 0) {
|
|
379
|
-
return {
|
|
380
|
-
...where,
|
|
381
|
-
...extra
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
return extra;
|
|
385
|
-
}
|
|
386
|
-
chunkUSNT2KNT_cjs.__name(mergeWhereClause, "mergeWhereClause");
|
|
387
774
|
function applyVendorScopeToQueryBuilder(qb, alias, scope) {
|
|
388
775
|
if (scope.type === "all") return;
|
|
389
776
|
if (scope.type === "deny") {
|
|
@@ -395,7 +782,7 @@ function applyVendorScopeToQueryBuilder(qb, alias, scope) {
|
|
|
395
782
|
});
|
|
396
783
|
}
|
|
397
784
|
chunkUSNT2KNT_cjs.__name(applyVendorScopeToQueryBuilder, "applyVendorScopeToQueryBuilder");
|
|
398
|
-
function rowMatchesVendorScope(row, scope, resource) {
|
|
785
|
+
function rowMatchesVendorScope(row, scope, resource, flags) {
|
|
399
786
|
if (!row) return false;
|
|
400
787
|
if (scope.type === "all") return true;
|
|
401
788
|
if (scope.type === "deny") return false;
|
|
@@ -403,27 +790,32 @@ function rowMatchesVendorScope(row, scope, resource) {
|
|
|
403
790
|
const id = Number(row.id);
|
|
404
791
|
return scope.vendorIds.includes(id);
|
|
405
792
|
}
|
|
406
|
-
if (resource
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
return Number(row.vendorId) === scope.vendorId && !
|
|
793
|
+
if (CATALOG_LIST_RESOURCES.has(resource) && scope.type === "vendor") {
|
|
794
|
+
const isCatalog = resource === "product_categories" ? isCatalogCategoryRow(row) : resource === "collections" ? isCatalogCollectionRow(row) : isCatalogBrandRow(row);
|
|
795
|
+
if (isCatalog) return true;
|
|
796
|
+
const canCreate = flags ? vendorCanCreateResource(resource, flags) : false;
|
|
797
|
+
return canCreate && Number(row.vendorId) === scope.vendorId && !isCatalog;
|
|
411
798
|
}
|
|
412
799
|
return Number(row.vendorId) === scope.vendorId;
|
|
413
800
|
}
|
|
414
801
|
chunkUSNT2KNT_cjs.__name(rowMatchesVendorScope, "rowMatchesVendorScope");
|
|
415
|
-
function
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
chunkUSNT2KNT_cjs.__name(vendorCannotMutateCatalogCategories, "vendorCannotMutateCatalogCategories");
|
|
419
|
-
function vendorCannotMutateCatalogCollections(resource, scope, body) {
|
|
420
|
-
if (resource !== "collections" || scope.type !== "vendor") return false;
|
|
802
|
+
function vendorCannotMutateCatalogResource(resource, scope, flags, body) {
|
|
803
|
+
if (scope.type !== "vendor" || !CATALOG_LIST_RESOURCES.has(resource)) return false;
|
|
804
|
+
if (!vendorCanCreateResource(resource, flags)) return true;
|
|
421
805
|
return body?.isCatalog === true;
|
|
422
806
|
}
|
|
423
|
-
chunkUSNT2KNT_cjs.__name(
|
|
424
|
-
function
|
|
807
|
+
chunkUSNT2KNT_cjs.__name(vendorCannotMutateCatalogResource, "vendorCannotMutateCatalogResource");
|
|
808
|
+
function vendorCannotMutateExistingCatalogRow(resource, scope, row) {
|
|
809
|
+
if (scope.type !== "vendor" || !CATALOG_LIST_RESOURCES.has(resource) || !row) return false;
|
|
810
|
+
if (resource === "product_categories") return isCatalogCategoryRow(row);
|
|
811
|
+
if (resource === "collections") return isCatalogCollectionRow(row);
|
|
812
|
+
if (resource === "brands") return isCatalogBrandRow(row);
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
chunkUSNT2KNT_cjs.__name(vendorCannotMutateExistingCatalogRow, "vendorCannotMutateExistingCatalogRow");
|
|
816
|
+
function vendorScopeRowAccess(row, scope, resource, flags) {
|
|
425
817
|
if (!row) return "not_found";
|
|
426
|
-
if (rowMatchesVendorScope(row, scope, resource)) return "ok";
|
|
818
|
+
if (rowMatchesVendorScope(row, scope, resource, flags)) return "ok";
|
|
427
819
|
return scope.type === "vendor" ? "forbidden" : "not_found";
|
|
428
820
|
}
|
|
429
821
|
chunkUSNT2KNT_cjs.__name(vendorScopeRowAccess, "vendorScopeRowAccess");
|
|
@@ -455,14 +847,7 @@ function requireVendorIdForScopedCreate(resource, persistBody, scope, repo, cont
|
|
|
455
847
|
ok: true
|
|
456
848
|
};
|
|
457
849
|
}
|
|
458
|
-
if (resource === "collections" && persistBody.isCatalog === true) {
|
|
459
|
-
delete persistBody.vendorId;
|
|
460
|
-
persistBody.vendorId = getDefaultVendorId();
|
|
461
|
-
return {
|
|
462
|
-
ok: true
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
if (resource === "product_categories" && persistBody.isCatalog === true) {
|
|
850
|
+
if ((resource === "collections" || resource === "product_categories" || resource === "brands") && persistBody.isCatalog === true) {
|
|
466
851
|
delete persistBody.vendorId;
|
|
467
852
|
persistBody.vendorId = getDefaultVendorId();
|
|
468
853
|
return {
|
|
@@ -474,7 +859,7 @@ function requireVendorIdForScopedCreate(resource, persistBody, scope, repo, cont
|
|
|
474
859
|
};
|
|
475
860
|
enforceVendorIdOnCreateBody(persistBody, scope, repo);
|
|
476
861
|
if (scope.type === "vendor") {
|
|
477
|
-
if (resource === "collections") {
|
|
862
|
+
if (resource === "collections" || resource === "product_categories" || resource === "brands") {
|
|
478
863
|
persistBody.isCatalog = false;
|
|
479
864
|
}
|
|
480
865
|
return {
|
|
@@ -3421,6 +3806,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3421
3806
|
const scope = await resolveScope();
|
|
3422
3807
|
const repo2 = dataSource.getRepository(entity);
|
|
3423
3808
|
const statusFilter = searchParams.get("status")?.trim();
|
|
3809
|
+
const approvalStatusFilter = searchParams.get("approvalStatus")?.trim();
|
|
3424
3810
|
const inventory = searchParams.get("inventory")?.trim();
|
|
3425
3811
|
let productWhere = {
|
|
3426
3812
|
deleted: false,
|
|
@@ -3428,6 +3814,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3428
3814
|
};
|
|
3429
3815
|
productWhere = mergeVendorScopeIntoWhere(productWhere, scope, resource);
|
|
3430
3816
|
if (statusFilter) productWhere.status = statusFilter;
|
|
3817
|
+
if (approvalStatusFilter) productWhere.approvalStatus = approvalStatusFilter;
|
|
3431
3818
|
if (inventory === "in_stock") productWhere.quantity = typeorm.MoreThan(0);
|
|
3432
3819
|
if (inventory === "out_of_stock") productWhere.quantity = 0;
|
|
3433
3820
|
for (const key of [
|
|
@@ -3728,6 +4115,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3728
4115
|
where = mergeDeletedFalseWhere(repo, where);
|
|
3729
4116
|
if (resourceUsesVendorScope(resource)) {
|
|
3730
4117
|
const scope = await resolveScope();
|
|
4118
|
+
const catalogFlags = await getVendorCatalogCreateFlags(dataSource);
|
|
3731
4119
|
if (scope.type === "deny") {
|
|
3732
4120
|
where = resource === "vendors" ? {
|
|
3733
4121
|
id: -1
|
|
@@ -3736,7 +4124,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3736
4124
|
};
|
|
3737
4125
|
} else if (resource === "collections") {
|
|
3738
4126
|
if (scope.type === "vendor") {
|
|
3739
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4127
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3740
4128
|
} else if (searchParams.get("isCatalog") !== "true") {
|
|
3741
4129
|
where = mergeListWhereAnd(where, {
|
|
3742
4130
|
isCatalog: false
|
|
@@ -3744,14 +4132,22 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3744
4132
|
}
|
|
3745
4133
|
} else if (resource === "product_categories") {
|
|
3746
4134
|
if (scope.type === "vendor") {
|
|
3747
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4135
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
4136
|
+
} else if (searchParams.get("isCatalog") !== "false") {
|
|
4137
|
+
where = mergeListWhereAnd(where, {
|
|
4138
|
+
isCatalog: true
|
|
4139
|
+
});
|
|
4140
|
+
}
|
|
4141
|
+
} else if (resource === "brands") {
|
|
4142
|
+
if (scope.type === "vendor") {
|
|
4143
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3748
4144
|
} else if (searchParams.get("isCatalog") !== "false") {
|
|
3749
4145
|
where = mergeListWhereAnd(where, {
|
|
3750
4146
|
isCatalog: true
|
|
3751
4147
|
});
|
|
3752
4148
|
}
|
|
3753
4149
|
} else {
|
|
3754
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4150
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3755
4151
|
}
|
|
3756
4152
|
}
|
|
3757
4153
|
let data;
|
|
@@ -3821,16 +4217,11 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3821
4217
|
});
|
|
3822
4218
|
}
|
|
3823
4219
|
const body = rawPostBody;
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
}, {
|
|
3828
|
-
status: 403
|
|
3829
|
-
});
|
|
3830
|
-
}
|
|
3831
|
-
if (vendorCannotMutateCatalogCollections(resource, scopePost, body)) {
|
|
4220
|
+
const catalogFlagsPost = await getVendorCatalogCreateFlags(dataSource);
|
|
4221
|
+
if (vendorCannotMutateCatalogResource(resource, scopePost, catalogFlagsPost, body)) {
|
|
4222
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
3832
4223
|
return json({
|
|
3833
|
-
error:
|
|
4224
|
+
error: `${label} are managed by the platform administrator`
|
|
3834
4225
|
}, {
|
|
3835
4226
|
status: 403
|
|
3836
4227
|
});
|
|
@@ -4215,8 +4606,15 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4215
4606
|
}
|
|
4216
4607
|
if (resource === "products") {
|
|
4217
4608
|
const scopeForProduct = await resolveScope();
|
|
4609
|
+
const productFlags = await getVendorCatalogCreateFlags(dataSource);
|
|
4610
|
+
const requireApproval = await getRequireProductApproval(dataSource);
|
|
4611
|
+
applyVendorProductCreateApproval(persistBody, {
|
|
4612
|
+
isVendor: scopeForProduct.type === "vendor",
|
|
4613
|
+
requireApproval
|
|
4614
|
+
});
|
|
4218
4615
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, persistBody.categoryId, {
|
|
4219
|
-
required: scopeForProduct.type === "vendor"
|
|
4616
|
+
required: scopeForProduct.type === "vendor",
|
|
4617
|
+
allowVendorId: scopeForProduct.type === "vendor" && productFlags.categories ? scopeForProduct.vendorId : void 0
|
|
4220
4618
|
});
|
|
4221
4619
|
if (categoryErr) return json({
|
|
4222
4620
|
error: categoryErr
|
|
@@ -4225,7 +4623,9 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4225
4623
|
});
|
|
4226
4624
|
if (scopeForProduct.type === "vendor") {
|
|
4227
4625
|
if (entityMap.collections && persistBody.collectionId != null && persistBody.collectionId !== "") {
|
|
4228
|
-
const collectionErr = await
|
|
4626
|
+
const collectionErr = await assertCollectionForVendorProduct(dataSource, entityMap.collections, persistBody.collectionId, persistBody.categoryId, scopeForProduct.vendorId, {
|
|
4627
|
+
allowVendorOwned: productFlags.collections
|
|
4628
|
+
});
|
|
4229
4629
|
if (collectionErr) return json({
|
|
4230
4630
|
error: collectionErr
|
|
4231
4631
|
}, {
|
|
@@ -4234,6 +4634,14 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4234
4634
|
}
|
|
4235
4635
|
}
|
|
4236
4636
|
}
|
|
4637
|
+
if (resource === "events") {
|
|
4638
|
+
const scopeForEvent = await resolveScope();
|
|
4639
|
+
const requireEventApproval = await getRequireEventApproval(dataSource);
|
|
4640
|
+
applyVendorEventCreateApproval(persistBody, {
|
|
4641
|
+
isVendor: scopeForEvent.type === "vendor",
|
|
4642
|
+
requireApproval: requireEventApproval
|
|
4643
|
+
});
|
|
4644
|
+
}
|
|
4237
4645
|
if (resource === "collections" && scopePost.type === "vendor") {
|
|
4238
4646
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, persistBody.categoryId, {
|
|
4239
4647
|
required: true
|
|
@@ -4438,7 +4846,27 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4438
4846
|
}
|
|
4439
4847
|
}
|
|
4440
4848
|
}
|
|
4441
|
-
if (
|
|
4849
|
+
if (resource === "brands" && scopeCreate.type === "all") {
|
|
4850
|
+
applyPlatformCatalogBrandFields(persistBody);
|
|
4851
|
+
const slug = String(persistBody.slug ?? "").trim();
|
|
4852
|
+
if (slug) {
|
|
4853
|
+
const dup = await repo.findOne({
|
|
4854
|
+
where: {
|
|
4855
|
+
slug,
|
|
4856
|
+
isCatalog: true,
|
|
4857
|
+
deleted: false
|
|
4858
|
+
}
|
|
4859
|
+
});
|
|
4860
|
+
if (dup) {
|
|
4861
|
+
return json({
|
|
4862
|
+
error: "A catalog brand with this slug already exists"
|
|
4863
|
+
}, {
|
|
4864
|
+
status: 400
|
|
4865
|
+
});
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
if (!((resource === "collections" || resource === "product_categories" || resource === "brands") && persistBody.isCatalog === true)) {
|
|
4442
4870
|
await tryAssignSingleVendorOnAdminCreate(resource, scopeCreate, persistBody);
|
|
4443
4871
|
}
|
|
4444
4872
|
const vendorIdCheck = requireVendorIdForScopedCreate(resource, persistBody, scopeCreate, repo, await vendorCreateContext(body));
|
|
@@ -4918,13 +5346,14 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4918
5346
|
}
|
|
4919
5347
|
chunkUSNT2KNT_cjs.__name(createCrudHandler, "createCrudHandler");
|
|
4920
5348
|
function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
4921
|
-
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId, getVendorScope } = options;
|
|
5349
|
+
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId, getVendorScope, getHydratedSessionUser } = options;
|
|
4922
5350
|
const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
|
|
4923
5351
|
const resolveScopeById = getVendorScope ?? (async () => ({
|
|
4924
5352
|
type: "all"
|
|
4925
5353
|
}));
|
|
4926
|
-
function vendorScopeAccessJson(row, scope, resource) {
|
|
4927
|
-
const
|
|
5354
|
+
async function vendorScopeAccessJson(row, scope, resource) {
|
|
5355
|
+
const flags = await getVendorCatalogCreateFlags(dataSource);
|
|
5356
|
+
const access = vendorScopeRowAccess(row, scope, resource, flags);
|
|
4928
5357
|
if (access === "ok") return null;
|
|
4929
5358
|
if (access === "forbidden") return json({
|
|
4930
5359
|
error: "Forbidden"
|
|
@@ -5004,7 +5433,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5004
5433
|
"rules"
|
|
5005
5434
|
]
|
|
5006
5435
|
});
|
|
5007
|
-
const discountDenied = vendorScopeAccessJson(discount, scope2, resource);
|
|
5436
|
+
const discountDenied = await vendorScopeAccessJson(discount, scope2, resource);
|
|
5008
5437
|
if (discountDenied) return discountDenied;
|
|
5009
5438
|
const flatRules = discount.rules ?? [];
|
|
5010
5439
|
const nestedRules = nestDiscountRules2(flatRules);
|
|
@@ -5062,7 +5491,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5062
5491
|
"payments"
|
|
5063
5492
|
]
|
|
5064
5493
|
});
|
|
5065
|
-
const orderDenied = vendorScopeAccessJson(order, scope2, resource);
|
|
5494
|
+
const orderDenied = await vendorScopeAccessJson(order, scope2, resource);
|
|
5066
5495
|
if (orderDenied) return orderDenied;
|
|
5067
5496
|
const relatedOrders = await repo.find({
|
|
5068
5497
|
where: {
|
|
@@ -5126,7 +5555,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5126
5555
|
"contact"
|
|
5127
5556
|
]
|
|
5128
5557
|
});
|
|
5129
|
-
const paymentDenied = vendorScopeAccessJson(payment, scope2, resource);
|
|
5558
|
+
const paymentDenied = await vendorScopeAccessJson(payment, scope2, resource);
|
|
5130
5559
|
if (paymentDenied) return paymentDenied;
|
|
5131
5560
|
const p = payment;
|
|
5132
5561
|
const order = p.order;
|
|
@@ -5165,7 +5594,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5165
5594
|
"attributes.attribute"
|
|
5166
5595
|
]
|
|
5167
5596
|
});
|
|
5168
|
-
const productDenied = vendorScopeAccessJson(product, scope2, resource);
|
|
5597
|
+
const productDenied = await vendorScopeAccessJson(product, scope2, resource);
|
|
5169
5598
|
if (productDenied) return productDenied;
|
|
5170
5599
|
return product ? json(hydrateProductDisplayName(product)) : json({
|
|
5171
5600
|
message: "Not found"
|
|
@@ -5183,7 +5612,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5183
5612
|
"contact"
|
|
5184
5613
|
]
|
|
5185
5614
|
});
|
|
5186
|
-
const vcDenied = vendorScopeAccessJson(row, scope2, resource);
|
|
5615
|
+
const vcDenied = await vendorScopeAccessJson(row, scope2, resource);
|
|
5187
5616
|
if (vcDenied) return vcDenied;
|
|
5188
5617
|
const contact = row.contact;
|
|
5189
5618
|
return json({
|
|
@@ -5206,7 +5635,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5206
5635
|
"items.product"
|
|
5207
5636
|
]
|
|
5208
5637
|
});
|
|
5209
|
-
const comboDenied = vendorScopeAccessJson(combo, scope2, resource);
|
|
5638
|
+
const comboDenied = await vendorScopeAccessJson(combo, scope2, resource);
|
|
5210
5639
|
if (comboDenied) return comboDenied;
|
|
5211
5640
|
return combo ? json(combo) : json({
|
|
5212
5641
|
message: "Not found"
|
|
@@ -5243,7 +5672,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5243
5672
|
where: idWhere
|
|
5244
5673
|
});
|
|
5245
5674
|
if (resourceUsesVendorScope(resource)) {
|
|
5246
|
-
const itemDenied = vendorScopeAccessJson(item, scope, resource);
|
|
5675
|
+
const itemDenied = await vendorScopeAccessJson(item, scope, resource);
|
|
5247
5676
|
if (itemDenied) return itemDenied;
|
|
5248
5677
|
} else if (!item) {
|
|
5249
5678
|
return json({
|
|
@@ -5272,16 +5701,11 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5272
5701
|
}
|
|
5273
5702
|
const rawBody = await req.json();
|
|
5274
5703
|
const scopePutEarly = await resolveScopeById();
|
|
5275
|
-
|
|
5704
|
+
const catalogFlagsPut = await getVendorCatalogCreateFlags(dataSource);
|
|
5705
|
+
if (vendorCannotMutateCatalogResource(resource, scopePutEarly, catalogFlagsPut, rawBody ?? void 0)) {
|
|
5706
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
5276
5707
|
return json({
|
|
5277
|
-
error:
|
|
5278
|
-
}, {
|
|
5279
|
-
status: 403
|
|
5280
|
-
});
|
|
5281
|
-
}
|
|
5282
|
-
if (vendorCannotMutateCatalogCollections(resource, scopePutEarly, rawBody ?? void 0)) {
|
|
5283
|
-
return json({
|
|
5284
|
-
error: "Collections are managed by the platform administrator"
|
|
5708
|
+
error: `${label} are managed by the platform administrator`
|
|
5285
5709
|
}, {
|
|
5286
5710
|
status: 403
|
|
5287
5711
|
});
|
|
@@ -5647,7 +6071,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5647
6071
|
id: numericId
|
|
5648
6072
|
}
|
|
5649
6073
|
});
|
|
5650
|
-
const discountPutDenied = vendorScopeAccessJson(existing, scopePut2, resource);
|
|
6074
|
+
const discountPutDenied = await vendorScopeAccessJson(existing, scopePut2, resource);
|
|
5651
6075
|
if (discountPutDenied) return discountPutDenied;
|
|
5652
6076
|
const updatePayload2 = pickColumnUpdates(repo, rawBody);
|
|
5653
6077
|
delete updatePayload2.vendorId;
|
|
@@ -5705,8 +6129,16 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5705
6129
|
const existingScope = await repo.findOne({
|
|
5706
6130
|
where: idWhereCheck
|
|
5707
6131
|
});
|
|
5708
|
-
const scopePutDenied = vendorScopeAccessJson(existingScope, scopePut, resource);
|
|
6132
|
+
const scopePutDenied = await vendorScopeAccessJson(existingScope, scopePut, resource);
|
|
5709
6133
|
if (scopePutDenied) return scopePutDenied;
|
|
6134
|
+
if (vendorCannotMutateExistingCatalogRow(resource, scopePut, existingScope)) {
|
|
6135
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : "Brands";
|
|
6136
|
+
return json({
|
|
6137
|
+
error: `${label} are managed by the platform administrator`
|
|
6138
|
+
}, {
|
|
6139
|
+
status: 403
|
|
6140
|
+
});
|
|
6141
|
+
}
|
|
5710
6142
|
}
|
|
5711
6143
|
const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
|
|
5712
6144
|
if (resourceUsesVendorScope(resource)) {
|
|
@@ -5853,7 +6285,8 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5853
6285
|
});
|
|
5854
6286
|
const mergedCategoryId = "categoryId" in updatePayload ? updatePayload.categoryId : currentRow.categoryId;
|
|
5855
6287
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, "categoryId" in updatePayload ? updatePayload.categoryId : mergedCategoryId, {
|
|
5856
|
-
required: scopePut.type === "vendor"
|
|
6288
|
+
required: scopePut.type === "vendor",
|
|
6289
|
+
allowVendorId: scopePut.type === "vendor" && catalogFlagsPut.categories ? scopePut.vendorId : void 0
|
|
5857
6290
|
});
|
|
5858
6291
|
if (categoryErr) return json({
|
|
5859
6292
|
error: categoryErr
|
|
@@ -5862,7 +6295,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5862
6295
|
});
|
|
5863
6296
|
if (scopePut.type === "vendor") {
|
|
5864
6297
|
if (entityMap.collections && "collectionId" in updatePayload && updatePayload.collectionId != null) {
|
|
5865
|
-
const collectionErr = await
|
|
6298
|
+
const collectionErr = await assertCollectionForVendorProduct(dataSource, entityMap.collections, updatePayload.collectionId, mergedCategoryId, scopePut.vendorId, {
|
|
6299
|
+
allowVendorOwned: catalogFlagsPut.collections
|
|
6300
|
+
});
|
|
5866
6301
|
if (collectionErr) return json({
|
|
5867
6302
|
error: collectionErr
|
|
5868
6303
|
}, {
|
|
@@ -5870,6 +6305,88 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5870
6305
|
});
|
|
5871
6306
|
}
|
|
5872
6307
|
}
|
|
6308
|
+
if ("status" in updatePayload || "approvalStatus" in updatePayload || "rejectionReason" in updatePayload) {
|
|
6309
|
+
const fromStatus = String(currentRow.status ?? "draft");
|
|
6310
|
+
const toStatus = String("status" in updatePayload ? updatePayload.status ?? fromStatus : fromStatus);
|
|
6311
|
+
const fromApproval = currentRow.approvalStatus;
|
|
6312
|
+
const toApproval = "approvalStatus" in updatePayload ? updatePayload.approvalStatus : fromApproval;
|
|
6313
|
+
const requireApproval = await getRequireProductApproval(dataSource);
|
|
6314
|
+
const reasonFromBody = "rejectionReason" in updatePayload ? updatePayload.rejectionReason : currentRow.rejectionReason;
|
|
6315
|
+
const reasonStr = typeof reasonFromBody === "string" ? reasonFromBody : reasonFromBody == null ? null : String(reasonFromBody);
|
|
6316
|
+
const transition = assertProductApprovalUpdate({
|
|
6317
|
+
fromApproval,
|
|
6318
|
+
toApproval,
|
|
6319
|
+
fromStatus,
|
|
6320
|
+
toStatus,
|
|
6321
|
+
isVendor: scopePut.type === "vendor",
|
|
6322
|
+
requireApproval,
|
|
6323
|
+
approvalChanged: "approvalStatus" in updatePayload,
|
|
6324
|
+
statusChanged: "status" in updatePayload,
|
|
6325
|
+
rejectionReason: reasonStr
|
|
6326
|
+
});
|
|
6327
|
+
if (!transition.ok) return json({
|
|
6328
|
+
error: transition.error
|
|
6329
|
+
}, {
|
|
6330
|
+
status: 400
|
|
6331
|
+
});
|
|
6332
|
+
if ("approvalStatus" in updatePayload && scopePut.type !== "vendor") {
|
|
6333
|
+
const session = await getHydratedSessionUser?.() ?? null;
|
|
6334
|
+
const rejectedByRaw = session?.id != null ? Number(session.id) : null;
|
|
6335
|
+
applyApprovalStatusSideEffects(updatePayload, {
|
|
6336
|
+
toApproval,
|
|
6337
|
+
currentStatus: fromStatus,
|
|
6338
|
+
rejectionReason: reasonStr,
|
|
6339
|
+
rejectedBy: Number.isFinite(rejectedByRaw) ? rejectedByRaw : null
|
|
6340
|
+
});
|
|
6341
|
+
}
|
|
6342
|
+
}
|
|
6343
|
+
}
|
|
6344
|
+
if (resource === "events") {
|
|
6345
|
+
const currentEvent = await repo.findOne({
|
|
6346
|
+
where: {
|
|
6347
|
+
id: numericId,
|
|
6348
|
+
deleted: false
|
|
6349
|
+
}
|
|
6350
|
+
});
|
|
6351
|
+
if (!currentEvent) return json({
|
|
6352
|
+
message: "Not found"
|
|
6353
|
+
}, {
|
|
6354
|
+
status: 404
|
|
6355
|
+
});
|
|
6356
|
+
if ("isActive" in updatePayload || "approvalStatus" in updatePayload || "rejectionReason" in updatePayload) {
|
|
6357
|
+
const fromActive = Boolean(currentEvent.isActive);
|
|
6358
|
+
const toActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : fromActive;
|
|
6359
|
+
const fromApproval = currentEvent.approvalStatus;
|
|
6360
|
+
const toApproval = "approvalStatus" in updatePayload ? updatePayload.approvalStatus : fromApproval;
|
|
6361
|
+
const requireEventApproval = await getRequireEventApproval(dataSource);
|
|
6362
|
+
const reasonFromBody = "rejectionReason" in updatePayload ? updatePayload.rejectionReason : currentEvent.rejectionReason;
|
|
6363
|
+
const reasonStr = typeof reasonFromBody === "string" ? reasonFromBody : reasonFromBody == null ? null : String(reasonFromBody);
|
|
6364
|
+
const transition = assertEventApprovalUpdate({
|
|
6365
|
+
fromApproval,
|
|
6366
|
+
toApproval,
|
|
6367
|
+
toActive,
|
|
6368
|
+
isVendor: scopePut.type === "vendor",
|
|
6369
|
+
requireApproval: requireEventApproval,
|
|
6370
|
+
approvalChanged: "approvalStatus" in updatePayload,
|
|
6371
|
+
activeChanged: "isActive" in updatePayload,
|
|
6372
|
+
rejectionReason: reasonStr
|
|
6373
|
+
});
|
|
6374
|
+
if (!transition.ok) return json({
|
|
6375
|
+
error: transition.error
|
|
6376
|
+
}, {
|
|
6377
|
+
status: 400
|
|
6378
|
+
});
|
|
6379
|
+
if ("approvalStatus" in updatePayload && scopePut.type !== "vendor") {
|
|
6380
|
+
const session = await getHydratedSessionUser?.() ?? null;
|
|
6381
|
+
const rejectedByRaw = session?.id != null ? Number(session.id) : null;
|
|
6382
|
+
applyEventApprovalStatusSideEffects(updatePayload, {
|
|
6383
|
+
toApproval,
|
|
6384
|
+
currentActive: fromActive,
|
|
6385
|
+
rejectionReason: reasonStr,
|
|
6386
|
+
rejectedBy: Number.isFinite(rejectedByRaw) ? rejectedByRaw : null
|
|
6387
|
+
});
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
5873
6390
|
}
|
|
5874
6391
|
if (resource === "product_categories" && scopePut.type === "all") {
|
|
5875
6392
|
const existingCatalogCat = await repo.findOne({
|
|
@@ -5927,6 +6444,34 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5927
6444
|
}
|
|
5928
6445
|
}
|
|
5929
6446
|
}
|
|
6447
|
+
if (resource === "brands" && scopePut.type === "all") {
|
|
6448
|
+
const existingCatalogBrand = await repo.findOne({
|
|
6449
|
+
where: {
|
|
6450
|
+
id: numericId,
|
|
6451
|
+
deleted: false
|
|
6452
|
+
}
|
|
6453
|
+
});
|
|
6454
|
+
if (existingCatalogBrand && existingCatalogBrand.isCatalog === true) {
|
|
6455
|
+
applyPlatformCatalogBrandFields(updatePayload);
|
|
6456
|
+
const slug = String(updatePayload.slug ?? existingCatalogBrand.slug ?? "").trim();
|
|
6457
|
+
if (slug && "slug" in updatePayload) {
|
|
6458
|
+
const dup = await repo.findOne({
|
|
6459
|
+
where: {
|
|
6460
|
+
slug,
|
|
6461
|
+
isCatalog: true,
|
|
6462
|
+
deleted: false
|
|
6463
|
+
}
|
|
6464
|
+
});
|
|
6465
|
+
if (dup && Number(dup.id) !== numericId) {
|
|
6466
|
+
return json({
|
|
6467
|
+
error: "A catalog brand with this slug already exists"
|
|
6468
|
+
}, {
|
|
6469
|
+
status: 400
|
|
6470
|
+
});
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
5930
6475
|
if (resource === "addresses" && Object.keys(updatePayload).length > 0) {
|
|
5931
6476
|
const currentRow = await repo.findOne({
|
|
5932
6477
|
where: {
|
|
@@ -6082,9 +6627,11 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6082
6627
|
const authError = await authz(req, resource, "delete");
|
|
6083
6628
|
if (authError) return authError;
|
|
6084
6629
|
const scopeDeleteEarly = await resolveScopeById();
|
|
6085
|
-
|
|
6630
|
+
const catalogFlagsDelete = await getVendorCatalogCreateFlags(dataSource);
|
|
6631
|
+
if (vendorCannotMutateCatalogResource(resource, scopeDeleteEarly, catalogFlagsDelete)) {
|
|
6632
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
6086
6633
|
return json({
|
|
6087
|
-
error:
|
|
6634
|
+
error: `${label} are managed by the platform administrator`
|
|
6088
6635
|
}, {
|
|
6089
6636
|
status: 403
|
|
6090
6637
|
});
|
|
@@ -6113,7 +6660,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6113
6660
|
}
|
|
6114
6661
|
});
|
|
6115
6662
|
if (resourceUsesVendorScope(resource)) {
|
|
6116
|
-
const deleteDenied = vendorScopeAccessJson(existing, scopeDelete, resource);
|
|
6663
|
+
const deleteDenied = await vendorScopeAccessJson(existing, scopeDelete, resource);
|
|
6117
6664
|
if (deleteDenied) return deleteDenied;
|
|
6118
6665
|
} else if (!existing) {
|
|
6119
6666
|
return json({
|
|
@@ -6171,7 +6718,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6171
6718
|
id: numericId
|
|
6172
6719
|
}
|
|
6173
6720
|
});
|
|
6174
|
-
const hardDeleteDenied = vendorScopeAccessJson(existingHard, scopeDelete, resource);
|
|
6721
|
+
const hardDeleteDenied = await vendorScopeAccessJson(existingHard, scopeDelete, resource);
|
|
6175
6722
|
if (hardDeleteDenied) return hardDeleteDenied;
|
|
6176
6723
|
}
|
|
6177
6724
|
const result = await repo.delete(numericId);
|
|
@@ -7649,7 +8196,7 @@ function createVendorDashboardHandler(config) {
|
|
|
7649
8196
|
if (pe) return pe;
|
|
7650
8197
|
}
|
|
7651
8198
|
const user = await getSessionUser();
|
|
7652
|
-
if (!user || !
|
|
8199
|
+
if (!user || !chunkX6UQFV4X_cjs.isVendorPortalUser(user)) {
|
|
7653
8200
|
return json({
|
|
7654
8201
|
error: "Forbidden"
|
|
7655
8202
|
}, {
|
|
@@ -11468,7 +12015,7 @@ chunkUSNT2KNT_cjs.__name(findActiveRefundPolicyForVendor, "findActiveRefundPolic
|
|
|
11468
12015
|
// src/api/admin-roles-handlers.ts
|
|
11469
12016
|
function createAdminRolesHandlers(config) {
|
|
11470
12017
|
const { dataSource, entityMap, json, getSessionUser } = config;
|
|
11471
|
-
const baseEntities =
|
|
12018
|
+
const baseEntities = chunkX6UQFV4X_cjs.getPermissionableEntityKeys(entityMap);
|
|
11472
12019
|
const allowEntities = /* @__PURE__ */ new Set([
|
|
11473
12020
|
...baseEntities,
|
|
11474
12021
|
"users"
|
|
@@ -11483,7 +12030,7 @@ function createAdminRolesHandlers(config) {
|
|
|
11483
12030
|
}, {
|
|
11484
12031
|
status: 401
|
|
11485
12032
|
});
|
|
11486
|
-
if (!
|
|
12033
|
+
if (!chunkZMRQ72F6_cjs.canManageRoles(u) && !chunkX6UQFV4X_cjs.canManageVendorRoles(u)) {
|
|
11487
12034
|
return json({
|
|
11488
12035
|
error: "Forbidden"
|
|
11489
12036
|
}, {
|
|
@@ -11494,11 +12041,11 @@ function createAdminRolesHandlers(config) {
|
|
|
11494
12041
|
}
|
|
11495
12042
|
chunkUSNT2KNT_cjs.__name(gate, "gate");
|
|
11496
12043
|
function isVendorRolesOnly(u) {
|
|
11497
|
-
return
|
|
12044
|
+
return chunkX6UQFV4X_cjs.canManageVendorRoles(u) && !chunkZMRQ72F6_cjs.canManageRoles(u);
|
|
11498
12045
|
}
|
|
11499
12046
|
chunkUSNT2KNT_cjs.__name(isVendorRolesOnly, "isVendorRolesOnly");
|
|
11500
12047
|
const vendorRoleEntities = [
|
|
11501
|
-
...
|
|
12048
|
+
...chunkX6UQFV4X_cjs.VENDOR_STORE_RBAC_ENTITIES,
|
|
11502
12049
|
"dashboard",
|
|
11503
12050
|
"settings"
|
|
11504
12051
|
].sort();
|
|
@@ -11655,7 +12202,7 @@ function createAdminRolesHandlers(config) {
|
|
|
11655
12202
|
}, {
|
|
11656
12203
|
status: 404
|
|
11657
12204
|
});
|
|
11658
|
-
if (
|
|
12205
|
+
if (chunkX6UQFV4X_cjs.isSuperAdminGroupName(g.name) && !chunkX6UQFV4X_cjs.isSuperAdminGroupName(name)) {
|
|
11659
12206
|
return json({
|
|
11660
12207
|
error: "Cannot rename the administrator group"
|
|
11661
12208
|
}, {
|
|
@@ -11712,7 +12259,7 @@ function createAdminRolesHandlers(config) {
|
|
|
11712
12259
|
}, {
|
|
11713
12260
|
status: 404
|
|
11714
12261
|
});
|
|
11715
|
-
if (
|
|
12262
|
+
if (chunkX6UQFV4X_cjs.isSuperAdminGroupName(g.name)) return json({
|
|
11716
12263
|
error: "Cannot delete the administrator group"
|
|
11717
12264
|
}, {
|
|
11718
12265
|
status: 400
|
|
@@ -11880,7 +12427,7 @@ chunkUSNT2KNT_cjs.__name(sendVendorOnboardEmails, "sendVendorOnboardEmails");
|
|
|
11880
12427
|
|
|
11881
12428
|
// src/lib/seed-vendor-roles.ts
|
|
11882
12429
|
async function insertRolePermissions(exec, vendorRoleId, permissions) {
|
|
11883
|
-
for (const entity of
|
|
12430
|
+
for (const entity of chunkX6UQFV4X_cjs.VENDOR_RBAC_ENTITIES) {
|
|
11884
12431
|
const flags = permissions[entity];
|
|
11885
12432
|
if (!flags) continue;
|
|
11886
12433
|
await exec.query(`
|
|
@@ -11911,7 +12458,7 @@ async function seedVendorDefaultRoles(em, vendorId) {
|
|
|
11911
12458
|
for (const r of existing) {
|
|
11912
12459
|
roleIdsByName2[r.name] = Number(r.id);
|
|
11913
12460
|
if (r.isOwnerRole) ownerRoleId2 = Number(r.id);
|
|
11914
|
-
if (r.name ===
|
|
12461
|
+
if (r.name === chunkX6UQFV4X_cjs.VENDOR_VIEWER_ROLE_NAME) viewerRoleId2 = Number(r.id);
|
|
11915
12462
|
}
|
|
11916
12463
|
return {
|
|
11917
12464
|
roleIdsByName: roleIdsByName2,
|
|
@@ -11922,7 +12469,7 @@ async function seedVendorDefaultRoles(em, vendorId) {
|
|
|
11922
12469
|
const roleIdsByName = {};
|
|
11923
12470
|
let ownerRoleId = 0;
|
|
11924
12471
|
let viewerRoleId = 0;
|
|
11925
|
-
for (const def of
|
|
12472
|
+
for (const def of chunkX6UQFV4X_cjs.DEFAULT_VENDOR_ROLE_DEFS) {
|
|
11926
12473
|
const inserted = await exec.query(`
|
|
11927
12474
|
INSERT INTO "vendor_roles"
|
|
11928
12475
|
("vendorId", "name", "description", "isSystem", "isOwnerRole")
|
|
@@ -11939,7 +12486,7 @@ async function seedVendorDefaultRoles(em, vendorId) {
|
|
|
11939
12486
|
if (!roleId) continue;
|
|
11940
12487
|
roleIdsByName[def.name] = roleId;
|
|
11941
12488
|
if (def.isOwnerRole) ownerRoleId = roleId;
|
|
11942
|
-
if (def.name ===
|
|
12489
|
+
if (def.name === chunkX6UQFV4X_cjs.VENDOR_VIEWER_ROLE_NAME) viewerRoleId = roleId;
|
|
11943
12490
|
await insertRolePermissions(exec, roleId, def.permissions);
|
|
11944
12491
|
}
|
|
11945
12492
|
return {
|
|
@@ -11960,7 +12507,7 @@ async function backfillVendorUserRoleIds(em, vendorId, seeded) {
|
|
|
11960
12507
|
vendorId
|
|
11961
12508
|
]);
|
|
11962
12509
|
}
|
|
11963
|
-
const viewerId = seeded.viewerRoleId || seeded.roleIdsByName[
|
|
12510
|
+
const viewerId = seeded.viewerRoleId || seeded.roleIdsByName[chunkX6UQFV4X_cjs.VENDOR_VIEWER_ROLE_NAME];
|
|
11964
12511
|
if (viewerId) {
|
|
11965
12512
|
await em.query(`
|
|
11966
12513
|
UPDATE "vendor_users"
|
|
@@ -11986,7 +12533,7 @@ async function getDefaultStaffRoleIdForVendor(em, vendorId) {
|
|
|
11986
12533
|
LIMIT 1
|
|
11987
12534
|
`, [
|
|
11988
12535
|
vendorId,
|
|
11989
|
-
|
|
12536
|
+
chunkX6UQFV4X_cjs.VENDOR_VIEWER_ROLE_NAME
|
|
11990
12537
|
]);
|
|
11991
12538
|
const id = rows[0]?.id;
|
|
11992
12539
|
return id != null ? Number(id) : null;
|
|
@@ -12162,7 +12709,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12162
12709
|
}, {
|
|
12163
12710
|
status: 401
|
|
12164
12711
|
});
|
|
12165
|
-
if (!
|
|
12712
|
+
if (!chunkX6UQFV4X_cjs.isPlatformAdministrator(u)) return json({
|
|
12166
12713
|
error: "Forbidden",
|
|
12167
12714
|
reason: "admin_only"
|
|
12168
12715
|
}, {
|
|
@@ -12172,7 +12719,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12172
12719
|
}
|
|
12173
12720
|
chunkUSNT2KNT_cjs.__name(gateAdmin, "gateAdmin");
|
|
12174
12721
|
async function resolveActiveVendorId(u) {
|
|
12175
|
-
const scope =
|
|
12722
|
+
const scope = chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u);
|
|
12176
12723
|
if (scope.type === "vendor") return scope.vendorId;
|
|
12177
12724
|
if (scope.type === "all") {
|
|
12178
12725
|
const id = u.activeVendorId ?? u.vendorIds?.[0];
|
|
@@ -12188,7 +12735,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12188
12735
|
}, {
|
|
12189
12736
|
status: 401
|
|
12190
12737
|
});
|
|
12191
|
-
if (!
|
|
12738
|
+
if (!chunkX6UQFV4X_cjs.canManageVendorTeam(u)) return json({
|
|
12192
12739
|
error: "Forbidden"
|
|
12193
12740
|
}, {
|
|
12194
12741
|
status: 403
|
|
@@ -12304,19 +12851,19 @@ function createVendorOnboardHandlers(config) {
|
|
|
12304
12851
|
if (dupVendor) throw new Error("VENDOR_SLUG_EXISTS");
|
|
12305
12852
|
let ownerGroup = await groupRepo.findOne({
|
|
12306
12853
|
where: {
|
|
12307
|
-
name:
|
|
12854
|
+
name: chunkX6UQFV4X_cjs.VENDOR_OWNER_GROUP_NAME,
|
|
12308
12855
|
deleted: false
|
|
12309
12856
|
}
|
|
12310
12857
|
});
|
|
12311
12858
|
if (!ownerGroup) {
|
|
12312
12859
|
try {
|
|
12313
12860
|
await groupRepo.save(groupRepo.create({
|
|
12314
|
-
name:
|
|
12861
|
+
name: chunkX6UQFV4X_cjs.VENDOR_OWNER_GROUP_NAME,
|
|
12315
12862
|
deleted: false
|
|
12316
12863
|
}));
|
|
12317
12864
|
ownerGroup = await groupRepo.findOne({
|
|
12318
12865
|
where: {
|
|
12319
|
-
name:
|
|
12866
|
+
name: chunkX6UQFV4X_cjs.VENDOR_OWNER_GROUP_NAME,
|
|
12320
12867
|
deleted: false
|
|
12321
12868
|
}
|
|
12322
12869
|
});
|
|
@@ -12776,7 +13323,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12776
13323
|
if (!groupId) {
|
|
12777
13324
|
const g = await groupRepo.findOne({
|
|
12778
13325
|
where: {
|
|
12779
|
-
name:
|
|
13326
|
+
name: chunkX6UQFV4X_cjs.VENDOR_OWNER_GROUP_NAME,
|
|
12780
13327
|
deleted: false
|
|
12781
13328
|
}
|
|
12782
13329
|
});
|
|
@@ -13086,10 +13633,10 @@ chunkUSNT2KNT_cjs.__name(createVendorOnboardHandlers, "createVendorOnboardHandle
|
|
|
13086
13633
|
function createVendorRolesHandlers(config) {
|
|
13087
13634
|
const { dataSource, entityMap, json, getSessionUser } = config;
|
|
13088
13635
|
const vendorRoleEntities = [
|
|
13089
|
-
...
|
|
13636
|
+
...chunkX6UQFV4X_cjs.VENDOR_RBAC_ENTITIES
|
|
13090
13637
|
].sort();
|
|
13091
13638
|
async function resolveActiveVendorId(u) {
|
|
13092
|
-
const scope =
|
|
13639
|
+
const scope = chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u);
|
|
13093
13640
|
if (scope.type === "vendor") return scope.vendorId;
|
|
13094
13641
|
if (scope.type === "all") {
|
|
13095
13642
|
const id = u.activeVendorId ?? u.vendorIds?.[0];
|
|
@@ -13105,7 +13652,7 @@ function createVendorRolesHandlers(config) {
|
|
|
13105
13652
|
}, {
|
|
13106
13653
|
status: 401
|
|
13107
13654
|
});
|
|
13108
|
-
if (!
|
|
13655
|
+
if (!chunkX6UQFV4X_cjs.canManageVendorRoles(u)) return json({
|
|
13109
13656
|
error: "Forbidden"
|
|
13110
13657
|
}, {
|
|
13111
13658
|
status: 403
|
|
@@ -17044,6 +17591,7 @@ exports.Brand = class Brand {
|
|
|
17044
17591
|
chunkUSNT2KNT_cjs.__name(this, "Brand");
|
|
17045
17592
|
}
|
|
17046
17593
|
id;
|
|
17594
|
+
/** Null for platform catalog brands (`isCatalog`). */
|
|
17047
17595
|
vendorId;
|
|
17048
17596
|
name;
|
|
17049
17597
|
slug;
|
|
@@ -17051,6 +17599,8 @@ exports.Brand = class Brand {
|
|
|
17051
17599
|
metadata;
|
|
17052
17600
|
description;
|
|
17053
17601
|
active;
|
|
17602
|
+
/** Platform-wide catalog brand — vendors pick these on products unless allowed to create their own. */
|
|
17603
|
+
isCatalog;
|
|
17054
17604
|
sortOrder;
|
|
17055
17605
|
createdAt;
|
|
17056
17606
|
updatedAt;
|
|
@@ -17070,8 +17620,10 @@ _ts_decorate30([
|
|
|
17070
17620
|
_ts_metadata30("design:type", Number)
|
|
17071
17621
|
], exports.Brand.prototype, "id", void 0);
|
|
17072
17622
|
_ts_decorate30([
|
|
17073
|
-
typeorm.Column("int"
|
|
17074
|
-
|
|
17623
|
+
typeorm.Column("int", {
|
|
17624
|
+
nullable: true
|
|
17625
|
+
}),
|
|
17626
|
+
_ts_metadata30("design:type", Object)
|
|
17075
17627
|
], exports.Brand.prototype, "vendorId", void 0);
|
|
17076
17628
|
_ts_decorate30([
|
|
17077
17629
|
typeorm.Column("varchar"),
|
|
@@ -17105,6 +17657,12 @@ _ts_decorate30([
|
|
|
17105
17657
|
}),
|
|
17106
17658
|
_ts_metadata30("design:type", Boolean)
|
|
17107
17659
|
], exports.Brand.prototype, "active", void 0);
|
|
17660
|
+
_ts_decorate30([
|
|
17661
|
+
typeorm.Column("boolean", {
|
|
17662
|
+
default: false
|
|
17663
|
+
}),
|
|
17664
|
+
_ts_metadata30("design:type", Boolean)
|
|
17665
|
+
], exports.Brand.prototype, "isCatalog", void 0);
|
|
17108
17666
|
_ts_decorate30([
|
|
17109
17667
|
typeorm.Column("int", {
|
|
17110
17668
|
default: 0
|
|
@@ -17164,12 +17722,13 @@ _ts_decorate30([
|
|
|
17164
17722
|
], exports.Brand.prototype, "seoId", void 0);
|
|
17165
17723
|
_ts_decorate30([
|
|
17166
17724
|
typeorm.ManyToOne(() => exports.Vendor, {
|
|
17167
|
-
onDelete: "RESTRICT"
|
|
17725
|
+
onDelete: "RESTRICT",
|
|
17726
|
+
nullable: true
|
|
17168
17727
|
}),
|
|
17169
17728
|
typeorm.JoinColumn({
|
|
17170
17729
|
name: "vendorId"
|
|
17171
17730
|
}),
|
|
17172
|
-
_ts_metadata30("design:type",
|
|
17731
|
+
_ts_metadata30("design:type", Object)
|
|
17173
17732
|
], exports.Brand.prototype, "vendor", void 0);
|
|
17174
17733
|
_ts_decorate30([
|
|
17175
17734
|
typeorm.ManyToOne(() => exports.Seo, {
|
|
@@ -17453,6 +18012,14 @@ exports.Product = class Product {
|
|
|
17453
18012
|
currencyPrices;
|
|
17454
18013
|
quantity;
|
|
17455
18014
|
status;
|
|
18015
|
+
/**
|
|
18016
|
+
* Separate from catalog status. Used when multi_vendor.requireProductApproval is on.
|
|
18017
|
+
* `approved` also forces `status = available` (live).
|
|
18018
|
+
*/
|
|
18019
|
+
approvalStatus;
|
|
18020
|
+
rejectionReason;
|
|
18021
|
+
rejectedAt;
|
|
18022
|
+
rejectedBy;
|
|
17456
18023
|
featured;
|
|
17457
18024
|
metadata;
|
|
17458
18025
|
createdAt;
|
|
@@ -17576,6 +18143,31 @@ _ts_decorate32([
|
|
|
17576
18143
|
}),
|
|
17577
18144
|
_ts_metadata32("design:type", String)
|
|
17578
18145
|
], exports.Product.prototype, "status", void 0);
|
|
18146
|
+
_ts_decorate32([
|
|
18147
|
+
typeorm.Column("varchar", {
|
|
18148
|
+
nullable: true
|
|
18149
|
+
}),
|
|
18150
|
+
_ts_metadata32("design:type", Object)
|
|
18151
|
+
], exports.Product.prototype, "approvalStatus", void 0);
|
|
18152
|
+
_ts_decorate32([
|
|
18153
|
+
typeorm.Column("text", {
|
|
18154
|
+
nullable: true
|
|
18155
|
+
}),
|
|
18156
|
+
_ts_metadata32("design:type", Object)
|
|
18157
|
+
], exports.Product.prototype, "rejectionReason", void 0);
|
|
18158
|
+
_ts_decorate32([
|
|
18159
|
+
typeorm.Column({
|
|
18160
|
+
type: "timestamptz",
|
|
18161
|
+
nullable: true
|
|
18162
|
+
}),
|
|
18163
|
+
_ts_metadata32("design:type", Object)
|
|
18164
|
+
], exports.Product.prototype, "rejectedAt", void 0);
|
|
18165
|
+
_ts_decorate32([
|
|
18166
|
+
typeorm.Column("int", {
|
|
18167
|
+
nullable: true
|
|
18168
|
+
}),
|
|
18169
|
+
_ts_metadata32("design:type", Object)
|
|
18170
|
+
], exports.Product.prototype, "rejectedBy", void 0);
|
|
17579
18171
|
_ts_decorate32([
|
|
17580
18172
|
typeorm.Column("boolean", {
|
|
17581
18173
|
default: false
|
|
@@ -20664,6 +21256,14 @@ exports.Event = class Event {
|
|
|
20664
21256
|
expectedSpeakers;
|
|
20665
21257
|
expectedParticipants;
|
|
20666
21258
|
isActive;
|
|
21259
|
+
/**
|
|
21260
|
+
* Separate from isActive. Used when events.requireEventApproval is on.
|
|
21261
|
+
* `approved` also forces `isActive = true` (live).
|
|
21262
|
+
*/
|
|
21263
|
+
approvalStatus;
|
|
21264
|
+
rejectionReason;
|
|
21265
|
+
rejectedAt;
|
|
21266
|
+
rejectedBy;
|
|
20667
21267
|
comingSoon;
|
|
20668
21268
|
bannerImageUrl;
|
|
20669
21269
|
logoUrl;
|
|
@@ -20758,6 +21358,31 @@ _ts_decorate60([
|
|
|
20758
21358
|
}),
|
|
20759
21359
|
_ts_metadata60("design:type", Boolean)
|
|
20760
21360
|
], exports.Event.prototype, "isActive", void 0);
|
|
21361
|
+
_ts_decorate60([
|
|
21362
|
+
typeorm.Column("varchar", {
|
|
21363
|
+
nullable: true
|
|
21364
|
+
}),
|
|
21365
|
+
_ts_metadata60("design:type", Object)
|
|
21366
|
+
], exports.Event.prototype, "approvalStatus", void 0);
|
|
21367
|
+
_ts_decorate60([
|
|
21368
|
+
typeorm.Column("text", {
|
|
21369
|
+
nullable: true
|
|
21370
|
+
}),
|
|
21371
|
+
_ts_metadata60("design:type", Object)
|
|
21372
|
+
], exports.Event.prototype, "rejectionReason", void 0);
|
|
21373
|
+
_ts_decorate60([
|
|
21374
|
+
typeorm.Column({
|
|
21375
|
+
type: "timestamptz",
|
|
21376
|
+
nullable: true
|
|
21377
|
+
}),
|
|
21378
|
+
_ts_metadata60("design:type", Object)
|
|
21379
|
+
], exports.Event.prototype, "rejectedAt", void 0);
|
|
21380
|
+
_ts_decorate60([
|
|
21381
|
+
typeorm.Column("int", {
|
|
21382
|
+
nullable: true
|
|
21383
|
+
}),
|
|
21384
|
+
_ts_metadata60("design:type", Object)
|
|
21385
|
+
], exports.Event.prototype, "rejectedBy", void 0);
|
|
20761
21386
|
_ts_decorate60([
|
|
20762
21387
|
typeorm.Column("boolean", {
|
|
20763
21388
|
default: false
|
|
@@ -21318,18 +21943,20 @@ _ts_decorate63([
|
|
|
21318
21943
|
], exports.Combo.prototype, "desc", void 0);
|
|
21319
21944
|
_ts_decorate63([
|
|
21320
21945
|
typeorm.Column({
|
|
21321
|
-
type: "integer"
|
|
21946
|
+
type: "integer",
|
|
21947
|
+
nullable: true
|
|
21322
21948
|
}),
|
|
21323
|
-
_ts_metadata63("design:type",
|
|
21949
|
+
_ts_metadata63("design:type", Object)
|
|
21324
21950
|
], exports.Combo.prototype, "eventId", void 0);
|
|
21325
21951
|
_ts_decorate63([
|
|
21326
21952
|
typeorm.ManyToOne(() => exports.Event, {
|
|
21327
|
-
onDelete: "CASCADE"
|
|
21953
|
+
onDelete: "CASCADE",
|
|
21954
|
+
nullable: true
|
|
21328
21955
|
}),
|
|
21329
21956
|
typeorm.JoinColumn({
|
|
21330
21957
|
name: "eventId"
|
|
21331
21958
|
}),
|
|
21332
|
-
_ts_metadata63("design:type",
|
|
21959
|
+
_ts_metadata63("design:type", Object)
|
|
21333
21960
|
], exports.Combo.prototype, "event", void 0);
|
|
21334
21961
|
_ts_decorate63([
|
|
21335
21962
|
typeorm.Column({
|
|
@@ -25589,7 +26216,7 @@ function createCmsApiHandler(config) {
|
|
|
25589
26216
|
] : baseCrudResources;
|
|
25590
26217
|
const requireEntityPermissionEffective = /* @__PURE__ */ chunkUSNT2KNT_cjs.__name(async (_req, entity, action) => {
|
|
25591
26218
|
if (!resolveSessionUser) {
|
|
25592
|
-
|
|
26219
|
+
chunkX6UQFV4X_cjs.logRbac("requireEntityPermission: getSessionUser not passed \u2014 vendor store APIs may 403", {
|
|
25593
26220
|
entity,
|
|
25594
26221
|
action,
|
|
25595
26222
|
hint: "Pass getSessionUser: auth.getAuthenticatedUser from createCmsAuthBundle()"
|
|
@@ -25599,7 +26226,7 @@ function createCmsApiHandler(config) {
|
|
|
25599
26226
|
const raw = await resolveSessionUser();
|
|
25600
26227
|
const u = await hydrateVendorSessionUser(dataSource, raw);
|
|
25601
26228
|
if (!u?.email) {
|
|
25602
|
-
|
|
26229
|
+
chunkX6UQFV4X_cjs.logRbac("requireEntityPermission: no session user", {
|
|
25603
26230
|
entity,
|
|
25604
26231
|
action
|
|
25605
26232
|
});
|
|
@@ -25609,13 +26236,13 @@ function createCmsApiHandler(config) {
|
|
|
25609
26236
|
status: 401
|
|
25610
26237
|
});
|
|
25611
26238
|
}
|
|
25612
|
-
const allowed =
|
|
25613
|
-
await
|
|
26239
|
+
const allowed = chunkZMRQ72F6_cjs.sessionHasEntityAccess(u, entity, action);
|
|
26240
|
+
await chunkX6UQFV4X_cjs.logEntityAccessDecision(dataSource, "cmsApi.requireEntityPermission", u, entity, action, {
|
|
25614
26241
|
allowed,
|
|
25615
26242
|
resolvePath: "hydrated_session"
|
|
25616
26243
|
});
|
|
25617
26244
|
if (allowed) return null;
|
|
25618
|
-
const { reason } =
|
|
26245
|
+
const { reason } = chunkX6UQFV4X_cjs.explainSessionEntityAccess(u, entity, action);
|
|
25619
26246
|
return config.json({
|
|
25620
26247
|
error: "Forbidden",
|
|
25621
26248
|
entity,
|
|
@@ -25626,7 +26253,7 @@ function createCmsApiHandler(config) {
|
|
|
25626
26253
|
});
|
|
25627
26254
|
}
|
|
25628
26255
|
if (userRequireEntityPermission) {
|
|
25629
|
-
|
|
26256
|
+
chunkX6UQFV4X_cjs.logRbac("requireEntityPermission: using app callback only (no getSessionUser)", {
|
|
25630
26257
|
entity,
|
|
25631
26258
|
action
|
|
25632
26259
|
});
|
|
@@ -25713,10 +26340,10 @@ function createCmsApiHandler(config) {
|
|
|
25713
26340
|
getVendorScope: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name(async () => {
|
|
25714
26341
|
const multiVendorEnabled = await checkMultiVendorEnabled(dataSource);
|
|
25715
26342
|
if (!multiVendorEnabled) {
|
|
25716
|
-
return
|
|
26343
|
+
return chunkX6UQFV4X_cjs.resolveDisabledMultiVendorScope(dataSource);
|
|
25717
26344
|
}
|
|
25718
26345
|
const u = await hydrateVendorSessionUser(dataSource, await resolveSessionUser());
|
|
25719
|
-
return
|
|
26346
|
+
return chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u ?? null);
|
|
25720
26347
|
}, "getVendorScope"),
|
|
25721
26348
|
getHydratedSessionUser: /* @__PURE__ */ chunkUSNT2KNT_cjs.__name(async () => {
|
|
25722
26349
|
const u = await hydrateVendorSessionUser(dataSource, await resolveSessionUser());
|
|
@@ -26642,16 +27269,24 @@ function createCmsApiHandler(config) {
|
|
|
26642
27269
|
if (pe) return pe;
|
|
26643
27270
|
if (group === "multi_vendor") {
|
|
26644
27271
|
invalidateMultiVendorCache();
|
|
27272
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
27273
|
+
invalidateRequireProductApprovalCache();
|
|
27274
|
+
invalidateRequireEventApprovalCache();
|
|
26645
27275
|
}
|
|
26646
27276
|
if (group === "events") {
|
|
26647
27277
|
invalidateEventsCache();
|
|
27278
|
+
invalidateRequireEventApprovalCache();
|
|
26648
27279
|
}
|
|
26649
27280
|
const res = await settingsHandlers.PUT(req, group);
|
|
26650
27281
|
if (group === "multi_vendor") {
|
|
26651
27282
|
invalidateMultiVendorCache();
|
|
27283
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
27284
|
+
invalidateRequireProductApprovalCache();
|
|
27285
|
+
invalidateRequireEventApprovalCache();
|
|
26652
27286
|
}
|
|
26653
27287
|
if (group === "events") {
|
|
26654
27288
|
invalidateEventsCache();
|
|
27289
|
+
invalidateRequireEventApprovalCache();
|
|
26655
27290
|
}
|
|
26656
27291
|
return res;
|
|
26657
27292
|
}
|
|
@@ -26975,7 +27610,7 @@ function createCmsApiHandler(config) {
|
|
|
26975
27610
|
let vendorId = null;
|
|
26976
27611
|
if (resolveSessionUser) {
|
|
26977
27612
|
const u = await hydrateVendorSessionUser(dataSource, await resolveSessionUser());
|
|
26978
|
-
const scope =
|
|
27613
|
+
const scope = chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u ?? null);
|
|
26979
27614
|
if (scope.type === "vendor") vendorId = scope.vendorId;
|
|
26980
27615
|
}
|
|
26981
27616
|
const result = await validateCoupon(dataSource, entityMap, couponCode, orderLinesNorm, currency, contactId, isAutomatic, discountId ?? void 0, vendorId);
|
|
@@ -27055,7 +27690,7 @@ function createCmsApiHandler(config) {
|
|
|
27055
27690
|
let vendorId = null;
|
|
27056
27691
|
if (resolveSessionUser) {
|
|
27057
27692
|
const u = await hydrateVendorSessionUser(dataSource, await resolveSessionUser());
|
|
27058
|
-
const scope =
|
|
27693
|
+
const scope = chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u ?? null);
|
|
27059
27694
|
if (scope.type === "vendor") vendorId = scope.vendorId;
|
|
27060
27695
|
}
|
|
27061
27696
|
const orderLinesNorm = normalizeOrderLinesInput(body?.orderLines);
|
|
@@ -27669,7 +28304,7 @@ function createCmsApiHandler(config) {
|
|
|
27669
28304
|
if (resolveSessionUser) {
|
|
27670
28305
|
const raw = await resolveSessionUser();
|
|
27671
28306
|
const u = await hydrateVendorSessionUser(dataSource, raw);
|
|
27672
|
-
const scope =
|
|
28307
|
+
const scope = chunkX6UQFV4X_cjs.resolveVendorScopeFromSessionUser(u ?? null);
|
|
27673
28308
|
if (scope.type === "vendor") {
|
|
27674
28309
|
scopedVendorIds = scope.vendorIds;
|
|
27675
28310
|
}
|
|
@@ -30968,10 +31603,16 @@ exports.BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG = BLOG_METADATA_ENRICHER_LLM_AGENT
|
|
|
30968
31603
|
exports.BlogGeneratorService = BlogGeneratorService;
|
|
30969
31604
|
exports.CMS_ENTITY_MAP = CMS_ENTITY_MAP;
|
|
30970
31605
|
exports.ZIP_MIME_TYPES = ZIP_MIME_TYPES;
|
|
31606
|
+
exports.applyApprovalStatusSideEffects = applyApprovalStatusSideEffects;
|
|
31607
|
+
exports.applyEventApprovalStatusSideEffects = applyEventApprovalStatusSideEffects;
|
|
30971
31608
|
exports.applyRotatingVendorInvite = applyRotatingVendorInvite;
|
|
30972
31609
|
exports.applyVendorCustomersContactFilter = applyVendorCustomersContactFilter;
|
|
31610
|
+
exports.applyVendorEventCreateApproval = applyVendorEventCreateApproval;
|
|
31611
|
+
exports.applyVendorProductCreateApproval = applyVendorProductCreateApproval;
|
|
30973
31612
|
exports.assertCaptchaOk = assertCaptchaOk;
|
|
30974
31613
|
exports.assertContactAllowedForVendorOrder = assertContactAllowedForVendorOrder;
|
|
31614
|
+
exports.assertEventApprovalUpdate = assertEventApprovalUpdate;
|
|
31615
|
+
exports.assertProductApprovalUpdate = assertProductApprovalUpdate;
|
|
30975
31616
|
exports.buildBlogMetadataUserPrompt = buildBlogMetadataUserPrompt;
|
|
30976
31617
|
exports.buildCronFromSchedule = buildCronFromSchedule;
|
|
30977
31618
|
exports.buildRssUserPromptFromFeeds = buildRssUserPromptFromFeeds;
|
|
@@ -31024,11 +31665,17 @@ exports.findVendorByInviteToken = findVendorByInviteToken;
|
|
|
31024
31665
|
exports.formatTierRange = formatTierRange;
|
|
31025
31666
|
exports.generateNumericOtp = generateNumericOtp;
|
|
31026
31667
|
exports.getPublicSettingsGroup = getPublicSettingsGroup;
|
|
31668
|
+
exports.getRequireEventApproval = getRequireEventApproval;
|
|
31669
|
+
exports.getRequireProductApproval = getRequireProductApproval;
|
|
31027
31670
|
exports.getRssArticleSummaryFromItem = getRssArticleSummaryFromItem;
|
|
31671
|
+
exports.getVendorCatalogCreateFlags = getVendorCatalogCreateFlags;
|
|
31028
31672
|
exports.hashOtpCode = hashOtpCode;
|
|
31029
31673
|
exports.hydrateVendorSessionUser = hydrateVendorSessionUser;
|
|
31030
31674
|
exports.invalidateEventsCache = invalidateEventsCache;
|
|
31031
31675
|
exports.invalidateMultiVendorCache = invalidateMultiVendorCache;
|
|
31676
|
+
exports.invalidateRequireEventApprovalCache = invalidateRequireEventApprovalCache;
|
|
31677
|
+
exports.invalidateRequireProductApprovalCache = invalidateRequireProductApprovalCache;
|
|
31678
|
+
exports.invalidateVendorCatalogCreateFlagsCache = invalidateVendorCatalogCreateFlagsCache;
|
|
31032
31679
|
exports.isCustomerTypeContact = isCustomerTypeContact;
|
|
31033
31680
|
exports.isZipMedia = isZipMedia;
|
|
31034
31681
|
exports.linkUnclaimedContactToUser = linkUnclaimedContactToUser;
|