@infuro/cms-core 1.0.30 → 1.0.33

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.
Files changed (61) hide show
  1. package/README.md +20 -15
  2. package/dist/admin.cjs +13061 -7814
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.d.cts +13 -2
  5. package/dist/admin.d.ts +13 -2
  6. package/dist/admin.js +8416 -3167
  7. package/dist/admin.js.map +1 -1
  8. package/dist/api.cjs +5667 -1110
  9. package/dist/api.cjs.map +1 -1
  10. package/dist/api.d.cts +2 -2
  11. package/dist/api.d.ts +2 -2
  12. package/dist/api.js +5418 -855
  13. package/dist/api.js.map +1 -1
  14. package/dist/auth.cjs +620 -76
  15. package/dist/auth.cjs.map +1 -1
  16. package/dist/auth.d.cts +93 -52
  17. package/dist/auth.d.ts +93 -52
  18. package/dist/auth.js +578 -52
  19. package/dist/auth.js.map +1 -1
  20. package/dist/cli.cjs +19 -15
  21. package/dist/cli.cjs.map +1 -1
  22. package/dist/cli.js +19 -15
  23. package/dist/cli.js.map +1 -1
  24. package/dist/{index-BPQSXgXF.d.cts → index-DWd5Gjc4.d.ts} +38 -5
  25. package/dist/{index-D9SdaDJ0.d.ts → index-rZTnpK7y.d.cts} +38 -5
  26. package/dist/index.cjs +5921 -1177
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +334 -59
  29. package/dist/index.d.ts +334 -59
  30. package/dist/index.js +5733 -1026
  31. package/dist/index.js.map +1 -1
  32. package/dist/migrations/1775400000001-AddDiscountAndOrderAddresses.ts +274 -0
  33. package/dist/migrations/1775800000000-VendorsAndVendorUsers.ts +74 -0
  34. package/dist/migrations/1775900000000-StoreVendorIdColumns.ts +124 -0
  35. package/dist/migrations/1775910000000-VendorOwnerRbacSeed.ts +54 -0
  36. package/dist/migrations/1775920000000-VendorOwnerSettingsPermission.ts +25 -0
  37. package/dist/migrations/1775930000000-VendorGroupStorePermissions.ts +54 -0
  38. package/dist/migrations/1775940000000-VendorRls.ts +71 -0
  39. package/dist/migrations/1775950000000-VendorCustomers.ts +87 -0
  40. package/dist/migrations/1775950000001-VendorCustomersPermissions.ts +67 -0
  41. package/dist/migrations/1778652250860-CreateCurrencyTables.ts +16 -0
  42. package/dist/migrations/1778652250861-OrderAddressTables.ts +88 -0
  43. package/dist/migrations/1778652250862-UpdateDiscountandRules.ts +100 -0
  44. package/dist/migrations/1778652250863-MakeCouponCodeNullable.ts +19 -0
  45. package/dist/migrations/1778652250864-RemoveUniqueConstraintFromDiscountCouponCode.ts +22 -0
  46. package/dist/migrations/1778652250865-FixOrdersAddressForeignKeys.ts +71 -0
  47. package/dist/migrations/1778660000000-DiscountVendorId.ts +90 -0
  48. package/dist/migrations/1778660000001-FixOrdersAddressFkToOrderAddresses.ts +79 -0
  49. package/dist/migrations/1778660000002-VendorUserIdInviteStatus.ts +61 -0
  50. package/dist/migrations/1778660000003-AddQrTokenToOrders.ts +32 -0
  51. package/dist/migrations/1779100000000-ChatConversationLeadEmailSent.ts +16 -0
  52. package/dist/migrations/1779200000000-LlmAgentScope.ts +72 -0
  53. package/dist/theme.d.cts +2 -2
  54. package/dist/theme.d.ts +2 -2
  55. package/dist/{types-D34wmivy.d.cts → types-DCVaXlPV.d.cts} +1 -1
  56. package/dist/{types-D34wmivy.d.ts → types-DCVaXlPV.d.ts} +1 -1
  57. package/dist/vendor-scope-DTYhJk_I.d.cts +129 -0
  58. package/dist/vendor-scope-DTYhJk_I.d.ts +129 -0
  59. package/package.json +3 -2
  60. package/dist/helpers-dlrF_49e.d.cts +0 -60
  61. package/dist/helpers-dlrF_49e.d.ts +0 -60
package/dist/auth.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,57 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
30
- // src/auth/index.ts
31
- var auth_exports = {};
32
- __export(auth_exports, {
33
- ADMIN_GROUP_NAME: () => ADMIN_GROUP_NAME,
34
- OPEN_ENDPOINTS: () => OPEN_ENDPOINTS,
35
- PERMISSION_REQUIRED_ENDPOINTS: () => PERMISSION_REQUIRED_ENDPOINTS,
36
- RBAC_ADMIN_ONLY_ENTITIES: () => RBAC_ADMIN_ONLY_ENTITIES,
37
- canManageRoles: () => canManageRoles,
38
- createAuthHelpers: () => createAuthHelpers,
39
- createCmsMiddleware: () => createCmsMiddleware,
40
- defaultPublicApiMethods: () => defaultPublicApiMethods,
41
- getNextAuthOptions: () => getNextAuthOptions,
42
- getPermissionableEntityKeys: () => getPermissionableEntityKeys,
43
- getRequiredPermission: () => getRequiredPermission,
44
- hasEntityPermission: () => hasEntityPermission,
45
- isOpenEndpoint: () => isOpenEndpoint,
46
- isPublicMethod: () => isPublicMethod,
47
- isSuperAdminGroupName: () => isSuperAdminGroupName,
48
- permissionRowsToRecord: () => permissionRowsToRecord,
49
- seedAdministratorPermissions: () => seedAdministratorPermissions,
50
- sessionHasEntityAccess: () => sessionHasEntityAccess
51
- });
52
- module.exports = __toCommonJS(auth_exports);
53
-
54
33
  // src/auth/permission-entities.ts
