@infuro/cms-core 1.0.33 → 1.0.34

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 (38) hide show
  1. package/README.md +9 -6
  2. package/dist/admin.cjs +980 -801
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.d.cts +7 -2
  5. package/dist/admin.d.ts +7 -2
  6. package/dist/admin.js +1021 -842
  7. package/dist/admin.js.map +1 -1
  8. package/dist/api.cjs +1858 -848
  9. package/dist/api.cjs.map +1 -1
  10. package/dist/api.d.cts +1 -1
  11. package/dist/api.d.ts +1 -1
  12. package/dist/api.js +1824 -815
  13. package/dist/api.js.map +1 -1
  14. package/dist/auth.cjs +94 -11
  15. package/dist/auth.cjs.map +1 -1
  16. package/dist/auth.d.cts +17 -1
  17. package/dist/auth.d.ts +17 -1
  18. package/dist/auth.js +89 -11
  19. package/dist/auth.js.map +1 -1
  20. package/dist/cli.cjs +39 -0
  21. package/dist/cli.cjs.map +1 -1
  22. package/dist/cli.js +39 -0
  23. package/dist/cli.js.map +1 -1
  24. package/dist/{index-rZTnpK7y.d.cts → index-Bf5GO8fu.d.cts} +3 -2
  25. package/dist/{index-DWd5Gjc4.d.ts → index-DOiJuMQA.d.ts} +3 -2
  26. package/dist/index.cjs +2078 -841
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +83 -8
  29. package/dist/index.d.ts +83 -8
  30. package/dist/index.js +2013 -786
  31. package/dist/index.js.map +1 -1
  32. package/dist/migrations/1778660000004-CreateCustomerAndCustomerContacts.ts +99 -0
  33. package/dist/migrations/1778660000005-AddCustomerIdToVendorCustomers.ts +39 -0
  34. package/dist/migrations/1778660000006-UpdateVendorCustomersContactNullable.ts +36 -0
  35. package/dist/migrations/1778660000007-VendorOwnerCustomerContactsPermission.ts +39 -0
  36. package/dist/migrations/1779300000000-VendorOwnerContactsPermission.ts +39 -0
  37. package/dist/migrations/1779400000000-AddCustomerContactIdToOrders.ts +33 -0
  38. package/package.json +4 -3
package/dist/auth.d.ts CHANGED
@@ -49,8 +49,17 @@ interface NextAuthOptionsConfig {
49
49
  enableOtpLogin?: boolean;
50
50
  /** Validate OTP and return user (same shape as password flow) or null. */
51
51
  authorizeOtp?: (input: AuthorizeOtpInput) => Promise<NextAuthUser | null>;
52
+ /**
53
+ * Customer group sign-in policy for credentials/OTP on a shared `/api/auth` route:
54
+ * - `true` — always allow (dedicated storefront auth)
55
+ * - `false` — always block
56
+ * - omitted — auto: allow unless `callbackUrl` targets `/admin` (storefront `/signin` works unchanged)
57
+ */
58
+ allowCustomerLogin?: boolean;
52
59
  }
53
60
  declare function getNextAuthOptions(config: NextAuthOptionsConfig): NextAuthOptions;
61
+ /** Storefront sign-in: allows Customer group; use with signInPage `/signin`. */
62
+ declare function getStorefrontNextAuthOptions(config: Omit<NextAuthOptionsConfig, 'allowCustomerLogin'>): NextAuthOptions;
54
63
 
55
64
  /** Minimal DB handle for RBAC debug (avoids importing `typeorm` in the auth bundle). */
