@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.js
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
1
11
|
// src/auth/permission-entities.ts
|
|
2
|
-
var PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
|
|
3
|
-
"users",
|
|
4
|
-
"password_reset_tokens",
|
|
5
|
-
"user_groups",
|
|
6
|
-
"permissions",
|
|
7
|
-
"comments",
|
|
8
|
-
"form_fields",
|
|
9
|
-
"configs",
|
|
10
|
-
"knowledge_base_chunks",
|
|
11
|
-
"carts",
|
|
12
|
-
"cart_items",
|
|
13
|
-
"wishlists",
|
|
14
|
-
"wishlist_items",
|
|
15
|
-
"message_templates"
|
|
16
|
-
]);
|
|
17
|
-
var PERMISSION_LOGICAL_ENTITIES = [
|
|
18
|
-
"users",
|
|
19
|
-
"forms",
|
|
20
|
-
"form_submissions",
|
|
21
|
-
"dashboard",
|
|
22
|
-
"upload",
|
|
23
|
-
"settings",
|
|
24
|
-
"analytics",
|
|
25
|
-
"chat"
|
|
26
|
-
];
|
|
27
|
-
var ADMIN_GROUP_NAME = "Administrator";
|
|
28
12
|
function isSuperAdminGroupName(name) {
|
|
29
13
|
return name === ADMIN_GROUP_NAME;
|
|
30
14
|
}
|
|
@@ -54,13 +38,315 @@ function hasEntityPermission(record, entity, action) {
|
|
|
54
38
|
if (action === "update") return p.u;
|
|
55
39
|
return p.d;
|
|
56
40
|
}
|
|
41
|
+
var PERMISSION_ENTITY_INTERNAL_EXCLUDE, PERMISSION_LOGICAL_ENTITIES, ADMIN_GROUP_NAME;
|
|
42
|
+
var init_permission_entities = __esm({
|
|
43
|
+
"src/auth/permission-entities.ts"() {
|
|
44
|
+
"use strict";
|
|
45
|
+
PERMISSION_ENTITY_INTERNAL_EXCLUDE = /* @__PURE__ */ new Set([
|
|
46
|
+
"users",
|
|
47
|
+
"password_reset_tokens",
|
|
48
|
+
"user_groups",
|
|
49
|
+
"permissions",
|
|
50
|
+
"comments",
|
|
51
|
+
"form_fields",
|
|
52
|
+
"configs",
|
|
53
|
+
"knowledge_base_chunks",
|
|
54
|
+
"carts",
|
|
55
|
+
"cart_items",
|
|
56
|
+
"wishlists",
|
|
57
|
+
"wishlist_items",
|
|
58
|
+
"message_templates",
|
|
59
|
+
"vendor_users"
|
|
60
|
+
]);
|
|
61
|
+
PERMISSION_LOGICAL_ENTITIES = [
|
|
62
|
+
"users",
|
|
63
|
+
"forms",
|
|
64
|
+
"form_submissions",
|
|
65
|
+
"dashboard",
|
|
66
|
+
"upload",
|
|
67
|
+
"settings",
|
|
68
|
+
"analytics",
|
|
69
|
+
"chat"
|
|
70
|
+
];
|
|
71
|
+
ADMIN_GROUP_NAME = "Administrator";
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// src/auth/vendor-scope.ts
|
|
76
|
+
function isVendorGroupName(name) {
|
|
77
|
+
if (!name?.trim()) return false;
|
|
78
|
+
const n = name.trim().toLowerCase();
|
|
79
|
+
return n === VENDOR_OWNER_GROUP_NAME.toLowerCase() || n.includes("vendor");
|
|
80
|
+
}
|
|
81
|
+
function isPlatformAdministrator(user) {
|
|
82
|
+
if (!user?.email) return false;
|
|
83
|
+
return !!(user.isRBACAdmin || isSuperAdminGroupName(user.groupName));
|
|
84
|
+
}
|
|
85
|
+
function isVendorPortalUser(user) {
|
|
86
|
+
if (user?.isVendorPortal === true) return true;
|
|
87
|
+
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
88
|
+
if ((user.vendorIds?.length ?? 0) > 0) return true;
|
|
89
|
+
return isVendorGroupName(user.groupName);
|
|
90
|
+
}
|
|
91
|
+
function isVendorStaff(user) {
|
|
92
|
+
return isVendorPortalUser(user);
|
|
93
|
+
}
|
|
94
|
+
function isVendorOwner(user) {
|
|
95
|
+
if (user?.isVendorOwner === true) return true;
|
|
96
|
+
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
97
|
+
if (user.vendorRole === "staff") return false;
|
|
98
|
+
if (user.vendorRole === "owner") return true;
|
|
99
|
+
if (!isVendorPortalUser(user)) return false;
|
|
100
|
+
return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();
|
|
101
|
+
}
|
|
102
|
+
function canManageVendorTeam(user) {
|
|
103
|
+
return isPlatformAdministrator(user) || isVendorOwner(user);
|
|
104
|
+
}
|
|
105
|
+
function canManageVendorRoles(user) {
|
|
106
|
+
return isPlatformAdministrator(user) || isVendorOwner(user);
|
|
107
|
+
}
|
|
108
|
+
function canOnboardVendors(user) {
|
|
109
|
+
return isPlatformAdministrator(user);
|
|
110
|
+
}
|
|
111
|
+
function resolveVendorScopeFromSessionUser(user) {
|
|
112
|
+
if (!user?.email) return { type: "deny" };
|
|
113
|
+
if (isPlatformAdministrator(user)) return { type: "all" };
|
|
114
|
+
const vendorIds = user.vendorIds ?? [];
|
|
115
|
+
if (vendorIds.length === 0) return { type: "deny" };
|
|
116
|
+
const preferred = user.activeVendorId ?? vendorIds[0];
|
|
117
|
+
const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0];
|
|
118
|
+
return { type: "vendor", vendorId, vendorIds };
|
|
119
|
+
}
|
|
120
|
+
function vendorPortalFlagsFromUser(input) {
|
|
121
|
+
const vendorIds = input.vendorIds ?? [];
|
|
122
|
+
const isVendorPortal = !input.isRBACAdmin && (vendorIds.length > 0 || isVendorGroupName(input.groupName));
|
|
123
|
+
const isVendorOwner2 = isVendorPortal && input.vendorRole !== "staff" && (input.vendorRole === "owner" || input.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase());
|
|
124
|
+
return { isVendorPortal, isVendorOwner: isVendorOwner2 };
|
|
125
|
+
}
|
|
126
|
+
var VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, VENDOR_OWNER_GROUP_NAME;
|
|
127
|
+
var init_vendor_scope = __esm({
|
|
128
|
+
"src/auth/vendor-scope.ts"() {
|
|
129
|
+
"use strict";
|
|
130
|
+
init_permission_entities();
|
|
131
|
+
VENDOR_SCOPED_STORE_ENTITIES = /* @__PURE__ */ new Set([
|
|
132
|
+
"products",
|
|
133
|
+
"collections",
|
|
134
|
+
"brands",
|
|
135
|
+
"product_categories",
|
|
136
|
+
"orders",
|
|
137
|
+
"payments",
|
|
138
|
+
"taxes",
|
|
139
|
+
"attributes",
|
|
140
|
+
"vendor_customers",
|
|
141
|
+
"discounts"
|
|
142
|
+
]);
|
|
143
|
+
VENDOR_STORE_RBAC_ENTITIES = /* @__PURE__ */ new Set([
|
|
144
|
+
...VENDOR_SCOPED_STORE_ENTITIES,
|
|
145
|
+
"order_discounts",
|
|
146
|
+
"order_addresses"
|
|
147
|
+
]);
|
|
148
|
+
VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// src/auth/rbac-debug-db.ts
|
|
153
|
+
var rbac_debug_db_exports = {};
|
|
154
|
+
__export(rbac_debug_db_exports, {
|
|
155
|
+
loadDbPermissionsForUser: () => loadDbPermissionsForUser
|
|
156
|
+
});
|
|
157
|
+
async function loadDbPermissionsForUser(dataSource, userId) {
|
|
158
|
+
const rows = await dataSource.query(
|
|
159
|
+
`
|
|
160
|
+
SELECT u."groupId" AS "groupId", g.name AS "groupName",
|
|
161
|
+
p.entity, p."canCreate", p."canRead", p."canUpdate", p."canDelete"
|
|
162
|
+
FROM users u
|
|
163
|
+
LEFT JOIN user_groups g ON g.id = u."groupId" AND g.deleted = false
|
|
164
|
+
LEFT JOIN permissions p ON p."groupId" = g.id
|
|
165
|
+
WHERE u.id = $1
|
|
166
|
+
`,
|
|
167
|
+
[userId]
|
|
168
|
+
);
|
|
169
|
+
const groupId = rows[0]?.groupId ?? null;
|
|
170
|
+
const groupName = rows[0]?.groupName ?? null;
|
|
171
|
+
const permRows = rows.filter((r) => r.entity).map((r) => ({
|
|
172
|
+
entity: r.entity,
|
|
173
|
+
canCreate: !!r.canCreate,
|
|
174
|
+
canRead: !!r.canRead,
|
|
175
|
+
canUpdate: !!r.canUpdate,
|
|
176
|
+
canDelete: !!r.canDelete
|
|
177
|
+
}));
|
|
178
|
+
return {
|
|
179
|
+
groupId,
|
|
180
|
+
groupName,
|
|
181
|
+
dbEntityPerms: summarizeEntityPerms(permissionRowsToRecord(permRows))
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
var init_rbac_debug_db = __esm({
|
|
185
|
+
"src/auth/rbac-debug-db.ts"() {
|
|
186
|
+
"use strict";
|
|
187
|
+
init_permission_entities();
|
|
188
|
+
init_rbac_debug();
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// src/auth/rbac-debug.ts
|
|
193
|
+
function isRbacDebugEnabled() {
|
|
194
|
+
const v = process.env.CMS_RBAC_DEBUG?.trim().toLowerCase();
|
|
195
|
+
if (v === "1" || v === "true" || v === "yes") return true;
|
|
196
|
+
if (v === "0" || v === "false" || v === "no") return false;
|
|
197
|
+
return process.env.NODE_ENV === "development";
|
|
198
|
+
}
|
|
199
|
+
function logRbac(message, data) {
|
|
200
|
+
if (!isRbacDebugEnabled()) return;
|
|
201
|
+
if (data) console.info(LOG_PREFIX, message, data);
|
|
202
|
+
else console.info(LOG_PREFIX, message);
|
|
203
|
+
}
|
|
204
|
+
function summarizeEntityPerms(entityPerms) {
|
|
205
|
+
const out = {};
|
|
206
|
+
if (!entityPerms) return out;
|
|
207
|
+
for (const [entity, p] of Object.entries(entityPerms)) {
|
|
208
|
+
out[entity] = { c: p.c, r: p.r, u: p.u, d: p.d };
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
function vendorPortalFallbackReason(user, entity, action) {
|
|
213
|
+
if (!isVendorPortalUser(user)) return null;
|
|
214
|
+
if (entity === "dashboard" && action === "read") return "vendor_portal_dashboard_fallback";
|
|
215
|
+
if (entity === "analytics" && action === "read") return "vendor_portal_analytics_fallback";
|
|
216
|
+
if (entity === "settings" && action === "read") return "vendor_portal_settings_read_fallback";
|
|
217
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity) && action === "read") return "vendor_portal_store_read_fallback";
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
function explainSessionEntityAccess(user, entity, action) {
|
|
221
|
+
const userSnapshot = {
|
|
222
|
+
email: user?.email ?? null,
|
|
223
|
+
id: user?.id ?? null,
|
|
224
|
+
groupId: user?.groupId ?? null,
|
|
225
|
+
groupName: user?.groupName ?? null,
|
|
226
|
+
isRBACAdmin: user?.isRBACAdmin ?? false,
|
|
227
|
+
adminAccess: user?.adminAccess ?? null,
|
|
228
|
+
vendorIds: user?.vendorIds ?? [],
|
|
229
|
+
activeVendorId: user?.activeVendorId ?? null,
|
|
230
|
+
vendorRole: user?.vendorRole ?? null,
|
|
231
|
+
isVendorPortal: user?.isVendorPortal ?? false,
|
|
232
|
+
isVendorOwner: user?.isVendorOwner ?? false,
|
|
233
|
+
isVendorPortalComputed: isVendorPortalUser(user),
|
|
234
|
+
isVendorOwnerComputed: isVendorOwner(user),
|
|
235
|
+
jwtEntityPerms: summarizeEntityPerms(user?.entityPerms),
|
|
236
|
+
jwtEntityPermForTarget: user?.entityPerms?.[entity] ?? null
|
|
237
|
+
};
|
|
238
|
+
if (!user?.email) {
|
|
239
|
+
return { allowed: false, reason: "no_session_email", userSnapshot };
|
|
240
|
+
}
|
|
241
|
+
if (user.isRBACAdmin) {
|
|
242
|
+
return { allowed: true, reason: "platform_administrator", userSnapshot };
|
|
243
|
+
}
|
|
244
|
+
const vendorIds = user.vendorIds ?? [];
|
|
245
|
+
const isStaff = user.vendorRole === "staff";
|
|
246
|
+
if (vendorIds.length > 0) {
|
|
247
|
+
if (entity === "dashboard" && action === "read") {
|
|
248
|
+
return { allowed: true, reason: "vendor_link_dashboard_read", userSnapshot };
|
|
249
|
+
}
|
|
250
|
+
if (entity === "analytics" && action === "read") {
|
|
251
|
+
return { allowed: true, reason: "vendor_link_analytics_read", userSnapshot };
|
|
252
|
+
}
|
|
253
|
+
if (entity === "settings") {
|
|
254
|
+
if (action === "read") {
|
|
255
|
+
return { allowed: true, reason: "vendor_link_settings_read", userSnapshot };
|
|
256
|
+
}
|
|
257
|
+
if (action === "update" && !isStaff) {
|
|
258
|
+
return { allowed: true, reason: "vendor_link_settings_update", userSnapshot };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
262
|
+
if (isStaff && action === "read") {
|
|
263
|
+
return { allowed: true, reason: "vendor_staff_store_read", userSnapshot };
|
|
264
|
+
}
|
|
265
|
+
if (!isStaff) {
|
|
266
|
+
return { allowed: true, reason: "vendor_link_store_full", userSnapshot };
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
allowed: false,
|
|
270
|
+
reason: "vendor_staff_store_write_denied",
|
|
271
|
+
userSnapshot
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (isVendorPortalUser(user) && isVendorOwner(user)) {
|
|
276
|
+
if (entity === "dashboard" && action === "read") {
|
|
277
|
+
return { allowed: true, reason: "vendor_owner_group_dashboard", userSnapshot };
|
|
278
|
+
}
|
|
279
|
+
if (entity === "analytics" && action === "read") {
|
|
280
|
+
return { allowed: true, reason: "vendor_owner_group_analytics", userSnapshot };
|
|
281
|
+
}
|
|
282
|
+
if (entity === "settings" && (action === "read" || action === "update")) {
|
|
283
|
+
return { allowed: true, reason: "vendor_owner_group_settings", userSnapshot };
|
|
284
|
+
}
|
|
285
|
+
if (VENDOR_STORE_RBAC_ENTITIES.has(entity)) {
|
|
286
|
+
return { allowed: true, reason: "vendor_owner_group_store", userSnapshot };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const vendorPortalReason = vendorPortalFallbackReason(user, entity, action);
|
|
290
|
+
if (vendorPortalReason) {
|
|
291
|
+
return { allowed: true, reason: vendorPortalReason, userSnapshot };
|
|
292
|
+
}
|
|
293
|
+
const explicit = user.entityPerms?.[entity];
|
|
294
|
+
if (explicit !== void 0) {
|
|
295
|
+
const allowed2 = hasEntityPermission(user.entityPerms, entity, action);
|
|
296
|
+
return {
|
|
297
|
+
allowed: allowed2,
|
|
298
|
+
reason: allowed2 ? "jwt_entity_perms_allow" : "jwt_entity_perms_deny",
|
|
299
|
+
userSnapshot
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const allowed = hasEntityPermission(user.entityPerms, entity, action);
|
|
303
|
+
return {
|
|
304
|
+
allowed,
|
|
305
|
+
reason: allowed ? "entity_perms_fallback_allow" : "no_matching_rule",
|
|
306
|
+
userSnapshot
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
async function logEntityAccessDecision(dataSource, context, user, entity, action, extra) {
|
|
310
|
+
if (!isRbacDebugEnabled()) return;
|
|
311
|
+
const explanation = explainSessionEntityAccess(user, entity, action);
|
|
312
|
+
let dbPermissions;
|
|
313
|
+
if (dataSource && user?.id) {
|
|
314
|
+
const id = Number(user.id);
|
|
315
|
+
if (Number.isFinite(id)) {
|
|
316
|
+
try {
|
|
317
|
+
const { loadDbPermissionsForUser: loadDbPermissionsForUser2 } = await Promise.resolve().then(() => (init_rbac_debug_db(), rbac_debug_db_exports));
|
|
318
|
+
dbPermissions = await loadDbPermissionsForUser2(dataSource, id);
|
|
319
|
+
} catch (e) {
|
|
320
|
+
dbPermissions = { error: e instanceof Error ? e.message : String(e) };
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
logRbac(context, {
|
|
325
|
+
entity,
|
|
326
|
+
action,
|
|
327
|
+
allowed: explanation.allowed,
|
|
328
|
+
reason: explanation.reason,
|
|
329
|
+
...explanation.userSnapshot,
|
|
330
|
+
dbPermissions,
|
|
331
|
+
...extra
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
var LOG_PREFIX;
|
|
335
|
+
var init_rbac_debug = __esm({
|
|
336
|
+
"src/auth/rbac-debug.ts"() {
|
|
337
|
+
"use strict";
|
|
338
|
+
init_permission_entities();
|
|
339
|
+
init_vendor_scope();
|
|
340
|
+
LOG_PREFIX = "[cms-rbac]";
|
|
341
|
+
}
|
|
342
|
+
});
|
|
57
343
|
|
|
58
344
|
// src/auth/helpers.ts
|
|
345
|
+
init_rbac_debug();
|
|
346
|
+
init_vendor_scope();
|
|
59
347
|
var RBAC_ADMIN_ONLY_ENTITIES = /* @__PURE__ */ new Set(["users", "user_groups", "permissions"]);
|
|
60
348
|
function sessionHasEntityAccess(user, entity, action) {
|
|
61
|
-
|
|
62
|
-
if (user.isRBACAdmin && RBAC_ADMIN_ONLY_ENTITIES.has(entity)) return true;
|
|
63
|
-
return hasEntityPermission(user.entityPerms, entity, action);
|
|
349
|
+
return explainSessionEntityAccess(user, entity, action).allowed;
|
|
64
350
|
}
|
|
65
351
|
function canManageRoles(user) {
|
|
66
352
|
return !!(user?.email && user.isRBACAdmin);
|
|
@@ -85,6 +371,19 @@ function isPublicMethod(pathname, method) {
|
|
|
85
371
|
return false;
|
|
86
372
|
}
|
|
87
373
|
function createAuthHelpers(getSession, NextResponse) {
|
|
374
|
+
return createAuthHelpersFromGetSession(getSession, NextResponse);
|
|
375
|
+
}
|
|
376
|
+
function createCmsAuthBundle(getSession, NextResponse) {
|
|
377
|
+
const auth = createAuthHelpers(getSession, NextResponse);
|
|
378
|
+
return {
|
|
379
|
+
requireAuth: auth.requireAuth,
|
|
380
|
+
requireAdminAccess: auth.requireAdminAccess,
|
|
381
|
+
requireEntityPermission: auth.requireEntityPermission,
|
|
382
|
+
getSessionUser: auth.getAuthenticatedUser,
|
|
383
|
+
getAuthenticatedUser: auth.getAuthenticatedUser
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
function createAuthHelpersFromGetSession(getSession, NextResponse) {
|
|
88
387
|
return {
|
|
89
388
|
async requireAuth() {
|
|
90
389
|
const session = await getSession();
|
|
@@ -106,8 +405,21 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
106
405
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
107
406
|
}
|
|
108
407
|
const u = session.user;
|
|
109
|
-
|
|
110
|
-
|
|
408
|
+
const allowed = sessionHasEntityAccess(u, entity, action);
|
|
409
|
+
const { reason } = explainSessionEntityAccess(u, entity, action);
|
|
410
|
+
logRbac("authHelpers.requireEntityPermission", {
|
|
411
|
+
entity,
|
|
412
|
+
action,
|
|
413
|
+
allowed,
|
|
414
|
+
reason,
|
|
415
|
+
email: u.email,
|
|
416
|
+
groupName: u.groupName,
|
|
417
|
+
vendorIds: u.vendorIds,
|
|
418
|
+
isVendorPortal: u.isVendorPortal,
|
|
419
|
+
isVendorOwner: u.isVendorOwner
|
|
420
|
+
});
|
|
421
|
+
if (allowed) return null;
|
|
422
|
+
return NextResponse.json({ error: "Forbidden", entity, action, reason }, { status: 403 });
|
|
111
423
|
},
|
|
112
424
|
async requireAdminAccess() {
|
|
113
425
|
const session = await getSession();
|
|
@@ -116,8 +428,23 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
116
428
|
}
|
|
117
429
|
const u = session.user;
|
|
118
430
|
if (u.isRBACAdmin) return null;
|
|
119
|
-
if (u
|
|
120
|
-
return null;
|
|
431
|
+
if (isVendorPortalUser(u)) return null;
|
|
432
|
+
if (u.adminAccess === true) return null;
|
|
433
|
+
if (u.adminAccess === false) {
|
|
434
|
+
logRbac("requireAdminAccess denied (adminAccess:false)", {
|
|
435
|
+
email: u.email,
|
|
436
|
+
groupName: u.groupName,
|
|
437
|
+
isVendorPortal: u.isVendorPortal
|
|
438
|
+
});
|
|
439
|
+
return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
|
|
440
|
+
}
|
|
441
|
+
logRbac("requireAdminAccess denied (no matching rule)", {
|
|
442
|
+
email: u.email,
|
|
443
|
+
adminAccess: u.adminAccess,
|
|
444
|
+
groupName: u.groupName,
|
|
445
|
+
isVendorPortal: u.isVendorPortal
|
|
446
|
+
});
|
|
447
|
+
return NextResponse.json({ error: "Forbidden", reason: "admin_access" }, { status: 403 });
|
|
121
448
|
},
|
|
122
449
|
async getAuthenticatedUser() {
|
|
123
450
|
const session = await getSession();
|
|
@@ -126,18 +453,26 @@ function createAuthHelpers(getSession, NextResponse) {
|
|
|
126
453
|
};
|
|
127
454
|
}
|
|
128
455
|
|
|
456
|
+
// src/auth/index.ts
|
|
457
|
+
init_rbac_debug();
|
|
458
|
+
init_vendor_scope();
|
|
459
|
+
init_permission_entities();
|
|
460
|
+
|
|
129
461
|
// src/auth/seed-permissions.ts
|
|
462
|
+
init_permission_entities();
|
|
130
463
|
async function seedAdministratorPermissions(dataSource, entityMap) {
|
|
131
464
|
const entities = getPermissionableEntityKeys(entityMap);
|
|
132
465
|
const groupRepo = dataSource.getRepository(entityMap.user_groups);
|
|
133
466
|
const permRepo = dataSource.getRepository(entityMap.permissions);
|
|
134
467
|
const adminGroup = await groupRepo.findOne({ where: { name: ADMIN_GROUP_NAME, deleted: false } });
|
|
468
|
+
console.log("ADMIN GROUP", adminGroup);
|
|
135
469
|
if (!adminGroup) return;
|
|
136
470
|
const fullCrud = { canCreate: true, canRead: true, canUpdate: true, canDelete: true };
|
|
137
471
|
for (const entity of entities) {
|
|
138
472
|
const existing = await permRepo.findOne({
|
|
139
473
|
where: { groupId: adminGroup.id, entity }
|
|
140
474
|
});
|
|
475
|
+
console.log("EXISTING", existing);
|
|
141
476
|
if (existing) {
|
|
142
477
|
existing.canCreate = true;
|
|
143
478
|
existing.canRead = true;
|
|
@@ -210,21 +545,39 @@ function createCmsMiddleware(config = {}) {
|
|
|
210
545
|
}
|
|
211
546
|
|
|
212
547
|
// src/auth/nextauth-options.ts
|
|
548
|
+
init_permission_entities();
|
|
549
|
+
init_vendor_scope();
|
|
213
550
|
import _CredentialsProvider from "next-auth/providers/credentials";
|
|
214
551
|
var CredentialsProvider = _CredentialsProvider.default ?? _CredentialsProvider;
|
|
215
552
|
function sessionUserFromNextAuthUser(user) {
|
|
216
553
|
const g = user.group;
|
|
217
554
|
const isRBACAdmin = isSuperAdminGroupName(g?.name);
|
|
218
555
|
const entityPerms = permissionRowsToRecord(g?.permissions);
|
|
219
|
-
const
|
|
556
|
+
const rawAdminAccess = user.adminAccess;
|
|
557
|
+
const adminAccess = rawAdminAccess === true ? true : rawAdminAccess === false ? false : void 0;
|
|
558
|
+
const vendorIds = user.vendorIds ?? [];
|
|
559
|
+
const vendorRole = user.vendorRole ?? null;
|
|
560
|
+
const { isVendorPortal, isVendorOwner: isVendorOwner2 } = vendorPortalFlagsFromUser({
|
|
561
|
+
email: user.email,
|
|
562
|
+
isRBACAdmin,
|
|
563
|
+
groupName: g?.name,
|
|
564
|
+
vendorIds,
|
|
565
|
+
vendorRole
|
|
566
|
+
});
|
|
220
567
|
return {
|
|
221
568
|
id: user.id.toString(),
|
|
222
569
|
email: user.email,
|
|
223
570
|
name: user.name,
|
|
224
571
|
groupId: user.groupId ?? void 0,
|
|
572
|
+
groupName: g?.name ?? void 0,
|
|
225
573
|
isRBACAdmin,
|
|
226
574
|
entityPerms,
|
|
227
|
-
adminAccess
|
|
575
|
+
adminAccess,
|
|
576
|
+
vendorIds,
|
|
577
|
+
activeVendorId: user.activeVendorId ?? vendorIds[0] ?? null,
|
|
578
|
+
vendorRole,
|
|
579
|
+
isVendorPortal,
|
|
580
|
+
isVendorOwner: isVendorOwner2
|
|
228
581
|
};
|
|
229
582
|
}
|
|
230
583
|
function getNextAuthOptions(config) {
|
|
@@ -255,7 +608,8 @@ function getNextAuthOptions(config) {
|
|
|
255
608
|
const valid = await comparePassword(credentials.password, user.password);
|
|
256
609
|
if (!valid) return null;
|
|
257
610
|
return sessionUserFromNextAuthUser(user);
|
|
258
|
-
} catch {
|
|
611
|
+
} catch (err) {
|
|
612
|
+
console.error("[cms-auth] authorize error (credentials):", err instanceof Error ? err.message : err);
|
|
259
613
|
return null;
|
|
260
614
|
}
|
|
261
615
|
}
|
|
@@ -281,7 +635,8 @@ function getNextAuthOptions(config) {
|
|
|
281
635
|
const user = await authorizeOtp({ identifier, channel: ch, code });
|
|
282
636
|
if (!user || user.blocked || user.deleted) return null;
|
|
283
637
|
return sessionUserFromNextAuthUser(user);
|
|
284
|
-
} catch {
|
|
638
|
+
} catch (err) {
|
|
639
|
+
console.error("[cms-auth] authorize error (otp):", err instanceof Error ? err.message : err);
|
|
285
640
|
return null;
|
|
286
641
|
}
|
|
287
642
|
}
|
|
@@ -310,15 +665,22 @@ function getNextAuthOptions(config) {
|
|
|
310
665
|
const u = user;
|
|
311
666
|
token.id = u.id;
|
|
312
667
|
token.groupId = u.groupId;
|
|
668
|
+
token.groupName = u.groupName;
|
|
313
669
|
token.isRBACAdmin = u.isRBACAdmin;
|
|
314
670
|
token.entityPerms = u.entityPerms;
|
|
315
671
|
token.adminAccess = u.adminAccess;
|
|
672
|
+
token.vendorIds = u.vendorIds;
|
|
673
|
+
token.activeVendorId = u.activeVendorId;
|
|
674
|
+
token.vendorRole = u.vendorRole;
|
|
675
|
+
token.isVendorPortal = u.isVendorPortal;
|
|
676
|
+
token.isVendorOwner = u.isVendorOwner;
|
|
316
677
|
}
|
|
317
678
|
if (trigger === "update" && session && typeof session === "object") {
|
|
318
679
|
const s = session;
|
|
319
680
|
const t = token;
|
|
320
681
|
if (typeof s.name === "string") t.name = s.name;
|
|
321
682
|
if (typeof s.email === "string") t.email = s.email;
|
|
683
|
+
if (typeof s.activeVendorId === "number") t.activeVendorId = s.activeVendorId;
|
|
322
684
|
}
|
|
323
685
|
return token;
|
|
324
686
|
},
|
|
@@ -329,9 +691,15 @@ function getNextAuthOptions(config) {
|
|
|
329
691
|
if (typeof t.email === "string") session.user.email = t.email;
|
|
330
692
|
session.user.id = t.id;
|
|
331
693
|
session.user.groupId = t.groupId;
|
|
694
|
+
session.user.groupName = t.groupName;
|
|
332
695
|
session.user.isRBACAdmin = t.isRBACAdmin;
|
|
333
696
|
session.user.entityPerms = t.entityPerms;
|
|
334
697
|
session.user.adminAccess = t.adminAccess;
|
|
698
|
+
session.user.vendorIds = t.vendorIds;
|
|
699
|
+
session.user.activeVendorId = t.activeVendorId;
|
|
700
|
+
session.user.vendorRole = t.vendorRole;
|
|
701
|
+
session.user.isVendorPortal = t.isVendorPortal;
|
|
702
|
+
session.user.isVendorOwner = t.isVendorOwner;
|
|
335
703
|
}
|
|
336
704
|
return session;
|
|
337
705
|
}
|
|
@@ -344,19 +712,38 @@ export {
|
|
|
344
712
|
OPEN_ENDPOINTS,
|
|
345
713
|
PERMISSION_REQUIRED_ENDPOINTS,
|
|
346
714
|
RBAC_ADMIN_ONLY_ENTITIES,
|
|
715
|
+
VENDOR_OWNER_GROUP_NAME,
|
|
716
|
+
VENDOR_SCOPED_STORE_ENTITIES,
|
|
717
|
+
VENDOR_STORE_RBAC_ENTITIES,
|
|
347
718
|
canManageRoles,
|
|
719
|
+
canManageVendorRoles,
|
|
720
|
+
canManageVendorTeam,
|
|
721
|
+
canOnboardVendors,
|
|
348
722
|
createAuthHelpers,
|
|
723
|
+
createCmsAuthBundle,
|
|
349
724
|
createCmsMiddleware,
|
|
350
725
|
defaultPublicApiMethods,
|
|
726
|
+
explainSessionEntityAccess,
|
|
351
727
|
getNextAuthOptions,
|
|
352
728
|
getPermissionableEntityKeys,
|
|
353
729
|
getRequiredPermission,
|
|
354
730
|
hasEntityPermission,
|
|
355
731
|
isOpenEndpoint,
|
|
732
|
+
isPlatformAdministrator,
|
|
356
733
|
isPublicMethod,
|
|
734
|
+
isRbacDebugEnabled,
|
|
357
735
|
isSuperAdminGroupName,
|
|
736
|
+
isVendorGroupName,
|
|
737
|
+
isVendorOwner,
|
|
738
|
+
isVendorPortalUser,
|
|
739
|
+
isVendorStaff,
|
|
740
|
+
logEntityAccessDecision,
|
|
741
|
+
logRbac,
|
|
358
742
|
permissionRowsToRecord,
|
|
743
|
+
resolveVendorScopeFromSessionUser,
|
|
359
744
|
seedAdministratorPermissions,
|
|
360
|
-
sessionHasEntityAccess
|
|
745
|
+
sessionHasEntityAccess,
|
|
746
|
+
summarizeEntityPerms,
|
|
747
|
+
vendorPortalFlagsFromUser
|
|
361
748
|
};
|
|
362
749
|
//# sourceMappingURL=auth.js.map
|