@7365admin1/core 3.68.1 → 3.68.3
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/CHANGELOG.md +12 -0
- package/dist/index.d.ts +66 -52
- package/dist/index.js +57 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/user-invite-dedupe.e2e.test.mjs +138 -0
- package/test/member-duplicate-error.test.mjs +30 -0
package/dist/index.mjs
CHANGED
|
@@ -9073,6 +9073,9 @@ import { BadRequestError as BadRequestError12 } from "@7365admin1/node-server-ut
|
|
|
9073
9073
|
import Joi7 from "joi";
|
|
9074
9074
|
import { ObjectId as ObjectId12 } from "mongodb";
|
|
9075
9075
|
var PLATFORM_STAFF_MEMBER_TYPE = "admin";
|
|
9076
|
+
function isDuplicateMemberError(error) {
|
|
9077
|
+
return error?.code === 11e3 || /E11000|duplicate key/i.test(error?.message ?? "");
|
|
9078
|
+
}
|
|
9076
9079
|
var MEMBER_TYPES = [
|
|
9077
9080
|
PLATFORM_STAFF_MEMBER_TYPE,
|
|
9078
9081
|
"organization",
|
|
@@ -9226,8 +9229,7 @@ function useMemberRepo() {
|
|
|
9226
9229
|
});
|
|
9227
9230
|
return "Successfully added member.";
|
|
9228
9231
|
} catch (error) {
|
|
9229
|
-
|
|
9230
|
-
if (isDuplicated && error.message.includes("org_1_user_1"))
|
|
9232
|
+
if (isDuplicateMemberError(error))
|
|
9231
9233
|
throw new BadRequestError13(
|
|
9232
9234
|
"The user is already a member of this organization."
|
|
9233
9235
|
);
|
|
@@ -10517,17 +10519,6 @@ import {
|
|
|
10517
10519
|
useAtlas as useAtlas23
|
|
10518
10520
|
} from "@7365admin1/node-server-utils";
|
|
10519
10521
|
|
|
10520
|
-
// src/repositories/verification.repo.ts
|
|
10521
|
-
import {
|
|
10522
|
-
BadRequestError as BadRequestError17,
|
|
10523
|
-
InternalServerError as InternalServerError8,
|
|
10524
|
-
logger as logger8,
|
|
10525
|
-
makeCacheKey as makeCacheKey6,
|
|
10526
|
-
paginate as paginate6,
|
|
10527
|
-
useAtlas as useAtlas11,
|
|
10528
|
-
useCache as useCache8
|
|
10529
|
-
} from "@7365admin1/node-server-utils";
|
|
10530
|
-
|
|
10531
10522
|
// src/models/verification.model.ts
|
|
10532
10523
|
import { BadRequestError as BadRequestError16 } from "@7365admin1/node-server-utils";
|
|
10533
10524
|
import { ObjectId as ObjectId16 } from "mongodb";
|
|
@@ -10576,6 +10567,15 @@ var MVerification = class {
|
|
|
10576
10567
|
};
|
|
10577
10568
|
|
|
10578
10569
|
// src/repositories/verification.repo.ts
|
|
10570
|
+
import {
|
|
10571
|
+
BadRequestError as BadRequestError17,
|
|
10572
|
+
InternalServerError as InternalServerError8,
|
|
10573
|
+
logger as logger8,
|
|
10574
|
+
makeCacheKey as makeCacheKey6,
|
|
10575
|
+
paginate as paginate6,
|
|
10576
|
+
useAtlas as useAtlas11,
|
|
10577
|
+
useCache as useCache8
|
|
10578
|
+
} from "@7365admin1/node-server-utils";
|
|
10579
10579
|
import { ObjectId as ObjectId17 } from "mongodb";
|
|
10580
10580
|
function useVerificationRepo() {
|
|
10581
10581
|
const db2 = useAtlas11.getDb();
|
|
@@ -10805,6 +10805,28 @@ function useVerificationRepo() {
|
|
|
10805
10805
|
throw new InternalServerError8("Error updating verification status.");
|
|
10806
10806
|
}
|
|
10807
10807
|
}
|
|
10808
|
+
async function reissuePendingById(_id, { metadata, expireAt }) {
|
|
10809
|
+
try {
|
|
10810
|
+
_id = new ObjectId17(_id);
|
|
10811
|
+
} catch (error) {
|
|
10812
|
+
throw new BadRequestError17("Invalid verification ID format.");
|
|
10813
|
+
}
|
|
10814
|
+
try {
|
|
10815
|
+
const result = await collection.updateOne(
|
|
10816
|
+
{ _id, status: "pending" },
|
|
10817
|
+
{ $set: { metadata, expireAt, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
10818
|
+
);
|
|
10819
|
+
delNamespace().catch(
|
|
10820
|
+
(err) => logger8.error(`Failed to clear cache for namespace: ${namespace_collection3}`, err)
|
|
10821
|
+
);
|
|
10822
|
+
delCache(makeCacheKey6(namespace_collection3, { _id })).catch(
|
|
10823
|
+
(err) => logger8.error(`Failed to delete cache for verification ${_id}`, err)
|
|
10824
|
+
);
|
|
10825
|
+
return result.modifiedCount;
|
|
10826
|
+
} catch (error) {
|
|
10827
|
+
throw new InternalServerError8("Error re-sending the invitation.");
|
|
10828
|
+
}
|
|
10829
|
+
}
|
|
10808
10830
|
async function getByStatus(status) {
|
|
10809
10831
|
try {
|
|
10810
10832
|
const data = await collection.find({ status }).toArray();
|
|
@@ -10874,6 +10896,7 @@ function useVerificationRepo() {
|
|
|
10874
10896
|
getVerifications,
|
|
10875
10897
|
getByIdByType,
|
|
10876
10898
|
updateStatusById,
|
|
10899
|
+
reissuePendingById,
|
|
10877
10900
|
getByStatus,
|
|
10878
10901
|
findOne,
|
|
10879
10902
|
completePendingInvites
|
|
@@ -16935,7 +16958,8 @@ function useVerificationService() {
|
|
|
16935
16958
|
add,
|
|
16936
16959
|
getById: _getById,
|
|
16937
16960
|
updateStatusById: _updateStatusById,
|
|
16938
|
-
getByStatus: _getByStatus
|
|
16961
|
+
getByStatus: _getByStatus,
|
|
16962
|
+
reissuePendingById
|
|
16939
16963
|
} = useVerificationRepo();
|
|
16940
16964
|
const { getUserByEmail } = useUserRepo();
|
|
16941
16965
|
const { getById: getOrgById, getByEmail: getOrgByEmail } = useOrgRepo();
|
|
@@ -17010,13 +17034,6 @@ function useVerificationService() {
|
|
|
17010
17034
|
}
|
|
17011
17035
|
const verificationIds = [];
|
|
17012
17036
|
for (const app of apps) {
|
|
17013
|
-
await useVerificationRepo().findOne({
|
|
17014
|
-
type,
|
|
17015
|
-
email,
|
|
17016
|
-
"metadata.app": app,
|
|
17017
|
-
"metadata.org": metadata.org,
|
|
17018
|
-
"metadata.siteId": metadata.siteId
|
|
17019
|
-
});
|
|
17020
17037
|
const value = {
|
|
17021
17038
|
type,
|
|
17022
17039
|
email,
|
|
@@ -17027,7 +17044,24 @@ function useVerificationService() {
|
|
|
17027
17044
|
expireAt: new Date(Date.now() + 72 * 60 * 60 * 1e3).toISOString(),
|
|
17028
17045
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17029
17046
|
};
|
|
17030
|
-
const
|
|
17047
|
+
const stored = new MVerification({
|
|
17048
|
+
...value,
|
|
17049
|
+
metadata: { ...value.metadata }
|
|
17050
|
+
}).metadata;
|
|
17051
|
+
const pending = await useVerificationRepo().findOne({
|
|
17052
|
+
type,
|
|
17053
|
+
// same address in any letter case, as `completePendingInvites` reads it
|
|
17054
|
+
email: new RegExp(`^${email.replace(/[.*+?^$()|[\]{}\\]/g, "\\$&")}$`, "i"),
|
|
17055
|
+
status: "pending",
|
|
17056
|
+
"metadata.app": app,
|
|
17057
|
+
"metadata.org": stored.org,
|
|
17058
|
+
"metadata.siteId": stored.siteId
|
|
17059
|
+
});
|
|
17060
|
+
const reissued = pending?._id && await reissuePendingById(pending._id, {
|
|
17061
|
+
metadata: stored,
|
|
17062
|
+
expireAt: value.expireAt
|
|
17063
|
+
});
|
|
17064
|
+
const createdId = reissued ? pending._id : await add(value);
|
|
17031
17065
|
verificationIds.push(createdId.toString());
|
|
17032
17066
|
const link = `${APP_MAIN}/verify/invitation/${createdId}`;
|
|
17033
17067
|
const emailContent = compileHandlebar2({
|
|
@@ -29191,6 +29225,7 @@ function useMemberController() {
|
|
|
29191
29225
|
// src/controllers/verification.controller.ts
|
|
29192
29226
|
import { BadRequestError as BadRequestError51, logger as logger38 } from "@7365admin1/node-server-utils";
|
|
29193
29227
|
import Joi28 from "joi";
|
|
29228
|
+
var withoutEmail = (payload) => JSON.stringify({ ...payload, email: payload?.email ? "[redacted]" : void 0 });
|
|
29194
29229
|
function callerId2(req) {
|
|
29195
29230
|
const user = req.user;
|
|
29196
29231
|
return user?.user?.toString?.() || user?._id?.toString?.();
|
|
@@ -29257,7 +29292,7 @@ function useVerificationController() {
|
|
|
29257
29292
|
const payload = { ...req.body };
|
|
29258
29293
|
logger38.log({
|
|
29259
29294
|
level: "info",
|
|
29260
|
-
message: `[invite/user] payload: ${
|
|
29295
|
+
message: `[invite/user] payload: ${withoutEmail(payload)}`
|
|
29261
29296
|
});
|
|
29262
29297
|
const validation = Joi28.object({
|
|
29263
29298
|
email: Joi28.string().email().required(),
|
|
@@ -29313,7 +29348,7 @@ function useVerificationController() {
|
|
|
29313
29348
|
} catch (error2) {
|
|
29314
29349
|
logger38.log({
|
|
29315
29350
|
level: "error",
|
|
29316
|
-
message: `[invite/user] error for payload ${
|
|
29351
|
+
message: `[invite/user] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29317
29352
|
});
|
|
29318
29353
|
next(error2);
|
|
29319
29354
|
return;
|
|
@@ -29323,7 +29358,7 @@ function useVerificationController() {
|
|
|
29323
29358
|
const payload = { ...req.body };
|
|
29324
29359
|
logger38.log({
|
|
29325
29360
|
level: "info",
|
|
29326
|
-
message: `[invite/member] payload: ${
|
|
29361
|
+
message: `[invite/member] payload: ${withoutEmail(payload)}`
|
|
29327
29362
|
});
|
|
29328
29363
|
const validation = Joi28.object({
|
|
29329
29364
|
email: Joi28.string().email().required(),
|
|
@@ -29375,7 +29410,7 @@ function useVerificationController() {
|
|
|
29375
29410
|
} catch (error2) {
|
|
29376
29411
|
logger38.log({
|
|
29377
29412
|
level: "error",
|
|
29378
|
-
message: `[invite/member] error for payload ${
|
|
29413
|
+
message: `[invite/member] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29379
29414
|
});
|
|
29380
29415
|
next(error2);
|
|
29381
29416
|
return;
|
|
@@ -29385,7 +29420,7 @@ function useVerificationController() {
|
|
|
29385
29420
|
const payload = req.body;
|
|
29386
29421
|
logger38.log({
|
|
29387
29422
|
level: "info",
|
|
29388
|
-
message: `[service-providers/invite] payload: ${
|
|
29423
|
+
message: `[service-providers/invite] payload: ${withoutEmail(payload)}`
|
|
29389
29424
|
});
|
|
29390
29425
|
const validation = Joi28.object({
|
|
29391
29426
|
email: Joi28.string().email().required(),
|
|
@@ -29442,7 +29477,7 @@ function useVerificationController() {
|
|
|
29442
29477
|
} catch (error2) {
|
|
29443
29478
|
logger38.log({
|
|
29444
29479
|
level: "error",
|
|
29445
|
-
message: `[service-providers/invite] error for payload ${
|
|
29480
|
+
message: `[service-providers/invite] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29446
29481
|
});
|
|
29447
29482
|
next(error2);
|
|
29448
29483
|
return;
|
|
@@ -96921,6 +96956,7 @@ export {
|
|
|
96921
96956
|
incidents_namespace_collection,
|
|
96922
96957
|
invitationOffersRole,
|
|
96923
96958
|
isCameraEntitled,
|
|
96959
|
+
isDuplicateMemberError,
|
|
96924
96960
|
isDuplicateVersionError,
|
|
96925
96961
|
isLikelySelfServiceEmail,
|
|
96926
96962
|
isPatrolCctvCamera,
|