56
65
  type RbacDebugDataSource = {
@@ -74,6 +83,13 @@ interface EntityAccessExplanation {
74
83
  declare function explainSessionEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): EntityAccessExplanation;
75
84
  declare function logEntityAccessDecision(dataSource: RbacDebugDataSource | undefined, context: string, user: SessionUser | null | undefined, entity: string, action: EntityCrudAction, extra?: Record<string, unknown>): Promise<void>;
76
85
 
86
+ /** Platform super admin (`user_groups.id = 1` or Administrator group). */
87
+ declare const SUPER_ADMIN_GROUP_ID = 1;
88
+ /** Vendor store admin (`user_groups.id = 5` or vendor-linked portal users). */
89
+ declare const VENDOR_ADMIN_GROUP_ID = 5;
90
+ declare function isSuperAdmin(user: SessionUser | null | undefined): boolean;
91
+ declare function isVendorAdmin(user: SessionUser | null | undefined): boolean;
92
+
77
93
  /**
78
94
  * Ensures the Administrator group has full CRUD on every permissionable entity
79
95
  * for the given entity map. Idempotent: upserts per entity.
@@ -138,4 +154,4 @@ declare function logAuthClient(message: string, data?: Record<string, unknown>):
138
154
  declare function summarizeSessionUserForLog(user: unknown): Record<string, unknown>;
139
155
  declare function nextAuthCookieDebugInfo(): Record<string, unknown>;
140
156
 
141
- export { type AuthorizeOtpInput, type CmsMiddlewareConfig, type CmsMiddlewareRequest, EntityCrudAction, EntityPermissionFlags, type NextAuthOptionsConfig, type NextAuthUser, SessionUser, createCmsMiddleware, defaultPublicApiMethods, explainSessionEntityAccess, getNextAuthOptions, isAuthDebugClientEnabled, isAuthDebugEnabled, isRbacDebugEnabled, logAuth, logAuthClient, logEntityAccessDecision, logRbac, nextAuthCookieDebugInfo, seedAdministratorPermissions, summarizeEntityPerms, summarizeSessionUserForLog };
157
+ export { type AuthorizeOtpInput, type CmsMiddlewareConfig, type CmsMiddlewareRequest, EntityCrudAction, EntityPermissionFlags, type NextAuthOptionsConfig, type NextAuthUser, SUPER_ADMIN_GROUP_ID, SessionUser, VENDOR_ADMIN_GROUP_ID, createCmsMiddleware, defaultPublicApiMethods, explainSessionEntityAccess, getNextAuthOptions, getStorefrontNextAuthOptions, isAuthDebugClientEnabled, isAuthDebugEnabled, isRbacDebugEnabled, isSuperAdmin, isVendorAdmin, logAuth, logAuthClient, logEntityAccessDecision, logRbac, nextAuthCookieDebugInfo, seedAdministratorPermissions, summarizeEntityPerms, summarizeSessionUserForLog };
package/dist/auth.js CHANGED
@@ -72,6 +72,30 @@ var init_permission_entities = __esm({
72
72
  }
73
73
  });
74
74
 
75
+ // src/auth/role-helpers.ts
76
+ function isSuperAdmin(user) {
77
+ if (!user) return false;
78
+ if (user.groupId === SUPER_ADMIN_GROUP_ID) return true;
79
+ if (user.isRBACAdmin === true) return true;
80
+ return isSuperAdminGroupName(user.groupName);
81
+ }
82
+ function isVendorAdmin(user) {
83
+ if (!user?.email || isSuperAdmin(user)) return false;
84
+ if (user.groupId === VENDOR_ADMIN_GROUP_ID) return true;
85
+ if ((user.vendorIds?.length ?? 0) > 0) return true;
86
+ return isVendorGroupName(user.groupName);
87
+ }
88
+ var SUPER_ADMIN_GROUP_ID, VENDOR_ADMIN_GROUP_ID;
89
+ var init_role_helpers = __esm({
90
+ "src/auth/role-helpers.ts"() {
91
+ "use strict";
92
+ init_permission_entities();
93
+ init_vendor_scope();
94
+ SUPER_ADMIN_GROUP_ID = 1;
95
+ VENDOR_ADMIN_GROUP_ID = 5;
96
+ }
97
+ });
98
+
75
99
  // src/auth/vendor-scope.ts
76
100
  function isVendorGroupName(name) {
77
101
  if (!name?.trim()) return false;
@@ -80,12 +104,12 @@ function isVendorGroupName(name) {
80
104
  }
81
105
  function isPlatformAdministrator(user) {
82
106
  if (!user?.email) return false;
83
- return !!(user.isRBACAdmin || isSuperAdminGroupName(user.groupName));
107
+ return isSuperAdmin(user);
84
108
  }
85
109
  function isVendorPortalUser(user) {
86
110
  if (user?.isVendorPortal === true) return true;
87
111
  if (!user?.email || isPlatformAdministrator(user)) return false;
88
- if ((user.vendorIds?.length ?? 0) > 0) return true;
112
+ if (isVendorAdmin(user)) return true;
89
113
  return isVendorGroupName(user.groupName);
90
114
  }
91
115
  function isVendorStaff(user) {
@@ -127,7 +151,7 @@ var VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, VENDOR_OWNER_GROUP
127
151
  var init_vendor_scope = __esm({
128
152
  "src/auth/vendor-scope.ts"() {
129
153
  "use strict";
130
- init_permission_entities();
154
+ init_role_helpers();
131
155
  VENDOR_SCOPED_STORE_ENTITIES = /* @__PURE__ */ new Set([
132
156
  "products",
133
157
  "collections",
@@ -455,6 +479,7 @@ function createAuthHelpersFromGetSession(getSession, NextResponse) {
455
479
 
456
480
  // src/auth/index.ts
457
481
  init_rbac_debug();
482
+ init_role_helpers();
458
483
  init_vendor_scope();
459
484
  init_permission_entities();
460
485
 
@@ -640,12 +665,17 @@ function createCmsMiddleware(config = {}) {
640
665
 
641
666
  // src/auth/nextauth-options.ts
642
667
  init_permission_entities();
668
+ init_role_helpers();
643
669
  init_vendor_scope();
644
670
  import _CredentialsProvider from "next-auth/providers/credentials";
645
671
  var CredentialsProvider = _CredentialsProvider.default ?? _CredentialsProvider;
646
672
  function sessionUserFromNextAuthUser(user) {
647
673
  const g = user.group;
648
- const isRBACAdmin = isSuperAdminGroupName(g?.name);
674
+ const isRBACAdmin = isSuperAdmin({
675
+ groupId: user.groupId ?? void 0,
676
+ groupName: g?.name,
677
+ isRBACAdmin: false
678
+ });
649
679
  const entityPerms = permissionRowsToRecord(g?.permissions);
650
680
  const rawAdminAccess = user.adminAccess;
651
681
  const adminAccess = rawAdminAccess === true ? true : rawAdminAccess === false ? false : void 0;
@@ -674,6 +704,26 @@ function sessionUserFromNextAuthUser(user) {
674
704
  isVendorOwner: isVendorOwner2
675
705
  };
676
706
  }
707
+ function isCustomerGroupUser(user) {
708
+ return user.group?.name?.toLocaleLowerCase().trim() === "customer";
709
+ }
710
+ function callbackUrlTargetsAdmin(callbackUrl) {
711
+ const raw = callbackUrl.trim();
712
+ if (!raw) return false;
713
+ if (raw.startsWith("/admin")) return true;
714
+ try {
715
+ const path = raw.startsWith("http") ? new URL(raw).pathname : raw.split("?")[0] ?? raw;
716
+ return path.startsWith("/admin");
717
+ } catch {
718
+ return raw.includes("/admin");
719
+ }
720
+ }
721
+ function permitsCustomerLogin(allowCustomerLogin, credentials) {
722
+ if (allowCustomerLogin === true) return true;
723
+ if (allowCustomerLogin === false) return false;
724
+ const callbackUrl = typeof credentials?.callbackUrl === "string" ? credentials.callbackUrl : "";
725
+ return !callbackUrlTargetsAdmin(callbackUrl);
726
+ }
677
727
  function getNextAuthOptions(config) {
678
728
  const {
679
729
  getUserByEmail,
@@ -683,7 +733,8 @@ function getNextAuthOptions(config) {
683
733
  extend,
684
734
  enablePasswordLogin = true,
685
735
  enableOtpLogin = false,
686
- authorizeOtp
736
+ authorizeOtp,
737
+ allowCustomerLogin
687
738
  } = config;
688
739
  logAuth("getNextAuthOptions init", nextAuthCookieDebugInfo());
689
740
  const providers = [];
@@ -696,8 +747,9 @@ function getNextAuthOptions(config) {
696
747
  password: { label: "Password", type: "password" }
697
748
  },
698
749
  async authorize(credentials) {
699
- const email = credentials?.email?.trim() ?? "";
700
- if (!email || !credentials?.password) {
750
+ const creds = credentials;
751
+ const email = creds?.email?.trim() ?? "";
752
+ if (!email || !creds?.password) {
701
753
  logAuth("authorize(credentials) rejected", { reason: "missing_email_or_password" });
702
754
  return null;
703
755
  }
@@ -719,11 +771,20 @@ function getNextAuthOptions(config) {
719
771
  logAuth("authorize(credentials) rejected", { reason: "no_password", email, userId: user.id });
720
772
  return null;
721
773
  }
722
- const valid = await comparePassword(credentials.password, user.password);
774
+ const valid = await comparePassword(creds.password, user.password);
723
775
  if (!valid) {
724
776
  logAuth("authorize(credentials) rejected", { reason: "invalid_password", email, userId: user.id });
725
777
  return null;
726
778
  }
779
+ if (isCustomerGroupUser(user) && !permitsCustomerLogin(allowCustomerLogin, creds)) {
780
+ logAuth("authorize(credentials) rejected", {
781
+ reason: "customer_group",
782
+ email,
783
+ userId: user.id,
784
+ callbackUrl: creds?.callbackUrl ?? null
785
+ });
786
+ return null;
787
+ }
727
788
  const sessionUser = sessionUserFromNextAuthUser(user);
728
789
  logAuth("authorize(credentials) ok", summarizeSessionUserForLog(sessionUser));
729
790
  return sessionUser;
@@ -750,13 +811,22 @@ function getNextAuthOptions(config) {
750
811
  channel: { label: "Channel", type: "text" }
751
812
  },
752
813
  async authorize(credentials) {
753
- const identifier = typeof credentials?.identifier === "string" ? credentials.identifier.trim() : "";
754
- const code = typeof credentials?.code === "string" ? credentials.code.trim() : "";
755
- const ch = credentials?.channel === "sms" ? "sms" : "email";
814
+ const creds = credentials;
815
+ const identifier = typeof creds?.identifier === "string" ? creds.identifier.trim() : "";
816
+ const code = typeof creds?.code === "string" ? creds.code.trim() : "";
817
+ const ch = creds?.channel === "sms" ? "sms" : "email";
756
818
  if (!identifier || !code) return null;
757
819
  try {
758
820
  const user = await authorizeOtp({ identifier, channel: ch, code });
759
821
  if (!user || user.blocked || user.deleted) return null;
822
+ if (isCustomerGroupUser(user) && !permitsCustomerLogin(allowCustomerLogin, creds)) {
823
+ logAuth("authorize(otp) rejected", {
824
+ reason: "customer_group",
825
+ identifier,
826
+ callbackUrl: creds?.callbackUrl ?? null
827
+ });
828
+ return null;
829
+ }
760
830
  return sessionUserFromNextAuthUser(user);
761
831
  } catch (err) {
762
832
  console.error("[cms-auth] authorize error (otp):", err instanceof Error ? err.message : err);
@@ -840,11 +910,16 @@ function getNextAuthOptions(config) {
840
910
  };
841
911
  return extend ? extend(options) : options;
842
912
  }
913
+ function getStorefrontNextAuthOptions(config) {
914
+ return getNextAuthOptions({ ...config, allowCustomerLogin: true });
915
+ }
843
916
  export {
844
917
  ADMIN_GROUP_NAME,
845
918
  OPEN_ENDPOINTS,
846
919
  PERMISSION_REQUIRED_ENDPOINTS,
847
920
  RBAC_ADMIN_ONLY_ENTITIES,
921
+ SUPER_ADMIN_GROUP_ID,
922
+ VENDOR_ADMIN_GROUP_ID,
848
923
  VENDOR_OWNER_GROUP_NAME,
849
924
  VENDOR_SCOPED_STORE_ENTITIES,
850
925
  VENDOR_STORE_RBAC_ENTITIES,
@@ -860,6 +935,7 @@ export {
860
935
  getNextAuthOptions,
861
936
  getPermissionableEntityKeys,
862
937
  getRequiredPermission,
938
+ getStorefrontNextAuthOptions,
863
939
  hasEntityPermission,
864
940
  isAuthDebugClientEnabled,
865
941
  isAuthDebugEnabled,
@@ -867,7 +943,9 @@ export {
867
943
  isPlatformAdministrator,
868
944
  isPublicMethod,
869
945
  isRbacDebugEnabled,
946
+ isSuperAdmin,
870
947
  isSuperAdminGroupName,
948
+ isVendorAdmin,
871
949
  isVendorGroupName,
872
950
  isVendorOwner,
873
951
  isVendorPortalUser,
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/permission-entities.ts","../src/auth/vendor-scope.ts","../src/auth/rbac-debug-db.ts","../src/auth/rbac-debug.ts","../src/auth/helpers.ts","../src/auth/index.ts","../src/auth/seed-permissions.ts","../src/auth/middleware.ts","../src/auth/auth-debug.ts","../src/auth/nextauth-options.ts"],"sourcesContent":["/** API resource keys excluded from the permission matrix (internal / not admin-CRUD). */\r\nexport const PERMISSION_ENTITY_INTERNAL_EXCLUDE = new Set([\r\n 'users',\r\n 'password_reset_tokens',\r\n 'user_groups',\r\n 'permissions',\r\n 'comments',\r\n 'form_fields',\r\n 'configs',\r\n 'knowledge_base_chunks',\r\n 'carts',\r\n 'cart_items',\r\n 'wishlists',\r\n 'wishlist_items',\r\n 'message_templates',\r\n 'vendor_users',\r\n]);\r\n\r\n/** Non-CRUD admin surfaces mapped to entity keys for RBAC. */\r\nexport const PERMISSION_LOGICAL_ENTITIES = [\r\n 'users',\r\n 'forms',\r\n 'form_submissions',\r\n 'dashboard',\r\n 'upload',\r\n 'settings',\r\n 'analytics',\r\n 'chat',\r\n] as const;\r\n\r\n/** Canonical name for new installs / migrations */\r\nexport const ADMIN_GROUP_NAME = 'Administrator';\r\n\r\n/** System administrator group (roles UI + users / user_groups / permissions bypass). */\r\nexport function isSuperAdminGroupName(name: string | null | undefined): boolean {\r\n return name === ADMIN_GROUP_NAME;\r\n}\r\n\r\nexport type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';\r\n\r\nexport type EntityPermissionFlags = { c: boolean; r: boolean; u: boolean; d: boolean };\r\n\r\nexport function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[] {\r\n const fromMap = Object.keys(entityMap).filter((k) => !PERMISSION_ENTITY_INTERNAL_EXCLUDE.has(k));\r\n const logical = PERMISSION_LOGICAL_ENTITIES.filter((k) => !fromMap.includes(k));\r\n return [...fromMap.sort(), ...logical].filter((k, i, a) => a.indexOf(k) === i);\r\n}\r\n\r\nexport function permissionRowsToRecord(\r\n rows: Array<{ entity: string; canCreate: boolean; canRead: boolean; canUpdate: boolean; canDelete: boolean }> | undefined\r\n): Record<string, EntityPermissionFlags> {\r\n const out: Record<string, EntityPermissionFlags> = {};\r\n if (!rows?.length) return out;\r\n for (const p of rows) {\r\n out[p.entity] = {\r\n c: !!p.canCreate,\r\n r: !!p.canRead,\r\n u: !!p.canUpdate,\r\n d: !!p.canDelete,\r\n };\r\n }\r\n return out;\r\n}\r\n\r\nexport function hasEntityPermission(\r\n record: Record<string, EntityPermissionFlags> | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n const p = record?.[entity];\r\n if (!p) return false;\r\n if (action === 'create') return p.c;\r\n if (action === 'read') return p.r;\r\n if (action === 'update') return p.u;\r\n return p.d;\r\n}\r\n","import type { SessionUser } from './helpers';\r\nimport { isSuperAdminGroupName } from './permission-entities';\r\n\r\n/** Entities with a `vendorId` column (store data). */\r\nexport const VENDOR_SCOPED_STORE_ENTITIES = new Set([\r\n 'products',\r\n 'collections',\r\n 'brands',\r\n 'product_categories',\r\n 'orders',\r\n 'payments',\r\n 'taxes',\r\n 'attributes',\r\n 'vendor_customers',\r\n 'discounts',\r\n]);\r\n\r\n/**\r\n * Store admin RBAC for vendor portal users (read/create/update/delete fallbacks in rbac-debug).\r\n * Includes entities without `vendorId` that are still part of the store admin UI.\r\n */\r\nexport const VENDOR_STORE_RBAC_ENTITIES = new Set<string>([\r\n ...VENDOR_SCOPED_STORE_ENTITIES,\r\n 'order_discounts',\r\n 'order_addresses',\r\n]);\r\n\r\nexport type VendorScope =\r\n | { type: 'all' }\r\n | { type: 'vendor'; vendorId: number; vendorIds: number[] }\r\n | { type: 'deny' };\r\n\r\nexport const VENDOR_OWNER_GROUP_NAME = 'Vendor Owner';\r\n\r\n/** User groups treated as vendor store staff (sidebar + scoped admin). */\r\nexport function isVendorGroupName(name: string | null | undefined): boolean {\r\n if (!name?.trim()) return false;\r\n const n = name.trim().toLowerCase();\r\n return n === VENDOR_OWNER_GROUP_NAME.toLowerCase() || n.includes('vendor');\r\n}\r\n\r\nexport function isPlatformAdministrator(user: SessionUser | null | undefined): boolean {\r\n if (!user?.email) return false;\r\n return !!(user.isRBACAdmin || isSuperAdminGroupName(user.groupName));\r\n}\r\n\r\n/** Vendor portal UI (store + store admin), not platform admin. */\r\nexport function isVendorPortalUser(user: SessionUser | null | undefined): boolean {\r\n if (user?.isVendorPortal === true) return true;\r\n if (!user?.email || isPlatformAdministrator(user)) return false;\r\n if ((user.vendorIds?.length ?? 0) > 0) return true;\r\n return isVendorGroupName(user.groupName);\r\n}\r\n\r\nexport function isVendorStaff(user: SessionUser | null | undefined): boolean {\r\n return isVendorPortalUser(user);\r\n}\r\n\r\n/** Vendor store owner (manages team + role permissions for their group). */\r\nexport function isVendorOwner(user: SessionUser | null | undefined): boolean {\r\n if (user?.isVendorOwner === true) return true;\r\n if (!user?.email || isPlatformAdministrator(user)) return false;\r\n if (user.vendorRole === 'staff') return false;\r\n if (user.vendorRole === 'owner') return true;\r\n if (!isVendorPortalUser(user)) return false;\r\n return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();\r\n}\r\n\r\nexport function canManageVendorTeam(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user) || isVendorOwner(user);\r\n}\r\n\r\nexport function canManageVendorRoles(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user) || isVendorOwner(user);\r\n}\r\n\r\n/** Platform admins (Administrator group) can onboard vendors. */\r\nexport function canOnboardVendors(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user);\r\n}\r\n\r\nexport function resolveVendorScopeFromSessionUser(user: SessionUser | null | undefined): VendorScope {\r\n if (!user?.email) return { type: 'deny' };\r\n if (isPlatformAdministrator(user)) return { type: 'all' };\r\n const vendorIds = user.vendorIds ?? [];\r\n if (vendorIds.length === 0) return { type: 'deny' };\r\n const preferred = user.activeVendorId ?? vendorIds[0]!;\r\n const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0]!;\r\n return { type: 'vendor', vendorId, vendorIds };\r\n}\r\n\r\n/** Compute portal flags at login (persist on JWT). */\r\nexport function vendorPortalFlagsFromUser(input: {\r\n email: string;\r\n isRBACAdmin: boolean;\r\n groupName?: string | null;\r\n vendorIds?: number[];\r\n vendorRole?: 'owner' | 'staff' | null;\r\n}): { isVendorPortal: boolean; isVendorOwner: boolean } {\r\n const vendorIds = input.vendorIds ?? [];\r\n const isVendorPortal =\r\n !input.isRBACAdmin &&\r\n (vendorIds.length > 0 || isVendorGroupName(input.groupName));\r\n const isVendorOwner =\r\n isVendorPortal &&\r\n input.vendorRole !== 'staff' &&\r\n (input.vendorRole === 'owner' ||\r\n input.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase());\r\n return { isVendorPortal, isVendorOwner };\r\n}\r\n","import { permissionRowsToRecord } from './permission-entities';\r\nimport type { RbacDebugDataSource } from './rbac-debug';\r\nimport { summarizeEntityPerms } from './rbac-debug';\r\n\r\n/** Load permission rows from DB for debug (server/API only — do not import from `@infuro/cms-core/auth`). */\r\nexport async function loadDbPermissionsForUser(\r\n dataSource: RbacDebugDataSource,\r\n userId: number\r\n): Promise<{\r\n groupId: number | null;\r\n groupName: string | null;\r\n dbEntityPerms: Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }>;\r\n}> {\r\n const rows = (await dataSource.query(\r\n `\r\n SELECT u.\"groupId\" AS \"groupId\", g.name AS \"groupName\",\r\n p.entity, p.\"canCreate\", p.\"canRead\", p.\"canUpdate\", p.\"canDelete\"\r\n FROM users u\r\n LEFT JOIN user_groups g ON g.id = u.\"groupId\" AND g.deleted = false\r\n LEFT JOIN permissions p ON p.\"groupId\" = g.id\r\n WHERE u.id = $1\r\n `,\r\n [userId]\r\n )) as Array<{\r\n groupId: number | null;\r\n groupName: string | null;\r\n entity: string | null;\r\n canCreate: boolean | null;\r\n canRead: boolean | null;\r\n canUpdate: boolean | null;\r\n canDelete: boolean | null;\r\n }>;\r\n\r\n const groupId = rows[0]?.groupId ?? null;\r\n const groupName = rows[0]?.groupName ?? null;\r\n const permRows = rows\r\n .filter((r) => r.entity)\r\n .map((r) => ({\r\n entity: r.entity!,\r\n canCreate: !!r.canCreate,\r\n canRead: !!r.canRead,\r\n canUpdate: !!r.canUpdate,\r\n canDelete: !!r.canDelete,\r\n }));\r\n\r\n return {\r\n groupId,\r\n groupName,\r\n dbEntityPerms: summarizeEntityPerms(permissionRowsToRecord(permRows)),\r\n };\r\n}\r\n","import type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nimport { hasEntityPermission } from './permission-entities';\r\nimport type { SessionUser } from './helpers';\r\nimport { isVendorOwner, isVendorPortalUser, VENDOR_STORE_RBAC_ENTITIES } from './vendor-scope';\r\n\r\nconst LOG_PREFIX = '[cms-rbac]';\r\n\r\n/** Minimal DB handle for RBAC debug (avoids importing `typeorm` in the auth bundle). */\r\nexport type RbacDebugDataSource = {\r\n query: (sql: string, parameters?: unknown[]) => Promise<unknown>;\r\n};\r\n\r\n/** Set `CMS_RBAC_DEBUG=true` in `.env` to log permission decisions (server console). */\r\nexport function isRbacDebugEnabled(): boolean {\r\n const v = process.env.CMS_RBAC_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\nexport function logRbac(message: string, data?: Record<string, unknown>): void {\r\n if (!isRbacDebugEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function summarizeEntityPerms(\r\n entityPerms: Record<string, EntityPermissionFlags> | undefined\r\n): Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }> {\r\n const out: Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }> = {};\r\n if (!entityPerms) return out;\r\n for (const [entity, p] of Object.entries(entityPerms)) {\r\n out[entity] = { c: p.c, r: p.r, u: p.u, d: p.d };\r\n }\r\n return out;\r\n}\r\n\r\nexport interface EntityAccessExplanation {\r\n allowed: boolean;\r\n reason: string;\r\n userSnapshot: Record<string, unknown>;\r\n}\r\n\r\nfunction vendorPortalFallbackReason(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): string | null {\r\n if (!isVendorPortalUser(user)) return null;\r\n if (entity === 'dashboard' && action === 'read') return 'vendor_portal_dashboard_fallback';\r\n if (entity === 'analytics' && action === 'read') return 'vendor_portal_analytics_fallback';\r\n if (entity === 'settings' && action === 'read') return 'vendor_portal_settings_read_fallback';\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === 'read') return 'vendor_portal_store_read_fallback';\r\n return null;\r\n}\r\n\r\n/** Same rules as `sessionHasEntityAccess`, but returns why access was granted or denied. */\r\nexport function explainSessionEntityAccess(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): EntityAccessExplanation {\r\n const userSnapshot: Record<string, unknown> = {\r\n email: user?.email ?? null,\r\n id: user?.id ?? null,\r\n groupId: user?.groupId ?? null,\r\n groupName: user?.groupName ?? null,\r\n isRBACAdmin: user?.isRBACAdmin ?? false,\r\n adminAccess: user?.adminAccess ?? null,\r\n vendorIds: user?.vendorIds ?? [],\r\n activeVendorId: user?.activeVendorId ?? null,\r\n vendorRole: user?.vendorRole ?? null,\r\n isVendorPortal: user?.isVendorPortal ?? false,\r\n isVendorOwner: user?.isVendorOwner ?? false,\r\n isVendorPortalComputed: isVendorPortalUser(user),\r\n isVendorOwnerComputed: isVendorOwner(user),\r\n jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),\r\n jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null,\r\n };\r\n\r\n if (!user?.email) {\r\n return { allowed: false, reason: 'no_session_email', userSnapshot };\r\n }\r\n if (user.isRBACAdmin) {\r\n return { allowed: true, reason: 'platform_administrator', userSnapshot };\r\n }\r\n\r\n const vendorIds = user.vendorIds ?? [];\r\n const isStaff = user.vendorRole === 'staff';\r\n\r\n if (vendorIds.length > 0) {\r\n if (entity === 'dashboard' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_dashboard_read', userSnapshot };\r\n }\r\n if (entity === 'analytics' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_analytics_read', userSnapshot };\r\n }\r\n if (entity === 'settings') {\r\n if (action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_settings_read', userSnapshot };\r\n }\r\n if (action === 'update' && !isStaff) {\r\n return { allowed: true, reason: 'vendor_link_settings_update', userSnapshot };\r\n }\r\n }\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {\r\n if (isStaff && action === 'read') {\r\n return { allowed: true, reason: 'vendor_staff_store_read', userSnapshot };\r\n }\r\n if (!isStaff) {\r\n return { allowed: true, reason: 'vendor_link_store_full', userSnapshot };\r\n }\r\n return {\r\n allowed: false,\r\n reason: 'vendor_staff_store_write_denied',\r\n userSnapshot,\r\n };\r\n }\r\n }\r\n\r\n if (isVendorPortalUser(user) && isVendorOwner(user)) {\r\n if (entity === 'dashboard' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_owner_group_dashboard', userSnapshot };\r\n }\r\n if (entity === 'analytics' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_owner_group_analytics', userSnapshot };\r\n }\r\n if (entity === 'settings' && (action === 'read' || action === 'update')) {\r\n return { allowed: true, reason: 'vendor_owner_group_settings', userSnapshot };\r\n }\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {\r\n return { allowed: true, reason: 'vendor_owner_group_store', userSnapshot };\r\n }\r\n }\r\n\r\n const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);\r\n if (vendorPortalReason) {\r\n return { allowed: true, reason: vendorPortalReason, userSnapshot };\r\n }\r\n\r\n const explicit = user.entityPerms?.[entity];\r\n if (explicit !== undefined) {\r\n const allowed = hasEntityPermission(user.entityPerms, entity, action);\r\n return {\r\n allowed,\r\n reason: allowed ? 'jwt_entity_perms_allow' : 'jwt_entity_perms_deny',\r\n userSnapshot,\r\n };\r\n }\r\n\r\n const allowed = hasEntityPermission(user.entityPerms, entity, action);\r\n return {\r\n allowed,\r\n reason: allowed ? 'entity_perms_fallback_allow' : 'no_matching_rule',\r\n userSnapshot,\r\n };\r\n}\r\n\r\nexport function sessionHasEntityAccessFromExplanation(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n return explainSessionEntityAccess(user, entity, action).allowed;\r\n}\r\n\r\nexport async function logEntityAccessDecision(\r\n dataSource: RbacDebugDataSource | undefined,\r\n context: string,\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction,\r\n extra?: Record<string, unknown>\r\n): Promise<void> {\r\n if (!isRbacDebugEnabled()) return;\r\n\r\n const explanation = explainSessionEntityAccess(user, entity, action);\r\n let dbPermissions: Record<string, unknown> | undefined;\r\n if (dataSource && user?.id) {\r\n const id = Number(user.id);\r\n if (Number.isFinite(id)) {\r\n try {\r\n const { loadDbPermissionsForUser } = await import('./rbac-debug-db');\r\n dbPermissions = await loadDbPermissionsForUser(dataSource, id);\r\n } catch (e) {\r\n dbPermissions = { error: e instanceof Error ? e.message : String(e) };\r\n }\r\n }\r\n }\r\n\r\n logRbac(context, {\r\n entity,\r\n action,\r\n allowed: explanation.allowed,\r\n reason: explanation.reason,\r\n ...explanation.userSnapshot,\r\n dbPermissions,\r\n ...extra,\r\n });\r\n}\r\n","import type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nimport { explainSessionEntityAccess, logRbac } from './rbac-debug';\r\nimport { isVendorPortalUser } from './vendor-scope';\r\n\r\n/**\r\n * @deprecated Administrator bypass is now full entity access via `isRBACAdmin` in `sessionHasEntityAccess`.\r\n * Kept for backwards-compatible imports.\r\n */\r\nexport const RBAC_ADMIN_ONLY_ENTITIES = new Set(['users', 'user_groups', 'permissions']);\r\n\r\nexport interface SessionUser {\r\n id?: string;\r\n email?: string | null;\r\n name?: string | null;\r\n groupId?: number;\r\n /** User group display name (from login). */\r\n groupName?: string | null;\r\n /** @deprecated use entityPerms / isRBACAdmin */\r\n permissions?: string[];\r\n /** Administrator group: bypasses entity-level RBAC on all resources */\r\n isRBACAdmin?: boolean;\r\n entityPerms?: Record<string, EntityPermissionFlags>;\r\n /** When false and not isRBACAdmin, admin API/UI is denied. */\r\n adminAccess?: boolean;\r\n /** Vendor stores this user can access (from vendor_users). */\r\n vendorIds?: number[];\r\n /** Active vendor for scoped CRUD (vendor staff). */\r\n activeVendorId?: number | null;\r\n /** Role for the active vendor link (`vendor_users.role`). */\r\n vendorRole?: 'owner' | 'staff' | null;\r\n /** Set at login: vendor store portal (not platform admin). */\r\n isVendorPortal?: boolean;\r\n /** Set at login: vendor store owner (team + permissions). */\r\n isVendorOwner?: boolean;\r\n}\r\n\r\nexport function sessionHasEntityAccess(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n return explainSessionEntityAccess(user, entity, action).allowed;\r\n}\r\n\r\nexport function canManageRoles(user: SessionUser | null | undefined): boolean {\r\n return !!(user?.email && user.isRBACAdmin);\r\n}\r\n\r\nexport type GetSession = () => Promise<{ user?: SessionUser } | null>;\r\n\r\nexport const OPEN_ENDPOINTS: Array<Record<string, string[]>> = [\r\n { '/api/contacts': ['POST'] },\r\n { '/api/form-submissions': ['POST'] },\r\n { '/api/blogs': ['GET'] },\r\n];\r\n\r\nexport const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]> = {};\r\n\r\nexport function isOpenEndpoint(pathname: string): boolean {\r\n return OPEN_ENDPOINTS.some((endpoint) => pathname.startsWith(Object.keys(endpoint)[0]));\r\n}\r\n\r\nexport function getRequiredPermission(pathname: string): string[] | null {\r\n return null;\r\n}\r\n\r\nexport function isPublicMethod(pathname: string, method: string): boolean {\r\n for (const endpoint of OPEN_ENDPOINTS) {\r\n const key = Object.keys(endpoint)[0];\r\n if (pathname.startsWith(key) && endpoint[key].includes(method)) return true;\r\n }\r\n return false;\r\n}\r\n\r\nexport interface AuthHelpers {\r\n requireAuth(req: Request): Promise<Response | null>;\r\n requirePermission(req: Request, permission: string): Promise<Response | null>;\r\n requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;\r\n requireAdminAccess(req: Request): Promise<Response | null>;\r\n getAuthenticatedUser(): Promise<SessionUser | null>;\r\n}\r\n\r\nexport function createAuthHelpers(getSession: GetSession, NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }): AuthHelpers {\r\n return createAuthHelpersFromGetSession(getSession, NextResponse);\r\n}\r\n\r\n/** Pass return value into `createCmsApiHandler` (includes `getSessionUser` for vendor store APIs). */\r\nexport function createCmsAuthBundle(\r\n getSession: GetSession,\r\n NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }\r\n) {\r\n const auth = createAuthHelpers(getSession, NextResponse);\r\n return {\r\n requireAuth: auth.requireAuth,\r\n requireAdminAccess: auth.requireAdminAccess,\r\n requireEntityPermission: auth.requireEntityPermission,\r\n getSessionUser: auth.getAuthenticatedUser,\r\n getAuthenticatedUser: auth.getAuthenticatedUser,\r\n };\r\n}\r\n\r\nfunction createAuthHelpersFromGetSession(\r\n getSession: GetSession,\r\n NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }\r\n): AuthHelpers {\r\n return {\r\n async requireAuth() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n return null;\r\n },\r\n async requirePermission() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n return null;\r\n },\r\n async requireEntityPermission(_req: Request, entity: string, action: EntityCrudAction) {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n const u = session.user as SessionUser;\r\n const allowed = sessionHasEntityAccess(u, entity, action);\r\n const { reason } = explainSessionEntityAccess(u, entity, action);\r\n logRbac('authHelpers.requireEntityPermission', {\r\n entity,\r\n action,\r\n allowed,\r\n reason,\r\n email: u.email,\r\n groupName: u.groupName,\r\n vendorIds: u.vendorIds,\r\n isVendorPortal: u.isVendorPortal,\r\n isVendorOwner: u.isVendorOwner,\r\n });\r\n if (allowed) return null;\r\n return NextResponse.json({ error: 'Forbidden', entity, action, reason }, { status: 403 });\r\n },\r\n async requireAdminAccess() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n const u = session.user as SessionUser;\r\n if (u.isRBACAdmin) return null;\r\n // Vendor portal users always have admin UI access for their store — check\r\n // before adminAccess so that vendor users (who have adminAccess:false from\r\n // the DB default) are not incorrectly denied.\r\n if (isVendorPortalUser(u)) return null;\r\n if (u.adminAccess === true) return null;\r\n if (u.adminAccess === false) {\r\n logRbac('requireAdminAccess denied (adminAccess:false)', {\r\n email: u.email,\r\n groupName: u.groupName,\r\n isVendorPortal: u.isVendorPortal,\r\n });\r\n return NextResponse.json({ error: 'Forbidden', reason: 'admin_access' }, { status: 403 });\r\n }\r\n logRbac('requireAdminAccess denied (no matching rule)', {\r\n email: u.email,\r\n adminAccess: u.adminAccess,\r\n groupName: u.groupName,\r\n isVendorPortal: u.isVendorPortal,\r\n });\r\n return NextResponse.json({ error: 'Forbidden', reason: 'admin_access' }, { status: 403 });\r\n },\r\n async getAuthenticatedUser() {\r\n const session = await getSession();\r\n return (session?.user as SessionUser) ?? null;\r\n },\r\n };\r\n}\r\n","export {\r\n createAuthHelpers,\r\n createCmsAuthBundle,\r\n OPEN_ENDPOINTS,\r\n PERMISSION_REQUIRED_ENDPOINTS,\r\n isOpenEndpoint,\r\n isPublicMethod,\r\n getRequiredPermission,\r\n} from './helpers';\r\nexport type { SessionUser, GetSession, AuthHelpers } from './helpers';\r\nexport { sessionHasEntityAccess, canManageRoles, RBAC_ADMIN_ONLY_ENTITIES } from './helpers';\r\nexport {\r\n isRbacDebugEnabled,\r\n logRbac,\r\n explainSessionEntityAccess,\r\n logEntityAccessDecision,\r\n summarizeEntityPerms,\r\n} from './rbac-debug';\r\nexport {\r\n resolveVendorScopeFromSessionUser,\r\n VENDOR_SCOPED_STORE_ENTITIES,\r\n VENDOR_STORE_RBAC_ENTITIES,\r\n VENDOR_OWNER_GROUP_NAME,\r\n isVendorStaff,\r\n isVendorPortalUser,\r\n isVendorOwner,\r\n isVendorGroupName,\r\n isPlatformAdministrator,\r\n vendorPortalFlagsFromUser,\r\n canOnboardVendors,\r\n canManageVendorTeam,\r\n canManageVendorRoles,\r\n} from './vendor-scope';\r\nexport {\r\n getPermissionableEntityKeys,\r\n ADMIN_GROUP_NAME,\r\n isSuperAdminGroupName,\r\n permissionRowsToRecord,\r\n hasEntityPermission,\r\n} from './permission-entities';\r\nexport { seedAdministratorPermissions } from './seed-permissions';\r\nexport type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nexport { createCmsMiddleware, defaultPublicApiMethods } from './middleware';\r\nexport type { CmsMiddlewareConfig, CmsMiddlewareRequest } from './middleware';\r\nexport {\r\n isAuthDebugEnabled,\r\n isAuthDebugClientEnabled,\r\n logAuth,\r\n logAuthClient,\r\n summarizeSessionUserForLog,\r\n nextAuthCookieDebugInfo,\r\n} from './auth-debug';\r\nexport { getNextAuthOptions } from './nextauth-options';\r\nexport type { NextAuthOptionsConfig, NextAuthUser, AuthorizeOtpInput } from './nextauth-options';\r\n","import type { DataSource } from 'typeorm';\r\nimport type { EntityTarget } from 'typeorm';\r\nimport type { ObjectLiteral } from 'typeorm';\r\nimport { getPermissionableEntityKeys, ADMIN_GROUP_NAME } from './permission-entities';\r\n\r\n/**\r\n * Ensures the Administrator group has full CRUD on every permissionable entity\r\n * for the given entity map. Idempotent: upserts per entity.\r\n */\r\nexport async function seedAdministratorPermissions(\r\n dataSource: DataSource,\r\n entityMap: Record<string, unknown>\r\n): Promise<void> {\r\n const entities = getPermissionableEntityKeys(entityMap);\r\n const groupRepo = dataSource.getRepository(entityMap.user_groups as EntityTarget<ObjectLiteral>);\r\n const permRepo = dataSource.getRepository(entityMap.permissions as EntityTarget<ObjectLiteral>);\r\n\r\n const adminGroup = await groupRepo.findOne({ where: { name: ADMIN_GROUP_NAME, deleted: false } });\r\n console.log(\"ADMIN GROUP\", adminGroup);\r\n if (!adminGroup) return;\r\n\r\n const fullCrud = { canCreate: true, canRead: true, canUpdate: true, canDelete: true };\r\n\r\n for (const entity of entities) {\r\n const existing = await permRepo.findOne({\r\n where: { groupId: adminGroup.id, entity },\r\n });\r\n console.log(\"EXISTING\", existing);\r\n if (existing) {\r\n existing.canCreate = true;\r\n existing.canRead = true;\r\n existing.canUpdate = true;\r\n existing.canDelete = true;\r\n await permRepo.save(existing);\r\n } else {\r\n await permRepo.save(\r\n permRepo.create({\r\n groupId: adminGroup.id,\r\n entity,\r\n ...fullCrud,\r\n })\r\n );\r\n }\r\n }\r\n}\r\n","import { getToken } from 'next-auth/jwt';\r\nimport { logAuth } from './auth-debug';\r\n\r\nexport interface CmsMiddlewareRequest {\r\n nextUrl: { pathname: string };\r\n url: string;\r\n method: string;\r\n cookies: { get: (name: string) => { value?: string } | undefined };\r\n /**\r\n * Full Next.js request (e.g. `NextRequest`). When provided, session is resolved via\r\n * `getToken()` so chunked `next-auth.session-token.N` cookies work.\r\n */\r\n req?: Parameters<typeof getToken>[0]['req'];\r\n}\r\n\r\nexport interface CmsMiddlewareConfig {\r\n publicAdminPaths?: string[];\r\n publicApiPaths?: string[];\r\n /** path -> allowed methods */\r\n publicApiMethods?: Record<string, string[]>;\r\n signInPath?: string;\r\n /** @deprecated Prefer passing `req` on the request; used only when `req` is omitted. */\r\n getSessionToken?: (request: CmsMiddlewareRequest) => string | undefined;\r\n secret?: string;\r\n}\r\n\r\n/** Default public API paths (no auth). Sites should extend this with their own routes. */\r\nexport const defaultPublicApiMethods: Record<string, string[]> = {\r\n '/api/contacts': ['POST'],\r\n '/api/form-submissions': ['POST'],\r\n '/api/blogs': ['GET'],\r\n '/api/forms': ['GET'],\r\n '/api/auth': ['GET', 'POST'],\r\n '/api/health': ['GET'],\r\n '/api/users/forgot-password': ['POST'],\r\n '/api/users/set-password': ['POST'],\r\n '/api/users/invite': ['POST'],\r\n};\r\n\r\nfunction legacyGetSessionToken(request: CmsMiddlewareRequest): string | undefined {\r\n const secure = request.cookies.get('__Secure-next-auth.session-token')?.value;\r\n const regular = request.cookies.get('next-auth.session-token')?.value;\r\n return secure ?? regular;\r\n}\r\n\r\nfunction sessionCookiePresence(request: CmsMiddlewareRequest) {\r\n const secure = request.cookies.get('__Secure-next-auth.session-token')?.value;\r\n const regular = request.cookies.get('next-auth.session-token')?.value;\r\n const hasChunked =\r\n Boolean(request.cookies.get('next-auth.session-token.0')?.value) ||\r\n Boolean(request.cookies.get('__Secure-next-auth.session-token.0')?.value);\r\n return {\r\n hasSecureToken: Boolean(secure),\r\n hasRegularToken: Boolean(regular),\r\n hasChunkedToken: hasChunked,\r\n resolved: Boolean(secure ?? regular),\r\n };\r\n}\r\n\r\nfunction isPublicMethod(pathname: string, method: string, publicApiMethods: Record<string, string[]>): boolean {\r\n for (const [endpoint, methods] of Object.entries(publicApiMethods)) {\r\n if (pathname.startsWith(endpoint) && methods.includes(method)) return true;\r\n }\r\n return false;\r\n}\r\n\r\nasync function hasValidSession(\r\n request: CmsMiddlewareRequest,\r\n secret: string | undefined,\r\n legacyGetToken: (request: CmsMiddlewareRequest) => string | undefined\r\n): Promise<boolean> {\r\n if (request.req) {\r\n const token = await getToken({ req: request.req, secret });\r\n return token != null;\r\n }\r\n return Boolean(legacyGetToken(request));\r\n}\r\n\r\n/**\r\n * Returns middleware logic. Use from Next.js middleware:\r\n * import { createCmsMiddleware } from '@infuro/cms-core';\r\n * export async function middleware(request: NextRequest) {\r\n * const result = await cmsMiddleware({ ...request fields, req: request });\r\n * ...\r\n * }\r\n * export const config = { matcher: ['/admin/:path*', '/api/:path*'] };\r\n */\r\nexport function createCmsMiddleware(config: CmsMiddlewareConfig = {}) {\r\n const {\r\n publicAdminPaths = ['/admin/signin', '/admin/forgot-password', '/admin/reset-password', '/admin/invite'],\r\n publicApiMethods = defaultPublicApiMethods,\r\n signInPath = '/admin/signin',\r\n getSessionToken = legacyGetSessionToken,\r\n secret = process.env.NEXTAUTH_SECRET,\r\n } = config;\r\n\r\n return async function cmsMiddleware(\r\n request: CmsMiddlewareRequest\r\n ): Promise<{ type: 'next' } | { type: 'redirect'; url: string } | { type: 'json'; status: number; body: unknown }> {\r\n const pathname = request.nextUrl.pathname;\r\n const method = request.method;\r\n\r\n if (publicAdminPaths.some((p) => pathname === p || pathname.startsWith(p + '/'))) {\r\n return { type: 'next' };\r\n }\r\n\r\n if (pathname.startsWith('/admin')) {\r\n const authenticated = await hasValidSession(request, secret, getSessionToken);\r\n const cookies = sessionCookiePresence(request);\r\n if (!authenticated) {\r\n logAuth('middleware: admin redirect to signin (no session)', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...cookies,\r\n expectedCookieName: process.env.NEXTAUTH_URL?.startsWith('https')\r\n ? '__Secure-next-auth.session-token'\r\n : 'next-auth.session-token',\r\n });\r\n return { type: 'redirect', url: new URL(signInPath, request.url).toString() };\r\n }\r\n logAuth('middleware: admin allowed', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...cookies,\r\n });\r\n }\r\n\r\n if (pathname.startsWith('/api')) {\r\n if (isPublicMethod(pathname, method, publicApiMethods)) {\r\n return { type: 'next' };\r\n }\r\n const authenticated = await hasValidSession(request, secret, getSessionToken);\r\n if (!authenticated) {\r\n logAuth('middleware: api 401 (no session)', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...sessionCookiePresence(request),\r\n });\r\n return { type: 'json', status: 401, body: { error: 'Unauthorized' } };\r\n }\r\n }\r\n\r\n return { type: 'next' };\r\n };\r\n}\r\n","const LOG_PREFIX = '[cms-auth]';\r\n\r\n/** Set `CMS_AUTH_DEBUG=false` to silence server auth logs in development. */\r\nexport function isAuthDebugEnabled(): boolean {\r\n const v = process.env.CMS_AUTH_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\n/** Browser console logs; set `NEXT_PUBLIC_CMS_AUTH_DEBUG=false` to silence. */\r\nexport function isAuthDebugClientEnabled(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n const v = process.env.NEXT_PUBLIC_CMS_AUTH_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\nexport function logAuth(message: string, data?: Record<string, unknown>): void {\r\n if (!isAuthDebugEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function logAuthClient(message: string, data?: Record<string, unknown>): void {\r\n if (!isAuthDebugClientEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function summarizeSessionUserForLog(user: unknown): Record<string, unknown> {\r\n if (!user || typeof user !== 'object') return { present: false };\r\n const u = user as Record<string, unknown>;\r\n return {\r\n present: true,\r\n email: u.email ?? null,\r\n id: u.id ?? null,\r\n adminAccess: u.adminAccess ?? null,\r\n isRBACAdmin: u.isRBACAdmin ?? null,\r\n isVendorPortal: u.isVendorPortal ?? null,\r\n groupName: u.groupName ?? null,\r\n };\r\n}\r\n\r\nexport function nextAuthCookieDebugInfo(): Record<string, unknown> {\r\n const nextAuthUrl = process.env.NEXTAUTH_URL ?? '(unset)';\r\n const isHttps = nextAuthUrl.startsWith('https');\r\n return {\r\n nextAuthUrl,\r\n hasSecret: Boolean(process.env.NEXTAUTH_SECRET),\r\n cookieName: isHttps ? '__Secure-next-auth.session-token' : 'next-auth.session-token',\r\n cookieSecure: isHttps,\r\n nodeEnv: process.env.NODE_ENV ?? '(unset)',\r\n };\r\n}\r\n","/**\r\n * Build NextAuth options for credentials auth. App can extend/override via extend().\r\n */\r\nimport type { NextAuthOptions } from 'next-auth';\r\nimport _CredentialsProvider from 'next-auth/providers/credentials';\r\nconst CredentialsProvider = (_CredentialsProvider as unknown as { default: typeof _CredentialsProvider }).default ?? _CredentialsProvider;\r\nimport { isSuperAdminGroupName, permissionRowsToRecord } from './permission-entities';\r\nimport { vendorPortalFlagsFromUser } from './vendor-scope';\r\nimport { logAuth, nextAuthCookieDebugInfo, summarizeSessionUserForLog } from './auth-debug';\r\n\r\nexport interface NextAuthUser {\r\n id: number;\r\n email: string;\r\n name: string | null;\r\n password: string | null;\r\n blocked?: boolean;\r\n deleted?: boolean;\r\n groupId?: number | null;\r\n adminAccess?: boolean;\r\n group?: {\r\n name?: string;\r\n permissions?: Array<{\r\n entity: string;\r\n canCreate: boolean;\r\n canRead: boolean;\r\n canUpdate: boolean;\r\n canDelete: boolean;\r\n }>;\r\n };\r\n vendorIds?: number[];\r\n activeVendorId?: number | null;\r\n vendorRole?: 'owner' | 'staff' | null;\r\n}\r\n\r\nexport interface AuthorizeOtpInput {\r\n identifier: string;\r\n channel: 'email' | 'sms';\r\n code: string;\r\n}\r\n\r\nexport interface NextAuthOptionsConfig {\r\n /** Resolve user by email (e.g. from TypeORM). Return null if not found. */\r\n getUserByEmail: (email: string) => Promise<NextAuthUser | null>;\r\n comparePassword: (plain: string, hash: string) => Promise<boolean>;\r\n signInPage?: string;\r\n secret?: string;\r\n extend?: (options: NextAuthOptions) => NextAuthOptions;\r\n /** When false, password CredentialsProvider is omitted. Default true. */\r\n enablePasswordLogin?: boolean;\r\n /** When true, registers CredentialsProvider id `otp`. Requires authorizeOtp. Default false. */\r\n enableOtpLogin?: boolean;\r\n /** Validate OTP and return user (same shape as password flow) or null. */\r\n authorizeOtp?: (input: AuthorizeOtpInput) => Promise<NextAuthUser | null>;\r\n}\r\n\r\nfunction sessionUserFromNextAuthUser(user: NextAuthUser) {\r\n const g = user.group;\r\n const isRBACAdmin = isSuperAdminGroupName(g?.name);\r\n const entityPerms = permissionRowsToRecord(g?.permissions);\r\n // Preserve the DB value as-is: true → true, false → false, null/undefined → undefined.\r\n // Coercing null to false would make requireAdminAccess deny vendor/unset users before\r\n // the vendor-portal check can allow them.\r\n const rawAdminAccess = (user as NextAuthUser & { adminAccess?: boolean }).adminAccess;\r\n const adminAccess: boolean | undefined =\r\n rawAdminAccess === true ? true : rawAdminAccess === false ? false : undefined;\r\n const vendorIds = user.vendorIds ?? [];\r\n const vendorRole = user.vendorRole ?? null;\r\n const { isVendorPortal, isVendorOwner } = vendorPortalFlagsFromUser({\r\n email: user.email,\r\n isRBACAdmin,\r\n groupName: g?.name,\r\n vendorIds,\r\n vendorRole,\r\n });\r\n return {\r\n id: user.id.toString(),\r\n email: user.email,\r\n name: user.name,\r\n groupId: user.groupId ?? undefined,\r\n groupName: g?.name ?? undefined,\r\n isRBACAdmin,\r\n entityPerms,\r\n adminAccess,\r\n vendorIds,\r\n activeVendorId: user.activeVendorId ?? vendorIds[0] ?? null,\r\n vendorRole,\r\n isVendorPortal,\r\n isVendorOwner,\r\n };\r\n}\r\n\r\nexport function getNextAuthOptions(config: NextAuthOptionsConfig): NextAuthOptions {\r\n const {\r\n getUserByEmail,\r\n comparePassword,\r\n signInPage = '/admin/signin',\r\n secret,\r\n extend,\r\n enablePasswordLogin = true,\r\n enableOtpLogin = false,\r\n authorizeOtp,\r\n } = config;\r\n\r\n logAuth('getNextAuthOptions init', nextAuthCookieDebugInfo());\r\n\r\n const providers: NextAuthOptions['providers'] = [];\r\n\r\n if (enablePasswordLogin) {\r\n providers.push(\r\n CredentialsProvider({\r\n name: 'credentials',\r\n credentials: {\r\n email: { label: 'Email', type: 'email' },\r\n password: { label: 'Password', type: 'password' },\r\n },\r\n async authorize(credentials) {\r\n const email = credentials?.email?.trim() ?? '';\r\n if (!email || !credentials?.password) {\r\n logAuth('authorize(credentials) rejected', { reason: 'missing_email_or_password' });\r\n return null;\r\n }\r\n try {\r\n const user = await getUserByEmail(email);\r\n if (!user) {\r\n logAuth('authorize(credentials) rejected', { reason: 'user_not_found', email });\r\n return null;\r\n }\r\n if (user.blocked) {\r\n logAuth('authorize(credentials) rejected', { reason: 'blocked', email, userId: user.id });\r\n return null;\r\n }\r\n if ((user as { deleted?: boolean }).deleted) {\r\n logAuth('authorize(credentials) rejected', { reason: 'deleted', email, userId: user.id });\r\n return null;\r\n }\r\n if (!user.password) {\r\n logAuth('authorize(credentials) rejected', { reason: 'no_password', email, userId: user.id });\r\n return null;\r\n }\r\n const valid = await comparePassword(credentials.password, user.password);\r\n if (!valid) {\r\n logAuth('authorize(credentials) rejected', { reason: 'invalid_password', email, userId: user.id });\r\n return null;\r\n }\r\n const sessionUser = sessionUserFromNextAuthUser(user);\r\n logAuth('authorize(credentials) ok', summarizeSessionUserForLog(sessionUser));\r\n return sessionUser;\r\n } catch (err) {\r\n // Log so infrastructure errors (DB down, missing entity, etc.) are\r\n // visible in server logs rather than silently failing as \"wrong password\".\r\n console.error('[cms-auth] authorize error (credentials):', err instanceof Error ? err.message : err);\r\n logAuth('authorize(credentials) error', {\r\n email,\r\n message: err instanceof Error ? err.message : String(err),\r\n });\r\n return null;\r\n }\r\n },\r\n })\r\n );\r\n }\r\n\r\n if (enableOtpLogin && authorizeOtp) {\r\n providers.push(\r\n CredentialsProvider({\r\n id: 'otp',\r\n name: 'otp',\r\n credentials: {\r\n identifier: { label: 'Email or phone', type: 'text' },\r\n code: { label: 'Code', type: 'text' },\r\n channel: { label: 'Channel', type: 'text' },\r\n },\r\n async authorize(credentials) {\r\n const identifier = typeof credentials?.identifier === 'string' ? credentials.identifier.trim() : '';\r\n const code = typeof credentials?.code === 'string' ? credentials.code.trim() : '';\r\n const ch = credentials?.channel === 'sms' ? 'sms' : 'email';\r\n if (!identifier || !code) return null;\r\n try {\r\n const user = await authorizeOtp({ identifier, channel: ch, code });\r\n if (!user || user.blocked || (user as { deleted?: boolean }).deleted) return null;\r\n return sessionUserFromNextAuthUser(user);\r\n } catch (err) {\r\n console.error('[cms-auth] authorize error (otp):', err instanceof Error ? err.message : err);\r\n return null;\r\n }\r\n },\r\n })\r\n );\r\n }\r\n\r\n const options: NextAuthOptions = {\r\n secret: secret ?? process.env.NEXTAUTH_SECRET,\r\n providers,\r\n session: { strategy: 'jwt' },\r\n pages: { signIn: signInPage },\r\n cookies: {\r\n sessionToken: {\r\n name: process.env.NEXTAUTH_URL?.startsWith('https')\r\n ? '__Secure-next-auth.session-token'\r\n : 'next-auth.session-token',\r\n options: {\r\n httpOnly: true,\r\n sameSite: 'lax',\r\n path: '/',\r\n secure: process.env.NEXTAUTH_URL?.startsWith('https') ?? false,\r\n },\r\n },\r\n },\r\n callbacks: {\r\n async jwt({ token, user, trigger, session }) {\r\n if (user) {\r\n logAuth('jwt callback: new sign-in', {\r\n trigger,\r\n user: summarizeSessionUserForLog(user),\r\n });\r\n const u = user as unknown as Record<string, unknown>;\r\n (token as Record<string, unknown>).id = u.id;\r\n (token as Record<string, unknown>).groupId = u.groupId;\r\n (token as Record<string, unknown>).groupName = u.groupName;\r\n (token as Record<string, unknown>).isRBACAdmin = u.isRBACAdmin;\r\n (token as Record<string, unknown>).entityPerms = u.entityPerms;\r\n (token as Record<string, unknown>).adminAccess = u.adminAccess;\r\n (token as Record<string, unknown>).vendorIds = u.vendorIds;\r\n (token as Record<string, unknown>).activeVendorId = u.activeVendorId;\r\n (token as Record<string, unknown>).vendorRole = u.vendorRole;\r\n (token as Record<string, unknown>).isVendorPortal = u.isVendorPortal;\r\n (token as Record<string, unknown>).isVendorOwner = u.isVendorOwner;\r\n }\r\n if (trigger === 'update' && session && typeof session === 'object') {\r\n logAuth('jwt callback: session update', { trigger });\r\n const s = session as Record<string, unknown>;\r\n const t = token as Record<string, unknown>;\r\n if (typeof s.name === 'string') t.name = s.name;\r\n if (typeof s.email === 'string') t.email = s.email;\r\n if (typeof s.activeVendorId === 'number') t.activeVendorId = s.activeVendorId;\r\n }\r\n return token;\r\n },\r\n async session({ session, token }) {\r\n const t = token as Record<string, unknown>;\r\n logAuth('session callback', {\r\n tokenHasId: t.id != null,\r\n tokenEmail: typeof t.email === 'string' ? t.email : null,\r\n sessionUser: summarizeSessionUserForLog(session.user),\r\n });\r\n if (session.user) {\r\n if (typeof t.name === 'string') session.user.name = t.name;\r\n if (typeof t.email === 'string') session.user.email = t.email;\r\n (session.user as Record<string, unknown>).id = t.id;\r\n (session.user as Record<string, unknown>).groupId = t.groupId;\r\n (session.user as Record<string, unknown>).groupName = t.groupName;\r\n (session.user as Record<string, unknown>).isRBACAdmin = t.isRBACAdmin;\r\n (session.user as Record<string, unknown>).entityPerms = t.entityPerms;\r\n (session.user as Record<string, unknown>).adminAccess = t.adminAccess;\r\n (session.user as Record<string, unknown>).vendorIds = t.vendorIds;\r\n (session.user as Record<string, unknown>).activeVendorId = t.activeVendorId;\r\n (session.user as Record<string, unknown>).vendorRole = t.vendorRole;\r\n (session.user as Record<string, unknown>).isVendorPortal = t.isVendorPortal;\r\n (session.user as Record<string, unknown>).isVendorOwner = t.isVendorOwner;\r\n }\r\n return session;\r\n },\r\n },\r\n };\r\n\r\n return extend ? extend(options) : options;\r\n}\r\n"],"mappings":"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","names":["isVendorOwner","allowed","loadDbPermissionsForUser","LOG_PREFIX","isPublicMethod","isVendorOwner"]}
1
+ {"version":3,"sources":["../src/auth/permission-entities.ts","../src/auth/role-helpers.ts","../src/auth/vendor-scope.ts","../src/auth/rbac-debug-db.ts","../src/auth/rbac-debug.ts","../src/auth/helpers.ts","../src/auth/index.ts","../src/auth/seed-permissions.ts","../src/auth/middleware.ts","../src/auth/auth-debug.ts","../src/auth/nextauth-options.ts"],"sourcesContent":["/** API resource keys excluded from the permission matrix (internal / not admin-CRUD). */\r\nexport const PERMISSION_ENTITY_INTERNAL_EXCLUDE = new Set([\r\n 'users',\r\n 'password_reset_tokens',\r\n 'user_groups',\r\n 'permissions',\r\n 'comments',\r\n 'form_fields',\r\n 'configs',\r\n 'knowledge_base_chunks',\r\n 'carts',\r\n 'cart_items',\r\n 'wishlists',\r\n 'wishlist_items',\r\n 'message_templates',\r\n 'vendor_users',\r\n]);\r\n\r\n/** Non-CRUD admin surfaces mapped to entity keys for RBAC. */\r\nexport const PERMISSION_LOGICAL_ENTITIES = [\r\n 'users',\r\n 'forms',\r\n 'form_submissions',\r\n 'dashboard',\r\n 'upload',\r\n 'settings',\r\n 'analytics',\r\n 'chat',\r\n] as const;\r\n\r\n/** Canonical name for new installs / migrations */\r\nexport const ADMIN_GROUP_NAME = 'Administrator';\r\n\r\n/** System administrator group (roles UI + users / user_groups / permissions bypass). */\r\nexport function isSuperAdminGroupName(name: string | null | undefined): boolean {\r\n return name === ADMIN_GROUP_NAME;\r\n}\r\n\r\nexport type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';\r\n\r\nexport type EntityPermissionFlags = { c: boolean; r: boolean; u: boolean; d: boolean };\r\n\r\nexport function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[] {\r\n const fromMap = Object.keys(entityMap).filter((k) => !PERMISSION_ENTITY_INTERNAL_EXCLUDE.has(k));\r\n const logical = PERMISSION_LOGICAL_ENTITIES.filter((k) => !fromMap.includes(k));\r\n return [...fromMap.sort(), ...logical].filter((k, i, a) => a.indexOf(k) === i);\r\n}\r\n\r\nexport function permissionRowsToRecord(\r\n rows: Array<{ entity: string; canCreate: boolean; canRead: boolean; canUpdate: boolean; canDelete: boolean }> | undefined\r\n): Record<string, EntityPermissionFlags> {\r\n const out: Record<string, EntityPermissionFlags> = {};\r\n if (!rows?.length) return out;\r\n for (const p of rows) {\r\n out[p.entity] = {\r\n c: !!p.canCreate,\r\n r: !!p.canRead,\r\n u: !!p.canUpdate,\r\n d: !!p.canDelete,\r\n };\r\n }\r\n return out;\r\n}\r\n\r\nexport function hasEntityPermission(\r\n record: Record<string, EntityPermissionFlags> | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n const p = record?.[entity];\r\n if (!p) return false;\r\n if (action === 'create') return p.c;\r\n if (action === 'read') return p.r;\r\n if (action === 'update') return p.u;\r\n return p.d;\r\n}\r\n","import type { SessionUser } from './helpers';\r\nimport { isSuperAdminGroupName } from './permission-entities';\r\nimport { isVendorGroupName } from './vendor-scope';\r\n\r\n/** Platform super admin (`user_groups.id = 1` or Administrator group). */\r\nexport const SUPER_ADMIN_GROUP_ID = 1;\r\n\r\n/** Vendor store admin (`user_groups.id = 5` or vendor-linked portal users). */\r\nexport const VENDOR_ADMIN_GROUP_ID = 5;\r\n\r\nexport function isSuperAdmin(user: SessionUser | null | undefined): boolean {\r\n if (!user) return false;\r\n if (user.groupId === SUPER_ADMIN_GROUP_ID) return true;\r\n if (user.isRBACAdmin === true) return true;\r\n return isSuperAdminGroupName(user.groupName);\r\n}\r\n\r\nexport function isVendorAdmin(user: SessionUser | null | undefined): boolean {\r\n if (!user?.email || isSuperAdmin(user)) return false;\r\n if (user.groupId === VENDOR_ADMIN_GROUP_ID) return true;\r\n if ((user.vendorIds?.length ?? 0) > 0) return true;\r\n return isVendorGroupName(user.groupName);\r\n}\r\n","import type { SessionUser } from './helpers';\r\nimport { isSuperAdmin, isVendorAdmin } from './role-helpers';\r\n\r\n/** Entities with a `vendorId` column (store data). */\r\nexport const VENDOR_SCOPED_STORE_ENTITIES = new Set([\r\n 'products',\r\n 'collections',\r\n 'brands',\r\n 'product_categories',\r\n 'orders',\r\n 'payments',\r\n 'taxes',\r\n 'attributes',\r\n 'vendor_customers',\r\n 'discounts',\r\n]);\r\n\r\n/**\r\n * Store admin RBAC for vendor portal users (read/create/update/delete fallbacks in rbac-debug).\r\n * Includes entities without `vendorId` that are still part of the store admin UI.\r\n */\r\nexport const VENDOR_STORE_RBAC_ENTITIES = new Set<string>([\r\n ...VENDOR_SCOPED_STORE_ENTITIES,\r\n 'order_discounts',\r\n 'order_addresses',\r\n]);\r\n\r\nexport type VendorScope =\r\n | { type: 'all' }\r\n | { type: 'vendor'; vendorId: number; vendorIds: number[] }\r\n | { type: 'deny' };\r\n\r\nexport const VENDOR_OWNER_GROUP_NAME = 'Vendor Owner';\r\n\r\n/** User groups treated as vendor store staff (sidebar + scoped admin). */\r\nexport function isVendorGroupName(name: string | null | undefined): boolean {\r\n if (!name?.trim()) return false;\r\n const n = name.trim().toLowerCase();\r\n return n === VENDOR_OWNER_GROUP_NAME.toLowerCase() || n.includes('vendor');\r\n}\r\n\r\nexport function isPlatformAdministrator(user: SessionUser | null | undefined): boolean {\r\n if (!user?.email) return false;\r\n return isSuperAdmin(user);\r\n}\r\n\r\n/** Vendor portal UI (store + store admin), not platform admin. */\r\nexport function isVendorPortalUser(user: SessionUser | null | undefined): boolean {\r\n if (user?.isVendorPortal === true) return true;\r\n if (!user?.email || isPlatformAdministrator(user)) return false;\r\n if (isVendorAdmin(user)) return true;\r\n return isVendorGroupName(user.groupName);\r\n}\r\n\r\nexport function isVendorStaff(user: SessionUser | null | undefined): boolean {\r\n return isVendorPortalUser(user);\r\n}\r\n\r\n/** Vendor store owner (manages team + role permissions for their group). */\r\nexport function isVendorOwner(user: SessionUser | null | undefined): boolean {\r\n if (user?.isVendorOwner === true) return true;\r\n if (!user?.email || isPlatformAdministrator(user)) return false;\r\n if (user.vendorRole === 'staff') return false;\r\n if (user.vendorRole === 'owner') return true;\r\n if (!isVendorPortalUser(user)) return false;\r\n return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();\r\n}\r\n\r\nexport function canManageVendorTeam(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user) || isVendorOwner(user);\r\n}\r\n\r\nexport function canManageVendorRoles(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user) || isVendorOwner(user);\r\n}\r\n\r\n/** Platform admins (Administrator group) can onboard vendors. */\r\nexport function canOnboardVendors(user: SessionUser | null | undefined): boolean {\r\n return isPlatformAdministrator(user);\r\n}\r\n\r\nexport function resolveVendorScopeFromSessionUser(user: SessionUser | null | undefined): VendorScope {\r\n if (!user?.email) return { type: 'deny' };\r\n if (isPlatformAdministrator(user)) return { type: 'all' };\r\n const vendorIds = user.vendorIds ?? [];\r\n if (vendorIds.length === 0) return { type: 'deny' };\r\n const preferred = user.activeVendorId ?? vendorIds[0]!;\r\n const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0]!;\r\n return { type: 'vendor', vendorId, vendorIds };\r\n}\r\n\r\n/** Compute portal flags at login (persist on JWT). */\r\nexport function vendorPortalFlagsFromUser(input: {\r\n email: string;\r\n isRBACAdmin: boolean;\r\n groupName?: string | null;\r\n vendorIds?: number[];\r\n vendorRole?: 'owner' | 'staff' | null;\r\n}): { isVendorPortal: boolean; isVendorOwner: boolean } {\r\n const vendorIds = input.vendorIds ?? [];\r\n const isVendorPortal =\r\n !input.isRBACAdmin &&\r\n (vendorIds.length > 0 || isVendorGroupName(input.groupName));\r\n const isVendorOwner =\r\n isVendorPortal &&\r\n input.vendorRole !== 'staff' &&\r\n (input.vendorRole === 'owner' ||\r\n input.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase());\r\n return { isVendorPortal, isVendorOwner };\r\n}\r\n","import { permissionRowsToRecord } from './permission-entities';\r\nimport type { RbacDebugDataSource } from './rbac-debug';\r\nimport { summarizeEntityPerms } from './rbac-debug';\r\n\r\n/** Load permission rows from DB for debug (server/API only — do not import from `@infuro/cms-core/auth`). */\r\nexport async function loadDbPermissionsForUser(\r\n dataSource: RbacDebugDataSource,\r\n userId: number\r\n): Promise<{\r\n groupId: number | null;\r\n groupName: string | null;\r\n dbEntityPerms: Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }>;\r\n}> {\r\n const rows = (await dataSource.query(\r\n `\r\n SELECT u.\"groupId\" AS \"groupId\", g.name AS \"groupName\",\r\n p.entity, p.\"canCreate\", p.\"canRead\", p.\"canUpdate\", p.\"canDelete\"\r\n FROM users u\r\n LEFT JOIN user_groups g ON g.id = u.\"groupId\" AND g.deleted = false\r\n LEFT JOIN permissions p ON p.\"groupId\" = g.id\r\n WHERE u.id = $1\r\n `,\r\n [userId]\r\n )) as Array<{\r\n groupId: number | null;\r\n groupName: string | null;\r\n entity: string | null;\r\n canCreate: boolean | null;\r\n canRead: boolean | null;\r\n canUpdate: boolean | null;\r\n canDelete: boolean | null;\r\n }>;\r\n\r\n const groupId = rows[0]?.groupId ?? null;\r\n const groupName = rows[0]?.groupName ?? null;\r\n const permRows = rows\r\n .filter((r) => r.entity)\r\n .map((r) => ({\r\n entity: r.entity!,\r\n canCreate: !!r.canCreate,\r\n canRead: !!r.canRead,\r\n canUpdate: !!r.canUpdate,\r\n canDelete: !!r.canDelete,\r\n }));\r\n\r\n return {\r\n groupId,\r\n groupName,\r\n dbEntityPerms: summarizeEntityPerms(permissionRowsToRecord(permRows)),\r\n };\r\n}\r\n","import type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nimport { hasEntityPermission } from './permission-entities';\r\nimport type { SessionUser } from './helpers';\r\nimport { isVendorOwner, isVendorPortalUser, VENDOR_STORE_RBAC_ENTITIES } from './vendor-scope';\r\n\r\nconst LOG_PREFIX = '[cms-rbac]';\r\n\r\n/** Minimal DB handle for RBAC debug (avoids importing `typeorm` in the auth bundle). */\r\nexport type RbacDebugDataSource = {\r\n query: (sql: string, parameters?: unknown[]) => Promise<unknown>;\r\n};\r\n\r\n/** Set `CMS_RBAC_DEBUG=true` in `.env` to log permission decisions (server console). */\r\nexport function isRbacDebugEnabled(): boolean {\r\n const v = process.env.CMS_RBAC_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\nexport function logRbac(message: string, data?: Record<string, unknown>): void {\r\n if (!isRbacDebugEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function summarizeEntityPerms(\r\n entityPerms: Record<string, EntityPermissionFlags> | undefined\r\n): Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }> {\r\n const out: Record<string, { c: boolean; r: boolean; u: boolean; d: boolean }> = {};\r\n if (!entityPerms) return out;\r\n for (const [entity, p] of Object.entries(entityPerms)) {\r\n out[entity] = { c: p.c, r: p.r, u: p.u, d: p.d };\r\n }\r\n return out;\r\n}\r\n\r\nexport interface EntityAccessExplanation {\r\n allowed: boolean;\r\n reason: string;\r\n userSnapshot: Record<string, unknown>;\r\n}\r\n\r\nfunction vendorPortalFallbackReason(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): string | null {\r\n if (!isVendorPortalUser(user)) return null;\r\n if (entity === 'dashboard' && action === 'read') return 'vendor_portal_dashboard_fallback';\r\n if (entity === 'analytics' && action === 'read') return 'vendor_portal_analytics_fallback';\r\n if (entity === 'settings' && action === 'read') return 'vendor_portal_settings_read_fallback';\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === 'read') return 'vendor_portal_store_read_fallback';\r\n return null;\r\n}\r\n\r\n/** Same rules as `sessionHasEntityAccess`, but returns why access was granted or denied. */\r\nexport function explainSessionEntityAccess(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): EntityAccessExplanation {\r\n const userSnapshot: Record<string, unknown> = {\r\n email: user?.email ?? null,\r\n id: user?.id ?? null,\r\n groupId: user?.groupId ?? null,\r\n groupName: user?.groupName ?? null,\r\n isRBACAdmin: user?.isRBACAdmin ?? false,\r\n adminAccess: user?.adminAccess ?? null,\r\n vendorIds: user?.vendorIds ?? [],\r\n activeVendorId: user?.activeVendorId ?? null,\r\n vendorRole: user?.vendorRole ?? null,\r\n isVendorPortal: user?.isVendorPortal ?? false,\r\n isVendorOwner: user?.isVendorOwner ?? false,\r\n isVendorPortalComputed: isVendorPortalUser(user),\r\n isVendorOwnerComputed: isVendorOwner(user),\r\n jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),\r\n jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null,\r\n };\r\n\r\n if (!user?.email) {\r\n return { allowed: false, reason: 'no_session_email', userSnapshot };\r\n }\r\n if (user.isRBACAdmin) {\r\n return { allowed: true, reason: 'platform_administrator', userSnapshot };\r\n }\r\n\r\n const vendorIds = user.vendorIds ?? [];\r\n const isStaff = user.vendorRole === 'staff';\r\n\r\n if (vendorIds.length > 0) {\r\n if (entity === 'dashboard' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_dashboard_read', userSnapshot };\r\n }\r\n if (entity === 'analytics' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_analytics_read', userSnapshot };\r\n }\r\n if (entity === 'settings') {\r\n if (action === 'read') {\r\n return { allowed: true, reason: 'vendor_link_settings_read', userSnapshot };\r\n }\r\n if (action === 'update' && !isStaff) {\r\n return { allowed: true, reason: 'vendor_link_settings_update', userSnapshot };\r\n }\r\n }\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {\r\n if (isStaff && action === 'read') {\r\n return { allowed: true, reason: 'vendor_staff_store_read', userSnapshot };\r\n }\r\n if (!isStaff) {\r\n return { allowed: true, reason: 'vendor_link_store_full', userSnapshot };\r\n }\r\n return {\r\n allowed: false,\r\n reason: 'vendor_staff_store_write_denied',\r\n userSnapshot,\r\n };\r\n }\r\n }\r\n\r\n if (isVendorPortalUser(user) && isVendorOwner(user)) {\r\n if (entity === 'dashboard' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_owner_group_dashboard', userSnapshot };\r\n }\r\n if (entity === 'analytics' && action === 'read') {\r\n return { allowed: true, reason: 'vendor_owner_group_analytics', userSnapshot };\r\n }\r\n if (entity === 'settings' && (action === 'read' || action === 'update')) {\r\n return { allowed: true, reason: 'vendor_owner_group_settings', userSnapshot };\r\n }\r\n if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {\r\n return { allowed: true, reason: 'vendor_owner_group_store', userSnapshot };\r\n }\r\n }\r\n\r\n const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);\r\n if (vendorPortalReason) {\r\n return { allowed: true, reason: vendorPortalReason, userSnapshot };\r\n }\r\n\r\n const explicit = user.entityPerms?.[entity];\r\n if (explicit !== undefined) {\r\n const allowed = hasEntityPermission(user.entityPerms, entity, action);\r\n return {\r\n allowed,\r\n reason: allowed ? 'jwt_entity_perms_allow' : 'jwt_entity_perms_deny',\r\n userSnapshot,\r\n };\r\n }\r\n\r\n const allowed = hasEntityPermission(user.entityPerms, entity, action);\r\n return {\r\n allowed,\r\n reason: allowed ? 'entity_perms_fallback_allow' : 'no_matching_rule',\r\n userSnapshot,\r\n };\r\n}\r\n\r\nexport function sessionHasEntityAccessFromExplanation(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n return explainSessionEntityAccess(user, entity, action).allowed;\r\n}\r\n\r\nexport async function logEntityAccessDecision(\r\n dataSource: RbacDebugDataSource | undefined,\r\n context: string,\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction,\r\n extra?: Record<string, unknown>\r\n): Promise<void> {\r\n if (!isRbacDebugEnabled()) return;\r\n\r\n const explanation = explainSessionEntityAccess(user, entity, action);\r\n let dbPermissions: Record<string, unknown> | undefined;\r\n if (dataSource && user?.id) {\r\n const id = Number(user.id);\r\n if (Number.isFinite(id)) {\r\n try {\r\n const { loadDbPermissionsForUser } = await import('./rbac-debug-db');\r\n dbPermissions = await loadDbPermissionsForUser(dataSource, id);\r\n } catch (e) {\r\n dbPermissions = { error: e instanceof Error ? e.message : String(e) };\r\n }\r\n }\r\n }\r\n\r\n logRbac(context, {\r\n entity,\r\n action,\r\n allowed: explanation.allowed,\r\n reason: explanation.reason,\r\n ...explanation.userSnapshot,\r\n dbPermissions,\r\n ...extra,\r\n });\r\n}\r\n","import type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nimport { explainSessionEntityAccess, logRbac } from './rbac-debug';\r\nimport { isVendorPortalUser } from './vendor-scope';\r\n\r\n/**\r\n * @deprecated Administrator bypass is now full entity access via `isRBACAdmin` in `sessionHasEntityAccess`.\r\n * Kept for backwards-compatible imports.\r\n */\r\nexport const RBAC_ADMIN_ONLY_ENTITIES = new Set(['users', 'user_groups', 'permissions']);\r\n\r\nexport interface SessionUser {\r\n id?: string;\r\n email?: string | null;\r\n name?: string | null;\r\n groupId?: number;\r\n /** User group display name (from login). */\r\n groupName?: string | null;\r\n /** @deprecated use entityPerms / isRBACAdmin */\r\n permissions?: string[];\r\n /** Administrator group: bypasses entity-level RBAC on all resources */\r\n isRBACAdmin?: boolean;\r\n entityPerms?: Record<string, EntityPermissionFlags>;\r\n /** When false and not isRBACAdmin, admin API/UI is denied. */\r\n adminAccess?: boolean;\r\n /** Vendor stores this user can access (from vendor_users). */\r\n vendorIds?: number[];\r\n /** Active vendor for scoped CRUD (vendor staff). */\r\n activeVendorId?: number | null;\r\n /** Role for the active vendor link (`vendor_users.role`). */\r\n vendorRole?: 'owner' | 'staff' | null;\r\n /** Set at login: vendor store portal (not platform admin). */\r\n isVendorPortal?: boolean;\r\n /** Set at login: vendor store owner (team + permissions). */\r\n isVendorOwner?: boolean;\r\n}\r\n\r\nexport function sessionHasEntityAccess(\r\n user: SessionUser | null | undefined,\r\n entity: string,\r\n action: EntityCrudAction\r\n): boolean {\r\n return explainSessionEntityAccess(user, entity, action).allowed;\r\n}\r\n\r\nexport function canManageRoles(user: SessionUser | null | undefined): boolean {\r\n return !!(user?.email && user.isRBACAdmin);\r\n}\r\n\r\nexport type GetSession = () => Promise<{ user?: SessionUser } | null>;\r\n\r\nexport const OPEN_ENDPOINTS: Array<Record<string, string[]>> = [\r\n { '/api/contacts': ['POST'] },\r\n { '/api/form-submissions': ['POST'] },\r\n { '/api/blogs': ['GET'] },\r\n];\r\n\r\nexport const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]> = {};\r\n\r\nexport function isOpenEndpoint(pathname: string): boolean {\r\n return OPEN_ENDPOINTS.some((endpoint) => pathname.startsWith(Object.keys(endpoint)[0]));\r\n}\r\n\r\nexport function getRequiredPermission(pathname: string): string[] | null {\r\n return null;\r\n}\r\n\r\nexport function isPublicMethod(pathname: string, method: string): boolean {\r\n for (const endpoint of OPEN_ENDPOINTS) {\r\n const key = Object.keys(endpoint)[0];\r\n if (pathname.startsWith(key) && endpoint[key].includes(method)) return true;\r\n }\r\n return false;\r\n}\r\n\r\nexport interface AuthHelpers {\r\n requireAuth(req: Request): Promise<Response | null>;\r\n requirePermission(req: Request, permission: string): Promise<Response | null>;\r\n requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;\r\n requireAdminAccess(req: Request): Promise<Response | null>;\r\n getAuthenticatedUser(): Promise<SessionUser | null>;\r\n}\r\n\r\nexport function createAuthHelpers(getSession: GetSession, NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }): AuthHelpers {\r\n return createAuthHelpersFromGetSession(getSession, NextResponse);\r\n}\r\n\r\n/** Pass return value into `createCmsApiHandler` (includes `getSessionUser` for vendor store APIs). */\r\nexport function createCmsAuthBundle(\r\n getSession: GetSession,\r\n NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }\r\n) {\r\n const auth = createAuthHelpers(getSession, NextResponse);\r\n return {\r\n requireAuth: auth.requireAuth,\r\n requireAdminAccess: auth.requireAdminAccess,\r\n requireEntityPermission: auth.requireEntityPermission,\r\n getSessionUser: auth.getAuthenticatedUser,\r\n getAuthenticatedUser: auth.getAuthenticatedUser,\r\n };\r\n}\r\n\r\nfunction createAuthHelpersFromGetSession(\r\n getSession: GetSession,\r\n NextResponse: { json: (body: unknown, init?: { status?: number }) => Response }\r\n): AuthHelpers {\r\n return {\r\n async requireAuth() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n return null;\r\n },\r\n async requirePermission() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n return null;\r\n },\r\n async requireEntityPermission(_req: Request, entity: string, action: EntityCrudAction) {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n const u = session.user as SessionUser;\r\n const allowed = sessionHasEntityAccess(u, entity, action);\r\n const { reason } = explainSessionEntityAccess(u, entity, action);\r\n logRbac('authHelpers.requireEntityPermission', {\r\n entity,\r\n action,\r\n allowed,\r\n reason,\r\n email: u.email,\r\n groupName: u.groupName,\r\n vendorIds: u.vendorIds,\r\n isVendorPortal: u.isVendorPortal,\r\n isVendorOwner: u.isVendorOwner,\r\n });\r\n if (allowed) return null;\r\n return NextResponse.json({ error: 'Forbidden', entity, action, reason }, { status: 403 });\r\n },\r\n async requireAdminAccess() {\r\n const session = await getSession();\r\n if (!session?.user?.email) {\r\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });\r\n }\r\n const u = session.user as SessionUser;\r\n if (u.isRBACAdmin) return null;\r\n // Vendor portal users always have admin UI access for their store — check\r\n // before adminAccess so that vendor users (who have adminAccess:false from\r\n // the DB default) are not incorrectly denied.\r\n if (isVendorPortalUser(u)) return null;\r\n if (u.adminAccess === true) return null;\r\n if (u.adminAccess === false) {\r\n logRbac('requireAdminAccess denied (adminAccess:false)', {\r\n email: u.email,\r\n groupName: u.groupName,\r\n isVendorPortal: u.isVendorPortal,\r\n });\r\n return NextResponse.json({ error: 'Forbidden', reason: 'admin_access' }, { status: 403 });\r\n }\r\n logRbac('requireAdminAccess denied (no matching rule)', {\r\n email: u.email,\r\n adminAccess: u.adminAccess,\r\n groupName: u.groupName,\r\n isVendorPortal: u.isVendorPortal,\r\n });\r\n return NextResponse.json({ error: 'Forbidden', reason: 'admin_access' }, { status: 403 });\r\n },\r\n async getAuthenticatedUser() {\r\n const session = await getSession();\r\n return (session?.user as SessionUser) ?? null;\r\n },\r\n };\r\n}\r\n","export {\r\n createAuthHelpers,\r\n createCmsAuthBundle,\r\n OPEN_ENDPOINTS,\r\n PERMISSION_REQUIRED_ENDPOINTS,\r\n isOpenEndpoint,\r\n isPublicMethod,\r\n getRequiredPermission,\r\n} from './helpers';\r\nexport type { SessionUser, GetSession, AuthHelpers } from './helpers';\r\nexport { sessionHasEntityAccess, canManageRoles, RBAC_ADMIN_ONLY_ENTITIES } from './helpers';\r\nexport {\r\n isRbacDebugEnabled,\r\n logRbac,\r\n explainSessionEntityAccess,\r\n logEntityAccessDecision,\r\n summarizeEntityPerms,\r\n} from './rbac-debug';\r\nexport {\r\n isSuperAdmin,\r\n isVendorAdmin,\r\n SUPER_ADMIN_GROUP_ID,\r\n VENDOR_ADMIN_GROUP_ID,\r\n} from './role-helpers';\r\nexport {\r\n resolveVendorScopeFromSessionUser,\r\n VENDOR_SCOPED_STORE_ENTITIES,\r\n VENDOR_STORE_RBAC_ENTITIES,\r\n VENDOR_OWNER_GROUP_NAME,\r\n isVendorStaff,\r\n isVendorPortalUser,\r\n isVendorOwner,\r\n isVendorGroupName,\r\n isPlatformAdministrator,\r\n vendorPortalFlagsFromUser,\r\n canOnboardVendors,\r\n canManageVendorTeam,\r\n canManageVendorRoles,\r\n} from './vendor-scope';\r\nexport {\r\n getPermissionableEntityKeys,\r\n ADMIN_GROUP_NAME,\r\n isSuperAdminGroupName,\r\n permissionRowsToRecord,\r\n hasEntityPermission,\r\n} from './permission-entities';\r\nexport { seedAdministratorPermissions } from './seed-permissions';\r\nexport type { EntityCrudAction, EntityPermissionFlags } from './permission-entities';\r\nexport { createCmsMiddleware, defaultPublicApiMethods } from './middleware';\r\nexport type { CmsMiddlewareConfig, CmsMiddlewareRequest } from './middleware';\r\nexport {\r\n isAuthDebugEnabled,\r\n isAuthDebugClientEnabled,\r\n logAuth,\r\n logAuthClient,\r\n summarizeSessionUserForLog,\r\n nextAuthCookieDebugInfo,\r\n} from './auth-debug';\r\nexport { getNextAuthOptions, getStorefrontNextAuthOptions } from './nextauth-options';\r\nexport type { NextAuthOptionsConfig, NextAuthUser, AuthorizeOtpInput } from './nextauth-options';\r\n","import type { DataSource } from 'typeorm';\r\nimport type { EntityTarget } from 'typeorm';\r\nimport type { ObjectLiteral } from 'typeorm';\r\nimport { getPermissionableEntityKeys, ADMIN_GROUP_NAME } from './permission-entities';\r\n\r\n/**\r\n * Ensures the Administrator group has full CRUD on every permissionable entity\r\n * for the given entity map. Idempotent: upserts per entity.\r\n */\r\nexport async function seedAdministratorPermissions(\r\n dataSource: DataSource,\r\n entityMap: Record<string, unknown>\r\n): Promise<void> {\r\n const entities = getPermissionableEntityKeys(entityMap);\r\n const groupRepo = dataSource.getRepository(entityMap.user_groups as EntityTarget<ObjectLiteral>);\r\n const permRepo = dataSource.getRepository(entityMap.permissions as EntityTarget<ObjectLiteral>);\r\n\r\n const adminGroup = await groupRepo.findOne({ where: { name: ADMIN_GROUP_NAME, deleted: false } });\r\n console.log(\"ADMIN GROUP\", adminGroup);\r\n if (!adminGroup) return;\r\n\r\n const fullCrud = { canCreate: true, canRead: true, canUpdate: true, canDelete: true };\r\n\r\n for (const entity of entities) {\r\n const existing = await permRepo.findOne({\r\n where: { groupId: adminGroup.id, entity },\r\n });\r\n console.log(\"EXISTING\", existing);\r\n if (existing) {\r\n existing.canCreate = true;\r\n existing.canRead = true;\r\n existing.canUpdate = true;\r\n existing.canDelete = true;\r\n await permRepo.save(existing);\r\n } else {\r\n await permRepo.save(\r\n permRepo.create({\r\n groupId: adminGroup.id,\r\n entity,\r\n ...fullCrud,\r\n })\r\n );\r\n }\r\n }\r\n}\r\n","import { getToken } from 'next-auth/jwt';\r\nimport { logAuth } from './auth-debug';\r\n\r\nexport interface CmsMiddlewareRequest {\r\n nextUrl: { pathname: string };\r\n url: string;\r\n method: string;\r\n cookies: { get: (name: string) => { value?: string } | undefined };\r\n /**\r\n * Full Next.js request (e.g. `NextRequest`). When provided, session is resolved via\r\n * `getToken()` so chunked `next-auth.session-token.N` cookies work.\r\n */\r\n req?: Parameters<typeof getToken>[0]['req'];\r\n}\r\n\r\nexport interface CmsMiddlewareConfig {\r\n publicAdminPaths?: string[];\r\n publicApiPaths?: string[];\r\n /** path -> allowed methods */\r\n publicApiMethods?: Record<string, string[]>;\r\n signInPath?: string;\r\n /** @deprecated Prefer passing `req` on the request; used only when `req` is omitted. */\r\n getSessionToken?: (request: CmsMiddlewareRequest) => string | undefined;\r\n secret?: string;\r\n}\r\n\r\n/** Default public API paths (no auth). Sites should extend this with their own routes. */\r\nexport const defaultPublicApiMethods: Record<string, string[]> = {\r\n '/api/contacts': ['POST'],\r\n '/api/form-submissions': ['POST'],\r\n '/api/blogs': ['GET'],\r\n '/api/forms': ['GET'],\r\n '/api/auth': ['GET', 'POST'],\r\n '/api/health': ['GET'],\r\n '/api/users/forgot-password': ['POST'],\r\n '/api/users/set-password': ['POST'],\r\n '/api/users/invite': ['POST'],\r\n};\r\n\r\nfunction legacyGetSessionToken(request: CmsMiddlewareRequest): string | undefined {\r\n const secure = request.cookies.get('__Secure-next-auth.session-token')?.value;\r\n const regular = request.cookies.get('next-auth.session-token')?.value;\r\n return secure ?? regular;\r\n}\r\n\r\nfunction sessionCookiePresence(request: CmsMiddlewareRequest) {\r\n const secure = request.cookies.get('__Secure-next-auth.session-token')?.value;\r\n const regular = request.cookies.get('next-auth.session-token')?.value;\r\n const hasChunked =\r\n Boolean(request.cookies.get('next-auth.session-token.0')?.value) ||\r\n Boolean(request.cookies.get('__Secure-next-auth.session-token.0')?.value);\r\n return {\r\n hasSecureToken: Boolean(secure),\r\n hasRegularToken: Boolean(regular),\r\n hasChunkedToken: hasChunked,\r\n resolved: Boolean(secure ?? regular),\r\n };\r\n}\r\n\r\nfunction isPublicMethod(pathname: string, method: string, publicApiMethods: Record<string, string[]>): boolean {\r\n for (const [endpoint, methods] of Object.entries(publicApiMethods)) {\r\n if (pathname.startsWith(endpoint) && methods.includes(method)) return true;\r\n }\r\n return false;\r\n}\r\n\r\nasync function hasValidSession(\r\n request: CmsMiddlewareRequest,\r\n secret: string | undefined,\r\n legacyGetToken: (request: CmsMiddlewareRequest) => string | undefined\r\n): Promise<boolean> {\r\n if (request.req) {\r\n const token = await getToken({ req: request.req, secret });\r\n return token != null;\r\n }\r\n return Boolean(legacyGetToken(request));\r\n}\r\n\r\n/**\r\n * Returns middleware logic. Use from Next.js middleware:\r\n * import { createCmsMiddleware } from '@infuro/cms-core';\r\n * export async function middleware(request: NextRequest) {\r\n * const result = await cmsMiddleware({ ...request fields, req: request });\r\n * ...\r\n * }\r\n * export const config = { matcher: ['/admin/:path*', '/api/:path*'] };\r\n */\r\nexport function createCmsMiddleware(config: CmsMiddlewareConfig = {}) {\r\n const {\r\n publicAdminPaths = ['/admin/signin', '/admin/forgot-password', '/admin/reset-password', '/admin/invite'],\r\n publicApiMethods = defaultPublicApiMethods,\r\n signInPath = '/admin/signin',\r\n getSessionToken = legacyGetSessionToken,\r\n secret = process.env.NEXTAUTH_SECRET,\r\n } = config;\r\n\r\n return async function cmsMiddleware(\r\n request: CmsMiddlewareRequest\r\n ): Promise<{ type: 'next' } | { type: 'redirect'; url: string } | { type: 'json'; status: number; body: unknown }> {\r\n const pathname = request.nextUrl.pathname;\r\n const method = request.method;\r\n\r\n if (publicAdminPaths.some((p) => pathname === p || pathname.startsWith(p + '/'))) {\r\n return { type: 'next' };\r\n }\r\n\r\n if (pathname.startsWith('/admin')) {\r\n const authenticated = await hasValidSession(request, secret, getSessionToken);\r\n const cookies = sessionCookiePresence(request);\r\n if (!authenticated) {\r\n logAuth('middleware: admin redirect to signin (no session)', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...cookies,\r\n expectedCookieName: process.env.NEXTAUTH_URL?.startsWith('https')\r\n ? '__Secure-next-auth.session-token'\r\n : 'next-auth.session-token',\r\n });\r\n return { type: 'redirect', url: new URL(signInPath, request.url).toString() };\r\n }\r\n logAuth('middleware: admin allowed', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...cookies,\r\n });\r\n }\r\n\r\n if (pathname.startsWith('/api')) {\r\n if (isPublicMethod(pathname, method, publicApiMethods)) {\r\n return { type: 'next' };\r\n }\r\n const authenticated = await hasValidSession(request, secret, getSessionToken);\r\n if (!authenticated) {\r\n logAuth('middleware: api 401 (no session)', {\r\n pathname,\r\n method,\r\n usesGetToken: Boolean(request.req),\r\n ...sessionCookiePresence(request),\r\n });\r\n return { type: 'json', status: 401, body: { error: 'Unauthorized' } };\r\n }\r\n }\r\n\r\n return { type: 'next' };\r\n };\r\n}\r\n","const LOG_PREFIX = '[cms-auth]';\r\n\r\n/** Set `CMS_AUTH_DEBUG=false` to silence server auth logs in development. */\r\nexport function isAuthDebugEnabled(): boolean {\r\n const v = process.env.CMS_AUTH_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\n/** Browser console logs; set `NEXT_PUBLIC_CMS_AUTH_DEBUG=false` to silence. */\r\nexport function isAuthDebugClientEnabled(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n const v = process.env.NEXT_PUBLIC_CMS_AUTH_DEBUG?.trim().toLowerCase();\r\n if (v === '1' || v === 'true' || v === 'yes') return true;\r\n if (v === '0' || v === 'false' || v === 'no') return false;\r\n return process.env.NODE_ENV === 'development';\r\n}\r\n\r\nexport function logAuth(message: string, data?: Record<string, unknown>): void {\r\n if (!isAuthDebugEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function logAuthClient(message: string, data?: Record<string, unknown>): void {\r\n if (!isAuthDebugClientEnabled()) return;\r\n if (data) console.info(LOG_PREFIX, message, data);\r\n else console.info(LOG_PREFIX, message);\r\n}\r\n\r\nexport function summarizeSessionUserForLog(user: unknown): Record<string, unknown> {\r\n if (!user || typeof user !== 'object') return { present: false };\r\n const u = user as Record<string, unknown>;\r\n return {\r\n present: true,\r\n email: u.email ?? null,\r\n id: u.id ?? null,\r\n adminAccess: u.adminAccess ?? null,\r\n isRBACAdmin: u.isRBACAdmin ?? null,\r\n isVendorPortal: u.isVendorPortal ?? null,\r\n groupName: u.groupName ?? null,\r\n };\r\n}\r\n\r\nexport function nextAuthCookieDebugInfo(): Record<string, unknown> {\r\n const nextAuthUrl = process.env.NEXTAUTH_URL ?? '(unset)';\r\n const isHttps = nextAuthUrl.startsWith('https');\r\n return {\r\n nextAuthUrl,\r\n hasSecret: Boolean(process.env.NEXTAUTH_SECRET),\r\n cookieName: isHttps ? '__Secure-next-auth.session-token' : 'next-auth.session-token',\r\n cookieSecure: isHttps,\r\n nodeEnv: process.env.NODE_ENV ?? '(unset)',\r\n };\r\n}\r\n","/**\r\n * Build NextAuth options for credentials auth. App can extend/override via extend().\r\n */\r\nimport type { NextAuthOptions } from 'next-auth';\r\nimport _CredentialsProvider from 'next-auth/providers/credentials';\r\nconst CredentialsProvider = (_CredentialsProvider as unknown as { default: typeof _CredentialsProvider }).default ?? _CredentialsProvider;\r\nimport { permissionRowsToRecord } from './permission-entities';\r\nimport { isSuperAdmin } from './role-helpers';\r\nimport { vendorPortalFlagsFromUser } from './vendor-scope';\r\nimport { logAuth, nextAuthCookieDebugInfo, summarizeSessionUserForLog } from './auth-debug';\r\n\r\nexport interface NextAuthUser {\r\n id: number;\r\n email: string;\r\n name: string | null;\r\n password: string | null;\r\n blocked?: boolean;\r\n deleted?: boolean;\r\n groupId?: number | null;\r\n adminAccess?: boolean;\r\n group?: {\r\n name?: string;\r\n permissions?: Array<{\r\n entity: string;\r\n canCreate: boolean;\r\n canRead: boolean;\r\n canUpdate: boolean;\r\n canDelete: boolean;\r\n }>;\r\n };\r\n vendorIds?: number[];\r\n activeVendorId?: number | null;\r\n vendorRole?: 'owner' | 'staff' | null;\r\n}\r\n\r\nexport interface AuthorizeOtpInput {\r\n identifier: string;\r\n channel: 'email' | 'sms';\r\n code: string;\r\n}\r\n\r\nexport interface NextAuthOptionsConfig {\r\n /** Resolve user by email (e.g. from TypeORM). Return null if not found. */\r\n getUserByEmail: (email: string) => Promise<NextAuthUser | null>;\r\n comparePassword: (plain: string, hash: string) => Promise<boolean>;\r\n signInPage?: string;\r\n secret?: string;\r\n extend?: (options: NextAuthOptions) => NextAuthOptions;\r\n /** When false, password CredentialsProvider is omitted. Default true. */\r\n enablePasswordLogin?: boolean;\r\n /** When true, registers CredentialsProvider id `otp`. Requires authorizeOtp. Default false. */\r\n enableOtpLogin?: boolean;\r\n /** Validate OTP and return user (same shape as password flow) or null. */\r\n authorizeOtp?: (input: AuthorizeOtpInput) => Promise<NextAuthUser | null>;\r\n /**\r\n * Customer group sign-in policy for credentials/OTP on a shared `/api/auth` route:\r\n * - `true` — always allow (dedicated storefront auth)\r\n * - `false` — always block\r\n * - omitted — auto: allow unless `callbackUrl` targets `/admin` (storefront `/signin` works unchanged)\r\n */\r\n allowCustomerLogin?: boolean;\r\n}\r\n\r\nfunction sessionUserFromNextAuthUser(user: NextAuthUser) {\r\n const g = user.group;\r\n const isRBACAdmin = isSuperAdmin({\r\n groupId: user.groupId ?? undefined,\r\n groupName: g?.name,\r\n isRBACAdmin: false,\r\n });\r\n const entityPerms = permissionRowsToRecord(g?.permissions);\r\n // Preserve the DB value as-is: true → true, false → false, null/undefined → undefined.\r\n // Coercing null to false would make requireAdminAccess deny vendor/unset users before\r\n // the vendor-portal check can allow them.\r\n const rawAdminAccess = (user as NextAuthUser & { adminAccess?: boolean }).adminAccess;\r\n const adminAccess: boolean | undefined =\r\n rawAdminAccess === true ? true : rawAdminAccess === false ? false : undefined;\r\n const vendorIds = user.vendorIds ?? [];\r\n const vendorRole = user.vendorRole ?? null;\r\n const { isVendorPortal, isVendorOwner } = vendorPortalFlagsFromUser({\r\n email: user.email,\r\n isRBACAdmin,\r\n groupName: g?.name,\r\n vendorIds,\r\n vendorRole,\r\n });\r\n return {\r\n id: user.id.toString(),\r\n email: user.email,\r\n name: user.name,\r\n groupId: user.groupId ?? undefined,\r\n groupName: g?.name ?? undefined,\r\n isRBACAdmin,\r\n entityPerms,\r\n adminAccess,\r\n vendorIds,\r\n activeVendorId: user.activeVendorId ?? vendorIds[0] ?? null,\r\n vendorRole,\r\n isVendorPortal,\r\n isVendorOwner,\r\n };\r\n}\r\n\r\nfunction isCustomerGroupUser(user: NextAuthUser): boolean {\r\n return user.group?.name?.toLocaleLowerCase().trim() === 'customer';\r\n}\r\n\r\nfunction callbackUrlTargetsAdmin(callbackUrl: string): boolean {\r\n const raw = callbackUrl.trim();\r\n if (!raw) return false;\r\n if (raw.startsWith('/admin')) return true;\r\n try {\r\n const path = raw.startsWith('http') ? new URL(raw).pathname : raw.split('?')[0] ?? raw;\r\n return path.startsWith('/admin');\r\n } catch {\r\n return raw.includes('/admin');\r\n }\r\n}\r\n\r\n/** Whether a Customer-group user may complete this credentials/OTP sign-in attempt. */\r\nfunction permitsCustomerLogin(\r\n allowCustomerLogin: boolean | undefined,\r\n credentials: Record<string, string> | undefined\r\n): boolean {\r\n if (allowCustomerLogin === true) return true;\r\n if (allowCustomerLogin === false) return false;\r\n const callbackUrl = typeof credentials?.callbackUrl === 'string' ? credentials.callbackUrl : '';\r\n return !callbackUrlTargetsAdmin(callbackUrl);\r\n}\r\n\r\nexport function getNextAuthOptions(config: NextAuthOptionsConfig): NextAuthOptions {\r\n const {\r\n getUserByEmail,\r\n comparePassword,\r\n signInPage = '/admin/signin',\r\n secret,\r\n extend,\r\n enablePasswordLogin = true,\r\n enableOtpLogin = false,\r\n authorizeOtp,\r\n allowCustomerLogin,\r\n } = config;\r\n\r\n logAuth('getNextAuthOptions init', nextAuthCookieDebugInfo());\r\n\r\n const providers: NextAuthOptions['providers'] = [];\r\n\r\n if (enablePasswordLogin) {\r\n providers.push(\r\n CredentialsProvider({\r\n name: 'credentials',\r\n credentials: {\r\n email: { label: 'Email', type: 'email' },\r\n password: { label: 'Password', type: 'password' },\r\n },\r\n async authorize(credentials) {\r\n const creds = credentials as Record<string, string> | undefined;\r\n const email = creds?.email?.trim() ?? '';\r\n if (!email || !creds?.password) {\r\n logAuth('authorize(credentials) rejected', { reason: 'missing_email_or_password' });\r\n return null;\r\n }\r\n try {\r\n const user = await getUserByEmail(email);\r\n if (!user) {\r\n logAuth('authorize(credentials) rejected', { reason: 'user_not_found', email });\r\n return null;\r\n }\r\n if (user.blocked) {\r\n logAuth('authorize(credentials) rejected', { reason: 'blocked', email, userId: user.id });\r\n return null;\r\n }\r\n if ((user as { deleted?: boolean }).deleted) {\r\n logAuth('authorize(credentials) rejected', { reason: 'deleted', email, userId: user.id });\r\n return null;\r\n }\r\n if (!user.password) {\r\n logAuth('authorize(credentials) rejected', { reason: 'no_password', email, userId: user.id });\r\n return null;\r\n }\r\n const valid = await comparePassword(creds.password, user.password);\r\n if (!valid) {\r\n logAuth('authorize(credentials) rejected', { reason: 'invalid_password', email, userId: user.id });\r\n return null;\r\n }\r\n if (isCustomerGroupUser(user) && !permitsCustomerLogin(allowCustomerLogin, creds)) {\r\n logAuth('authorize(credentials) rejected', {\r\n reason: 'customer_group',\r\n email,\r\n userId: user.id,\r\n callbackUrl: creds?.callbackUrl ?? null,\r\n });\r\n return null;\r\n }\r\n const sessionUser = sessionUserFromNextAuthUser(user);\r\n logAuth('authorize(credentials) ok', summarizeSessionUserForLog(sessionUser));\r\n return sessionUser;\r\n } catch (err) {\r\n // Log so infrastructure errors (DB down, missing entity, etc.) are\r\n // visible in server logs rather than silently failing as \"wrong password\".\r\n console.error('[cms-auth] authorize error (credentials):', err instanceof Error ? err.message : err);\r\n logAuth('authorize(credentials) error', {\r\n email,\r\n message: err instanceof Error ? err.message : String(err),\r\n });\r\n return null;\r\n }\r\n },\r\n })\r\n );\r\n }\r\n\r\n if (enableOtpLogin && authorizeOtp) {\r\n providers.push(\r\n CredentialsProvider({\r\n id: 'otp',\r\n name: 'otp',\r\n credentials: {\r\n identifier: { label: 'Email or phone', type: 'text' },\r\n code: { label: 'Code', type: 'text' },\r\n channel: { label: 'Channel', type: 'text' },\r\n },\r\n async authorize(credentials) {\r\n const creds = credentials as Record<string, string> | undefined;\r\n const identifier = typeof creds?.identifier === 'string' ? creds.identifier.trim() : '';\r\n const code = typeof creds?.code === 'string' ? creds.code.trim() : '';\r\n const ch = creds?.channel === 'sms' ? 'sms' : 'email';\r\n if (!identifier || !code) return null;\r\n try {\r\n const user = await authorizeOtp({ identifier, channel: ch, code });\r\n if (!user || user.blocked || (user as { deleted?: boolean }).deleted) return null;\r\n if (isCustomerGroupUser(user) && !permitsCustomerLogin(allowCustomerLogin, creds)) {\r\n logAuth('authorize(otp) rejected', {\r\n reason: 'customer_group',\r\n identifier,\r\n callbackUrl: creds?.callbackUrl ?? null,\r\n });\r\n return null;\r\n }\r\n return sessionUserFromNextAuthUser(user);\r\n } catch (err) {\r\n console.error('[cms-auth] authorize error (otp):', err instanceof Error ? err.message : err);\r\n return null;\r\n }\r\n },\r\n })\r\n );\r\n }\r\n\r\n const options: NextAuthOptions = {\r\n secret: secret ?? process.env.NEXTAUTH_SECRET,\r\n providers,\r\n session: { strategy: 'jwt' },\r\n pages: { signIn: signInPage },\r\n cookies: {\r\n sessionToken: {\r\n name: process.env.NEXTAUTH_URL?.startsWith('https')\r\n ? '__Secure-next-auth.session-token'\r\n : 'next-auth.session-token',\r\n options: {\r\n httpOnly: true,\r\n sameSite: 'lax',\r\n path: '/',\r\n secure: process.env.NEXTAUTH_URL?.startsWith('https') ?? false,\r\n },\r\n },\r\n },\r\n callbacks: {\r\n async jwt({ token, user, trigger, session }) {\r\n if (user) {\r\n logAuth('jwt callback: new sign-in', {\r\n trigger,\r\n user: summarizeSessionUserForLog(user),\r\n });\r\n const u = user as unknown as Record<string, unknown>;\r\n (token as Record<string, unknown>).id = u.id;\r\n (token as Record<string, unknown>).groupId = u.groupId;\r\n (token as Record<string, unknown>).groupName = u.groupName;\r\n (token as Record<string, unknown>).isRBACAdmin = u.isRBACAdmin;\r\n (token as Record<string, unknown>).entityPerms = u.entityPerms;\r\n (token as Record<string, unknown>).adminAccess = u.adminAccess;\r\n (token as Record<string, unknown>).vendorIds = u.vendorIds;\r\n (token as Record<string, unknown>).activeVendorId = u.activeVendorId;\r\n (token as Record<string, unknown>).vendorRole = u.vendorRole;\r\n (token as Record<string, unknown>).isVendorPortal = u.isVendorPortal;\r\n (token as Record<string, unknown>).isVendorOwner = u.isVendorOwner;\r\n }\r\n if (trigger === 'update' && session && typeof session === 'object') {\r\n logAuth('jwt callback: session update', { trigger });\r\n const s = session as Record<string, unknown>;\r\n const t = token as Record<string, unknown>;\r\n if (typeof s.name === 'string') t.name = s.name;\r\n if (typeof s.email === 'string') t.email = s.email;\r\n if (typeof s.activeVendorId === 'number') t.activeVendorId = s.activeVendorId;\r\n }\r\n return token;\r\n },\r\n async session({ session, token }) {\r\n const t = token as Record<string, unknown>;\r\n logAuth('session callback', {\r\n tokenHasId: t.id != null,\r\n tokenEmail: typeof t.email === 'string' ? t.email : null,\r\n sessionUser: summarizeSessionUserForLog(session.user),\r\n });\r\n if (session.user) {\r\n if (typeof t.name === 'string') session.user.name = t.name;\r\n if (typeof t.email === 'string') session.user.email = t.email;\r\n (session.user as Record<string, unknown>).id = t.id;\r\n (session.user as Record<string, unknown>).groupId = t.groupId;\r\n (session.user as Record<string, unknown>).groupName = t.groupName;\r\n (session.user as Record<string, unknown>).isRBACAdmin = t.isRBACAdmin;\r\n (session.user as Record<string, unknown>).entityPerms = t.entityPerms;\r\n (session.user as Record<string, unknown>).adminAccess = t.adminAccess;\r\n (session.user as Record<string, unknown>).vendorIds = t.vendorIds;\r\n (session.user as Record<string, unknown>).activeVendorId = t.activeVendorId;\r\n (session.user as Record<string, unknown>).vendorRole = t.vendorRole;\r\n (session.user as Record<string, unknown>).isVendorPortal = t.isVendorPortal;\r\n (session.user as Record<string, unknown>).isVendorOwner = t.isVendorOwner;\r\n }\r\n return session;\r\n },\r\n },\r\n };\r\n\r\n return extend ? extend(options) : options;\r\n}\r\n\r\n/** Storefront sign-in: allows Customer group; use with signInPage `/signin`. */\r\nexport function getStorefrontNextAuthOptions(\r\n config: Omit<NextAuthOptionsConfig, 'allowCustomerLogin'>\r\n): NextAuthOptions {\r\n return getNextAuthOptions({ ...config, allowCustomerLogin: true });\r\n}\r\n"],"mappings":"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","names":["isVendorOwner","allowed","loadDbPermissionsForUser","LOG_PREFIX","isPublicMethod","isVendorOwner"]}