@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.
- package/README.md +9 -6
- package/dist/admin.cjs +980 -801
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +7 -2
- package/dist/admin.d.ts +7 -2
- package/dist/admin.js +1021 -842
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +1858 -848
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1824 -815
- package/dist/api.js.map +1 -1
- package/dist/auth.cjs +94 -11
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +17 -1
- package/dist/auth.d.ts +17 -1
- package/dist/auth.js +89 -11
- package/dist/auth.js.map +1 -1
- package/dist/cli.cjs +39 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +39 -0
- package/dist/cli.js.map +1 -1
- package/dist/{index-rZTnpK7y.d.cts → index-Bf5GO8fu.d.cts} +3 -2
- package/dist/{index-DWd5Gjc4.d.ts → index-DOiJuMQA.d.ts} +3 -2
- package/dist/index.cjs +2078 -841
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -8
- package/dist/index.d.ts +83 -8
- package/dist/index.js +2013 -786
- package/dist/index.js.map +1 -1
- package/dist/migrations/1778660000004-CreateCustomerAndCustomerContacts.ts +99 -0
- package/dist/migrations/1778660000005-AddCustomerIdToVendorCustomers.ts +39 -0
- package/dist/migrations/1778660000006-UpdateVendorCustomersContactNullable.ts +36 -0
- package/dist/migrations/1778660000007-VendorOwnerCustomerContactsPermission.ts +39 -0
- package/dist/migrations/1779300000000-VendorOwnerContactsPermission.ts +39 -0
- package/dist/migrations/1779400000000-AddCustomerContactIdToOrders.ts +33 -0
- 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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
700
|
-
|
|
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(
|
|
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
|
|
754
|
-
const
|
|
755
|
-
const
|
|
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"]}
|