@infuro/cms-core 1.0.39 → 1.0.41
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/dist/admin.cjs +214 -111
- package/dist/admin.js +215 -112
- package/dist/api.cjs +32 -32
- package/dist/api.d.cts +4 -1
- package/dist/api.d.ts +4 -1
- package/dist/api.js +1 -1
- package/dist/auth.cjs +12 -12
- package/dist/auth.js +1 -1
- package/dist/{chunk-SBRBR3VO.js → chunk-4BG7XYSH.js} +1 -0
- package/dist/{chunk-SFDZMGHD.js → chunk-EG4ICILK.js} +460 -102
- package/dist/{chunk-E6WVP7BK.cjs → chunk-ETZN4OQI.cjs} +1 -0
- package/dist/{chunk-ERJK5QXN.cjs → chunk-QU554KAZ.cjs} +461 -100
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +210 -198
- package/dist/index.d.cts +84 -68
- package/dist/index.d.ts +84 -68
- package/dist/index.js +3 -3
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ import { isErpIntegrationEnabled } from './chunk-JC6DLWTE.js';
|
|
|
12
12
|
import { __name } from './chunk-SHUYVCID.js';
|
|
13
13
|
import { PrimaryGeneratedColumn, Column, Entity, ManyToOne, JoinColumn, OneToMany, Index, ManyToMany, JoinTable, Unique, CreateDateColumn, UpdateDateColumn, In, IsNull, ILike, Between, MoreThanOrEqual, LessThanOrEqual, Not, MoreThan } from 'typeorm';
|
|
14
14
|
import { Country, State, City } from 'country-state-city';
|
|
15
|
-
import crypto2, { randomUUID, createHmac, timingSafeEqual, randomInt } from 'crypto';
|
|
15
|
+
import crypto2, { randomBytes, randomUUID, createHmac, timingSafeEqual, randomInt } from 'crypto';
|
|
16
16
|
import Parser from 'rss-parser';
|
|
17
17
|
import fs from 'fs/promises';
|
|
18
18
|
import path from 'path';
|
|
@@ -6179,6 +6179,225 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6179
6179
|
};
|
|
6180
6180
|
}
|
|
6181
6181
|
__name(createCrudByIdHandler, "createCrudByIdHandler");
|
|
6182
|
+
var VENDOR_INVITE_METADATA_TOKEN = "inviteToken";
|
|
6183
|
+
var VENDOR_INVITE_METADATA_EXPIRES = "inviteExpiresAt";
|
|
6184
|
+
var VENDOR_INVITE_METADATA_SENT = "inviteSentAt";
|
|
6185
|
+
async function loadOwnerVendorForUser(dataSource, vendorEntity, userId) {
|
|
6186
|
+
const repo = dataSource.getRepository(vendorEntity);
|
|
6187
|
+
const row = await repo.findOne({
|
|
6188
|
+
where: {
|
|
6189
|
+
userId,
|
|
6190
|
+
deleted: false
|
|
6191
|
+
}
|
|
6192
|
+
});
|
|
6193
|
+
if (!row) return null;
|
|
6194
|
+
const v = row;
|
|
6195
|
+
return {
|
|
6196
|
+
id: v.id,
|
|
6197
|
+
inviteStatus: v.inviteStatus,
|
|
6198
|
+
metadata: v.metadata && typeof v.metadata === "object" && !Array.isArray(v.metadata) ? v.metadata : null
|
|
6199
|
+
};
|
|
6200
|
+
}
|
|
6201
|
+
__name(loadOwnerVendorForUser, "loadOwnerVendorForUser");
|
|
6202
|
+
function invalidatedInviteMessage() {
|
|
6203
|
+
return "This invitation is no longer valid. Ask an admin to resend the invite.";
|
|
6204
|
+
}
|
|
6205
|
+
__name(invalidatedInviteMessage, "invalidatedInviteMessage");
|
|
6206
|
+
async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
6207
|
+
const trimmedToken = String(token ?? "").trim();
|
|
6208
|
+
if (!trimmedToken) {
|
|
6209
|
+
return {
|
|
6210
|
+
ok: false,
|
|
6211
|
+
error: "Invalid invite link. Token is missing."
|
|
6212
|
+
};
|
|
6213
|
+
}
|
|
6214
|
+
const userRepo = entityMap.users ? dataSource.getRepository(entityMap.users) : null;
|
|
6215
|
+
if (entityMap.vendors && userRepo) {
|
|
6216
|
+
const vendorMatch = await findVendorByInviteToken(dataSource, entityMap.vendors, trimmedToken);
|
|
6217
|
+
if (vendorMatch) {
|
|
6218
|
+
const vendorRepo = dataSource.getRepository(entityMap.vendors);
|
|
6219
|
+
const freshVendor = await vendorRepo.findOne({
|
|
6220
|
+
where: {
|
|
6221
|
+
id: vendorMatch.id,
|
|
6222
|
+
deleted: false
|
|
6223
|
+
}
|
|
6224
|
+
});
|
|
6225
|
+
const v = freshVendor;
|
|
6226
|
+
if (!v?.userId) {
|
|
6227
|
+
return {
|
|
6228
|
+
ok: false,
|
|
6229
|
+
error: invalidatedInviteMessage()
|
|
6230
|
+
};
|
|
6231
|
+
}
|
|
6232
|
+
if (v.inviteStatus === "accepted") {
|
|
6233
|
+
return {
|
|
6234
|
+
ok: false,
|
|
6235
|
+
error: "This invitation has already been accepted"
|
|
6236
|
+
};
|
|
6237
|
+
}
|
|
6238
|
+
if (v.inviteStatus === "expired") {
|
|
6239
|
+
await vendorRepo.update(v.id, {
|
|
6240
|
+
inviteStatus: "pending"
|
|
6241
|
+
});
|
|
6242
|
+
v.inviteStatus = "pending";
|
|
6243
|
+
}
|
|
6244
|
+
const user2 = await userRepo.findOne({
|
|
6245
|
+
where: {
|
|
6246
|
+
id: v.userId
|
|
6247
|
+
},
|
|
6248
|
+
select: [
|
|
6249
|
+
"id",
|
|
6250
|
+
"email",
|
|
6251
|
+
"blocked",
|
|
6252
|
+
"password"
|
|
6253
|
+
]
|
|
6254
|
+
});
|
|
6255
|
+
if (!user2) return {
|
|
6256
|
+
ok: false,
|
|
6257
|
+
error: "User not found"
|
|
6258
|
+
};
|
|
6259
|
+
const hasPassword2 = !!user2.password;
|
|
6260
|
+
if (!user2.blocked && hasPassword2) {
|
|
6261
|
+
return {
|
|
6262
|
+
ok: false,
|
|
6263
|
+
error: "User is already active"
|
|
6264
|
+
};
|
|
6265
|
+
}
|
|
6266
|
+
return {
|
|
6267
|
+
ok: true,
|
|
6268
|
+
target: {
|
|
6269
|
+
userId: user2.id,
|
|
6270
|
+
email: String(user2.email),
|
|
6271
|
+
vendorId: v.id
|
|
6272
|
+
}
|
|
6273
|
+
};
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
let email;
|
|
6277
|
+
try {
|
|
6278
|
+
email = Buffer.from(trimmedToken, "base64").toString("utf8").trim();
|
|
6279
|
+
} catch {
|
|
6280
|
+
return {
|
|
6281
|
+
ok: false,
|
|
6282
|
+
error: invalidatedInviteMessage()
|
|
6283
|
+
};
|
|
6284
|
+
}
|
|
6285
|
+
if (!email.includes("@")) {
|
|
6286
|
+
return {
|
|
6287
|
+
ok: false,
|
|
6288
|
+
error: invalidatedInviteMessage()
|
|
6289
|
+
};
|
|
6290
|
+
}
|
|
6291
|
+
if (!userRepo) {
|
|
6292
|
+
return {
|
|
6293
|
+
ok: false,
|
|
6294
|
+
error: "User not found"
|
|
6295
|
+
};
|
|
6296
|
+
}
|
|
6297
|
+
const user = await userRepo.findOne({
|
|
6298
|
+
where: {
|
|
6299
|
+
email
|
|
6300
|
+
},
|
|
6301
|
+
select: [
|
|
6302
|
+
"id",
|
|
6303
|
+
"email",
|
|
6304
|
+
"blocked",
|
|
6305
|
+
"password"
|
|
6306
|
+
]
|
|
6307
|
+
});
|
|
6308
|
+
if (!user) return {
|
|
6309
|
+
ok: false,
|
|
6310
|
+
error: "User not found"
|
|
6311
|
+
};
|
|
6312
|
+
const hasPassword = !!user.password;
|
|
6313
|
+
if (!user.blocked && hasPassword) {
|
|
6314
|
+
return {
|
|
6315
|
+
ok: false,
|
|
6316
|
+
error: "User is already active"
|
|
6317
|
+
};
|
|
6318
|
+
}
|
|
6319
|
+
if (entityMap.vendors) {
|
|
6320
|
+
const ownerVendor = await loadOwnerVendorForUser(dataSource, entityMap.vendors, user.id);
|
|
6321
|
+
if (ownerVendor && readVendorInviteToken(ownerVendor.metadata)) {
|
|
6322
|
+
return {
|
|
6323
|
+
ok: false,
|
|
6324
|
+
error: invalidatedInviteMessage()
|
|
6325
|
+
};
|
|
6326
|
+
}
|
|
6327
|
+
}
|
|
6328
|
+
return {
|
|
6329
|
+
ok: true,
|
|
6330
|
+
target: {
|
|
6331
|
+
userId: user.id,
|
|
6332
|
+
email: String(user.email)
|
|
6333
|
+
}
|
|
6334
|
+
};
|
|
6335
|
+
}
|
|
6336
|
+
__name(validateInviteTokenForActivation, "validateInviteTokenForActivation");
|
|
6337
|
+
function buildVendorInviteLink(baseUrl, token) {
|
|
6338
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
6339
|
+
return `${base}/admin/invite?token=${encodeURIComponent(token)}`;
|
|
6340
|
+
}
|
|
6341
|
+
__name(buildVendorInviteLink, "buildVendorInviteLink");
|
|
6342
|
+
function applyRotatingVendorInvite(existing) {
|
|
6343
|
+
const next = {
|
|
6344
|
+
...existing ?? {}
|
|
6345
|
+
};
|
|
6346
|
+
next[VENDOR_INVITE_METADATA_TOKEN] = randomBytes(32).toString("hex");
|
|
6347
|
+
next[VENDOR_INVITE_METADATA_SENT] = (/* @__PURE__ */ new Date()).toISOString();
|
|
6348
|
+
delete next[VENDOR_INVITE_METADATA_EXPIRES];
|
|
6349
|
+
return next;
|
|
6350
|
+
}
|
|
6351
|
+
__name(applyRotatingVendorInvite, "applyRotatingVendorInvite");
|
|
6352
|
+
function clearVendorInviteMetadata(existing) {
|
|
6353
|
+
const next = {
|
|
6354
|
+
...existing ?? {}
|
|
6355
|
+
};
|
|
6356
|
+
delete next[VENDOR_INVITE_METADATA_TOKEN];
|
|
6357
|
+
delete next[VENDOR_INVITE_METADATA_EXPIRES];
|
|
6358
|
+
delete next[VENDOR_INVITE_METADATA_SENT];
|
|
6359
|
+
return Object.keys(next).length > 0 ? next : null;
|
|
6360
|
+
}
|
|
6361
|
+
__name(clearVendorInviteMetadata, "clearVendorInviteMetadata");
|
|
6362
|
+
function readVendorInviteToken(metadata) {
|
|
6363
|
+
const raw = metadata?.[VENDOR_INVITE_METADATA_TOKEN];
|
|
6364
|
+
return typeof raw === "string" && raw.trim() ? raw.trim() : null;
|
|
6365
|
+
}
|
|
6366
|
+
__name(readVendorInviteToken, "readVendorInviteToken");
|
|
6367
|
+
async function findVendorByInviteToken(dataSource, vendorEntity, token) {
|
|
6368
|
+
const trimmed = token.trim();
|
|
6369
|
+
if (!trimmed) return null;
|
|
6370
|
+
const repo = dataSource.getRepository(vendorEntity);
|
|
6371
|
+
const row = await repo.createQueryBuilder("v").where("v.deleted = false").andWhere(`v.metadata->>'${VENDOR_INVITE_METADATA_TOKEN}' = :token`, {
|
|
6372
|
+
token: trimmed
|
|
6373
|
+
}).getOne();
|
|
6374
|
+
if (!row) return null;
|
|
6375
|
+
const v = row;
|
|
6376
|
+
return {
|
|
6377
|
+
id: v.id,
|
|
6378
|
+
userId: v.userId ?? null,
|
|
6379
|
+
inviteStatus: v.inviteStatus,
|
|
6380
|
+
metadata: v.metadata && typeof v.metadata === "object" && !Array.isArray(v.metadata) ? v.metadata : null
|
|
6381
|
+
};
|
|
6382
|
+
}
|
|
6383
|
+
__name(findVendorByInviteToken, "findVendorByInviteToken");
|
|
6384
|
+
async function completeVendorInviteAccept(dataSource, vendorEntity, vendorId) {
|
|
6385
|
+
const repo = dataSource.getRepository(vendorEntity);
|
|
6386
|
+
const row = await repo.findOne({
|
|
6387
|
+
where: {
|
|
6388
|
+
id: vendorId,
|
|
6389
|
+
deleted: false
|
|
6390
|
+
}
|
|
6391
|
+
});
|
|
6392
|
+
if (!row) return;
|
|
6393
|
+
const metadata = row.metadata;
|
|
6394
|
+
const cleared = clearVendorInviteMetadata(metadata);
|
|
6395
|
+
await repo.update(vendorId, {
|
|
6396
|
+
metadata: cleared,
|
|
6397
|
+
inviteStatus: "accepted"
|
|
6398
|
+
});
|
|
6399
|
+
}
|
|
6400
|
+
__name(completeVendorInviteAccept, "completeVendorInviteAccept");
|
|
6182
6401
|
|
|
6183
6402
|
// src/api/auth-handlers.ts
|
|
6184
6403
|
function createForgotPasswordHandler(config) {
|
|
@@ -6314,49 +6533,27 @@ function createInviteAcceptHandler(config) {
|
|
|
6314
6533
|
}, {
|
|
6315
6534
|
status: 400
|
|
6316
6535
|
});
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
email = Buffer.from(token, "base64").toString("utf8");
|
|
6320
|
-
} catch {
|
|
6536
|
+
const validation = await validateInviteTokenForActivation(dataSource, entityMap, token);
|
|
6537
|
+
if (!validation.ok) {
|
|
6321
6538
|
return json({
|
|
6322
|
-
error:
|
|
6323
|
-
}, {
|
|
6324
|
-
status: 400
|
|
6325
|
-
});
|
|
6326
|
-
}
|
|
6327
|
-
const userRepo = dataSource.getRepository(entityMap.users);
|
|
6328
|
-
const user = await userRepo.findOne({
|
|
6329
|
-
where: {
|
|
6330
|
-
email
|
|
6331
|
-
},
|
|
6332
|
-
select: [
|
|
6333
|
-
"id",
|
|
6334
|
-
"blocked",
|
|
6335
|
-
"password"
|
|
6336
|
-
]
|
|
6337
|
-
});
|
|
6338
|
-
if (!user) return json({
|
|
6339
|
-
error: "User not found"
|
|
6340
|
-
}, {
|
|
6341
|
-
status: 400
|
|
6342
|
-
});
|
|
6343
|
-
const hasPassword = !!user.password;
|
|
6344
|
-
if (!user.blocked && hasPassword) {
|
|
6345
|
-
return json({
|
|
6346
|
-
error: "User is already active"
|
|
6539
|
+
error: validation.error
|
|
6347
6540
|
}, {
|
|
6348
6541
|
status: 400
|
|
6349
6542
|
});
|
|
6350
6543
|
}
|
|
6544
|
+
const { userId, email, vendorId } = validation.target;
|
|
6351
6545
|
if (entityMap.contacts) {
|
|
6352
|
-
await linkUnclaimedContactToUser(dataSource, entityMap.contacts,
|
|
6546
|
+
await linkUnclaimedContactToUser(dataSource, entityMap.contacts, userId, email);
|
|
6353
6547
|
}
|
|
6354
|
-
if (beforeActivate) await beforeActivate(email,
|
|
6548
|
+
if (beforeActivate) await beforeActivate(email, userId);
|
|
6355
6549
|
const hashedPassword = await hashPassword(password);
|
|
6356
|
-
await
|
|
6550
|
+
await dataSource.getRepository(entityMap.users).update(userId, {
|
|
6357
6551
|
password: hashedPassword,
|
|
6358
6552
|
blocked: false
|
|
6359
6553
|
});
|
|
6554
|
+
if (vendorId != null && entityMap.vendors) {
|
|
6555
|
+
await completeVendorInviteAccept(dataSource, entityMap.vendors, vendorId);
|
|
6556
|
+
}
|
|
6360
6557
|
return json({
|
|
6361
6558
|
message: "User account activated successfully"
|
|
6362
6559
|
}, {
|
|
@@ -6372,6 +6569,35 @@ function createInviteAcceptHandler(config) {
|
|
|
6372
6569
|
}, "POST");
|
|
6373
6570
|
}
|
|
6374
6571
|
__name(createInviteAcceptHandler, "createInviteAcceptHandler");
|
|
6572
|
+
function createInviteValidateHandler(config) {
|
|
6573
|
+
const { dataSource, entityMap, json } = config;
|
|
6574
|
+
return /* @__PURE__ */ __name(async function GET(request) {
|
|
6575
|
+
try {
|
|
6576
|
+
const token = new URL(request.url).searchParams.get("token");
|
|
6577
|
+
const validation = await validateInviteTokenForActivation(dataSource, entityMap, token ?? "");
|
|
6578
|
+
if (!validation.ok) {
|
|
6579
|
+
return json({
|
|
6580
|
+
valid: false,
|
|
6581
|
+
error: validation.error
|
|
6582
|
+
}, {
|
|
6583
|
+
status: 400
|
|
6584
|
+
});
|
|
6585
|
+
}
|
|
6586
|
+
return json({
|
|
6587
|
+
valid: true
|
|
6588
|
+
});
|
|
6589
|
+
} catch (err) {
|
|
6590
|
+
console.error("[users/invite GET] validate failed", err);
|
|
6591
|
+
return json({
|
|
6592
|
+
valid: false,
|
|
6593
|
+
error: "Server Error"
|
|
6594
|
+
}, {
|
|
6595
|
+
status: 500
|
|
6596
|
+
});
|
|
6597
|
+
}
|
|
6598
|
+
}, "GET");
|
|
6599
|
+
}
|
|
6600
|
+
__name(createInviteValidateHandler, "createInviteValidateHandler");
|
|
6375
6601
|
function createChangePasswordHandler(config) {
|
|
6376
6602
|
const { dataSource, entityMap, json, comparePassword, hashPassword, getSession, minPasswordLength = 6, beforeUpdate } = config;
|
|
6377
6603
|
return /* @__PURE__ */ __name(async function POST(request) {
|
|
@@ -6450,12 +6676,22 @@ function createUserAuthApiRouter(config) {
|
|
|
6450
6676
|
const forgot = createForgotPasswordHandler(config);
|
|
6451
6677
|
const setPass = createSetPasswordHandler(config);
|
|
6452
6678
|
const invite = createInviteAcceptHandler(config);
|
|
6679
|
+
const inviteValidate = createInviteValidateHandler(config);
|
|
6453
6680
|
const changePass = config.getSession ? createChangePasswordHandler({
|
|
6454
6681
|
...config,
|
|
6455
6682
|
getSession: config.getSession,
|
|
6456
6683
|
beforeUpdate: config.beforeChangePasswordUpdate
|
|
6457
6684
|
}) : null;
|
|
6458
6685
|
return {
|
|
6686
|
+
async GET(req, pathname) {
|
|
6687
|
+
const path2 = pathname.replace(/\/$/, "");
|
|
6688
|
+
if (path2 === "invite") return inviteValidate(req);
|
|
6689
|
+
return config.json({
|
|
6690
|
+
error: "Not found"
|
|
6691
|
+
}, {
|
|
6692
|
+
status: 404
|
|
6693
|
+
});
|
|
6694
|
+
},
|
|
6459
6695
|
async POST(req, pathname) {
|
|
6460
6696
|
const path2 = pathname.replace(/\/$/, "");
|
|
6461
6697
|
if (!USER_AUTH_PATHS.includes(path2)) {
|
|
@@ -8861,13 +9097,31 @@ function createUsersApiHandlers(config) {
|
|
|
8861
9097
|
}, {
|
|
8862
9098
|
status: 404
|
|
8863
9099
|
});
|
|
8864
|
-
|
|
8865
|
-
const inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
|
|
8866
|
-
await trySendInviteEmail(user.email, inviteLink, user.name ?? "");
|
|
9100
|
+
let inviteLink = `${baseUrl}/admin/invite?token=${Buffer.from(user.email).toString("base64")}`;
|
|
8867
9101
|
if (entityMap.vendors) {
|
|
9102
|
+
const vendorRepo = dataSource.getRepository(entityMap.vendors);
|
|
9103
|
+
const vendor = await vendorRepo.findOne({
|
|
9104
|
+
where: {
|
|
9105
|
+
userId: user.id,
|
|
9106
|
+
deleted: false
|
|
9107
|
+
}
|
|
9108
|
+
});
|
|
9109
|
+
const v = vendor;
|
|
9110
|
+
if (v && (v.inviteStatus === "pending" || v.inviteStatus === "expired")) {
|
|
9111
|
+
const rotatedMetadata = applyRotatingVendorInvite(v.metadata);
|
|
9112
|
+
await vendorRepo.update(v.id, {
|
|
9113
|
+
metadata: rotatedMetadata,
|
|
9114
|
+
inviteStatus: "pending"
|
|
9115
|
+
});
|
|
9116
|
+
const token = readVendorInviteToken(rotatedMetadata);
|
|
9117
|
+
if (token) {
|
|
9118
|
+
inviteLink = buildVendorInviteLink(baseUrl, token);
|
|
9119
|
+
}
|
|
9120
|
+
}
|
|
8868
9121
|
const { markVendorInvitePendingForUser } = await import('./vendor-invite-status-PWJ3DE76.js');
|
|
8869
9122
|
await markVendorInvitePendingForUser(dataSource, entityMap.vendors, user.id);
|
|
8870
9123
|
}
|
|
9124
|
+
await trySendInviteEmail(user.email, inviteLink, user.name ?? "");
|
|
8871
9125
|
return json({
|
|
8872
9126
|
message: "New invite link generated successfully",
|
|
8873
9127
|
inviteLink
|
|
@@ -12002,6 +12256,13 @@ function createVendorOnboardHandlers(config) {
|
|
|
12002
12256
|
status: 400
|
|
12003
12257
|
});
|
|
12004
12258
|
}
|
|
12259
|
+
if (body.activation === "password" || body.user?.password) {
|
|
12260
|
+
return json({
|
|
12261
|
+
error: "Setting a password during vendor onboard is no longer supported. Create the vendor, then send an invite or copy the invite link so the owner can set their own password."
|
|
12262
|
+
}, {
|
|
12263
|
+
status: 400
|
|
12264
|
+
});
|
|
12265
|
+
}
|
|
12005
12266
|
const profile = parseVendorProfileFromBody(body.vendor, {
|
|
12006
12267
|
defaultRegistrationStatus: "approved"
|
|
12007
12268
|
});
|
|
@@ -12011,34 +12272,8 @@ function createVendorOnboardHandlers(config) {
|
|
|
12011
12272
|
}, {
|
|
12012
12273
|
status: 400
|
|
12013
12274
|
});
|
|
12014
|
-
const activation =
|
|
12015
|
-
const
|
|
12016
|
-
let ownerPasswordHash = null;
|
|
12017
|
-
if (activation === "password") {
|
|
12018
|
-
const plain = body.user?.password?.trim();
|
|
12019
|
-
if (!plain) {
|
|
12020
|
-
return json({
|
|
12021
|
-
error: "Password is required when activating with a set password"
|
|
12022
|
-
}, {
|
|
12023
|
-
status: 400
|
|
12024
|
-
});
|
|
12025
|
-
}
|
|
12026
|
-
if (plain.length < minPasswordLength) {
|
|
12027
|
-
return json({
|
|
12028
|
-
error: `Password must be at least ${minPasswordLength} characters`
|
|
12029
|
-
}, {
|
|
12030
|
-
status: 400
|
|
12031
|
-
});
|
|
12032
|
-
}
|
|
12033
|
-
if (!hashPassword) {
|
|
12034
|
-
return json({
|
|
12035
|
-
error: "Password hashing is not configured on the server"
|
|
12036
|
-
}, {
|
|
12037
|
-
status: 501
|
|
12038
|
-
});
|
|
12039
|
-
}
|
|
12040
|
-
ownerPasswordHash = await hashPassword(plain);
|
|
12041
|
-
}
|
|
12275
|
+
const activation = "invite";
|
|
12276
|
+
const ownerPasswordHash = null;
|
|
12042
12277
|
const slug = trimOrNull(body.vendor?.slug) || slugify(vendorName);
|
|
12043
12278
|
if (!slug) return json({
|
|
12044
12279
|
error: "Could not derive vendor slug"
|
|
@@ -12095,7 +12330,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12095
12330
|
email: userEmail,
|
|
12096
12331
|
phone: ownerPhone,
|
|
12097
12332
|
password: ownerPasswordHash,
|
|
12098
|
-
blocked:
|
|
12333
|
+
blocked: true,
|
|
12099
12334
|
groupId: ownerGroup.id,
|
|
12100
12335
|
adminAccess: true,
|
|
12101
12336
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -12112,10 +12347,14 @@ function createVendorOnboardHandlers(config) {
|
|
|
12112
12347
|
email: userEmail,
|
|
12113
12348
|
phone: ownerPhone,
|
|
12114
12349
|
password: ownerPasswordHash,
|
|
12115
|
-
blocked:
|
|
12350
|
+
blocked: true,
|
|
12116
12351
|
groupId: ownerGroup.id,
|
|
12117
12352
|
adminAccess: true
|
|
12118
12353
|
}));
|
|
12354
|
+
const metadata = applyRotatingVendorInvite(buildVendorMetadata(null, {
|
|
12355
|
+
ownerDesignation,
|
|
12356
|
+
termsAccepted: true
|
|
12357
|
+
}));
|
|
12119
12358
|
const vendor = await vendorRepo.save(vendorRepo.create({
|
|
12120
12359
|
name: vendorName,
|
|
12121
12360
|
slug,
|
|
@@ -12135,10 +12374,7 @@ function createVendorOnboardHandlers(config) {
|
|
|
12135
12374
|
gstin: profile.gstin,
|
|
12136
12375
|
pan: profile.pan,
|
|
12137
12376
|
registrationStatus: profile.registrationStatus,
|
|
12138
|
-
metadata
|
|
12139
|
-
ownerDesignation,
|
|
12140
|
-
termsAccepted: true
|
|
12141
|
-
}),
|
|
12377
|
+
metadata,
|
|
12142
12378
|
active: body.vendor?.active !== false,
|
|
12143
12379
|
deleted: false,
|
|
12144
12380
|
userId: newUser.id,
|
|
@@ -12186,37 +12422,14 @@ function createVendorOnboardHandlers(config) {
|
|
|
12186
12422
|
};
|
|
12187
12423
|
});
|
|
12188
12424
|
let inviteLink;
|
|
12189
|
-
|
|
12190
|
-
if (
|
|
12191
|
-
|
|
12192
|
-
inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
|
|
12425
|
+
const token = readVendorInviteToken(result.vendor.metadata);
|
|
12426
|
+
if (token) {
|
|
12427
|
+
inviteLink = buildVendorInviteLink(baseUrl, token);
|
|
12193
12428
|
}
|
|
12194
|
-
if (sendOwnerEmail) {
|
|
12195
|
-
emailSent = await trySendVendorOnboardEmails({
|
|
12196
|
-
vendorName,
|
|
12197
|
-
vendorSlug: slug,
|
|
12198
|
-
ownerName: userName,
|
|
12199
|
-
ownerEmail: userEmail,
|
|
12200
|
-
activation,
|
|
12201
|
-
inviteLink,
|
|
12202
|
-
sendToOwner: true
|
|
12203
|
-
});
|
|
12204
|
-
} else if (getCms) {
|
|
12205
|
-
await trySendVendorOnboardEmails({
|
|
12206
|
-
vendorName,
|
|
12207
|
-
vendorSlug: slug,
|
|
12208
|
-
ownerName: userName,
|
|
12209
|
-
ownerEmail: userEmail,
|
|
12210
|
-
activation,
|
|
12211
|
-
inviteLink,
|
|
12212
|
-
sendToOwner: false
|
|
12213
|
-
});
|
|
12214
|
-
}
|
|
12215
|
-
const message = activation === "password" ? emailSent ? "Vendor onboarded successfully. Welcome email sent to the owner." : sendOwnerEmail ? "Vendor onboarded successfully. Owner can sign in with the password you set (welcome email may not have been sent \u2014 check email plugin)." : "Vendor onboarded successfully. Owner can sign in with the password you set." : emailSent ? "Vendor onboarded successfully. Invite email sent." : sendOwnerEmail ? "Vendor onboarded successfully. Invite link created (email may not have been sent \u2014 check email plugin)." : "Vendor onboarded successfully. Share the invite link with the owner.";
|
|
12216
12429
|
return json({
|
|
12217
|
-
message,
|
|
12430
|
+
message: "Vendor created successfully.",
|
|
12218
12431
|
activation,
|
|
12219
|
-
emailSent,
|
|
12432
|
+
emailSent: false,
|
|
12220
12433
|
vendor: result.vendor,
|
|
12221
12434
|
user: {
|
|
12222
12435
|
id: result.user.id,
|
|
@@ -12231,6 +12444,137 @@ function createVendorOnboardHandlers(config) {
|
|
|
12231
12444
|
return vendorOnboardErrorResponse(json, e);
|
|
12232
12445
|
}
|
|
12233
12446
|
},
|
|
12447
|
+
/** POST /api/admin/vendors/:id/resend-invite — rotate owner invite token and resend email */
|
|
12448
|
+
async resendInvite(req, vendorIdStr) {
|
|
12449
|
+
const err = await gateAdmin();
|
|
12450
|
+
if (err) return err;
|
|
12451
|
+
if (!entityMap.vendors || !entityMap.users) {
|
|
12452
|
+
return json({
|
|
12453
|
+
error: "Vendor entities not configured"
|
|
12454
|
+
}, {
|
|
12455
|
+
status: 500
|
|
12456
|
+
});
|
|
12457
|
+
}
|
|
12458
|
+
const vendorId = Number(vendorIdStr);
|
|
12459
|
+
if (!Number.isFinite(vendorId) || vendorId <= 0) {
|
|
12460
|
+
return json({
|
|
12461
|
+
error: "Invalid vendor id"
|
|
12462
|
+
}, {
|
|
12463
|
+
status: 400
|
|
12464
|
+
});
|
|
12465
|
+
}
|
|
12466
|
+
let sendEmail = true;
|
|
12467
|
+
let rotate = true;
|
|
12468
|
+
try {
|
|
12469
|
+
const body = await req.json().catch(() => ({}));
|
|
12470
|
+
if (body.sendEmail === false) sendEmail = false;
|
|
12471
|
+
if (body.rotate === false) rotate = false;
|
|
12472
|
+
} catch {
|
|
12473
|
+
}
|
|
12474
|
+
try {
|
|
12475
|
+
const vendorRepo = dataSource.getRepository(entityMap.vendors);
|
|
12476
|
+
const vendor = await vendorRepo.findOne({
|
|
12477
|
+
where: {
|
|
12478
|
+
id: vendorId,
|
|
12479
|
+
deleted: false
|
|
12480
|
+
}
|
|
12481
|
+
});
|
|
12482
|
+
if (!vendor) return json({
|
|
12483
|
+
error: "Vendor not found"
|
|
12484
|
+
}, {
|
|
12485
|
+
status: 404
|
|
12486
|
+
});
|
|
12487
|
+
const v = vendor;
|
|
12488
|
+
if (v.inviteStatus === "accepted") {
|
|
12489
|
+
return json({
|
|
12490
|
+
error: "Owner has already accepted the invite"
|
|
12491
|
+
}, {
|
|
12492
|
+
status: 400
|
|
12493
|
+
});
|
|
12494
|
+
}
|
|
12495
|
+
if (v.inviteStatus === "none") {
|
|
12496
|
+
return json({
|
|
12497
|
+
error: "This vendor was not created with an invite link"
|
|
12498
|
+
}, {
|
|
12499
|
+
status: 400
|
|
12500
|
+
});
|
|
12501
|
+
}
|
|
12502
|
+
if (v.inviteStatus !== "pending" && v.inviteStatus !== "expired") {
|
|
12503
|
+
return json({
|
|
12504
|
+
error: "Invite cannot be resent for this vendor"
|
|
12505
|
+
}, {
|
|
12506
|
+
status: 400
|
|
12507
|
+
});
|
|
12508
|
+
}
|
|
12509
|
+
if (!v.userId) {
|
|
12510
|
+
return json({
|
|
12511
|
+
error: "Vendor has no owner user linked"
|
|
12512
|
+
}, {
|
|
12513
|
+
status: 400
|
|
12514
|
+
});
|
|
12515
|
+
}
|
|
12516
|
+
const userRepo = dataSource.getRepository(entityMap.users);
|
|
12517
|
+
const owner = await userRepo.findOne({
|
|
12518
|
+
where: {
|
|
12519
|
+
id: v.userId,
|
|
12520
|
+
deleted: false
|
|
12521
|
+
}
|
|
12522
|
+
});
|
|
12523
|
+
if (!owner) return json({
|
|
12524
|
+
error: "Owner user not found"
|
|
12525
|
+
}, {
|
|
12526
|
+
status: 404
|
|
12527
|
+
});
|
|
12528
|
+
const ownerRow = owner;
|
|
12529
|
+
const hasPassword = !!(ownerRow.password && String(ownerRow.password).trim());
|
|
12530
|
+
if (!ownerRow.blocked && hasPassword) {
|
|
12531
|
+
return json({
|
|
12532
|
+
error: "Owner account is already active"
|
|
12533
|
+
}, {
|
|
12534
|
+
status: 400
|
|
12535
|
+
});
|
|
12536
|
+
}
|
|
12537
|
+
const nextMetadata = rotate ? applyRotatingVendorInvite(v.metadata) : {
|
|
12538
|
+
...v.metadata ?? {}
|
|
12539
|
+
};
|
|
12540
|
+
if (rotate || v.inviteStatus !== "pending") {
|
|
12541
|
+
await vendorRepo.update(vendorId, {
|
|
12542
|
+
metadata: nextMetadata,
|
|
12543
|
+
inviteStatus: "pending"
|
|
12544
|
+
});
|
|
12545
|
+
}
|
|
12546
|
+
const token = readVendorInviteToken(nextMetadata);
|
|
12547
|
+
if (!token) {
|
|
12548
|
+
return json({
|
|
12549
|
+
error: "Failed to generate invite token"
|
|
12550
|
+
}, {
|
|
12551
|
+
status: 500
|
|
12552
|
+
});
|
|
12553
|
+
}
|
|
12554
|
+
const inviteLink = buildVendorInviteLink(baseUrl, token);
|
|
12555
|
+
let emailSent = false;
|
|
12556
|
+
if (sendEmail) {
|
|
12557
|
+
emailSent = await trySendVendorOnboardEmails({
|
|
12558
|
+
vendorName: v.name,
|
|
12559
|
+
vendorSlug: v.slug,
|
|
12560
|
+
ownerName: ownerRow.name,
|
|
12561
|
+
ownerEmail: ownerRow.email,
|
|
12562
|
+
activation: "invite",
|
|
12563
|
+
inviteLink,
|
|
12564
|
+
sendToOwner: true
|
|
12565
|
+
});
|
|
12566
|
+
}
|
|
12567
|
+
const rotatedNote = rotate ? " Previous invite link is no longer valid." : "";
|
|
12568
|
+
return json({
|
|
12569
|
+
message: emailSent ? `Invite email sent.${rotatedNote}` : sendEmail ? `Invite link ready (email may not have been sent \u2014 check email plugin).${rotatedNote}` : rotate ? "New invite link created. Previous invite link is no longer valid." : "Invite link ready.",
|
|
12570
|
+
emailSent,
|
|
12571
|
+
inviteLink,
|
|
12572
|
+
inviteStatus: "pending"
|
|
12573
|
+
});
|
|
12574
|
+
} catch (e) {
|
|
12575
|
+
return vendorOnboardErrorResponse(json, e);
|
|
12576
|
+
}
|
|
12577
|
+
},
|
|
12234
12578
|
/** POST /api/admin/vendor/switch — set active vendor in session (JWT update via client) */
|
|
12235
12579
|
async switchVendor(req) {
|
|
12236
12580
|
const u = await getSessionUser();
|
|
@@ -25592,6 +25936,14 @@ function createCmsApiHandler(config) {
|
|
|
25592
25936
|
});
|
|
25593
25937
|
return vendorHandlers.onboard(req);
|
|
25594
25938
|
}
|
|
25939
|
+
if (path2[0] === "admin" && path2[1] === "vendors" && path2.length === 4 && path2[3] === "resend-invite" && m === "POST") {
|
|
25940
|
+
if (!vendorHandlers) return config.json({
|
|
25941
|
+
error: "Not found"
|
|
25942
|
+
}, {
|
|
25943
|
+
status: 404
|
|
25944
|
+
});
|
|
25945
|
+
return vendorHandlers.resendInvite(req, path2[2]);
|
|
25946
|
+
}
|
|
25595
25947
|
if (path2[0] === "admin" && path2[1] === "vendor" && path2[2] === "switch" && path2.length === 3 && m === "POST") {
|
|
25596
25948
|
if (!vendorHandlers) return config.json({
|
|
25597
25949
|
error: "Not found"
|
|
@@ -26183,6 +26535,15 @@ function createCmsApiHandler(config) {
|
|
|
26183
26535
|
if (m === "PUT" || m === "PATCH") return formSaveHandlers.PUT(req, path2[1]);
|
|
26184
26536
|
}
|
|
26185
26537
|
}
|
|
26538
|
+
if (path2[0] === "users" && path2.length === 2 && userAuthRouter) {
|
|
26539
|
+
const authSegment = path2[1];
|
|
26540
|
+
if (m === "GET" && authSegment === "invite" && userAuthRouter.GET) {
|
|
26541
|
+
return userAuthRouter.GET(req, authSegment);
|
|
26542
|
+
}
|
|
26543
|
+
if (m === "POST" && (authSegment === "invite" || authSegment === "forgot-password" || authSegment === "set-password" || authSegment === "reset-password")) {
|
|
26544
|
+
return userAuthRouter.POST(req, authSegment);
|
|
26545
|
+
}
|
|
26546
|
+
}
|
|
26186
26547
|
if (path2[0] === "users" && usersHandlers) {
|
|
26187
26548
|
if (path2.length === 1) {
|
|
26188
26549
|
if (m === "GET") return usersHandlers.list(req);
|
|
@@ -26203,9 +26564,6 @@ function createCmsApiHandler(config) {
|
|
|
26203
26564
|
return usersHandlers.regenerateInvite(req, path2[1]);
|
|
26204
26565
|
}
|
|
26205
26566
|
}
|
|
26206
|
-
if (path2[0] === "users" && path2.length === 2 && userAuthRouter && m === "POST") {
|
|
26207
|
-
return userAuthRouter.POST(req, path2[1]);
|
|
26208
|
-
}
|
|
26209
26567
|
if (path2[0] === "social-media" && path2[1] === "linkedin" && socialMediaHandlers && path2.length === 3) {
|
|
26210
26568
|
const tail = path2[2];
|
|
26211
26569
|
if (tail === "status" && m === "GET") {
|
|
@@ -30588,4 +30946,4 @@ function createStorefrontApiHandler(config) {
|
|
|
30588
30946
|
}
|
|
30589
30947
|
__name(createStorefrontApiHandler, "createStorefrontApiHandler");
|
|
30590
30948
|
|
|
30591
|
-
export { Address, Attendee, Attribute, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyVendorCustomersContactFilter, assertCaptchaOk, assertContactAllowedForVendorOrder, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, calculateOrderRefundPreview, calculateRefundFromPolicy, checkEventsEnabled, checkMultiVendorEnabled, contactIsVendorCustomer, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, customerPhoneForUser, daysBeforeEventStart, describeEventTierPolicy, ensureCustomerForUser, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, findActiveRefundPolicyForVendor, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRssArticleSummaryFromItem, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, isCustomerTypeContact, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
|
|
30949
|
+
export { Address, Attendee, Attribute, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyRotatingVendorInvite, applyVendorCustomersContactFilter, assertCaptchaOk, assertContactAllowedForVendorOrder, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkEventsEnabled, checkMultiVendorEnabled, contactIsVendorCustomer, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, customerPhoneForUser, daysBeforeEventStart, describeEventTierPolicy, ensureCustomerForUser, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, findActiveRefundPolicyForVendor, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRssArticleSummaryFromItem, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, isCustomerTypeContact, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
|