55
- var PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
56
- "users",
57
- "password_reset_tokens",
58
- "user_groups",
59
- "permissions",
60
- "comments",
61
- "form_fields",
62
- "configs",
63
- "knowledge_base_chunks",
64
- "carts",
65
- "cart_items",
66
- "wishlists",
67
- "wishlist_items",
68
- "message_templates"
69
- ]);
70
- var PERMISSION_LOGICAL_ENTITIES = [
71
- "users",
72
- "forms",
73
- "form_submissions",
74
- "dashboard",
75
- "upload",
76
- "settings",
77
- "analytics",
78
- "chat"
79
- ];
80
- var ADMIN_GROUP_NAME = "Administrator";
81
34
  function isSuperAdminGroupName(name) {
82
35
  return name === ADMIN_GROUP_NAME;
83
36
  }
@@ -107,13 +60,364 @@ function hasEntityPermission(record, entity, action) {
107
60
  if (action === "update") return p.u;
108
61
  return p.d;
109
62
  }
63
+ var PERMISSION_ENTITY_INTERNAL_EXCLUDE, PERMISSION_LOGICAL_ENTITIES, ADMIN_GROUP_NAME;
64
+ var init_permission_entities = __esm({
65
+ "src/auth/permission-entities.ts"() {
66
+ "use strict";
67
+ PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
68
+ "users",
69
+ "password_reset_tokens",
70
+ "user_groups",
71
+ "permissions",
72
+ "comments",
73
+ "form_fields",
74
+ "configs",
75
+ "knowledge_base_chunks",
76
+ "carts",
77
+ "cart_items",
78
+ "wishlists",
79
+ "wishlist_items",
80
+ "message_templates",
81
+ "vendor_users"
82
+ ]);
83
+ PERMISSION_LOGICAL_ENTITIES = [
84
+ "users",
85
+ "forms",
86
+ "form_submissions",
87
+ "dashboard",
88
+ "upload",
89
+ "settings",
90
+ "analytics",
91
+ "chat"
92
+ ];
93
+ ADMIN_GROUP_NAME = "Administrator";
94
+ }
95
+ });
96
+
97
+ // src/auth/vendor-scope.ts
98
+ function isVendorGroupName(name) {
99
+ if (!name?.trim()) return false;
100
+ const n = name.trim().toLowerCase();
101
+ return n === VENDOR_OWNER_GROUP_NAME.toLowerCase() || n.includes("vendor");
102
+ }
103
+ function isPlatformAdministrator(user) {
104
+ if (!user?.email) return false;
105
+ return !!(user.isRBACAdmin || isSuperAdminGroupName(user.groupName));
106
+ }
107
+ function isVendorPortalUser(user) {
108
+ if (user?.isVendorPortal === true) return true;
109
+ if (!user?.email || isPlatformAdministrator(user)) return false;
110
+ if ((user.vendorIds?.length ?? 0) > 0) return true;
111
+ return isVendorGroupName(user.groupName);
112
+ }
113
+ function isVendorStaff(user) {
114
+ return isVendorPortalUser(user);
115
+ }
116
+ function isVendorOwner(user) {
117
+ if (user?.isVendorOwner === true) return true;
118
+ if (!user?.email || isPlatformAdministrator(user)) return false;
119
+ if (user.vendorRole === "staff") return false;
120
+ if (user.vendorRole === "owner") return true;
121
+ if (!isVendorPortalUser(user)) return false;
122
+ return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();
123
+ }
124
+ function canManageVendorTeam(user) {
125
+ return isPlatformAdministrator(user) || isVendorOwner(user);
126
+ }
127
+ function canManageVendorRoles(user) {
128
+ return isPlatformAdministrator(user) || isVendorOwner(user);
129
+ }
130
+ function canOnboardVendors(user) {
131
+ return isPlatformAdministrator(user);
132
+ }
133
+ function resolveVendorScopeFromSessionUser(user) {
134
+ if (!user?.email) return { type: "deny" };
135
+ if (isPlatformAdministrator(user)) return { type: "all" };
136
+ const vendorIds = user.vendorIds ?? [];
137
+ if (vendorIds.length === 0) return { type: "deny" };
138
+ const preferred = user.activeVendorId ?? vendorIds[0];
139
+ const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0];
140
+ return { type: "vendor", vendorId, vendorIds };
141
+ }
142
+ function vendorPortalFlagsFromUser(input) {
143
+ const vendorIds = input.vendorIds ?? [];
144
+ const isVendorPortal = !input.isRBACAdmin && (vendorIds.length > 0 || isVendorGroupName(input.groupName));
145
+ const isVendorOwner2 = isVendorPortal && input.vendorRole !== "staff" && (input.vendorRole === "owner" || input.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase());
146
+ return { isVendorPortal, isVendorOwner: isVendorOwner2 };
147
+ }
148
+ var VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, VENDOR_OWNER_GROUP_NAME;
149
+ var init_vendor_scope = __esm({
150
+ "src/auth/vendor-scope.ts"() {
151
+ "use strict";
152
+ init_permission_entities();
153
+ VENDOR_SCOPED_STORE_ENTITIES = /* @__PURE__ */ new Set([
154
+ "products",
155
+ "collections",
156
+ "brands",
157
+ "product_categories",
158
+ "orders",
159
+ "payments",
160
+ "taxes",
161
+ "attributes",
162
+ "vendor_customers",
163
+ "discounts"
164
+ ]);
165
+ VENDOR_STORE_RBAC_ENTITIES = /* @__PURE__ */ new Set([
166
+ ...VENDOR_SCOPED_STORE_ENTITIES,
167
+ "order_discounts",
168
+ "order_addresses"
169
+ ]);
170
+ VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
171
+ }
172
+ });
173
+
174
+ // src/auth/rbac-debug-db.ts
175
+ var rbac_debug_db_exports = {};
176
+ __export(rbac_debug_db_exports, {
177
+ loadDbPermissionsForUser: () => loadDbPermissionsForUser
178
+ });
179
+ async function loadDbPermissionsForUser(dataSource, userId) {
180
+ const rows = await dataSource.query(
181
+ `
182
+ SELECT u."groupId" AS "groupId", g.name AS "groupName",
183
+ p.entity, p."canCreate", p."canRead", p."canUpdate", p."canDelete"
184
+ FROM users u
185
+ LEFT JOIN user_groups g ON g.id = u."groupId" AND g.deleted = false
186
+ LEFT JOIN permissions p ON p."groupId" = g.id
187
+ WHERE u.id = $1
188
+ `,
189
+ [userId]
190
+ );
191
+ const groupId = rows[0]?.groupId ?? null;
192
+ const groupName = rows[0]?.groupName ?? null;
193
+ const permRows = rows.filter((r) => r.entity).map((r) => ({
194
+ entity: r.entity,
195
+ canCreate: !!r.canCreate,
196
+ canRead: !!r.canRead,
197
+ canUpdate: !!r.canUpdate,
198
+ canDelete: !!r.canDelete
199
+ }));
200
+ return {
201
+ groupId,
202
+ groupName,
203
+ dbEntityPerms: summarizeEntityPerms(permissionRowsToRecord(permRows))
204
+ };
205
+ }
206
+ var init_rbac_debug_db = __esm({
207
+ "src/auth/rbac-debug-db.ts"() {
208
+ "use strict";
209
+ init_permission_entities();
210
+ init_rbac_debug();
211
+ }
212
+ });
213
+
214
+ // src/auth/rbac-debug.ts
215
+ function isRbacDebugEnabled() {
216
+ const v = process.env.CMS_RBAC_DEBUG?.trim().toLowerCase();
217
+ if (v === "1" || v === "true" || v === "yes") return true;
218
+ if (v === "0" || v === "false" || v === "no") return false;
219
+ return process.env.NODE_ENV === "development";
220
+ }
221
+ function logRbac(message, data) {
222
+ if (!isRbacDebugEnabled()) return;
223
+ if (data) console.info(LOG_PREFIX, message, data);
224
+ else console.info(LOG_PREFIX, message);
225
+ }
226
+ function summarizeEntityPerms(entityPerms) {
227
+ const out = {};
228
+ if (!entityPerms) return out;
229
+ for (const [entity, p] of Object.entries(entityPerms)) {
230
+ out[entity] = { c: p.c, r: p.r, u: p.u, d: p.d };
231
+ }
232
+ return out;
233
+ }
234
+ function vendorPortalFallbackReason(user, entity, action) {
235
+ if (!isVendorPortalUser(user)) return null;
236
+ if (entity === "dashboard" && action === "read") return "vendor_portal_dashboard_fallback";
237
+ if (entity === "analytics" && action === "read") return "vendor_portal_analytics_fallback";
238
+ if (entity === "settings" && action === "read") return "vendor_portal_settings_read_fallback";
239
+ if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === "read") return "vendor_portal_store_read_fallback";
240
+ return null;
241
+ }
242
+ function explainSessionEntityAccess(user, entity, action) {
243
+ const userSnapshot = {
244
+ email: user?.email ?? null,
245
+ id: user?.id ?? null,
246
+ groupId: user?.groupId ?? null,
247
+ groupName: user?.groupName ?? null,
248
+ isRBACAdmin: user?.isRBACAdmin ?? false,
249
+ adminAccess: user?.adminAccess ?? null,
250
+ vendorIds: user?.vendorIds ?? [],
251
+ activeVendorId: user?.activeVendorId ?? null,
252
+ vendorRole: user?.vendorRole ?? null,
253
+ isVendorPortal: user?.isVendorPortal ?? false,
254
+ isVendorOwner: user?.isVendorOwner ?? false,
255
+ isVendorPortalComputed: isVendorPortalUser(user),
256
+ isVendorOwnerComputed: isVendorOwner(user),
257
+ jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),
258
+ jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null
259
+ };
260
+ if (!user?.email) {
261
+ return { allowed: false, reason: "no_session_email", userSnapshot };
262
+ }
263
+ if (user.isRBACAdmin) {
264
+ return { allowed: true, reason: "platform_administrator", userSnapshot };
265
+ }
266
+ const vendorIds = user.vendorIds ?? [];
267
+ const isStaff = user.vendorRole === "staff";
268
+ if (vendorIds.length > 0) {
269
+ if (entity === "dashboard" && action === "read") {
270
+ return { allowed: true, reason: "vendor_link_dashboard_read", userSnapshot };
271
+ }
272
+ if (entity === "analytics" && action === "read") {
273
+ return { allowed: true, reason: "vendor_link_analytics_read", userSnapshot };
274
+ }
275
+ if (entity === "settings") {
276
+ if (action === "read") {
277
+ return { allowed: true, reason: "vendor_link_settings_read", userSnapshot };
278
+ }
279
+ if (action === "update" && !isStaff) {
280
+ return { allowed: true, reason: "vendor_link_settings_update", userSnapshot };
281
+ }
282
+ }
283
+ if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
284
+ if (isStaff && action === "read") {
285
+ return { allowed: true, reason: "vendor_staff_store_read", userSnapshot };
286
+ }
287
+ if (!isStaff) {
288
+ return { allowed: true, reason: "vendor_link_store_full", userSnapshot };
289
+ }
290
+ return {
291
+ allowed: false,
292
+ reason: "vendor_staff_store_write_denied",
293
+ userSnapshot
294
+ };
295
+ }
296
+ }
297
+ if (isVendorPortalUser(user) && isVendorOwner(user)) {
298
+ if (entity === "dashboard" && action === "read") {
299
+ return { allowed: true, reason: "vendor_owner_group_dashboard", userSnapshot };
300
+ }
301
+ if (entity === "analytics" && action === "read") {
302
+ return { allowed: true, reason: "vendor_owner_group_analytics", userSnapshot };
303
+ }
304
+ if (entity === "settings" && (action === "read" || action === "update")) {
305
+ return { allowed: true, reason: "vendor_owner_group_settings", userSnapshot };
306
+ }
307
+ if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
308
+ return { allowed: true, reason: "vendor_owner_group_store", userSnapshot };
309
+ }
310
+ }
311
+ const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);
312
+ if (vendorPortalReason) {
313
+ return { allowed: true, reason: vendorPortalReason, userSnapshot };
314
+ }
315
+ const explicit = user.entityPerms?.[entity];
316
+ if (explicit !== void 0) {
317
+ const allowed2 = hasEntityPermission(user.entityPerms, entity, action);
318
+ return {
319
+ allowed: allowed2,
320
+ reason: allowed2 ? "jwt_entity_perms_allow" : "jwt_entity_perms_deny",
321
+ userSnapshot
322
+ };
323
+ }
324
+ const allowed = hasEntityPermission(user.entityPerms, entity, action);
325
+ return {
326
+ allowed,
327
+ reason: allowed ? "entity_perms_fallback_allow" : "no_matching_rule",
328
+ userSnapshot
329
+ };
330
+ }
331
+ async function logEntityAccessDecision(dataSource, context, user, entity, action, extra) {
332
+ if (!isRbacDebugEnabled()) return;
333
+ const explanation = explainSessionEntityAccess(user, entity, action);
334
+ let dbPermissions;
335
+ if (dataSource && user?.id) {
336
+ const id = Number(user.id);
337
+ if (Number.isFinite(id)) {
338
+ try {
339
+ const { loadDbPermissionsForUser: loadDbPermissionsForUser2 } = await Promise.resolve().then(() => (init_rbac_debug_db(), rbac_debug_db_exports));
340
+ dbPermissions = await loadDbPermissionsForUser2(dataSource, id);
341
+ } catch (e) {
342
+ dbPermissions = { error: e instanceof Error ? e.message : String(e) };
343
+ }
344
+ }
345
+ }
346
+ logRbac(context, {
347
+ entity,
348
+ action,
349
+ allowed: explanation.allowed,
350
+ reason: explanation.reason,
351
+ ...explanation.userSnapshot,
352
+ dbPermissions,
353
+ ...extra
354
+ });
355
+ }
356
+ var LOG_PREFIX;
357
+ var init_rbac_debug = __esm({
358
+ "src/auth/rbac-debug.ts"() {
359
+ "use strict";
360
+ init_permission_entities();
361
+ init_vendor_scope();
362
+ LOG_PREFIX = "[cms-rbac]";
363
+ }
364
+ });
365
+
366
+ // src/auth/index.ts
367
+ var auth_exports = {};
368
+ __export(auth_exports, {
369
+ ADMIN_GROUP_NAME: () => ADMIN_GROUP_NAME,
370
+ OPEN_ENDPOINTS: () => OPEN_ENDPOINTS,
371
+ PERMISSION_REQUIRED_ENDPOINTS: () => PERMISSION_REQUIRED_ENDPOINTS,
372
+ RBAC_ADMIN_ONLY_ENTITIES: () => RBAC_ADMIN_ONLY_ENTITIES,
373
+ VENDOR_OWNER_GROUP_NAME: () => VENDOR_OWNER_GROUP_NAME,
374
+ VENDOR_SCOPED_STORE_ENTITIES: () => VENDOR_SCOPED_STORE_ENTITIES,
375
+ VENDOR_STORE_RBAC_ENTITIES: () => VENDOR_STORE_RBAC_ENTITIES,
376
+ canManageRoles: () => canManageRoles,
377
+ canManageVendorRoles: () => canManageVendorRoles,
378
+ canManageVendorTeam: () => canManageVendorTeam,
379
+ canOnboardVendors: () => canOnboardVendors,
380
+ createAuthHelpers: () => createAuthHelpers,
381
+ createCmsAuthBundle: () => createCmsAuthBundle,
382
+ createCmsMiddleware: () => createCmsMiddleware,
383
+ defaultPublicApiMethods: () => defaultPublicApiMethods,
384
+ explainSessionEntityAccess: () => explainSessionEntityAccess,
385
+ getNextAuthOptions: () => getNextAuthOptions,
386
+ getPermissionableEntityKeys: () => getPermissionableEntityKeys,
387
+ getRequiredPermission: () => getRequiredPermission,
388
+ hasEntityPermission: () => hasEntityPermission,
389
+ isAuthDebugClientEnabled: () => isAuthDebugClientEnabled,
390
+ isAuthDebugEnabled: () => isAuthDebugEnabled,
391
+ isOpenEndpoint: () => isOpenEndpoint,
392
+ isPlatformAdministrator: () => isPlatformAdministrator,
393
+ isPublicMethod: () => isPublicMethod,
394
+ isRbacDebugEnabled: () => isRbacDebugEnabled,
395
+ isSuperAdminGroupName: () => isSuperAdminGroupName,
396
+ isVendorGroupName: () => isVendorGroupName,
397
+ isVendorOwner: () => isVendorOwner,
398
+ isVendorPortalUser: () => isVendorPortalUser,
399
+ isVendorStaff: () => isVendorStaff,
400
+ logAuth: () => logAuth,
401
+ logAuthClient: () => logAuthClient,
402
+ logEntityAccessDecision: () => logEntityAccessDecision,
403
+ logRbac: () => logRbac,
404
+ nextAuthCookieDebugInfo: () => nextAuthCookieDebugInfo,
405
+ permissionRowsToRecord: () => permissionRowsToRecord,
406
+ resolveVendorScopeFromSessionUser: () => resolveVendorScopeFromSessionUser,
407
+ seedAdministratorPermissions: () => seedAdministratorPermissions,
408
+ sessionHasEntityAccess: () => sessionHasEntityAccess,
409
+ summarizeEntityPerms: () => summarizeEntityPerms,
410
+ summarizeSessionUserForLog: () => summarizeSessionUserForLog,
411
+ vendorPortalFlagsFromUser: () => vendorPortalFlagsFromUser
412
+ });
413
+ module.exports = __toCommonJS(auth_exports);
110
414
 
