@infuro/cms-core 1.0.16 → 1.0.19
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 +739 -724
- package/dist/admin.cjs +1 -1
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.js +1 -1
- package/dist/admin.js.map +1 -1
- package/dist/api.cjs +132 -57
- 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 +132 -57
- package/dist/api.js.map +1 -1
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/cli.cjs +21 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21 -6
- package/dist/cli.js.map +1 -1
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/{index-h42MoUNq.d.cts → index-D2C1O9b4.d.cts} +8 -1
- package/dist/{index-C85X7cc7.d.ts → index-GMn7-9PX.d.ts} +8 -1
- package/dist/index.cjs +139 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +139 -57
- package/dist/index.js.map +1 -1
- package/dist/migrations/1772178563554-InitialSchema.ts +304 -304
- package/dist/migrations/1772178563555-ChatAndKnowledgeBase.ts +55 -55
- package/dist/migrations/1772178563556-KnowledgeBaseVector.ts +16 -16
- package/dist/migrations/1774300000000-RbacSeedGroupsAndPermissionUnique.ts +24 -24
- package/dist/migrations/1774300000001-SeedAdministratorUsersPermission.ts +35 -35
- package/dist/migrations/1774400000000-CustomerAdminAccessContactUser.ts +37 -37
- package/dist/migrations/1774400000001-StorefrontCartWishlist.ts +100 -100
- package/dist/migrations/1774400000002-WishlistGuestId.ts +29 -29
- package/dist/migrations/1774500000000-ProductCollectionHsn.ts +15 -15
- package/dist/migrations/1774600000000-OrderKindParentOrderNumber.ts +36 -36
- package/dist/migrations/1774700000000-CollectionVariants.ts +13 -0
- package/dist/migrations/1774800000000-OtpChallengesUserPhone.ts +41 -41
- package/dist/migrations/1774900000000-MessageTemplates.ts +39 -39
- package/dist/migrations/1775000000000-ProductUomTypeOrderItemSnapshots.ts +29 -29
- package/dist/migrations/1775200000000-MediaDriveFolders.ts +38 -38
- package/dist/migrations/README.md +3 -3
- package/dist/theme.cjs.map +1 -1
- package/dist/theme.js.map +1 -1
- package/package.json +13 -6
- package/src/admin/admin.css +72 -72
package/dist/index.cjs
CHANGED
|
@@ -4544,7 +4544,7 @@ function createFormSubmissionHandler(config) {
|
|
|
4544
4544
|
};
|
|
4545
4545
|
}
|
|
4546
4546
|
function createUsersApiHandlers(config) {
|
|
4547
|
-
const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails } = config;
|
|
4547
|
+
const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails, getSessionUser } = config;
|
|
4548
4548
|
async function trySendInviteEmail(toEmail, inviteLink, inviteeName) {
|
|
4549
4549
|
if (!getCms) return;
|
|
4550
4550
|
try {
|
|
@@ -4580,7 +4580,10 @@ function createUsersApiHandlers(config) {
|
|
|
4580
4580
|
const sortField = url.searchParams.get("sortField") || "createdAt";
|
|
4581
4581
|
const sortOrder = url.searchParams.get("sortOrder") === "desc" ? "DESC" : "ASC";
|
|
4582
4582
|
const search = url.searchParams.get("search");
|
|
4583
|
-
const where = search ? [
|
|
4583
|
+
const where = search ? [
|
|
4584
|
+
{ name: (0, import_typeorm5.ILike)(`%${search}%`), deleted: false },
|
|
4585
|
+
{ email: (0, import_typeorm5.ILike)(`%${search}%`), deleted: false }
|
|
4586
|
+
] : { deleted: false };
|
|
4584
4587
|
const [data, total] = await userRepo().findAndCount({
|
|
4585
4588
|
skip,
|
|
4586
4589
|
take: limit,
|
|
@@ -4645,7 +4648,7 @@ function createUsersApiHandlers(config) {
|
|
|
4645
4648
|
}
|
|
4646
4649
|
try {
|
|
4647
4650
|
const user = await userRepo().findOne({
|
|
4648
|
-
where: { id: parseInt(id, 10) },
|
|
4651
|
+
where: { id: parseInt(id, 10), deleted: false },
|
|
4649
4652
|
relations: ["group"],
|
|
4650
4653
|
select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
|
|
4651
4654
|
});
|
|
@@ -4663,11 +4666,14 @@ function createUsersApiHandlers(config) {
|
|
|
4663
4666
|
if (pe) return pe;
|
|
4664
4667
|
}
|
|
4665
4668
|
try {
|
|
4669
|
+
const uid = parseInt(id, 10);
|
|
4670
|
+
const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
|
|
4671
|
+
if (!existing) return json({ error: "Not found" }, { status: 404 });
|
|
4666
4672
|
const body = await req.json();
|
|
4667
4673
|
const { password: _p, ...safe } = body;
|
|
4668
|
-
await userRepo().update(
|
|
4674
|
+
await userRepo().update(uid, safe);
|
|
4669
4675
|
const updated = await userRepo().findOne({
|
|
4670
|
-
where: { id:
|
|
4676
|
+
where: { id: uid, deleted: false },
|
|
4671
4677
|
relations: ["group"],
|
|
4672
4678
|
select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
|
|
4673
4679
|
});
|
|
@@ -4684,8 +4690,23 @@ function createUsersApiHandlers(config) {
|
|
|
4684
4690
|
if (pe) return pe;
|
|
4685
4691
|
}
|
|
4686
4692
|
try {
|
|
4687
|
-
const
|
|
4688
|
-
|
|
4693
|
+
const uid = parseInt(id, 10);
|
|
4694
|
+
const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
|
|
4695
|
+
if (!existing) return json({ error: "User not found" }, { status: 404 });
|
|
4696
|
+
let deletedBy = null;
|
|
4697
|
+
if (getSessionUser) {
|
|
4698
|
+
try {
|
|
4699
|
+
const u = await getSessionUser();
|
|
4700
|
+
if (u?.id) {
|
|
4701
|
+
const n = Number(u.id);
|
|
4702
|
+
if (Number.isFinite(n)) deletedBy = n;
|
|
4703
|
+
}
|
|
4704
|
+
} catch {
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
const payload = { deleted: true, deletedAt: /* @__PURE__ */ new Date() };
|
|
4708
|
+
if (deletedBy != null) payload.deletedBy = deletedBy;
|
|
4709
|
+
await userRepo().update(uid, payload);
|
|
4689
4710
|
return json({ message: "User deleted successfully" });
|
|
4690
4711
|
} catch {
|
|
4691
4712
|
return json({ error: "Server Error" }, { status: 500 });
|
|
@@ -4699,7 +4720,10 @@ function createUsersApiHandlers(config) {
|
|
|
4699
4720
|
if (pe) return pe;
|
|
4700
4721
|
}
|
|
4701
4722
|
try {
|
|
4702
|
-
const user = await userRepo().findOne({
|
|
4723
|
+
const user = await userRepo().findOne({
|
|
4724
|
+
where: { id: parseInt(id, 10), deleted: false },
|
|
4725
|
+
select: ["email", "name"]
|
|
4726
|
+
});
|
|
4703
4727
|
if (!user) return json({ error: "User not found" }, { status: 404 });
|
|
4704
4728
|
const emailToken = Buffer.from(user.email).toString("base64");
|
|
4705
4729
|
const inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
|
|
@@ -6745,6 +6769,7 @@ var Collection = class {
|
|
|
6745
6769
|
description;
|
|
6746
6770
|
image;
|
|
6747
6771
|
metadata;
|
|
6772
|
+
variants;
|
|
6748
6773
|
active;
|
|
6749
6774
|
sortOrder;
|
|
6750
6775
|
createdAt;
|
|
@@ -6787,6 +6812,9 @@ __decorateClass([
|
|
|
6787
6812
|
__decorateClass([
|
|
6788
6813
|
(0, import_typeorm31.Column)("jsonb", { nullable: true })
|
|
6789
6814
|
], Collection.prototype, "metadata", 2);
|
|
6815
|
+
__decorateClass([
|
|
6816
|
+
(0, import_typeorm31.Column)("jsonb", { nullable: true })
|
|
6817
|
+
], Collection.prototype, "variants", 2);
|
|
6790
6818
|
__decorateClass([
|
|
6791
6819
|
(0, import_typeorm31.Column)("boolean", { default: true })
|
|
6792
6820
|
], Collection.prototype, "active", 2);
|
|
@@ -7945,6 +7973,28 @@ function buildSearchWhereClause(repo, search) {
|
|
|
7945
7973
|
if (ors.length === 0) return {};
|
|
7946
7974
|
return ors.length === 1 ? ors[0] : ors;
|
|
7947
7975
|
}
|
|
7976
|
+
function entityHasSoftDelete(repo) {
|
|
7977
|
+
return repo.metadata.columns.some((c) => c.propertyName === "deleted");
|
|
7978
|
+
}
|
|
7979
|
+
function mergeDeletedFalseWhere(repo, where) {
|
|
7980
|
+
if (!entityHasSoftDelete(repo)) return where;
|
|
7981
|
+
const d = { deleted: false };
|
|
7982
|
+
if (Array.isArray(where)) {
|
|
7983
|
+
if (where.length === 0) return [d];
|
|
7984
|
+
return where.map((w) => ({ ...w, ...d }));
|
|
7985
|
+
}
|
|
7986
|
+
return Object.keys(where).length > 0 ? { ...where, ...d } : d;
|
|
7987
|
+
}
|
|
7988
|
+
function buildSoftDeletePayload(meta, deletedBy) {
|
|
7989
|
+
const payload = { deleted: true };
|
|
7990
|
+
if (meta.columns.some((c) => c.propertyName === "deletedAt")) {
|
|
7991
|
+
payload.deletedAt = /* @__PURE__ */ new Date();
|
|
7992
|
+
}
|
|
7993
|
+
if (deletedBy != null && meta.columns.some((c) => c.propertyName === "deletedBy")) {
|
|
7994
|
+
payload.deletedBy = deletedBy;
|
|
7995
|
+
}
|
|
7996
|
+
return payload;
|
|
7997
|
+
}
|
|
7948
7998
|
function makeContactErpSync(dataSource, entityMap, getCms) {
|
|
7949
7999
|
return async function syncContactRowToErp(row) {
|
|
7950
8000
|
if (!getCms) return;
|
|
@@ -7969,10 +8019,11 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7969
8019
|
async function authz(req, resource, action) {
|
|
7970
8020
|
const authError = await requireAuth(req);
|
|
7971
8021
|
if (authError) return authError;
|
|
7972
|
-
if (reqPerm) {
|
|
7973
|
-
|
|
7974
|
-
if (pe) return pe;
|
|
8022
|
+
if (!reqPerm) {
|
|
8023
|
+
return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
|
|
7975
8024
|
}
|
|
8025
|
+
const pe = await reqPerm(req, resource, action);
|
|
8026
|
+
if (pe) return pe;
|
|
7976
8027
|
return null;
|
|
7977
8028
|
}
|
|
7978
8029
|
return {
|
|
@@ -8008,7 +8059,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8008
8059
|
return json({ total: 0, page, limit, totalPages: 0, data: [] });
|
|
8009
8060
|
}
|
|
8010
8061
|
}
|
|
8011
|
-
const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").orderBy(`order.${sortField2}`, sortOrderOrders).skip(skip).take(limit);
|
|
8062
|
+
const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").andWhere("order.deleted = :orderDel", { orderDel: false }).orderBy(`order.${sortField2}`, sortOrderOrders).skip(skip).take(limit);
|
|
8012
8063
|
if (search && typeof search === "string" && search.trim()) {
|
|
8013
8064
|
const term = `%${search.trim()}%`;
|
|
8014
8065
|
qb.andWhere(
|
|
@@ -8046,7 +8097,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8046
8097
|
const dateTo = searchParams.get("dateTo")?.trim();
|
|
8047
8098
|
const methodFilter = searchParams.get("method")?.trim();
|
|
8048
8099
|
const orderNumberParam = searchParams.get("orderNumber")?.trim();
|
|
8049
|
-
const qb = repo2.createQueryBuilder("payment").leftJoinAndSelect("payment.order", "ord").leftJoinAndSelect("ord.contact", "orderContact").leftJoinAndSelect("payment.contact", "contact").orderBy(`payment.${sortField2}`, sortOrderPayments).skip(skip).take(limit);
|
|
8100
|
+
const qb = repo2.createQueryBuilder("payment").leftJoinAndSelect("payment.order", "ord").leftJoinAndSelect("ord.contact", "orderContact").leftJoinAndSelect("payment.contact", "contact").andWhere("payment.deleted = :payDel", { payDel: false }).orderBy(`payment.${sortField2}`, sortOrderPayments).skip(skip).take(limit);
|
|
8050
8101
|
if (search && typeof search === "string" && search.trim()) {
|
|
8051
8102
|
const term = `%${search.trim()}%`;
|
|
8052
8103
|
qb.andWhere(
|
|
@@ -8077,7 +8128,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8077
8128
|
const repo2 = dataSource.getRepository(entity);
|
|
8078
8129
|
const statusFilter = searchParams.get("status")?.trim();
|
|
8079
8130
|
const inventory = searchParams.get("inventory")?.trim();
|
|
8080
|
-
const productWhere = {};
|
|
8131
|
+
const productWhere = { deleted: false };
|
|
8081
8132
|
if (statusFilter) productWhere.status = statusFilter;
|
|
8082
8133
|
if (inventory === "in_stock") productWhere.quantity = (0, import_typeorm44.MoreThan)(0);
|
|
8083
8134
|
if (inventory === "out_of_stock") productWhere.quantity = 0;
|
|
@@ -8100,7 +8151,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8100
8151
|
const typeFilter2 = searchParams.get("type")?.trim();
|
|
8101
8152
|
const orderIdParam = searchParams.get("orderId")?.trim();
|
|
8102
8153
|
const includeSummary = searchParams.get("includeSummary") === "1";
|
|
8103
|
-
const qb = repo2.createQueryBuilder("contact").orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
|
|
8154
|
+
const qb = repo2.createQueryBuilder("contact").andWhere("contact.deleted = :contactDel", { contactDel: false }).orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
|
|
8104
8155
|
if (search && typeof search === "string" && search.trim()) {
|
|
8105
8156
|
const term = `%${search.trim()}%`;
|
|
8106
8157
|
qb.andWhere("(contact.name ILIKE :term OR contact.email ILIKE :term OR contact.phone ILIKE :term)", { term });
|
|
@@ -8141,9 +8192,9 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8141
8192
|
if (parentIdParam != null && parentIdParam !== "") {
|
|
8142
8193
|
const n = Number(parentIdParam);
|
|
8143
8194
|
if (!Number.isFinite(n)) return json({ error: "Invalid parentId" }, { status: 400 });
|
|
8144
|
-
qb.where("m.parentId = :pid", { pid: n });
|
|
8195
|
+
qb.where("m.deleted = :mediaDel AND m.parentId = :pid", { mediaDel: false, pid: n });
|
|
8145
8196
|
} else {
|
|
8146
|
-
qb.where("m.parentId IS NULL");
|
|
8197
|
+
qb.where("m.deleted = :mediaDel AND m.parentId IS NULL", { mediaDel: false });
|
|
8147
8198
|
}
|
|
8148
8199
|
if (search && typeof search === "string" && search.trim()) {
|
|
8149
8200
|
qb.andWhere("m.filename ILIKE :search", { search: `%${search.trim()}%` });
|
|
@@ -8187,6 +8238,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8187
8238
|
where = extraWhere;
|
|
8188
8239
|
}
|
|
8189
8240
|
}
|
|
8241
|
+
where = mergeDeletedFalseWhere(repo, where);
|
|
8190
8242
|
const [data, total] = await repo.findAndCount({
|
|
8191
8243
|
skip,
|
|
8192
8244
|
take: limit,
|
|
@@ -8354,15 +8406,16 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8354
8406
|
};
|
|
8355
8407
|
}
|
|
8356
8408
|
function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
8357
|
-
const { requireAuth, json, requireEntityPermission: reqPerm, getCms } = options;
|
|
8409
|
+
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId } = options;
|
|
8358
8410
|
const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
|
|
8359
8411
|
async function authz(req, resource, action) {
|
|
8360
8412
|
const authError = await requireAuth(req);
|
|
8361
8413
|
if (authError) return authError;
|
|
8362
|
-
if (reqPerm) {
|
|
8363
|
-
|
|
8364
|
-
if (pe) return pe;
|
|
8414
|
+
if (!reqPerm) {
|
|
8415
|
+
return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
|
|
8365
8416
|
}
|
|
8417
|
+
const pe = await reqPerm(req, resource, action);
|
|
8418
|
+
if (pe) return pe;
|
|
8366
8419
|
return null;
|
|
8367
8420
|
}
|
|
8368
8421
|
return {
|
|
@@ -8374,7 +8427,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8374
8427
|
const repo = dataSource.getRepository(entity);
|
|
8375
8428
|
if (resource === "orders") {
|
|
8376
8429
|
const order = await repo.findOne({
|
|
8377
|
-
where: { id: Number(id) },
|
|
8430
|
+
where: { id: Number(id), deleted: false },
|
|
8378
8431
|
relations: ["contact", "billingAddress", "shippingAddress", "items", "items.product", "items.product.collection", "payments"]
|
|
8379
8432
|
});
|
|
8380
8433
|
if (!order) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8386,7 +8439,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8386
8439
|
}
|
|
8387
8440
|
if (resource === "contacts") {
|
|
8388
8441
|
const contact = await repo.findOne({
|
|
8389
|
-
where: { id: Number(id) },
|
|
8442
|
+
where: { id: Number(id), deleted: false },
|
|
8390
8443
|
relations: ["form_submissions", "form_submissions.form", "orders", "payments", "addresses"]
|
|
8391
8444
|
});
|
|
8392
8445
|
if (!contact) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8408,7 +8461,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8408
8461
|
}
|
|
8409
8462
|
if (resource === "payments") {
|
|
8410
8463
|
const payment = await repo.findOne({
|
|
8411
|
-
where: { id: Number(id) },
|
|
8464
|
+
where: { id: Number(id), deleted: false },
|
|
8412
8465
|
relations: ["order", "order.contact", "contact"]
|
|
8413
8466
|
});
|
|
8414
8467
|
if (!payment) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8416,12 +8469,13 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8416
8469
|
}
|
|
8417
8470
|
if (resource === "blogs") {
|
|
8418
8471
|
const blog = await repo.findOne({
|
|
8419
|
-
where: { id: Number(id) },
|
|
8472
|
+
where: { id: Number(id), deleted: false },
|
|
8420
8473
|
relations: ["category", "seo", "tags"]
|
|
8421
8474
|
});
|
|
8422
8475
|
return blog ? json(blog) : json({ message: "Not found" }, { status: 404 });
|
|
8423
8476
|
}
|
|
8424
|
-
const
|
|
8477
|
+
const idWhere = entityHasSoftDelete(repo) ? { id: Number(id), deleted: false } : { id: Number(id) };
|
|
8478
|
+
const item = await repo.findOne({ where: idWhere });
|
|
8425
8479
|
return item ? json(item) : json({ message: "Not found" }, { status: 404 });
|
|
8426
8480
|
},
|
|
8427
8481
|
async PUT(req, resource, id) {
|
|
@@ -8433,7 +8487,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8433
8487
|
const repo = dataSource.getRepository(entity);
|
|
8434
8488
|
const numericId = Number(id);
|
|
8435
8489
|
if (resource === "blogs" && rawBody && typeof rawBody === "object" && entityMap.categories && entityMap.seos && entityMap.tags) {
|
|
8436
|
-
const existing = await repo.findOne({
|
|
8490
|
+
const existing = await repo.findOne({
|
|
8491
|
+
where: { id: numericId, deleted: false }
|
|
8492
|
+
});
|
|
8437
8493
|
if (!existing) return json({ message: "Not found" }, { status: 404 });
|
|
8438
8494
|
const updatePayload2 = pickColumnUpdates(repo, rawBody);
|
|
8439
8495
|
if ("category" in rawBody) {
|
|
@@ -8509,6 +8565,12 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8509
8565
|
});
|
|
8510
8566
|
return updated2 ? json(updated2) : json({ message: "Not found" }, { status: 404 });
|
|
8511
8567
|
}
|
|
8568
|
+
if (entityHasSoftDelete(repo)) {
|
|
8569
|
+
const cur = await repo.findOne({
|
|
8570
|
+
where: { id: numericId, deleted: false }
|
|
8571
|
+
});
|
|
8572
|
+
if (!cur) return json({ message: "Not found" }, { status: 404 });
|
|
8573
|
+
}
|
|
8512
8574
|
const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
|
|
8513
8575
|
if (resource === "media") {
|
|
8514
8576
|
const u = updatePayload;
|
|
@@ -8535,7 +8597,24 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8535
8597
|
const entity = entityMap[resource];
|
|
8536
8598
|
if (!entity) return json({ error: "Invalid resource" }, { status: 400 });
|
|
8537
8599
|
const repo = dataSource.getRepository(entity);
|
|
8538
|
-
const
|
|
8600
|
+
const numericId = Number(id);
|
|
8601
|
+
if (entityHasSoftDelete(repo)) {
|
|
8602
|
+
const existing = await repo.findOne({
|
|
8603
|
+
where: { id: numericId, deleted: false }
|
|
8604
|
+
});
|
|
8605
|
+
if (!existing) return json({ message: "Not found" }, { status: 404 });
|
|
8606
|
+
let deletedBy = null;
|
|
8607
|
+
if (getDeletedByUserId) {
|
|
8608
|
+
try {
|
|
8609
|
+
deletedBy = await getDeletedByUserId(req);
|
|
8610
|
+
} catch {
|
|
8611
|
+
deletedBy = null;
|
|
8612
|
+
}
|
|
8613
|
+
}
|
|
8614
|
+
await repo.update(numericId, buildSoftDeletePayload(repo.metadata, deletedBy));
|
|
8615
|
+
return json({ message: "Deleted successfully" }, { status: 200 });
|
|
8616
|
+
}
|
|
8617
|
+
const result = await repo.delete(numericId);
|
|
8539
8618
|
if (result.affected === 0) return json({ message: "Not found" }, { status: 404 });
|
|
8540
8619
|
return json({ message: "Deleted successfully" }, { status: 200 });
|
|
8541
8620
|
}
|
|
@@ -8963,9 +9042,10 @@ function createCmsApiHandler(config) {
|
|
|
8963
9042
|
userProfile,
|
|
8964
9043
|
settings: settingsConfig,
|
|
8965
9044
|
chat: chatConfig,
|
|
8966
|
-
requireEntityPermission:
|
|
9045
|
+
requireEntityPermission: userRequireEntityPermission,
|
|
8967
9046
|
getSessionUser
|
|
8968
9047
|
} = config;
|
|
9048
|
+
const requireEntityPermissionEffective = userRequireEntityPermission ?? (async (_req, entity, action) => config.json({ error: "Forbidden", reason: "entity_rbac_required", entity, action }, { status: 403 }));
|
|
8969
9049
|
const analytics = analyticsConfig ?? (getCms ? {
|
|
8970
9050
|
json: config.json,
|
|
8971
9051
|
requireAuth: async () => null,
|
|
@@ -9003,12 +9083,20 @@ function createCmsApiHandler(config) {
|
|
|
9003
9083
|
const crudOpts = {
|
|
9004
9084
|
requireAuth: config.requireAuth,
|
|
9005
9085
|
json: config.json,
|
|
9006
|
-
requireEntityPermission:
|
|
9007
|
-
getCms
|
|
9086
|
+
requireEntityPermission: requireEntityPermissionEffective,
|
|
9087
|
+
getCms,
|
|
9088
|
+
...getSessionUser ? {
|
|
9089
|
+
getDeletedByUserId: async () => {
|
|
9090
|
+
const u = await getSessionUser();
|
|
9091
|
+
if (!u?.id) return null;
|
|
9092
|
+
const n = Number(u.id);
|
|
9093
|
+
return Number.isFinite(n) ? n : null;
|
|
9094
|
+
}
|
|
9095
|
+
} : {}
|
|
9008
9096
|
};
|
|
9009
9097
|
const crud = createCrudHandler(dataSource, entityMap, crudOpts);
|
|
9010
9098
|
const crudById = createCrudByIdHandler(dataSource, entityMap, crudOpts);
|
|
9011
|
-
const mergePerm = (c) => !c ? void 0 :
|
|
9099
|
+
const mergePerm = (c) => !c ? void 0 : { ...c, requireEntityPermission: requireEntityPermissionEffective };
|
|
9012
9100
|
const adminRoles = getSessionUser && createAdminRolesHandlers({
|
|
9013
9101
|
dataSource,
|
|
9014
9102
|
entityMap,
|
|
@@ -9024,12 +9112,7 @@ function createCmsApiHandler(config) {
|
|
|
9024
9112
|
json: config.json,
|
|
9025
9113
|
requireAuth: config.requireAuth
|
|
9026
9114
|
}
|
|
9027
|
-
)
|
|
9028
|
-
dataSource,
|
|
9029
|
-
entityMap,
|
|
9030
|
-
json: config.json,
|
|
9031
|
-
requireAuth: config.requireAuth
|
|
9032
|
-
};
|
|
9115
|
+
);
|
|
9033
9116
|
const ecommerceAnalyticsGet = createEcommerceAnalyticsHandler(ecommerceAnalyticsResolved);
|
|
9034
9117
|
const analyticsHandlers = analytics ? createAnalyticsHandlers(analytics) : null;
|
|
9035
9118
|
const uploadMerged = upload ? {
|
|
@@ -9048,7 +9131,11 @@ function createCmsApiHandler(config) {
|
|
|
9048
9131
|
const usersApiMerged = usersApi && getCms ? {
|
|
9049
9132
|
...usersApi,
|
|
9050
9133
|
getCms: usersApi.getCms ?? getCms,
|
|
9051
|
-
getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails
|
|
9134
|
+
getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails,
|
|
9135
|
+
...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
|
|
9136
|
+
} : usersApi ? {
|
|
9137
|
+
...usersApi,
|
|
9138
|
+
...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
|
|
9052
9139
|
} : usersApi;
|
|
9053
9140
|
const usersHandlers = usersApiMerged ? createUsersApiHandlers(mergePerm(usersApiMerged) ?? usersApiMerged) : null;
|
|
9054
9141
|
const avatarPost = userAvatar ? createUserAvatarHandler(userAvatar) : null;
|
|
@@ -9059,7 +9146,7 @@ function createCmsApiHandler(config) {
|
|
|
9059
9146
|
entityMap,
|
|
9060
9147
|
json: config.json,
|
|
9061
9148
|
requireAuth: config.requireAuth,
|
|
9062
|
-
requireEntityPermission:
|
|
9149
|
+
requireEntityPermission: requireEntityPermissionEffective
|
|
9063
9150
|
});
|
|
9064
9151
|
const chatHandlers = chatConfig ? createChatHandlers(chatConfig) : null;
|
|
9065
9152
|
function resolveResource(segment) {
|
|
@@ -9068,12 +9155,10 @@ function createCmsApiHandler(config) {
|
|
|
9068
9155
|
}
|
|
9069
9156
|
return {
|
|
9070
9157
|
async handle(method, path, req) {
|
|
9071
|
-
const perm = reqEntityPerm;
|
|
9072
9158
|
async function analyticsGate() {
|
|
9073
9159
|
const a = await config.requireAuth(req);
|
|
9074
9160
|
if (a) return a;
|
|
9075
|
-
|
|
9076
|
-
return null;
|
|
9161
|
+
return requireEntityPermissionEffective(req, "analytics", "read");
|
|
9077
9162
|
}
|
|
9078
9163
|
if (path[0] === "admin" && path[1] === "roles") {
|
|
9079
9164
|
if (!adminRoles) return config.json({ error: "Not found" }, { status: 404 });
|
|
@@ -9157,19 +9242,17 @@ function createCmsApiHandler(config) {
|
|
|
9157
9242
|
const group = path[1];
|
|
9158
9243
|
const isPublic = settingsConfig?.publicGetGroups?.includes(group);
|
|
9159
9244
|
if (method === "GET") {
|
|
9160
|
-
if (!isPublic
|
|
9245
|
+
if (!isPublic) {
|
|
9161
9246
|
const a = await config.requireAuth(req);
|
|
9162
9247
|
if (a) return a;
|
|
9163
|
-
const pe = await
|
|
9248
|
+
const pe = await requireEntityPermissionEffective(req, "settings", "read");
|
|
9164
9249
|
if (pe) return pe;
|
|
9165
9250
|
}
|
|
9166
9251
|
return settingsHandlers.GET(req, group);
|
|
9167
9252
|
}
|
|
9168
9253
|
if (method === "PUT") {
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
if (pe) return pe;
|
|
9172
|
-
}
|
|
9254
|
+
const pe = await requireEntityPermissionEffective(req, "settings", "update");
|
|
9255
|
+
if (pe) return pe;
|
|
9173
9256
|
return settingsHandlers.PUT(req, group);
|
|
9174
9257
|
}
|
|
9175
9258
|
}
|
|
@@ -9185,10 +9268,8 @@ function createCmsApiHandler(config) {
|
|
|
9185
9268
|
if (path[0] === "orders" && path.length === 3 && path[2] === "invoice" && method === "GET" && getCms) {
|
|
9186
9269
|
const a = await config.requireAuth(req);
|
|
9187
9270
|
if (a) return a;
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
if (pe) return pe;
|
|
9191
|
-
}
|
|
9271
|
+
const pe = await requireEntityPermissionEffective(req, "orders", "read");
|
|
9272
|
+
if (pe) return pe;
|
|
9192
9273
|
const cms = await getCms();
|
|
9193
9274
|
const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await Promise.resolve().then(() => (init_erp_order_invoice(), erp_order_invoice_exports));
|
|
9194
9275
|
const oid = Number(path[1]);
|
|
@@ -9198,10 +9279,8 @@ function createCmsApiHandler(config) {
|
|
|
9198
9279
|
if (path[0] === "orders" && path.length === 3 && path[2] === "repost-erp" && getCms) {
|
|
9199
9280
|
const a = await config.requireAuth(req);
|
|
9200
9281
|
if (a) return a;
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
if (pe) return pe;
|
|
9204
|
-
}
|
|
9282
|
+
const pe = await requireEntityPermissionEffective(req, "orders", method === "GET" ? "read" : "update");
|
|
9283
|
+
if (pe) return pe;
|
|
9205
9284
|
const oid = Number(path[1]);
|
|
9206
9285
|
if (!Number.isFinite(oid)) return config.json({ error: "Invalid id" }, { status: 400 });
|
|
9207
9286
|
const cms = await getCms();
|
|
@@ -10658,6 +10737,9 @@ var DEFAULT_ADMIN_NAV = [
|
|
|
10658
10737
|
{ href: "/admin/submissions", label: "Submissions" },
|
|
10659
10738
|
{ href: "/admin/pages", label: "Pages" }
|
|
10660
10739
|
];
|
|
10740
|
+
|
|
10741
|
+
// src/index.ts
|
|
10742
|
+
console.log("\u{1F525} USING LOCAL CMS CORE (index.ts loaded) \u{1F525}");
|
|
10661
10743
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10662
10744
|
0 && (module.exports = {
|
|
10663
10745
|
ADMIN_GROUP_NAME,
|