@7365admin1/core 3.68.2 → 3.69.0
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 +58 -51
- package/dist/index.js +99 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +107 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/client-invite-modules.e2e.test.mjs +164 -0
- package/test/e2e/user-invite-dedupe.e2e.test.mjs +138 -0
package/dist/index.mjs
CHANGED
|
@@ -10519,17 +10519,6 @@ import {
|
|
|
10519
10519
|
useAtlas as useAtlas23
|
|
10520
10520
|
} from "@7365admin1/node-server-utils";
|
|
10521
10521
|
|
|
10522
|
-
// src/repositories/verification.repo.ts
|
|
10523
|
-
import {
|
|
10524
|
-
BadRequestError as BadRequestError17,
|
|
10525
|
-
InternalServerError as InternalServerError8,
|
|
10526
|
-
logger as logger8,
|
|
10527
|
-
makeCacheKey as makeCacheKey6,
|
|
10528
|
-
paginate as paginate6,
|
|
10529
|
-
useAtlas as useAtlas11,
|
|
10530
|
-
useCache as useCache8
|
|
10531
|
-
} from "@7365admin1/node-server-utils";
|
|
10532
|
-
|
|
10533
10522
|
// src/models/verification.model.ts
|
|
10534
10523
|
import { BadRequestError as BadRequestError16 } from "@7365admin1/node-server-utils";
|
|
10535
10524
|
import { ObjectId as ObjectId16 } from "mongodb";
|
|
@@ -10578,6 +10567,15 @@ var MVerification = class {
|
|
|
10578
10567
|
};
|
|
10579
10568
|
|
|
10580
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";
|
|
10581
10579
|
import { ObjectId as ObjectId17 } from "mongodb";
|
|
10582
10580
|
function useVerificationRepo() {
|
|
10583
10581
|
const db2 = useAtlas11.getDb();
|
|
@@ -10807,6 +10805,28 @@ function useVerificationRepo() {
|
|
|
10807
10805
|
throw new InternalServerError8("Error updating verification status.");
|
|
10808
10806
|
}
|
|
10809
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
|
+
}
|
|
10810
10830
|
async function getByStatus(status) {
|
|
10811
10831
|
try {
|
|
10812
10832
|
const data = await collection.find({ status }).toArray();
|
|
@@ -10876,6 +10896,7 @@ function useVerificationRepo() {
|
|
|
10876
10896
|
getVerifications,
|
|
10877
10897
|
getByIdByType,
|
|
10878
10898
|
updateStatusById,
|
|
10899
|
+
reissuePendingById,
|
|
10879
10900
|
getByStatus,
|
|
10880
10901
|
findOne,
|
|
10881
10902
|
completePendingInvites
|
|
@@ -16937,7 +16958,8 @@ function useVerificationService() {
|
|
|
16937
16958
|
add,
|
|
16938
16959
|
getById: _getById,
|
|
16939
16960
|
updateStatusById: _updateStatusById,
|
|
16940
|
-
getByStatus: _getByStatus
|
|
16961
|
+
getByStatus: _getByStatus,
|
|
16962
|
+
reissuePendingById
|
|
16941
16963
|
} = useVerificationRepo();
|
|
16942
16964
|
const { getUserByEmail } = useUserRepo();
|
|
16943
16965
|
const { getById: getOrgById, getByEmail: getOrgByEmail } = useOrgRepo();
|
|
@@ -17012,13 +17034,6 @@ function useVerificationService() {
|
|
|
17012
17034
|
}
|
|
17013
17035
|
const verificationIds = [];
|
|
17014
17036
|
for (const app of apps) {
|
|
17015
|
-
await useVerificationRepo().findOne({
|
|
17016
|
-
type,
|
|
17017
|
-
email,
|
|
17018
|
-
"metadata.app": app,
|
|
17019
|
-
"metadata.org": metadata.org,
|
|
17020
|
-
"metadata.siteId": metadata.siteId
|
|
17021
|
-
});
|
|
17022
17037
|
const value = {
|
|
17023
17038
|
type,
|
|
17024
17039
|
email,
|
|
@@ -17029,7 +17044,24 @@ function useVerificationService() {
|
|
|
17029
17044
|
expireAt: new Date(Date.now() + 72 * 60 * 60 * 1e3).toISOString(),
|
|
17030
17045
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17031
17046
|
};
|
|
17032
|
-
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);
|
|
17033
17065
|
verificationIds.push(createdId.toString());
|
|
17034
17066
|
const link = `${APP_MAIN}/verify/invitation/${createdId}`;
|
|
17035
17067
|
const emailContent = compileHandlebar2({
|
|
@@ -29193,6 +29225,7 @@ function useMemberController() {
|
|
|
29193
29225
|
// src/controllers/verification.controller.ts
|
|
29194
29226
|
import { BadRequestError as BadRequestError51, logger as logger38 } from "@7365admin1/node-server-utils";
|
|
29195
29227
|
import Joi28 from "joi";
|
|
29228
|
+
var withoutEmail = (payload) => JSON.stringify({ ...payload, email: payload?.email ? "[redacted]" : void 0 });
|
|
29196
29229
|
function callerId2(req) {
|
|
29197
29230
|
const user = req.user;
|
|
29198
29231
|
return user?.user?.toString?.() || user?._id?.toString?.();
|
|
@@ -29259,7 +29292,7 @@ function useVerificationController() {
|
|
|
29259
29292
|
const payload = { ...req.body };
|
|
29260
29293
|
logger38.log({
|
|
29261
29294
|
level: "info",
|
|
29262
|
-
message: `[invite/user] payload: ${
|
|
29295
|
+
message: `[invite/user] payload: ${withoutEmail(payload)}`
|
|
29263
29296
|
});
|
|
29264
29297
|
const validation = Joi28.object({
|
|
29265
29298
|
email: Joi28.string().email().required(),
|
|
@@ -29268,7 +29301,9 @@ function useVerificationController() {
|
|
|
29268
29301
|
name: Joi28.string().optional().allow("", null),
|
|
29269
29302
|
org: Joi28.string().hex().optional().allow("", null),
|
|
29270
29303
|
siteId: Joi28.string().hex().optional().allow("", null),
|
|
29271
|
-
siteName: Joi28.string().optional().allow("", null)
|
|
29304
|
+
siteName: Joi28.string().optional().allow("", null),
|
|
29305
|
+
// The modules Seven365 gives a NEW client (the console's Invite Client).
|
|
29306
|
+
modules: modulesSchema.optional()
|
|
29272
29307
|
});
|
|
29273
29308
|
const { error, value } = validation.validate(payload);
|
|
29274
29309
|
if (error) {
|
|
@@ -29283,12 +29318,24 @@ function useVerificationController() {
|
|
|
29283
29318
|
const {
|
|
29284
29319
|
email,
|
|
29285
29320
|
app,
|
|
29286
|
-
role,
|
|
29287
29321
|
name,
|
|
29288
29322
|
org,
|
|
29289
29323
|
siteId,
|
|
29290
|
-
siteName
|
|
29324
|
+
siteName,
|
|
29325
|
+
modules
|
|
29291
29326
|
} = value;
|
|
29327
|
+
const newClient = !org && !app.includes(PLATFORM_STAFF_MEMBER_TYPE);
|
|
29328
|
+
const role = newClient ? "" : value.role;
|
|
29329
|
+
let clientModules;
|
|
29330
|
+
if (modules !== void 0) {
|
|
29331
|
+
const invitedBy = await requireConsolePermission(req, "organizations");
|
|
29332
|
+
if (!newClient || app.length !== 1) {
|
|
29333
|
+
throw new BadRequestError51(
|
|
29334
|
+
"Modules can only be chosen when inviting a new client, one application at a time."
|
|
29335
|
+
);
|
|
29336
|
+
}
|
|
29337
|
+
clientModules = { modules: normaliseModules(modules), invitedBy };
|
|
29338
|
+
}
|
|
29292
29339
|
await requireInviteReach(req, org, app, role);
|
|
29293
29340
|
const verificationIds = await _createSimpleUserInvite({
|
|
29294
29341
|
email,
|
|
@@ -29298,7 +29345,8 @@ function useVerificationController() {
|
|
|
29298
29345
|
name,
|
|
29299
29346
|
org,
|
|
29300
29347
|
siteId,
|
|
29301
|
-
siteName
|
|
29348
|
+
siteName,
|
|
29349
|
+
...clientModules
|
|
29302
29350
|
}
|
|
29303
29351
|
});
|
|
29304
29352
|
const responseBody = {
|
|
@@ -29315,7 +29363,7 @@ function useVerificationController() {
|
|
|
29315
29363
|
} catch (error2) {
|
|
29316
29364
|
logger38.log({
|
|
29317
29365
|
level: "error",
|
|
29318
|
-
message: `[invite/user] error for payload ${
|
|
29366
|
+
message: `[invite/user] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29319
29367
|
});
|
|
29320
29368
|
next(error2);
|
|
29321
29369
|
return;
|
|
@@ -29325,7 +29373,7 @@ function useVerificationController() {
|
|
|
29325
29373
|
const payload = { ...req.body };
|
|
29326
29374
|
logger38.log({
|
|
29327
29375
|
level: "info",
|
|
29328
|
-
message: `[invite/member] payload: ${
|
|
29376
|
+
message: `[invite/member] payload: ${withoutEmail(payload)}`
|
|
29329
29377
|
});
|
|
29330
29378
|
const validation = Joi28.object({
|
|
29331
29379
|
email: Joi28.string().email().required(),
|
|
@@ -29377,7 +29425,7 @@ function useVerificationController() {
|
|
|
29377
29425
|
} catch (error2) {
|
|
29378
29426
|
logger38.log({
|
|
29379
29427
|
level: "error",
|
|
29380
|
-
message: `[invite/member] error for payload ${
|
|
29428
|
+
message: `[invite/member] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29381
29429
|
});
|
|
29382
29430
|
next(error2);
|
|
29383
29431
|
return;
|
|
@@ -29387,7 +29435,7 @@ function useVerificationController() {
|
|
|
29387
29435
|
const payload = req.body;
|
|
29388
29436
|
logger38.log({
|
|
29389
29437
|
level: "info",
|
|
29390
|
-
message: `[service-providers/invite] payload: ${
|
|
29438
|
+
message: `[service-providers/invite] payload: ${withoutEmail(payload)}`
|
|
29391
29439
|
});
|
|
29392
29440
|
const validation = Joi28.object({
|
|
29393
29441
|
email: Joi28.string().email().required(),
|
|
@@ -29444,7 +29492,7 @@ function useVerificationController() {
|
|
|
29444
29492
|
} catch (error2) {
|
|
29445
29493
|
logger38.log({
|
|
29446
29494
|
level: "error",
|
|
29447
|
-
message: `[service-providers/invite] error for payload ${
|
|
29495
|
+
message: `[service-providers/invite] error for payload ${withoutEmail(payload)}: ${error2.message}`
|
|
29448
29496
|
});
|
|
29449
29497
|
next(error2);
|
|
29450
29498
|
return;
|
|
@@ -31103,6 +31151,7 @@ function useOrgController() {
|
|
|
31103
31151
|
let invitedFrom = null;
|
|
31104
31152
|
let invitedRole = null;
|
|
31105
31153
|
let inviteAlreadyComplete = false;
|
|
31154
|
+
let invitedModules = null;
|
|
31106
31155
|
let self = null;
|
|
31107
31156
|
if (inviteId) {
|
|
31108
31157
|
const [invite, caller] = await Promise.all([
|
|
@@ -31115,6 +31164,11 @@ function useOrgController() {
|
|
|
31115
31164
|
invitedFrom = String(invite._id);
|
|
31116
31165
|
invitedRole = invite.metadata?.role ? String(invite.metadata.role) : null;
|
|
31117
31166
|
inviteAlreadyComplete = invite.status === "complete" /* COMPLETE */;
|
|
31167
|
+
const chosen = normaliseModules(invite.metadata?.modules);
|
|
31168
|
+
const invitedBy = invite.metadata?.invitedBy;
|
|
31169
|
+
if (chosen.length && invitedBy && invite.metadata?.app === body.nature) {
|
|
31170
|
+
invitedModules = { modules: chosen, invitedBy: String(invitedBy) };
|
|
31171
|
+
}
|
|
31118
31172
|
} else {
|
|
31119
31173
|
logger41.log({
|
|
31120
31174
|
level: "warn",
|
|
@@ -31130,7 +31184,29 @@ function useOrgController() {
|
|
|
31130
31184
|
);
|
|
31131
31185
|
}
|
|
31132
31186
|
}
|
|
31133
|
-
const _id = await _add({
|
|
31187
|
+
const _id = await _add({
|
|
31188
|
+
...body,
|
|
31189
|
+
createdBy,
|
|
31190
|
+
invitedFrom,
|
|
31191
|
+
invitedRole,
|
|
31192
|
+
...invitedModules && { modules: invitedModules.modules }
|
|
31193
|
+
});
|
|
31194
|
+
if (invitedModules) {
|
|
31195
|
+
await recordConsoleAction({
|
|
31196
|
+
action: "client.modules-changed" /* CLIENT_MODULES_CHANGED */,
|
|
31197
|
+
actor: invitedModules.invitedBy,
|
|
31198
|
+
org: String(_id),
|
|
31199
|
+
target: String(_id).toLowerCase(),
|
|
31200
|
+
targetType: "organization" /* ORGANIZATION */,
|
|
31201
|
+
after: pickAuditFields("client.modules-changed" /* CLIENT_MODULES_CHANGED */, {
|
|
31202
|
+
modules: invitedModules.modules.join(", "),
|
|
31203
|
+
moduleCount: invitedModules.modules.length,
|
|
31204
|
+
gateListHash: moduleListHash(invitedModules.modules),
|
|
31205
|
+
acknowledged: false,
|
|
31206
|
+
impactMemberCount: 0
|
|
31207
|
+
})
|
|
31208
|
+
});
|
|
31209
|
+
}
|
|
31134
31210
|
if (invitedFrom && !inviteAlreadyComplete) {
|
|
31135
31211
|
try {
|
|
31136
31212
|
await useVerificationRepoV2().updateStatusById(
|