111
415
  // src/auth/helpers.ts
416
+ init_rbac_debug();
417
+ init_vendor_scope();
112
418
  var RBAC_ADMIN_ONLY_ENTITIES = /* @__PURE__ */ new Set(["users", "user_groups", "permissions"]);
113
419
  function sessionHasEntityAccess(user, entity, action) {
114
- if (!user?.email) return false;
115
- if (user.isRBACAdmin && RBAC_ADMIN_ONLY_ENTITIES.has(entity)) return true;
116
- return hasEntityPermission(user.entityPerms, entity, action);
420
+ return explainSessionEntityAccess(user, entity, action).allowed;
117
421
  }
118
422
  function canManageRoles(user) {
119
423
  return !!(user?.email && user.isRBACAdmin);
@@ -138,6 +442,19 @@ function isPublicMethod(pathname, method) {
138
442
  return false;
139
443
  }
140
444
  function createAuthHelpers(getSession, NextResponse) {
445
+ return createAuthHelpersFromGetSession(getSession, NextResponse);
446
+ }
447
+ function createCmsAuthBundle(getSession, NextResponse) {
448
+ const auth = createAuthHelpers(getSession, NextResponse);
449
+ return {
450
+ requireAuth: auth.requireAuth,
451
+ requireAdminAccess: auth.requireAdminAccess,
452
+ requireEntityPermission: auth.requireEntityPermission,
453
+ getSessionUser: auth.getAuthenticatedUser,
454
+ getAuthenticatedUser: auth.getAuthenticatedUser
455
+ };
456
+ }
457
+ function createAuthHelpersFromGetSession(getSession, NextResponse) {
141
458
  return {
142
459
  async requireAuth() {
143
460
  const session = await getSession();
@@ -159,8 +476,21 @@ function createAuthHelpers(getSession, NextResponse) {
159
476
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
160
477
  }
161
478
  const u = session.user;
162
- if (sessionHasEntityAccess(u, entity, action)) return null;
163
- return NextResponse.json({ error: "Forbidden", entity, action }, { status: 403 });
479
+ const allowed = sessionHasEntityAccess(u, entity, action);
480
+ const { reason } = explainSessionEntityAccess(u, entity, action);
481
+ logRbac("authHelpers.requireEntityPermission", {
482
+ entity,
483
+ action,
484
+ allowed,
485
+ reason,
486
+ email: u.email,
487
+ groupName: u.groupName,
488
+ vendorIds: u.vendorIds,
489
+ isVendorPortal: u.isVendorPortal,
490
+ isVendorOwner: u.isVendorOwner
491
+ });
492
+ if (allowed) return null;
493
+ return NextResponse.json({ error: "Forbidden", entity, action, reason }, { status: 403 });
164
494
  },
165
495
  async requireAdminAccess() {
166
496
  const session = await getSession();
@@ -169,8 +499,23 @@ function createAuthHelpers(getSession, NextResponse) {
169
499
  }
170
500
  const u = session.user;
171
501
  if (u.isRBACAdmin) return null;
172
- if (u.adminAccess === false) return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
173
- return null;
502
+ if (isVendorPortalUser(u)) return null;
503
+ if (u.adminAccess === true) return null;
504
+ if (u.adminAccess === false) {
505
+ logRbac("requireAdminAccess denied (adminAccess:false)", {
506
+ email: u.email,
507
+ groupName: u.groupName,
508
+ isVendorPortal: u.isVendorPortal
509
+ });
510
+ return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
511
+ }
512
+ logRbac("requireAdminAccess denied (no matching rule)", {
513
+ email: u.email,
514
+ adminAccess: u.adminAccess,
515
+ groupName: u.groupName,
516
+ isVendorPortal: u.isVendorPortal
517
+ });
518
+ return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
174
519
  },
175
520
  async getAuthenticatedUser() {
176
521
  const session = await getSession();
@@ -179,18 +524,26 @@ function createAuthHelpers(getSession, NextResponse) {
179
524
  };
180
525
  }
181
526
 
527
+ // src/auth/index.ts
528
+ init_rbac_debug();
529
+ init_vendor_scope();
530
+ init_permission_entities();
531
+
182
532
  // src/auth/seed-permissions.ts
533
+ init_permission_entities();
183
534
  async function seedAdministratorPermissions(dataSource, entityMap) {
184
535
  const entities = getPermissionableEntityKeys(entityMap);
185
536
  const groupRepo = dataSource.getRepository(entityMap.user_groups);
186
537
  const permRepo = dataSource.getRepository(entityMap.permissions);
187
538
  const adminGroup = await groupRepo.findOne({ where: { name: ADMIN_GROUP_NAME, deleted: false } });
539
+ console.log("ADMIN GROUP", adminGroup);
188
540
  if (!adminGroup) return;
189
541
  const fullCrud = { canCreate: true, canRead: true, canUpdate: true, canDelete: true };
190
542
  for (const entity of entities) {
191
543
  const existing = await permRepo.findOne({
192
544
  where: { groupId: adminGroup.id, entity }
193
545
  });
546
+ console.log("EXISTING", existing);
194
547
  if (existing) {
195
548
  existing.canCreate = true;
196
549
  existing.canRead = true;
@@ -209,6 +562,59 @@ async function seedAdministratorPermissions(dataSource, entityMap) {
209
562
  }
210
563
  }
211
564
 
565
+ // src/auth/middleware.ts
566
+ var import_jwt = require("next-auth/jwt");
567
+
568
+ // src/auth/auth-debug.ts
569
+ var LOG_PREFIX2 = "[cms-auth]";
570
+ function isAuthDebugEnabled() {
571
+ const v = process.env.CMS_AUTH_DEBUG?.trim().toLowerCase();
572
+ if (v === "1" || v === "true" || v === "yes") return true;
573
+ if (v === "0" || v === "false" || v === "no") return false;
574
+ return process.env.NODE_ENV === "development";
575
+ }
576
+ function isAuthDebugClientEnabled() {
577
+ if (typeof window === "undefined") return false;
578
+ const v = process.env.NEXT_PUBLIC_CMS_AUTH_DEBUG?.trim().toLowerCase();
579
+ if (v === "1" || v === "true" || v === "yes") return true;
580
+ if (v === "0" || v === "false" || v === "no") return false;
581
+ return process.env.NODE_ENV === "development";
582
+ }
583
+ function logAuth(message, data) {
584
+ if (!isAuthDebugEnabled()) return;
585
+ if (data) console.info(LOG_PREFIX2, message, data);
586
+ else console.info(LOG_PREFIX2, message);
587
+ }
588
+ function logAuthClient(message, data) {
589
+ if (!isAuthDebugClientEnabled()) return;
590
+ if (data) console.info(LOG_PREFIX2, message, data);
591
+ else console.info(LOG_PREFIX2, message);
592
+ }
593
+ function summarizeSessionUserForLog(user) {
594
+ if (!user || typeof user !== "object") return { present: false };
595
+ const u = user;
596
+ return {
597
+ present: true,
598
+ email: u.email ?? null,
599
+ id: u.id ?? null,
600
+ adminAccess: u.adminAccess ?? null,
601
+ isRBACAdmin: u.isRBACAdmin ?? null,
602
+ isVendorPortal: u.isVendorPortal ?? null,
603
+ groupName: u.groupName ?? null
604
+ };
605
+ }
606
+ function nextAuthCookieDebugInfo() {
607
+ const nextAuthUrl = process.env.NEXTAUTH_URL ?? "(unset)";
608
+ const isHttps = nextAuthUrl.startsWith("https");
609
+ return {
610
+ nextAuthUrl,
611
+ hasSecret: Boolean(process.env.NEXTAUTH_SECRET),
612
+ cookieName: isHttps ? "__Secure-next-auth.session-token" : "next-auth.session-token",
613
+ cookieSecure: isHttps,
614
+ nodeEnv: process.env.NODE_ENV ?? "(unset)"
615
+ };
616
+ }
617
+
212
618
  // src/auth/middleware.ts
213
619
  var defaultPublicApiMethods = {
214
620
  "/api/contacts": ["POST"],
@@ -221,8 +627,21 @@ var defaultPublicApiMethods = {
221
627
  "/api/users/set-password": ["POST"],
222
628
  "/api/users/invite": ["POST"]
223
629
  };
224
- function defaultGetSessionToken(request) {
225
- return request.cookies.get("__Secure-next-auth.session-token")?.value ?? request.cookies.get("next-auth.session-token")?.value;
630
+ function legacyGetSessionToken(request) {
631
+ const secure = request.cookies.get("__Secure-next-auth.session-token")?.value;
632
+ const regular = request.cookies.get("next-auth.session-token")?.value;
633
+ return secure ?? regular;
634
+ }
635
+ function sessionCookiePresence(request) {
636
+ const secure = request.cookies.get("__Secure-next-auth.session-token")?.value;
637
+ const regular = request.cookies.get("next-auth.session-token")?.value;
638
+ const hasChunked = Boolean(request.cookies.get("next-auth.session-token.0")?.value) || Boolean(request.cookies.get("__Secure-next-auth.session-token.0")?.value);
639
+ return {
640
+ hasSecureToken: Boolean(secure),
641
+ hasRegularToken: Boolean(regular),
642
+ hasChunkedToken: hasChunked,
643
+ resolved: Boolean(secure ?? regular)
644
+ };
226
645
  }
227
646
  function isPublicMethod2(pathname, method, publicApiMethods) {
228
647
  for (const [endpoint, methods] of Object.entries(publicApiMethods)) {
@@ -230,31 +649,59 @@ function isPublicMethod2(pathname, method, publicApiMethods) {
230
649
  }
231
650
  return false;
232
651
  }
652
+ async function hasValidSession(request, secret, legacyGetToken) {
653
+ if (request.req) {
654
+ const token = await (0, import_jwt.getToken)({ req: request.req, secret });
655
+ return token != null;
656
+ }
657
+ return Boolean(legacyGetToken(request));
658
+ }
233
659
  function createCmsMiddleware(config = {}) {
234
660
  const {
235
661
  publicAdminPaths = ["/admin/signin", "/admin/forgot-password", "/admin/reset-password", "/admin/invite"],
236
662
  publicApiMethods = defaultPublicApiMethods,
237
663
  signInPath = "/admin/signin",
238
- getSessionToken = defaultGetSessionToken
664
+ getSessionToken = legacyGetSessionToken,
665
+ secret = process.env.NEXTAUTH_SECRET
239
666
  } = config;
240
- return function cmsMiddleware(request) {
667
+ return async function cmsMiddleware(request) {
241
668
  const pathname = request.nextUrl.pathname;
242
669
  const method = request.method;
243
670
  if (publicAdminPaths.some((p) => pathname === p || pathname.startsWith(p + "/"))) {
244
671
  return { type: "next" };
245
672
  }
246
673
  if (pathname.startsWith("/admin")) {
247
- const token = getSessionToken(request);
248
- if (!token) {
674
+ const authenticated = await hasValidSession(request, secret, getSessionToken);
675
+ const cookies = sessionCookiePresence(request);
676
+ if (!authenticated) {
677
+ logAuth("middleware: admin redirect to signin (no session)", {
678
+ pathname,
679
+ method,
680
+ usesGetToken: Boolean(request.req),
681
+ ...cookies,
682
+ expectedCookieName: process.env.NEXTAUTH_URL?.startsWith("https") ? "__Secure-next-auth.session-token" : "next-auth.session-token"
683
+ });
249
684
  return { type: "redirect", url: new URL(signInPath, request.url).toString() };
250
685
  }
686
+ logAuth("middleware: admin allowed", {
687
+ pathname,
688
+ method,
689
+ usesGetToken: Boolean(request.req),
690
+ ...cookies
691
+ });
251
692
  }
252
693
  if (pathname.startsWith("/api")) {
253
694
  if (isPublicMethod2(pathname, method, publicApiMethods)) {
254
695
  return { type: "next" };
255
696
  }
256
- const token = getSessionToken(request);
257
- if (!token) {
697
+ const authenticated = await hasValidSession(request, secret, getSessionToken);
698
+ if (!authenticated) {
699
+ logAuth("middleware: api 401 (no session)", {
700
+ pathname,
701
+ method,
702
+ usesGetToken: Boolean(request.req),
703
+ ...sessionCookiePresence(request)
704
+ });
258
705
  return { type: "json", status: 401, body: { error: "Unauthorized" } };
259
706
  }
260
707
  }
@@ -264,20 +711,38 @@ function createCmsMiddleware(config = {}) {
264
711
 
265
712
  // src/auth/nextauth-options.ts
266
713
  var import_credentials = __toESM(require("next-auth/providers/credentials"), 1);
714
+ init_permission_entities();
715
+ init_vendor_scope();
267
716
  var CredentialsProvider = import_credentials.default.default ?? import_credentials.default;
268
717
  function sessionUserFromNextAuthUser(user) {
269
718
  const g = user.group;
270
719
  const isRBACAdmin = isSuperAdminGroupName(g?.name);
271
720
  const entityPerms = permissionRowsToRecord(g?.permissions);
272
- const adminAccess = user.adminAccess === true;
721
+ const rawAdminAccess = user.adminAccess;
722
+ const adminAccess = rawAdminAccess === true ? true : rawAdminAccess === false ? false : void 0;
723
+ const vendorIds = user.vendorIds ?? [];
724
+ const vendorRole = user.vendorRole ?? null;
725
+ const { isVendorPortal, isVendorOwner: isVendorOwner2 } = vendorPortalFlagsFromUser({
726
+ email: user.email,
727
+ isRBACAdmin,
728
+ groupName: g?.name,
729
+ vendorIds,
730
+ vendorRole
731
+ });
273
732
  return {
274
733
  id: user.id.toString(),
275
734
  email: user.email,
276
735
  name: user.name,
277
736
  groupId: user.groupId ?? void 0,
737
+ groupName: g?.name ?? void 0,
278
738
  isRBACAdmin,
279
739
  entityPerms,
280
- adminAccess
740
+ adminAccess,
741
+ vendorIds,
742
+ activeVendorId: user.activeVendorId ?? vendorIds[0] ?? null,
743
+ vendorRole,
744
+ isVendorPortal,
745
+ isVendorOwner: isVendorOwner2
281
746
  };
282
747
  }
283
748
  function getNextAuthOptions(config) {
@@ -291,6 +756,7 @@ function getNextAuthOptions(config) {
291
756
  enableOtpLogin = false,
292
757
  authorizeOtp
293
758
  } = config;
759
+ logAuth("getNextAuthOptions init", nextAuthCookieDebugInfo());
294
760
  const providers = [];
295
761
  if (enablePasswordLogin) {
296
762
  providers.push(
@@ -301,14 +767,43 @@ function getNextAuthOptions(config) {
301
767
  password: { label: "Password", type: "password" }
302
768
  },
303
769
  async authorize(credentials) {
304
- if (!credentials?.email || !credentials?.password) return null;
770
+ const email = credentials?.email?.trim() ?? "";
771
+ if (!email || !credentials?.password) {
772
+ logAuth("authorize(credentials) rejected", { reason: "missing_email_or_password" });
773
+ return null;
774
+ }
305
775
  try {
306
- const user = await getUserByEmail(credentials.email);
307
- if (!user || user.blocked || user.deleted || !user.password) return null;
776
+ const user = await getUserByEmail(email);
777
+ if (!user) {
778
+ logAuth("authorize(credentials) rejected", { reason: "user_not_found", email });
779
+ return null;
780
+ }
781
+ if (user.blocked) {
782
+ logAuth("authorize(credentials) rejected", { reason: "blocked", email, userId: user.id });
783
+ return null;
784
+ }
785
+ if (user.deleted) {
786
+ logAuth("authorize(credentials) rejected", { reason: "deleted", email, userId: user.id });
787
+ return null;
788
+ }
789
+ if (!user.password) {
790
+ logAuth("authorize(credentials) rejected", { reason: "no_password", email, userId: user.id });
791
+ return null;
792
+ }
308
793
  const valid = await comparePassword(credentials.password, user.password);
309
- if (!valid) return null;
310
- return sessionUserFromNextAuthUser(user);
311
- } catch {
794
+ if (!valid) {
795
+ logAuth("authorize(credentials) rejected", { reason: "invalid_password", email, userId: user.id });
796
+ return null;
797
+ }
798
+ const sessionUser = sessionUserFromNextAuthUser(user);
799
+ logAuth("authorize(credentials) ok", summarizeSessionUserForLog(sessionUser));
800
+ return sessionUser;
801
+ } catch (err) {
802
+ console.error("[cms-auth] authorize error (credentials):", err instanceof Error ? err.message : err);
803
+ logAuth("authorize(credentials) error", {
804
+ email,
805
+ message: err instanceof Error ? err.message : String(err)
806
+ });
312
807
  return null;
313
808
  }
314
809
  }
@@ -334,7 +829,8 @@ function getNextAuthOptions(config) {
334
829
  const user = await authorizeOtp({ identifier, channel: ch, code });
335
830
  if (!user || user.blocked || user.deleted) return null;
336
831
  return sessionUserFromNextAuthUser(user);
337
- } catch {
832
+ } catch (err) {
833
+ console.error("[cms-auth] authorize error (otp):", err instanceof Error ? err.message : err);
338
834
  return null;
339
835
  }
340
836
  }
@@ -360,31 +856,54 @@ function getNextAuthOptions(config) {
360
856
  callbacks: {
361
857
  async jwt({ token, user, trigger, session }) {
362
858
  if (user) {
859
+ logAuth("jwt callback: new sign-in", {
860
+ trigger,
861
+ user: summarizeSessionUserForLog(user)
862
+ });
363
863
  const u = user;
364
864
  token.id = u.id;
365
865
  token.groupId = u.groupId;
866
+ token.groupName = u.groupName;
366
867
  token.isRBACAdmin = u.isRBACAdmin;
367
868
  token.entityPerms = u.entityPerms;
368
869
  token.adminAccess = u.adminAccess;
870
+ token.vendorIds = u.vendorIds;
871
+ token.activeVendorId = u.activeVendorId;
872
+ token.vendorRole = u.vendorRole;
873
+ token.isVendorPortal = u.isVendorPortal;
874
+ token.isVendorOwner = u.isVendorOwner;
369
875
  }
370
876
  if (trigger === "update" && session && typeof session === "object") {
877
+ logAuth("jwt callback: session update", { trigger });
371
878
  const s = session;
372
879
  const t = token;
373
880
  if (typeof s.name === "string") t.name = s.name;
374
881
  if (typeof s.email === "string") t.email = s.email;
882
+ if (typeof s.activeVendorId === "number") t.activeVendorId = s.activeVendorId;
375
883
  }
376
884
  return token;
377
885
  },
378
886
  async session({ session, token }) {
887
+ const t = token;
888
+ logAuth("session callback", {
889
+ tokenHasId: t.id != null,
890
+ tokenEmail: typeof t.email === "string" ? t.email : null,
891
+ sessionUser: summarizeSessionUserForLog(session.user)
892
+ });
379
893
  if (session.user) {
380
- const t = token;
381
894
  if (typeof t.name === "string") session.user.name = t.name;
382
895
  if (typeof t.email === "string") session.user.email = t.email;
383
896
  session.user.id = t.id;
384
897
  session.user.groupId = t.groupId;
898
+ session.user.groupName = t.groupName;
385
899
  session.user.isRBACAdmin = t.isRBACAdmin;
386
900
  session.user.entityPerms = t.entityPerms;
387
901
  session.user.adminAccess = t.adminAccess;
902
+ session.user.vendorIds = t.vendorIds;
903
+ session.user.activeVendorId = t.activeVendorId;
904
+ session.user.vendorRole = t.vendorRole;
905
+ session.user.isVendorPortal = t.isVendorPortal;
906
+ session.user.isVendorOwner = t.isVendorOwner;
388
907
  }
389
908
  return session;
390
909
  }
@@ -398,19 +917,44 @@ function getNextAuthOptions(config) {
398
917
  OPEN_ENDPOINTS,
399
918
  PERMISSION_REQUIRED_ENDPOINTS,
400
919
  RBAC_ADMIN_ONLY_ENTITIES,
920
+ VENDOR_OWNER_GROUP_NAME,
921
+ VENDOR_SCOPED_STORE_ENTITIES,
922
+ VENDOR_STORE_RBAC_ENTITIES,
401
923
  canManageRoles,
924
+ canManageVendorRoles,
925
+ canManageVendorTeam,
926
+ canOnboardVendors,
402
927
  createAuthHelpers,
928
+ createCmsAuthBundle,
403
929
  createCmsMiddleware,
404
930
  defaultPublicApiMethods,
931
+ explainSessionEntityAccess,
405
932
  getNextAuthOptions,
406
933
  getPermissionableEntityKeys,
407
934
  getRequiredPermission,
408
935
  hasEntityPermission,
936
+ isAuthDebugClientEnabled,
937
+ isAuthDebugEnabled,
409
938
  isOpenEndpoint,
939
+ isPlatformAdministrator,
410
940
  isPublicMethod,
941
+ isRbacDebugEnabled,
411
942
  isSuperAdminGroupName,
943
+ isVendorGroupName,
944
+ isVendorOwner,
945
+ isVendorPortalUser,
946
+ isVendorStaff,
947
+ logAuth,
948
+ logAuthClient,
949
+ logEntityAccessDecision,
950
+ logRbac,
951
+ nextAuthCookieDebugInfo,
412
952
  permissionRowsToRecord,
953
+ resolveVendorScopeFromSessionUser,
413
954
  seedAdministratorPermissions,
414
- sessionHasEntityAccess
955
+ sessionHasEntityAccess,
956
+ summarizeEntityPerms,
957
+ summarizeSessionUserForLog,
958
+ vendorPortalFlagsFromUser
415
959
  });
416
960
  //# sourceMappingURL=auth.cjs.map