@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.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-
|
|
2
|
-
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-
|
|
1
|
+
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-D2C1O9b4.cjs';
|
|
2
|
+
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-D2C1O9b4.cjs';
|
|
3
3
|
import { ClassValue } from 'clsx';
|
|
4
4
|
import * as typeorm from 'typeorm';
|
|
5
5
|
import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
|
|
@@ -1048,6 +1048,7 @@ declare class Collection {
|
|
|
1048
1048
|
description: string | null;
|
|
1049
1049
|
image: string | null;
|
|
1050
1050
|
metadata: Record<string, unknown> | null;
|
|
1051
|
+
variants: Array<Record<string, unknown>> | null;
|
|
1051
1052
|
active: boolean;
|
|
1052
1053
|
sortOrder: number;
|
|
1053
1054
|
createdAt: Date;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-
|
|
2
|
-
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-
|
|
1
|
+
import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-GMn7-9PX.js';
|
|
2
|
+
export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-GMn7-9PX.js';
|
|
3
3
|
import { ClassValue } from 'clsx';
|
|
4
4
|
import * as typeorm from 'typeorm';
|
|
5
5
|
import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
|
|
@@ -1048,6 +1048,7 @@ declare class Collection {
|
|
|
1048
1048
|
description: string | null;
|
|
1049
1049
|
image: string | null;
|
|
1050
1050
|
metadata: Record<string, unknown> | null;
|
|
1051
|
+
variants: Array<Record<string, unknown>> | null;
|
|
1051
1052
|
active: boolean;
|
|
1052
1053
|
sortOrder: number;
|
|
1053
1054
|
createdAt: Date;
|
package/dist/index.js
CHANGED
|
@@ -4371,7 +4371,7 @@ function createFormSubmissionHandler(config) {
|
|
|
4371
4371
|
};
|
|
4372
4372
|
}
|
|
4373
4373
|
function createUsersApiHandlers(config) {
|
|
4374
|
-
const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails } = config;
|
|
4374
|
+
const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails, getSessionUser } = config;
|
|
4375
4375
|
async function trySendInviteEmail(toEmail, inviteLink, inviteeName) {
|
|
4376
4376
|
if (!getCms) return;
|
|
4377
4377
|
try {
|
|
@@ -4407,7 +4407,10 @@ function createUsersApiHandlers(config) {
|
|
|
4407
4407
|
const sortField = url.searchParams.get("sortField") || "createdAt";
|
|
4408
4408
|
const sortOrder = url.searchParams.get("sortOrder") === "desc" ? "DESC" : "ASC";
|
|
4409
4409
|
const search = url.searchParams.get("search");
|
|
4410
|
-
const where = search ? [
|
|
4410
|
+
const where = search ? [
|
|
4411
|
+
{ name: ILike(`%${search}%`), deleted: false },
|
|
4412
|
+
{ email: ILike(`%${search}%`), deleted: false }
|
|
4413
|
+
] : { deleted: false };
|
|
4411
4414
|
const [data, total] = await userRepo().findAndCount({
|
|
4412
4415
|
skip,
|
|
4413
4416
|
take: limit,
|
|
@@ -4472,7 +4475,7 @@ function createUsersApiHandlers(config) {
|
|
|
4472
4475
|
}
|
|
4473
4476
|
try {
|
|
4474
4477
|
const user = await userRepo().findOne({
|
|
4475
|
-
where: { id: parseInt(id, 10) },
|
|
4478
|
+
where: { id: parseInt(id, 10), deleted: false },
|
|
4476
4479
|
relations: ["group"],
|
|
4477
4480
|
select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
|
|
4478
4481
|
});
|
|
@@ -4490,11 +4493,14 @@ function createUsersApiHandlers(config) {
|
|
|
4490
4493
|
if (pe) return pe;
|
|
4491
4494
|
}
|
|
4492
4495
|
try {
|
|
4496
|
+
const uid = parseInt(id, 10);
|
|
4497
|
+
const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
|
|
4498
|
+
if (!existing) return json({ error: "Not found" }, { status: 404 });
|
|
4493
4499
|
const body = await req.json();
|
|
4494
4500
|
const { password: _p, ...safe } = body;
|
|
4495
|
-
await userRepo().update(
|
|
4501
|
+
await userRepo().update(uid, safe);
|
|
4496
4502
|
const updated = await userRepo().findOne({
|
|
4497
|
-
where: { id:
|
|
4503
|
+
where: { id: uid, deleted: false },
|
|
4498
4504
|
relations: ["group"],
|
|
4499
4505
|
select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
|
|
4500
4506
|
});
|
|
@@ -4511,8 +4517,23 @@ function createUsersApiHandlers(config) {
|
|
|
4511
4517
|
if (pe) return pe;
|
|
4512
4518
|
}
|
|
4513
4519
|
try {
|
|
4514
|
-
const
|
|
4515
|
-
|
|
4520
|
+
const uid = parseInt(id, 10);
|
|
4521
|
+
const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
|
|
4522
|
+
if (!existing) return json({ error: "User not found" }, { status: 404 });
|
|
4523
|
+
let deletedBy = null;
|
|
4524
|
+
if (getSessionUser) {
|
|
4525
|
+
try {
|
|
4526
|
+
const u = await getSessionUser();
|
|
4527
|
+
if (u?.id) {
|
|
4528
|
+
const n = Number(u.id);
|
|
4529
|
+
if (Number.isFinite(n)) deletedBy = n;
|
|
4530
|
+
}
|
|
4531
|
+
} catch {
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
const payload = { deleted: true, deletedAt: /* @__PURE__ */ new Date() };
|
|
4535
|
+
if (deletedBy != null) payload.deletedBy = deletedBy;
|
|
4536
|
+
await userRepo().update(uid, payload);
|
|
4516
4537
|
return json({ message: "User deleted successfully" });
|
|
4517
4538
|
} catch {
|
|
4518
4539
|
return json({ error: "Server Error" }, { status: 500 });
|
|
@@ -4526,7 +4547,10 @@ function createUsersApiHandlers(config) {
|
|
|
4526
4547
|
if (pe) return pe;
|
|
4527
4548
|
}
|
|
4528
4549
|
try {
|
|
4529
|
-
const user = await userRepo().findOne({
|
|
4550
|
+
const user = await userRepo().findOne({
|
|
4551
|
+
where: { id: parseInt(id, 10), deleted: false },
|
|
4552
|
+
select: ["email", "name"]
|
|
4553
|
+
});
|
|
4530
4554
|
if (!user) return json({ error: "User not found" }, { status: 404 });
|
|
4531
4555
|
const emailToken = Buffer.from(user.email).toString("base64");
|
|
4532
4556
|
const inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
|
|
@@ -6581,6 +6605,7 @@ var Collection = class {
|
|
|
6581
6605
|
description;
|
|
6582
6606
|
image;
|
|
6583
6607
|
metadata;
|
|
6608
|
+
variants;
|
|
6584
6609
|
active;
|
|
6585
6610
|
sortOrder;
|
|
6586
6611
|
createdAt;
|
|
@@ -6623,6 +6648,9 @@ __decorateClass([
|
|
|
6623
6648
|
__decorateClass([
|
|
6624
6649
|
Column26("jsonb", { nullable: true })
|
|
6625
6650
|
], Collection.prototype, "metadata", 2);
|
|
6651
|
+
__decorateClass([
|
|
6652
|
+
Column26("jsonb", { nullable: true })
|
|
6653
|
+
], Collection.prototype, "variants", 2);
|
|
6626
6654
|
__decorateClass([
|
|
6627
6655
|
Column26("boolean", { default: true })
|
|
6628
6656
|
], Collection.prototype, "active", 2);
|
|
@@ -7781,6 +7809,28 @@ function buildSearchWhereClause(repo, search) {
|
|
|
7781
7809
|
if (ors.length === 0) return {};
|
|
7782
7810
|
return ors.length === 1 ? ors[0] : ors;
|
|
7783
7811
|
}
|
|
7812
|
+
function entityHasSoftDelete(repo) {
|
|
7813
|
+
return repo.metadata.columns.some((c) => c.propertyName === "deleted");
|
|
7814
|
+
}
|
|
7815
|
+
function mergeDeletedFalseWhere(repo, where) {
|
|
7816
|
+
if (!entityHasSoftDelete(repo)) return where;
|
|
7817
|
+
const d = { deleted: false };
|
|
7818
|
+
if (Array.isArray(where)) {
|
|
7819
|
+
if (where.length === 0) return [d];
|
|
7820
|
+
return where.map((w) => ({ ...w, ...d }));
|
|
7821
|
+
}
|
|
7822
|
+
return Object.keys(where).length > 0 ? { ...where, ...d } : d;
|
|
7823
|
+
}
|
|
7824
|
+
function buildSoftDeletePayload(meta, deletedBy) {
|
|
7825
|
+
const payload = { deleted: true };
|
|
7826
|
+
if (meta.columns.some((c) => c.propertyName === "deletedAt")) {
|
|
7827
|
+
payload.deletedAt = /* @__PURE__ */ new Date();
|
|
7828
|
+
}
|
|
7829
|
+
if (deletedBy != null && meta.columns.some((c) => c.propertyName === "deletedBy")) {
|
|
7830
|
+
payload.deletedBy = deletedBy;
|
|
7831
|
+
}
|
|
7832
|
+
return payload;
|
|
7833
|
+
}
|
|
7784
7834
|
function makeContactErpSync(dataSource, entityMap, getCms) {
|
|
7785
7835
|
return async function syncContactRowToErp(row) {
|
|
7786
7836
|
if (!getCms) return;
|
|
@@ -7805,10 +7855,11 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7805
7855
|
async function authz(req, resource, action) {
|
|
7806
7856
|
const authError = await requireAuth(req);
|
|
7807
7857
|
if (authError) return authError;
|
|
7808
|
-
if (reqPerm) {
|
|
7809
|
-
|
|
7810
|
-
if (pe) return pe;
|
|
7858
|
+
if (!reqPerm) {
|
|
7859
|
+
return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
|
|
7811
7860
|
}
|
|
7861
|
+
const pe = await reqPerm(req, resource, action);
|
|
7862
|
+
if (pe) return pe;
|
|
7812
7863
|
return null;
|
|
7813
7864
|
}
|
|
7814
7865
|
return {
|
|
@@ -7844,7 +7895,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7844
7895
|
return json({ total: 0, page, limit, totalPages: 0, data: [] });
|
|
7845
7896
|
}
|
|
7846
7897
|
}
|
|
7847
|
-
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);
|
|
7898
|
+
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);
|
|
7848
7899
|
if (search && typeof search === "string" && search.trim()) {
|
|
7849
7900
|
const term = `%${search.trim()}%`;
|
|
7850
7901
|
qb.andWhere(
|
|
@@ -7882,7 +7933,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7882
7933
|
const dateTo = searchParams.get("dateTo")?.trim();
|
|
7883
7934
|
const methodFilter = searchParams.get("method")?.trim();
|
|
7884
7935
|
const orderNumberParam = searchParams.get("orderNumber")?.trim();
|
|
7885
|
-
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);
|
|
7936
|
+
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);
|
|
7886
7937
|
if (search && typeof search === "string" && search.trim()) {
|
|
7887
7938
|
const term = `%${search.trim()}%`;
|
|
7888
7939
|
qb.andWhere(
|
|
@@ -7913,7 +7964,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7913
7964
|
const repo2 = dataSource.getRepository(entity);
|
|
7914
7965
|
const statusFilter = searchParams.get("status")?.trim();
|
|
7915
7966
|
const inventory = searchParams.get("inventory")?.trim();
|
|
7916
|
-
const productWhere = {};
|
|
7967
|
+
const productWhere = { deleted: false };
|
|
7917
7968
|
if (statusFilter) productWhere.status = statusFilter;
|
|
7918
7969
|
if (inventory === "in_stock") productWhere.quantity = MoreThan2(0);
|
|
7919
7970
|
if (inventory === "out_of_stock") productWhere.quantity = 0;
|
|
@@ -7936,7 +7987,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7936
7987
|
const typeFilter2 = searchParams.get("type")?.trim();
|
|
7937
7988
|
const orderIdParam = searchParams.get("orderId")?.trim();
|
|
7938
7989
|
const includeSummary = searchParams.get("includeSummary") === "1";
|
|
7939
|
-
const qb = repo2.createQueryBuilder("contact").orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
|
|
7990
|
+
const qb = repo2.createQueryBuilder("contact").andWhere("contact.deleted = :contactDel", { contactDel: false }).orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
|
|
7940
7991
|
if (search && typeof search === "string" && search.trim()) {
|
|
7941
7992
|
const term = `%${search.trim()}%`;
|
|
7942
7993
|
qb.andWhere("(contact.name ILIKE :term OR contact.email ILIKE :term OR contact.phone ILIKE :term)", { term });
|
|
@@ -7977,9 +8028,9 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
7977
8028
|
if (parentIdParam != null && parentIdParam !== "") {
|
|
7978
8029
|
const n = Number(parentIdParam);
|
|
7979
8030
|
if (!Number.isFinite(n)) return json({ error: "Invalid parentId" }, { status: 400 });
|
|
7980
|
-
qb.where("m.parentId = :pid", { pid: n });
|
|
8031
|
+
qb.where("m.deleted = :mediaDel AND m.parentId = :pid", { mediaDel: false, pid: n });
|
|
7981
8032
|
} else {
|
|
7982
|
-
qb.where("m.parentId IS NULL");
|
|
8033
|
+
qb.where("m.deleted = :mediaDel AND m.parentId IS NULL", { mediaDel: false });
|
|
7983
8034
|
}
|
|
7984
8035
|
if (search && typeof search === "string" && search.trim()) {
|
|
7985
8036
|
qb.andWhere("m.filename ILIKE :search", { search: `%${search.trim()}%` });
|
|
@@ -8023,6 +8074,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8023
8074
|
where = extraWhere;
|
|
8024
8075
|
}
|
|
8025
8076
|
}
|
|
8077
|
+
where = mergeDeletedFalseWhere(repo, where);
|
|
8026
8078
|
const [data, total] = await repo.findAndCount({
|
|
8027
8079
|
skip,
|
|
8028
8080
|
take: limit,
|
|
@@ -8190,15 +8242,16 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
8190
8242
|
};
|
|
8191
8243
|
}
|
|
8192
8244
|
function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
8193
|
-
const { requireAuth, json, requireEntityPermission: reqPerm, getCms } = options;
|
|
8245
|
+
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId } = options;
|
|
8194
8246
|
const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
|
|
8195
8247
|
async function authz(req, resource, action) {
|
|
8196
8248
|
const authError = await requireAuth(req);
|
|
8197
8249
|
if (authError) return authError;
|
|
8198
|
-
if (reqPerm) {
|
|
8199
|
-
|
|
8200
|
-
if (pe) return pe;
|
|
8250
|
+
if (!reqPerm) {
|
|
8251
|
+
return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
|
|
8201
8252
|
}
|
|
8253
|
+
const pe = await reqPerm(req, resource, action);
|
|
8254
|
+
if (pe) return pe;
|
|
8202
8255
|
return null;
|
|
8203
8256
|
}
|
|
8204
8257
|
return {
|
|
@@ -8210,7 +8263,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8210
8263
|
const repo = dataSource.getRepository(entity);
|
|
8211
8264
|
if (resource === "orders") {
|
|
8212
8265
|
const order = await repo.findOne({
|
|
8213
|
-
where: { id: Number(id) },
|
|
8266
|
+
where: { id: Number(id), deleted: false },
|
|
8214
8267
|
relations: ["contact", "billingAddress", "shippingAddress", "items", "items.product", "items.product.collection", "payments"]
|
|
8215
8268
|
});
|
|
8216
8269
|
if (!order) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8222,7 +8275,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8222
8275
|
}
|
|
8223
8276
|
if (resource === "contacts") {
|
|
8224
8277
|
const contact = await repo.findOne({
|
|
8225
|
-
where: { id: Number(id) },
|
|
8278
|
+
where: { id: Number(id), deleted: false },
|
|
8226
8279
|
relations: ["form_submissions", "form_submissions.form", "orders", "payments", "addresses"]
|
|
8227
8280
|
});
|
|
8228
8281
|
if (!contact) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8244,7 +8297,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8244
8297
|
}
|
|
8245
8298
|
if (resource === "payments") {
|
|
8246
8299
|
const payment = await repo.findOne({
|
|
8247
|
-
where: { id: Number(id) },
|
|
8300
|
+
where: { id: Number(id), deleted: false },
|
|
8248
8301
|
relations: ["order", "order.contact", "contact"]
|
|
8249
8302
|
});
|
|
8250
8303
|
if (!payment) return json({ message: "Not found" }, { status: 404 });
|
|
@@ -8252,12 +8305,13 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8252
8305
|
}
|
|
8253
8306
|
if (resource === "blogs") {
|
|
8254
8307
|
const blog = await repo.findOne({
|
|
8255
|
-
where: { id: Number(id) },
|
|
8308
|
+
where: { id: Number(id), deleted: false },
|
|
8256
8309
|
relations: ["category", "seo", "tags"]
|
|
8257
8310
|
});
|
|
8258
8311
|
return blog ? json(blog) : json({ message: "Not found" }, { status: 404 });
|
|
8259
8312
|
}
|
|
8260
|
-
const
|
|
8313
|
+
const idWhere = entityHasSoftDelete(repo) ? { id: Number(id), deleted: false } : { id: Number(id) };
|
|
8314
|
+
const item = await repo.findOne({ where: idWhere });
|
|
8261
8315
|
return item ? json(item) : json({ message: "Not found" }, { status: 404 });
|
|
8262
8316
|
},
|
|
8263
8317
|
async PUT(req, resource, id) {
|
|
@@ -8269,7 +8323,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8269
8323
|
const repo = dataSource.getRepository(entity);
|
|
8270
8324
|
const numericId = Number(id);
|
|
8271
8325
|
if (resource === "blogs" && rawBody && typeof rawBody === "object" && entityMap.categories && entityMap.seos && entityMap.tags) {
|
|
8272
|
-
const existing = await repo.findOne({
|
|
8326
|
+
const existing = await repo.findOne({
|
|
8327
|
+
where: { id: numericId, deleted: false }
|
|
8328
|
+
});
|
|
8273
8329
|
if (!existing) return json({ message: "Not found" }, { status: 404 });
|
|
8274
8330
|
const updatePayload2 = pickColumnUpdates(repo, rawBody);
|
|
8275
8331
|
if ("category" in rawBody) {
|
|
@@ -8345,6 +8401,12 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8345
8401
|
});
|
|
8346
8402
|
return updated2 ? json(updated2) : json({ message: "Not found" }, { status: 404 });
|
|
8347
8403
|
}
|
|
8404
|
+
if (entityHasSoftDelete(repo)) {
|
|
8405
|
+
const cur = await repo.findOne({
|
|
8406
|
+
where: { id: numericId, deleted: false }
|
|
8407
|
+
});
|
|
8408
|
+
if (!cur) return json({ message: "Not found" }, { status: 404 });
|
|
8409
|
+
}
|
|
8348
8410
|
const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
|
|
8349
8411
|
if (resource === "media") {
|
|
8350
8412
|
const u = updatePayload;
|
|
@@ -8371,7 +8433,24 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
8371
8433
|
const entity = entityMap[resource];
|
|
8372
8434
|
if (!entity) return json({ error: "Invalid resource" }, { status: 400 });
|
|
8373
8435
|
const repo = dataSource.getRepository(entity);
|
|
8374
|
-
const
|
|
8436
|
+
const numericId = Number(id);
|
|
8437
|
+
if (entityHasSoftDelete(repo)) {
|
|
8438
|
+
const existing = await repo.findOne({
|
|
8439
|
+
where: { id: numericId, deleted: false }
|
|
8440
|
+
});
|
|
8441
|
+
if (!existing) return json({ message: "Not found" }, { status: 404 });
|
|
8442
|
+
let deletedBy = null;
|
|
8443
|
+
if (getDeletedByUserId) {
|
|
8444
|
+
try {
|
|
8445
|
+
deletedBy = await getDeletedByUserId(req);
|
|
8446
|
+
} catch {
|
|
8447
|
+
deletedBy = null;
|
|
8448
|
+
}
|
|
8449
|
+
}
|
|
8450
|
+
await repo.update(numericId, buildSoftDeletePayload(repo.metadata, deletedBy));
|
|
8451
|
+
return json({ message: "Deleted successfully" }, { status: 200 });
|
|
8452
|
+
}
|
|
8453
|
+
const result = await repo.delete(numericId);
|
|
8375
8454
|
if (result.affected === 0) return json({ message: "Not found" }, { status: 404 });
|
|
8376
8455
|
return json({ message: "Deleted successfully" }, { status: 200 });
|
|
8377
8456
|
}
|
|
@@ -8799,9 +8878,10 @@ function createCmsApiHandler(config) {
|
|
|
8799
8878
|
userProfile,
|
|
8800
8879
|
settings: settingsConfig,
|
|
8801
8880
|
chat: chatConfig,
|
|
8802
|
-
requireEntityPermission:
|
|
8881
|
+
requireEntityPermission: userRequireEntityPermission,
|
|
8803
8882
|
getSessionUser
|
|
8804
8883
|
} = config;
|
|
8884
|
+
const requireEntityPermissionEffective = userRequireEntityPermission ?? (async (_req, entity, action) => config.json({ error: "Forbidden", reason: "entity_rbac_required", entity, action }, { status: 403 }));
|
|
8805
8885
|
const analytics = analyticsConfig ?? (getCms ? {
|
|
8806
8886
|
json: config.json,
|
|
8807
8887
|
requireAuth: async () => null,
|
|
@@ -8839,12 +8919,20 @@ function createCmsApiHandler(config) {
|
|
|
8839
8919
|
const crudOpts = {
|
|
8840
8920
|
requireAuth: config.requireAuth,
|
|
8841
8921
|
json: config.json,
|
|
8842
|
-
requireEntityPermission:
|
|
8843
|
-
getCms
|
|
8922
|
+
requireEntityPermission: requireEntityPermissionEffective,
|
|
8923
|
+
getCms,
|
|
8924
|
+
...getSessionUser ? {
|
|
8925
|
+
getDeletedByUserId: async () => {
|
|
8926
|
+
const u = await getSessionUser();
|
|
8927
|
+
if (!u?.id) return null;
|
|
8928
|
+
const n = Number(u.id);
|
|
8929
|
+
return Number.isFinite(n) ? n : null;
|
|
8930
|
+
}
|
|
8931
|
+
} : {}
|
|
8844
8932
|
};
|
|
8845
8933
|
const crud = createCrudHandler(dataSource, entityMap, crudOpts);
|
|
8846
8934
|
const crudById = createCrudByIdHandler(dataSource, entityMap, crudOpts);
|
|
8847
|
-
const mergePerm = (c) => !c ? void 0 :
|
|
8935
|
+
const mergePerm = (c) => !c ? void 0 : { ...c, requireEntityPermission: requireEntityPermissionEffective };
|
|
8848
8936
|
const adminRoles = getSessionUser && createAdminRolesHandlers({
|
|
8849
8937
|
dataSource,
|
|
8850
8938
|
entityMap,
|
|
@@ -8860,12 +8948,7 @@ function createCmsApiHandler(config) {
|
|
|
8860
8948
|
json: config.json,
|
|
8861
8949
|
requireAuth: config.requireAuth
|
|
8862
8950
|
}
|
|
8863
|
-
)
|
|
8864
|
-
dataSource,
|
|
8865
|
-
entityMap,
|
|
8866
|
-
json: config.json,
|
|
8867
|
-
requireAuth: config.requireAuth
|
|
8868
|
-
};
|
|
8951
|
+
);
|
|
8869
8952
|
const ecommerceAnalyticsGet = createEcommerceAnalyticsHandler(ecommerceAnalyticsResolved);
|
|
8870
8953
|
const analyticsHandlers = analytics ? createAnalyticsHandlers(analytics) : null;
|
|
8871
8954
|
const uploadMerged = upload ? {
|
|
@@ -8884,7 +8967,11 @@ function createCmsApiHandler(config) {
|
|
|
8884
8967
|
const usersApiMerged = usersApi && getCms ? {
|
|
8885
8968
|
...usersApi,
|
|
8886
8969
|
getCms: usersApi.getCms ?? getCms,
|
|
8887
|
-
getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails
|
|
8970
|
+
getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails,
|
|
8971
|
+
...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
|
|
8972
|
+
} : usersApi ? {
|
|
8973
|
+
...usersApi,
|
|
8974
|
+
...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
|
|
8888
8975
|
} : usersApi;
|
|
8889
8976
|
const usersHandlers = usersApiMerged ? createUsersApiHandlers(mergePerm(usersApiMerged) ?? usersApiMerged) : null;
|
|
8890
8977
|
const avatarPost = userAvatar ? createUserAvatarHandler(userAvatar) : null;
|
|
@@ -8895,7 +8982,7 @@ function createCmsApiHandler(config) {
|
|
|
8895
8982
|
entityMap,
|
|
8896
8983
|
json: config.json,
|
|
8897
8984
|
requireAuth: config.requireAuth,
|
|
8898
|
-
requireEntityPermission:
|
|
8985
|
+
requireEntityPermission: requireEntityPermissionEffective
|
|
8899
8986
|
});
|
|
8900
8987
|
const chatHandlers = chatConfig ? createChatHandlers(chatConfig) : null;
|
|
8901
8988
|
function resolveResource(segment) {
|
|
@@ -8904,12 +8991,10 @@ function createCmsApiHandler(config) {
|
|
|
8904
8991
|
}
|
|
8905
8992
|
return {
|
|
8906
8993
|
async handle(method, path, req) {
|
|
8907
|
-
const perm = reqEntityPerm;
|
|
8908
8994
|
async function analyticsGate() {
|
|
8909
8995
|
const a = await config.requireAuth(req);
|
|
8910
8996
|
if (a) return a;
|
|
8911
|
-
|
|
8912
|
-
return null;
|
|
8997
|
+
return requireEntityPermissionEffective(req, "analytics", "read");
|
|
8913
8998
|
}
|
|
8914
8999
|
if (path[0] === "admin" && path[1] === "roles") {
|
|
8915
9000
|
if (!adminRoles) return config.json({ error: "Not found" }, { status: 404 });
|
|
@@ -8993,19 +9078,17 @@ function createCmsApiHandler(config) {
|
|
|
8993
9078
|
const group = path[1];
|
|
8994
9079
|
const isPublic = settingsConfig?.publicGetGroups?.includes(group);
|
|
8995
9080
|
if (method === "GET") {
|
|
8996
|
-
if (!isPublic
|
|
9081
|
+
if (!isPublic) {
|
|
8997
9082
|
const a = await config.requireAuth(req);
|
|
8998
9083
|
if (a) return a;
|
|
8999
|
-
const pe = await
|
|
9084
|
+
const pe = await requireEntityPermissionEffective(req, "settings", "read");
|
|
9000
9085
|
if (pe) return pe;
|
|
9001
9086
|
}
|
|
9002
9087
|
return settingsHandlers.GET(req, group);
|
|
9003
9088
|
}
|
|
9004
9089
|
if (method === "PUT") {
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
if (pe) return pe;
|
|
9008
|
-
}
|
|
9090
|
+
const pe = await requireEntityPermissionEffective(req, "settings", "update");
|
|
9091
|
+
if (pe) return pe;
|
|
9009
9092
|
return settingsHandlers.PUT(req, group);
|
|
9010
9093
|
}
|
|
9011
9094
|
}
|
|
@@ -9021,10 +9104,8 @@ function createCmsApiHandler(config) {
|
|
|
9021
9104
|
if (path[0] === "orders" && path.length === 3 && path[2] === "invoice" && method === "GET" && getCms) {
|
|
9022
9105
|
const a = await config.requireAuth(req);
|
|
9023
9106
|
if (a) return a;
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
if (pe) return pe;
|
|
9027
|
-
}
|
|
9107
|
+
const pe = await requireEntityPermissionEffective(req, "orders", "read");
|
|
9108
|
+
if (pe) return pe;
|
|
9028
9109
|
const cms = await getCms();
|
|
9029
9110
|
const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await Promise.resolve().then(() => (init_erp_order_invoice(), erp_order_invoice_exports));
|
|
9030
9111
|
const oid = Number(path[1]);
|
|
@@ -9034,10 +9115,8 @@ function createCmsApiHandler(config) {
|
|
|
9034
9115
|
if (path[0] === "orders" && path.length === 3 && path[2] === "repost-erp" && getCms) {
|
|
9035
9116
|
const a = await config.requireAuth(req);
|
|
9036
9117
|
if (a) return a;
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
if (pe) return pe;
|
|
9040
|
-
}
|
|
9118
|
+
const pe = await requireEntityPermissionEffective(req, "orders", method === "GET" ? "read" : "update");
|
|
9119
|
+
if (pe) return pe;
|
|
9041
9120
|
const oid = Number(path[1]);
|
|
9042
9121
|
if (!Number.isFinite(oid)) return config.json({ error: "Invalid id" }, { status: 400 });
|
|
9043
9122
|
const cms = await getCms();
|
|
@@ -10494,6 +10573,9 @@ var DEFAULT_ADMIN_NAV = [
|
|
|
10494
10573
|
{ href: "/admin/submissions", label: "Submissions" },
|
|
10495
10574
|
{ href: "/admin/pages", label: "Pages" }
|
|
10496
10575
|
];
|
|
10576
|
+
|
|
10577
|
+
// src/index.ts
|
|
10578
|
+
console.log("\u{1F525} USING LOCAL CMS CORE (index.ts loaded) \u{1F525}");
|
|
10497
10579
|
export {
|
|
10498
10580
|
ADMIN_GROUP_NAME,
|
|
10499
10581
|
Address,
|