@infuro/cms-core 1.0.29 → 1.0.31
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 +17 -13
- package/dist/admin.cjs +8522 -3281
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +13 -2
- package/dist/admin.d.ts +13 -2
- package/dist/admin.js +8210 -2957
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +5099 -1167
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +2 -2
- package/dist/api.d.ts +2 -2
- package/dist/api.js +4847 -909
- package/dist/api.js.map +1 -1
- package/dist/auth.cjs +461 -62
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +73 -47
- package/dist/auth.d.ts +73 -47
- package/dist/auth.js +425 -38
- package/dist/auth.js.map +1 -1
- package/dist/cli.cjs +21 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21 -14
- package/dist/cli.js.map +1 -1
- package/dist/{index-D9SdaDJ0.d.ts → index-BcMRGNjS.d.cts} +36 -3
- package/dist/{index-BPQSXgXF.d.cts → index-Bda8D1Rm.d.ts} +36 -3
- package/dist/index.cjs +4753 -740
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +301 -36
- package/dist/index.d.ts +301 -36
- package/dist/index.js +4750 -768
- package/dist/index.js.map +1 -1
- package/dist/migrations/1775400000001-AddDiscountAndOrderAddresses.ts +274 -0
- package/dist/migrations/1775800000000-VendorsAndVendorUsers.ts +74 -0
- package/dist/migrations/1775900000000-StoreVendorIdColumns.ts +124 -0
- package/dist/migrations/1775910000000-VendorOwnerRbacSeed.ts +54 -0
- package/dist/migrations/1775920000000-VendorOwnerSettingsPermission.ts +25 -0
- package/dist/migrations/1775930000000-VendorGroupStorePermissions.ts +54 -0
- package/dist/migrations/1775940000000-VendorRls.ts +71 -0
- package/dist/migrations/1775950000000-VendorCustomers.ts +87 -0
- package/dist/migrations/1775950000001-VendorCustomersPermissions.ts +67 -0
- package/dist/migrations/1778652250860-CreateCurrencyTables.ts +16 -0
- package/dist/migrations/1778652250861-OrderAddressTables.ts +88 -0
- package/dist/migrations/1778652250862-UpdateDiscountandRules.ts +100 -0
- package/dist/migrations/1778652250863-MakeCouponCodeNullable.ts +19 -0
- package/dist/migrations/1778652250864-RemoveUniqueConstraintFromDiscountCouponCode.ts +22 -0
- package/dist/migrations/1778652250865-FixOrdersAddressForeignKeys.ts +71 -0
- package/dist/migrations/1778660000000-DiscountVendorId.ts +90 -0
- package/dist/migrations/1778660000001-FixOrdersAddressFkToOrderAddresses.ts +79 -0
- package/dist/migrations/1778660000002-VendorUserIdInviteStatus.ts +61 -0
- package/dist/theme.d.cts +2 -2
- package/dist/theme.d.ts +2 -2
- package/dist/{types-D34wmivy.d.cts → types-DCVaXlPV.d.cts} +1 -1
- package/dist/{types-D34wmivy.d.ts → types-DCVaXlPV.d.ts} +1 -1
- package/dist/vendor-scope-DTYhJk_I.d.cts +129 -0
- package/dist/vendor-scope-DTYhJk_I.d.ts +129 -0
- package/package.json +9 -2
- package/dist/helpers-dlrF_49e.d.cts +0 -60
- package/dist/helpers-dlrF_49e.d.ts +0 -60
package/dist/auth.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,57 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
30
|
-
// src/auth/index.ts
|
|
31
|
-
var auth_exports = {};
|
|
32
|
-
__export(auth_exports, {
|
|
33
|
-
ADMIN_GROUP_NAME: () => ADMIN_GROUP_NAME,
|
|
34
|
-
OPEN_ENDPOINTS: () => OPEN_ENDPOINTS,
|
|
35
|
-
PERMISSION_REQUIRED_ENDPOINTS: () => PERMISSION_REQUIRED_ENDPOINTS,
|
|
36
|
-
RBAC_ADMIN_ONLY_ENTITIES: () => RBAC_ADMIN_ONLY_ENTITIES,
|
|
37
|
-
canManageRoles: () => canManageRoles,
|
|
38
|
-
createAuthHelpers: () => createAuthHelpers,
|
|
39
|
-
createCmsMiddleware: () => createCmsMiddleware,
|
|
40
|
-
defaultPublicApiMethods: () => defaultPublicApiMethods,
|
|
41
|
-
getNextAuthOptions: () => getNextAuthOptions,
|
|
42
|
-
getPermissionableEntityKeys: () => getPermissionableEntityKeys,
|
|
43
|
-
getRequiredPermission: () => getRequiredPermission,
|
|
44
|
-
hasEntityPermission: () => hasEntityPermission,
|
|
45
|
-
isOpenEndpoint: () => isOpenEndpoint,
|
|
46
|
-
isPublicMethod: () => isPublicMethod,
|
|
47
|
-
isSuperAdminGroupName: () => isSuperAdminGroupName,
|
|
48
|
-
permissionRowsToRecord: () => permissionRowsToRecord,
|
|
49
|
-
seedAdministratorPermissions: () => seedAdministratorPermissions,
|
|
50
|
-
sessionHasEntityAccess: () => sessionHasEntityAccess
|
|
51
|
-
});
|
|
52
|
-
module.exports = __toCommonJS(auth_exports);
|
|
53
|
-
|
|
54
33
|
// src/auth/permission-entities.ts
|
|
55
|
-
var PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
|
|
56
|
-
"users",
|
|
57
|
-
"password_reset_tokens",
|
|
58
|
-
"user_groups",
|
|
59
|
-
"permissions",
|
|
60
|
-
"comments",
|
|
61
|
-
"form_fields",
|
|
62
|
-
"configs",
|
|
63
|
-
"knowledge_base_chunks",
|
|
64
|
-
"carts",
|
|
65
|
-
"cart_items",
|
|
66
|
-
"wishlists",
|
|
67
|
-
"wishlist_items",
|
|
68
|
-
"message_templates"
|
|
69
|
-
]);
|
|
70
|
-
var PERMISSION_LOGICAL_ENTITIES = [
|
|
71
|
-
"users",
|
|
72
|
-
"forms",
|
|
73
|
-
"form_submissions",
|
|
74
|
-
"dashboard",
|
|
75
|
-
"upload",
|
|
76
|
-
"settings",
|
|
77
|
-
"analytics",
|
|
78
|
-
"chat"
|
|
79
|
-
];
|
|
80
|
-
var ADMIN_GROUP_NAME = "Administrator";
|
|
81
34
|
function isSuperAdminGroupName(name) {
|
|
82
35
|
return name === ADMIN_GROUP_NAME;
|
|
83
36
|
}
|
|
@@ -107,13 +60,358 @@ function hasEntityPermission(record, entity, action) {
|
|
|
107
60
|
if (action === "update") return p.u;
|
|
108
61
|
return p.d;
|
|
109
62
|
}
|
|
63
|
+
var PERMISSION_ENTITY_INTERNAL_EXCLUDE, PERMISSION_LOGICAL_ENTITIES, ADMIN_GROUP_NAME;
|
|
64
|
+
var init_permission_entities = __esm({
|
|
65
|
+
"src/auth/permission-entities.ts"() {
|
|
66
|
+
"use strict";
|
|
67
|
+
PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
|
|
68
|
+
"users",
|
|
69
|
+
"password_reset_tokens",
|
|
70
|
+
"user_groups",
|
|
71
|
+
"permissions",
|
|
72
|
+
"comments",
|
|
73
|
+
"form_fields",
|
|
74
|
+
"configs",
|
|
75
|
+
"knowledge_base_chunks",
|
|
76
|
+
"carts",
|
|
77
|
+
"cart_items",
|
|
78
|
+
"wishlists",
|
|
79
|
+
"wishlist_items",
|
|
80
|
+
"message_templates",
|
|
81
|
+
"vendor_users"
|
|
82
|
+
]);
|
|
83
|
+
PERMISSION_LOGICAL_ENTITIES = [
|
|
84
|
+
"users",
|
|
85
|
+
"forms",
|
|
86
|
+
"form_submissions",
|
|
87
|
+
"dashboard",
|
|
88
|
+
"upload",
|
|
89
|
+
"settings",
|
|
90
|
+
"analytics",
|
|
91
|
+
"chat"
|
|
92
|
+
];
|
|
93
|
+
ADMIN_GROUP_NAME = "Administrator";
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// src/auth/vendor-scope.ts
|
|
98
|
+
function isVendorGroupName(name) {
|
|
99
|
+
if (!name?.trim()) return false;
|
|
100
|
+
const n = name.trim().toLowerCase();
|
|
101
|
+
return n === VENDOR_OWNER_GROUP_NAME.toLowerCase() || n.includes("vendor");
|
|
102
|
+
}
|
|
103
|
+
function isPlatformAdministrator(user) {
|
|
104
|
+
if (!user?.email) return false;
|
|
105
|
+
return !!(user.isRBACAdmin || isSuperAdminGroupName(user.groupName));
|
|
106
|
+
}
|
|
107
|
+
function isVendorPortalUser(user) {
|
|
108
|
+
if (user?.isVendorPortal === true) return true;
|
|
109
|
+
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
110
|
+
if ((user.vendorIds?.length ?? 0) > 0) return true;
|
|
111
|
+
return isVendorGroupName(user.groupName);
|
|
112
|
+
}
|
|
113
|
+
function isVendorStaff(user) {
|
|
114
|
+
return isVendorPortalUser(user);
|
|
115
|
+
}
|
|
116
|
+
function isVendorOwner(user) {
|
|
117
|
+
if (user?.isVendorOwner === true) return true;
|
|
118
|
+
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
119
|
+
if (user.vendorRole === "staff") return false;
|
|
120
|
+
if (user.vendorRole === "owner") return true;
|
|
121
|
+
if (!isVendorPortalUser(user)) return false;
|
|
122
|
+
return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();
|
|
123
|
+
}
|
|
124
|
+
function canManageVendorTeam(user) {
|
|
125
|
+
return isPlatformAdministrator(user) || isVendorOwner(user);
|
|
126
|
+
}
|
|
127
|
+
function canManageVendorRoles(user) {
|
|
128
|
+
return isPlatformAdministrator(user) || isVendorOwner(user);
|
|
129
|
+
}
|
|
130
|
+
function canOnboardVendors(user) {
|
|
131
|
+
return isPlatformAdministrator(user);
|
|
132
|
+
}
|
|
133
|
+
function resolveVendorScopeFromSessionUser(user) {
|
|
134
|
+
if (!user?.email) return { type: "deny" };
|
|
135
|
+
if (isPlatformAdministrator(user)) return { type: "all" };
|
|
136
|
+
const vendorIds = user.vendorIds ?? [];
|
|
137
|
+
if (vendorIds.length === 0) return { type: "deny" };
|
|
138
|
+
const preferred = user.activeVendorId ?? vendorIds[0];
|
|
139
|
+
const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0];
|
|
140
|
+
return { type: "vendor", vendorId, vendorIds };
|
|
141
|
+
}
|
|
142
|
+
function vendorPortalFlagsFromUser(input) {
|
|
143
|
+
const vendorIds = input.vendorIds ?? [];
|
|
144
|
+
const isVendorPortal = !input.isRBACAdmin && (vendorIds.length > 0 || isVendorGroupName(input.groupName));
|
|
145
|
+
const isVendorOwner2 = isVendorPortal && input.vendorRole !== "staff" && (input.vendorRole === "owner" || input.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase());
|
|
146
|
+
return { isVendorPortal, isVendorOwner: isVendorOwner2 };
|
|
147
|
+
}
|
|
148
|
+
var VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, VENDOR_OWNER_GROUP_NAME;
|
|
149
|
+
var init_vendor_scope = __esm({
|
|
150
|
+
"src/auth/vendor-scope.ts"() {
|
|
151
|
+
"use strict";
|
|
152
|
+
init_permission_entities();
|
|
153
|
+
VENDOR_SCOPED_STORE_ENTITIES = /* @__PURE__ */ new Set([
|
|
154
|
+
"products",
|
|
155
|
+
"collections",
|
|
156
|
+
"brands",
|
|
157
|
+
"product_categories",
|
|
158
|
+
"orders",
|
|
159
|
+
"payments",
|
|
160
|
+
"taxes",
|
|
161
|
+
"attributes",
|
|
162
|
+
"vendor_customers",
|
|
163
|
+
"discounts"
|
|
164
|
+
]);
|
|
165
|
+
VENDOR_STORE_RBAC_ENTITIES = /* @__PURE__ */ new Set([
|
|
166
|
+
...VENDOR_SCOPED_STORE_ENTITIES,
|
|
167
|
+
"order_discounts",
|
|
168
|
+
"order_addresses"
|
|
169
|
+
]);
|
|
170
|
+
VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// src/auth/rbac-debug-db.ts
|
|
175
|
+
var rbac_debug_db_exports = {};
|
|
176
|
+
__export(rbac_debug_db_exports, {
|
|
177
|
+
loadDbPermissionsForUser: () => loadDbPermissionsForUser
|
|
178
|
+
});
|
|
179
|
+
async function loadDbPermissionsForUser(dataSource, userId) {
|
|
180
|
+
const rows = await dataSource.query(
|
|
181
|
+
`
|
|
182
|
+
SELECT u."groupId" AS "groupId", g.name AS "groupName",
|
|
183
|
+
p.entity, p."canCreate", p."canRead", p."canUpdate", p."canDelete"
|
|
184
|
+
FROM users u
|
|
185
|
+
LEFT JOIN user_groups g ON g.id = u."groupId" AND g.deleted = false
|
|
186
|
+
LEFT JOIN permissions p ON p."groupId" = g.id
|
|
187
|
+
WHERE u.id = $1
|
|
188
|
+
`,
|
|
189
|
+
[userId]
|
|
190
|
+
);
|
|
191
|
+
const groupId = rows[0]?.groupId ?? null;
|
|
192
|
+
const groupName = rows[0]?.groupName ?? null;
|
|
193
|
+
const permRows = rows.filter((r) => r.entity).map((r) => ({
|
|
194
|
+
entity: r.entity,
|
|
195
|
+
canCreate: !!r.canCreate,
|
|
196
|
+
canRead: !!r.canRead,
|
|
197
|
+
canUpdate: !!r.canUpdate,
|
|
198
|
+
canDelete: !!r.canDelete
|
|
199
|
+
}));
|
|
200
|
+
return {
|
|
201
|
+
groupId,
|
|
202
|
+
groupName,
|
|
203
|
+
dbEntityPerms: summarizeEntityPerms(permissionRowsToRecord(permRows))
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
var init_rbac_debug_db = __esm({
|
|
207
|
+
"src/auth/rbac-debug-db.ts"() {
|
|
208
|
+
"use strict";
|
|
209
|
+
init_permission_entities();
|
|
210
|
+
init_rbac_debug();
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// src/auth/rbac-debug.ts
|
|
215
|
+
function isRbacDebugEnabled() {
|
|
216
|
+
const v = process.env.CMS_RBAC_DEBUG?.trim().toLowerCase();
|
|
217
|
+
if (v === "1" || v === "true" || v === "yes") return true;
|
|
218
|
+
if (v === "0" || v === "false" || v === "no") return false;
|
|
219
|
+
return process.env.NODE_ENV === "development";
|
|
220
|
+
}
|
|
221
|
+
function logRbac(message, data) {
|
|
222
|
+
if (!isRbacDebugEnabled()) return;
|
|
223
|
+
if (data) console.info(LOG_PREFIX, message, data);
|
|
224
|
+
else console.info(LOG_PREFIX, message);
|
|
225
|
+
}
|
|
226
|
+
function summarizeEntityPerms(entityPerms) {
|
|
227
|
+
const out = {};
|
|
228
|
+
if (!entityPerms) return out;
|
|
229
|
+
for (const [entity, p] of Object.entries(entityPerms)) {
|
|
230
|
+
out[entity] = { c: p.c, r: p.r, u: p.u, d: p.d };
|
|
231
|
+
}
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
function vendorPortalFallbackReason(user, entity, action) {
|
|
235
|
+
if (!isVendorPortalUser(user)) return null;
|
|
236
|
+
if (entity === "dashboard" && action === "read") return "vendor_portal_dashboard_fallback";
|
|
237
|
+
if (entity === "analytics" && action === "read") return "vendor_portal_analytics_fallback";
|
|
238
|
+
if (entity === "settings" && action === "read") return "vendor_portal_settings_read_fallback";
|
|
239
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === "read") return "vendor_portal_store_read_fallback";
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
function explainSessionEntityAccess(user, entity, action) {
|
|
243
|
+
const userSnapshot = {
|
|
244
|
+
email: user?.email ?? null,
|
|
245
|
+
id: user?.id ?? null,
|
|
246
|
+
groupId: user?.groupId ?? null,
|
|
247
|
+
groupName: user?.groupName ?? null,
|
|
248
|
+
isRBACAdmin: user?.isRBACAdmin ?? false,
|
|
249
|
+
adminAccess: user?.adminAccess ?? null,
|
|
250
|
+
vendorIds: user?.vendorIds ?? [],
|
|
251
|
+
activeVendorId: user?.activeVendorId ?? null,
|
|
252
|
+
vendorRole: user?.vendorRole ?? null,
|
|
253
|
+
isVendorPortal: user?.isVendorPortal ?? false,
|
|
254
|
+
isVendorOwner: user?.isVendorOwner ?? false,
|
|
255
|
+
isVendorPortalComputed: isVendorPortalUser(user),
|
|
256
|
+
isVendorOwnerComputed: isVendorOwner(user),
|
|
257
|
+
jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),
|
|
258
|
+
jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null
|
|
259
|
+
};
|
|
260
|
+
if (!user?.email) {
|
|
261
|
+
return { allowed: false, reason: "no_session_email", userSnapshot };
|
|
262
|
+
}
|
|
263
|
+
if (user.isRBACAdmin) {
|
|
264
|
+
return { allowed: true, reason: "platform_administrator", userSnapshot };
|
|
265
|
+
}
|
|
266
|
+
const vendorIds = user.vendorIds ?? [];
|
|
267
|
+
const isStaff = user.vendorRole === "staff";
|
|
268
|
+
if (vendorIds.length > 0) {
|
|
269
|
+
if (entity === "dashboard" && action === "read") {
|
|
270
|
+
return { allowed: true, reason: "vendor_link_dashboard_read", userSnapshot };
|
|
271
|
+
}
|
|
272
|
+
if (entity === "analytics" && action === "read") {
|
|
273
|
+
return { allowed: true, reason: "vendor_link_analytics_read", userSnapshot };
|
|
274
|
+
}
|
|
275
|
+
if (entity === "settings") {
|
|
276
|
+
if (action === "read") {
|
|
277
|
+
return { allowed: true, reason: "vendor_link_settings_read", userSnapshot };
|
|
278
|
+
}
|
|
279
|
+
if (action === "update" && !isStaff) {
|
|
280
|
+
return { allowed: true, reason: "vendor_link_settings_update", userSnapshot };
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
284
|
+
if (isStaff && action === "read") {
|
|
285
|
+
return { allowed: true, reason: "vendor_staff_store_read", userSnapshot };
|
|
286
|
+
}
|
|
287
|
+
if (!isStaff) {
|
|
288
|
+
return { allowed: true, reason: "vendor_link_store_full", userSnapshot };
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
allowed: false,
|
|
292
|
+
reason: "vendor_staff_store_write_denied",
|
|
293
|
+
userSnapshot
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (isVendorPortalUser(user) && isVendorOwner(user)) {
|
|
298
|
+
if (entity === "dashboard" && action === "read") {
|
|
299
|
+
return { allowed: true, reason: "vendor_owner_group_dashboard", userSnapshot };
|
|
300
|
+
}
|
|
301
|
+
if (entity === "analytics" && action === "read") {
|
|
302
|
+
return { allowed: true, reason: "vendor_owner_group_analytics", userSnapshot };
|
|
303
|
+
}
|
|
304
|
+
if (entity === "settings" && (action === "read" || action === "update")) {
|
|
305
|
+
return { allowed: true, reason: "vendor_owner_group_settings", userSnapshot };
|
|
306
|
+
}
|
|
307
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
308
|
+
return { allowed: true, reason: "vendor_owner_group_store", userSnapshot };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);
|
|
312
|
+
if (vendorPortalReason) {
|
|
313
|
+
return { allowed: true, reason: vendorPortalReason, userSnapshot };
|
|
314
|
+
}
|
|
315
|
+
const explicit = user.entityPerms?.[entity];
|
|
316
|
+
if (explicit !== void 0) {
|
|
317
|
+
const allowed2 = hasEntityPermission(user.entityPerms, entity, action);
|
|
318
|
+
return {
|
|
319
|
+
allowed: allowed2,
|
|
320
|
+
reason: allowed2 ? "jwt_entity_perms_allow" : "jwt_entity_perms_deny",
|
|
321
|
+
userSnapshot
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const allowed = hasEntityPermission(user.entityPerms, entity, action);
|
|
325
|
+
return {
|
|
326
|
+
allowed,
|
|
327
|
+
reason: allowed ? "entity_perms_fallback_allow" : "no_matching_rule",
|
|
328
|
+
userSnapshot
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
async function logEntityAccessDecision(dataSource, context, user, entity, action, extra) {
|
|
332
|
+
if (!isRbacDebugEnabled()) return;
|
|
333
|
+
const explanation = explainSessionEntityAccess(user, entity, action);
|
|
334
|
+
let dbPermissions;
|
|
335
|
+
if (dataSource && user?.id) {
|
|
336
|
+
const id = Number(user.id);
|
|
337
|
+
if (Number.isFinite(id)) {
|
|
338
|
+
try {
|
|
339
|
+
const { loadDbPermissionsForUser: loadDbPermissionsForUser2 } = await Promise.resolve().then(() => (init_rbac_debug_db(), rbac_debug_db_exports));
|
|
340
|
+
dbPermissions = await loadDbPermissionsForUser2(dataSource, id);
|
|
341
|
+
} catch (e) {
|
|
342
|
+
dbPermissions = { error: e instanceof Error ? e.message : String(e) };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
logRbac(context, {
|
|
347
|
+
entity,
|
|
348
|
+
action,
|
|
349
|
+
allowed: explanation.allowed,
|
|
350
|
+
reason: explanation.reason,
|
|
351
|
+
...explanation.userSnapshot,
|
|
352
|
+
dbPermissions,
|
|
353
|
+
...extra
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
var LOG_PREFIX;
|
|
357
|
+
var init_rbac_debug = __esm({
|
|
358
|
+
"src/auth/rbac-debug.ts"() {
|
|
359
|
+
"use strict";
|
|
360
|
+
init_permission_entities();
|
|
361
|
+
init_vendor_scope();
|
|
362
|
+
LOG_PREFIX = "[cms-rbac]";
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// src/auth/index.ts
|
|
367
|
+
var auth_exports = {};
|
|
368
|
+
__export(auth_exports, {
|
|
369
|
+
ADMIN_GROUP_NAME: () => ADMIN_GROUP_NAME,
|
|
370
|
+
OPEN_ENDPOINTS: () => OPEN_ENDPOINTS,
|
|
371
|
+
PERMISSION_REQUIRED_ENDPOINTS: () => PERMISSION_REQUIRED_ENDPOINTS,
|
|
372
|
+
RBAC_ADMIN_ONLY_ENTITIES: () => RBAC_ADMIN_ONLY_ENTITIES,
|
|
373
|
+
VENDOR_OWNER_GROUP_NAME: () => VENDOR_OWNER_GROUP_NAME,
|
|
374
|
+
VENDOR_SCOPED_STORE_ENTITIES: () => VENDOR_SCOPED_STORE_ENTITIES,
|
|
375
|
+
VENDOR_STORE_RBAC_ENTITIES: () => VENDOR_STORE_RBAC_ENTITIES,
|
|
376
|
+
canManageRoles: () => canManageRoles,
|
|
377
|
+
canManageVendorRoles: () => canManageVendorRoles,
|
|
378
|
+
canManageVendorTeam: () => canManageVendorTeam,
|
|
379
|
+
canOnboardVendors: () => canOnboardVendors,
|
|
380
|
+
createAuthHelpers: () => createAuthHelpers,
|
|
381
|
+
createCmsAuthBundle: () => createCmsAuthBundle,
|
|
382
|
+
createCmsMiddleware: () => createCmsMiddleware,
|
|
383
|
+
defaultPublicApiMethods: () => defaultPublicApiMethods,
|
|
384
|
+
explainSessionEntityAccess: () => explainSessionEntityAccess,
|
|
385
|
+
getNextAuthOptions: () => getNextAuthOptions,
|
|
386
|
+
getPermissionableEntityKeys: () => getPermissionableEntityKeys,
|
|
387
|
+
getRequiredPermission: () => getRequiredPermission,
|
|
388
|
+
hasEntityPermission: () => hasEntityPermission,
|
|
389
|
+
isOpenEndpoint: () => isOpenEndpoint,
|
|
390
|
+
isPlatformAdministrator: () => isPlatformAdministrator,
|
|
391
|
+
isPublicMethod: () => isPublicMethod,
|
|
392
|
+
isRbacDebugEnabled: () => isRbacDebugEnabled,
|
|
393
|
+
isSuperAdminGroupName: () => isSuperAdminGroupName,
|
|
394
|
+
isVendorGroupName: () => isVendorGroupName,
|
|
395
|
+
isVendorOwner: () => isVendorOwner,
|
|
396
|
+
isVendorPortalUser: () => isVendorPortalUser,
|
|
397
|
+
isVendorStaff: () => isVendorStaff,
|
|
398
|
+
logEntityAccessDecision: () => logEntityAccessDecision,
|
|
399
|
+
logRbac: () => logRbac,
|
|
400
|
+
permissionRowsToRecord: () => permissionRowsToRecord,
|
|
401
|
+
resolveVendorScopeFromSessionUser: () => resolveVendorScopeFromSessionUser,
|
|
402
|
+
seedAdministratorPermissions: () => seedAdministratorPermissions,
|
|
403
|
+
sessionHasEntityAccess: () => sessionHasEntityAccess,
|
|
404
|
+
summarizeEntityPerms: () => summarizeEntityPerms,
|
|
405
|
+
vendorPortalFlagsFromUser: () => vendorPortalFlagsFromUser
|
|
406
|
+
});
|
|
407
|
+
module.exports = __toCommonJS(auth_exports);
|
|
110
408
|
|
|
111
409
|
// src/auth/helpers.ts
|
|
410
|
+
init_rbac_debug();
|
|
411
|
+
init_vendor_scope();
|
|
112
412
|
var RBAC_ADMIN_ONLY_ENTITIES = /* @__PURE__ */ new Set(["users", "user_groups", "permissions"]);
|
|
113
413
|
function sessionHasEntityAccess(user, entity, action) {
|
|
114
|
-
|
|
115
|
-
if (user.isRBACAdmin && RBAC_ADMIN_ONLY_ENTITIES.has(entity)) return true;
|
|
116
|
-
return hasEntityPermission(user.entityPerms, entity, action);
|
|
414
|
+
return explainSessionEntityAccess(user, entity, action).allowed;
|
|
117
415
|
}
|
|
118
416
|
function canManageRoles(user) {
|
|
119
417
|
return !!(user?.email && user.isRBACAdmin);
|
|
@@ -138,6 +436,19 @@ function isPublicMethod(pathname, method) {
|
|
|
138
436
|
return false;
|
|
139
437
|
}
|
|
140
438
|
function createAuthHelpers(getSession, NextResponse) {
|
|
439
|
+
return createAuthHelpersFromGetSession(getSession, NextResponse);
|
|
440
|
+
}
|
|
441
|
+
function createCmsAuthBundle(getSession, NextResponse) {
|
|
442
|
+
const auth = createAuthHelpers(getSession, NextResponse);
|
|
443
|
+
return {
|
|
444
|
+
requireAuth: auth.requireAuth,
|
|
445
|
+
requireAdminAccess: auth.requireAdminAccess,
|
|
446
|
+
requireEntityPermission: auth.requireEntityPermission,
|
|
447
|
+
getSessionUser: auth.getAuthenticatedUser,
|
|
448
|
+
getAuthenticatedUser: auth.getAuthenticatedUser
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function createAuthHelpersFromGetSession(getSession, NextResponse) {
|
|
141
452
|
return {
|
|
142
453
|
async requireAuth() {
|
|
143
454
|
const session = await getSession();
|
|
@@ -159,8 +470,21 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
159
470
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
160
471
|
}
|
|
161
472
|
const u = session.user;
|
|
162
|
-
|
|
163
|
-
|
|
473
|
+
const allowed = sessionHasEntityAccess(u, entity, action);
|
|
474
|
+
const { reason } = explainSessionEntityAccess(u, entity, action);
|
|
475
|
+
logRbac("authHelpers.requireEntityPermission", {
|
|
476
|
+
entity,
|
|
477
|
+
action,
|
|
478
|
+
allowed,
|
|
479
|
+
reason,
|
|
480
|
+
email: u.email,
|
|
481
|
+
groupName: u.groupName,
|
|
482
|
+
vendorIds: u.vendorIds,
|
|
483
|
+
isVendorPortal: u.isVendorPortal,
|
|
484
|
+
isVendorOwner: u.isVendorOwner
|
|
485
|
+
});
|
|
486
|
+
if (allowed) return null;
|
|
487
|
+
return NextResponse.json({ error: "Forbidden", entity, action, reason }, { status: 403 });
|
|
164
488
|
},
|
|
165
489
|
async requireAdminAccess() {
|
|
166
490
|
const session = await getSession();
|
|
@@ -169,8 +493,23 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
169
493
|
}
|
|
170
494
|
const u = session.user;
|
|
171
495
|
if (u.isRBACAdmin) return null;
|
|
172
|
-
if (u
|
|
173
|
-
return null;
|
|
496
|
+
if (isVendorPortalUser(u)) return null;
|
|
497
|
+
if (u.adminAccess === true) return null;
|
|
498
|
+
if (u.adminAccess === false) {
|
|
499
|
+
logRbac("requireAdminAccess denied (adminAccess:false)", {
|
|
500
|
+
email: u.email,
|
|
501
|
+
groupName: u.groupName,
|
|
502
|
+
isVendorPortal: u.isVendorPortal
|
|
503
|
+
});
|
|
504
|
+
return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
|
|
505
|
+
}
|
|
506
|
+
logRbac("requireAdminAccess denied (no matching rule)", {
|
|
507
|
+
email: u.email,
|
|
508
|
+
adminAccess: u.adminAccess,
|
|
509
|
+
groupName: u.groupName,
|
|
510
|
+
isVendorPortal: u.isVendorPortal
|
|
511
|
+
});
|
|
512
|
+
return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
|
|
174
513
|
},
|
|
175
514
|
async getAuthenticatedUser() {
|
|
176
515
|
const session = await getSession();
|
|
@@ -179,18 +518,26 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
179
518
|
};
|
|
180
519
|
}
|
|
181
520
|
|
|
521
|
+
// src/auth/index.ts
|
|
522
|
+
init_rbac_debug();
|
|
523
|
+
init_vendor_scope();
|
|
524
|
+
init_permission_entities();
|
|
525
|
+
|
|
182
526
|
// src/auth/seed-permissions.ts
|
|
527
|
+
init_permission_entities();
|
|
183
528
|
async function seedAdministratorPermissions(dataSource, entityMap) {
|
|
184
529
|
const entities = getPermissionableEntityKeys(entityMap);
|
|
185
530
|
const groupRepo = dataSource.getRepository(entityMap.user_groups);
|
|
186
531
|
const permRepo = dataSource.getRepository(entityMap.permissions);
|
|
187
532
|
const adminGroup = await groupRepo.findOne({ where: { name: ADMIN_GROUP_NAME, deleted: false } });
|
|
533
|
+
console.log("ADMIN GROUP", adminGroup);
|
|
188
534
|
if (!adminGroup) return;
|
|
189
535
|
const fullCrud = { canCreate: true, canRead: true, canUpdate: true, canDelete: true };
|
|
190
536
|
for (const entity of entities) {
|
|
191
537
|
const existing = await permRepo.findOne({
|
|
192
538
|
where: { groupId: adminGroup.id, entity }
|
|
193
539
|
});
|
|
540
|
+
console.log("EXISTING", existing);
|
|
194
541
|
if (existing) {
|
|
195
542
|
existing.canCreate = true;
|
|
196
543
|
existing.canRead = true;
|
|
@@ -264,20 +611,38 @@ function createCmsMiddleware(config = {}) {
|
|
|
264
611
|
|
|
265
612
|
// src/auth/nextauth-options.ts
|
|
266
613
|
var import_credentials = __toESM(require("next-auth/providers/credentials"), 1);
|
|
614
|
+
init_permission_entities();
|
|
615
|
+
init_vendor_scope();
|
|
267
616
|
var CredentialsProvider = import_credentials.default.default ?? import_credentials.default;
|
|
268
617
|
function sessionUserFromNextAuthUser(user) {
|
|
269
618
|
const g = user.group;
|
|
270
619
|
const isRBACAdmin = isSuperAdminGroupName(g?.name);
|
|
271
620
|
const entityPerms = permissionRowsToRecord(g?.permissions);
|
|
272
|
-
const
|
|
621
|
+
const rawAdminAccess = user.adminAccess;
|
|
622
|
+
const adminAccess = rawAdminAccess === true ? true : rawAdminAccess === false ? false : void 0;
|
|
623
|
+
const vendorIds = user.vendorIds ?? [];
|
|
624
|
+
const vendorRole = user.vendorRole ?? null;
|
|
625
|
+
const { isVendorPortal, isVendorOwner: isVendorOwner2 } = vendorPortalFlagsFromUser({
|
|
626
|
+
email: user.email,
|
|
627
|
+
isRBACAdmin,
|
|
628
|
+
groupName: g?.name,
|
|
629
|
+
vendorIds,
|
|
630
|
+
vendorRole
|
|
631
|
+
});
|
|
273
632
|
return {
|
|
274
633
|
id: user.id.toString(),
|
|
275
634
|
email: user.email,
|
|
276
635
|
name: user.name,
|
|
277
636
|
groupId: user.groupId ?? void 0,
|
|
637
|
+
groupName: g?.name ?? void 0,
|
|
278
638
|
isRBACAdmin,
|
|
279
639
|
entityPerms,
|
|
280
|
-
adminAccess
|
|
640
|
+
adminAccess,
|
|
641
|
+
vendorIds,
|
|
642
|
+
activeVendorId: user.activeVendorId ?? vendorIds[0] ?? null,
|
|
643
|
+
vendorRole,
|
|
644
|
+
isVendorPortal,
|
|
645
|
+
isVendorOwner: isVendorOwner2
|
|
281
646
|
};
|
|
282
647
|
}
|
|
283
648
|
function getNextAuthOptions(config) {
|
|
@@ -308,7 +673,8 @@ function getNextAuthOptions(config) {
|
|
|
308
673
|
const valid = await comparePassword(credentials.password, user.password);
|
|
309
674
|
if (!valid) return null;
|
|
310
675
|
return sessionUserFromNextAuthUser(user);
|
|
311
|
-
} catch {
|
|
676
|
+
} catch (err) {
|
|
677
|
+
console.error("[cms-auth] authorize error (credentials):", err instanceof Error ? err.message : err);
|
|
312
678
|
return null;
|
|
313
679
|
}
|
|
314
680
|
}
|
|
@@ -334,7 +700,8 @@ function getNextAuthOptions(config) {
|
|
|
334
700
|
const user = await authorizeOtp({ identifier, channel: ch, code });
|
|
335
701
|
if (!user || user.blocked || user.deleted) return null;
|
|
336
702
|
return sessionUserFromNextAuthUser(user);
|
|
337
|
-
} catch {
|
|
703
|
+
} catch (err) {
|
|
704
|
+
console.error("[cms-auth] authorize error (otp):", err instanceof Error ? err.message : err);
|
|
338
705
|
return null;
|
|
339
706
|
}
|
|
340
707
|
}
|
|
@@ -363,15 +730,22 @@ function getNextAuthOptions(config) {
|
|
|
363
730
|
const u = user;
|
|
364
731
|
token.id = u.id;
|
|
365
732
|
token.groupId = u.groupId;
|
|
733
|
+
token.groupName = u.groupName;
|
|
366
734
|
token.isRBACAdmin = u.isRBACAdmin;
|
|
367
735
|
token.entityPerms = u.entityPerms;
|
|
368
736
|
token.adminAccess = u.adminAccess;
|
|
737
|
+
token.vendorIds = u.vendorIds;
|
|
738
|
+
token.activeVendorId = u.activeVendorId;
|
|
739
|
+
token.vendorRole = u.vendorRole;
|
|
740
|
+
token.isVendorPortal = u.isVendorPortal;
|
|
741
|
+
token.isVendorOwner = u.isVendorOwner;
|
|
369
742
|
}
|
|
370
743
|
if (trigger === "update" && session && typeof session === "object") {
|
|
371
744
|
const s = session;
|
|
372
745
|
const t = token;
|
|
373
746
|
if (typeof s.name === "string") t.name = s.name;
|
|
374
747
|
if (typeof s.email === "string") t.email = s.email;
|
|
748
|
+
if (typeof s.activeVendorId === "number") t.activeVendorId = s.activeVendorId;
|
|
375
749
|
}
|
|
376
750
|
return token;
|
|
377
751
|
},
|
|
@@ -382,9 +756,15 @@ function getNextAuthOptions(config) {
|
|
|
382
756
|
if (typeof t.email === "string") session.user.email = t.email;
|
|
383
757
|
session.user.id = t.id;
|
|
384
758
|
session.user.groupId = t.groupId;
|
|
759
|
+
session.user.groupName = t.groupName;
|
|
385
760
|
session.user.isRBACAdmin = t.isRBACAdmin;
|
|
386
761
|
session.user.entityPerms = t.entityPerms;
|
|
387
762
|
session.user.adminAccess = t.adminAccess;
|
|
763
|
+
session.user.vendorIds = t.vendorIds;
|
|
764
|
+
session.user.activeVendorId = t.activeVendorId;
|
|
765
|
+
session.user.vendorRole = t.vendorRole;
|
|
766
|
+
session.user.isVendorPortal = t.isVendorPortal;
|
|
767
|
+
session.user.isVendorOwner = t.isVendorOwner;
|
|
388
768
|
}
|
|
389
769
|
return session;
|
|
390
770
|
}
|
|
@@ -398,19 +778,38 @@ function getNextAuthOptions(config) {
|
|
|
398
778
|
OPEN_ENDPOINTS,
|
|
399
779
|
PERMISSION_REQUIRED_ENDPOINTS,
|
|
400
780
|
RBAC_ADMIN_ONLY_ENTITIES,
|
|
781
|
+
VENDOR_OWNER_GROUP_NAME,
|
|
782
|
+
VENDOR_SCOPED_STORE_ENTITIES,
|
|
783
|
+
VENDOR_STORE_RBAC_ENTITIES,
|
|
401
784
|
canManageRoles,
|
|
785
|
+
canManageVendorRoles,
|
|
786
|
+
canManageVendorTeam,
|
|
787
|
+
canOnboardVendors,
|
|
402
788
|
createAuthHelpers,
|
|
789
|
+
createCmsAuthBundle,
|
|
403
790
|
createCmsMiddleware,
|
|
404
791
|
defaultPublicApiMethods,
|
|
792
|
+
explainSessionEntityAccess,
|
|
405
793
|
getNextAuthOptions,
|
|
406
794
|
getPermissionableEntityKeys,
|
|
407
795
|
getRequiredPermission,
|
|
408
796
|
hasEntityPermission,
|
|
409
797
|
isOpenEndpoint,
|
|
798
|
+
isPlatformAdministrator,
|
|
410
799
|
isPublicMethod,
|
|
800
|
+
isRbacDebugEnabled,
|
|
411
801
|
isSuperAdminGroupName,
|
|
802
|
+
isVendorGroupName,
|
|
803
|
+
isVendorOwner,
|
|
804
|
+
isVendorPortalUser,
|
|
805
|
+
isVendorStaff,
|
|
806
|
+
logEntityAccessDecision,
|
|
807
|
+
logRbac,
|
|
412
808
|
permissionRowsToRecord,
|
|
809
|
+
resolveVendorScopeFromSessionUser,
|
|
413
810
|
seedAdministratorPermissions,
|
|
414
|
-
sessionHasEntityAccess
|
|
811
|
+
sessionHasEntityAccess,
|
|
812
|
+
summarizeEntityPerms,
|
|
813
|
+
vendorPortalFlagsFromUser
|
|
415
814
|
});
|
|
416
815
|
//# sourceMappingURL=auth.cjs.map
|