@7365admin1/core 3.73.0 → 3.74.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 +2 -0
- package/dist/index.js +65 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -40
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/client-invite-service365.e2e.test.mjs +119 -0
- package/test/e2e/person-write-scope.e2e.test.mjs +57 -0
- package/test/people-create-gate.test.mjs +16 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @iservice365/core
|
|
2
2
|
|
|
3
|
+
## 3.74.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a30c5ea: Invite Client for a Property Management or real estate developer client can carry the Service365 resident app modules; onboarding writes them on the organisation
|
|
8
|
+
|
|
9
|
+
## 3.73.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- b66bf09: Enforce the reach check on `POST /api/people` by default: a signed-in caller can only create a person at a site (or organisation) they belong to or serve. `PEOPLE_CREATE_REACH_MODE=log` switches back to counting without refusing.
|
|
14
|
+
|
|
3
15
|
## 3.73.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -11262,6 +11262,8 @@ type TVerificationMetadataV2 = {
|
|
|
11262
11262
|
modules?: string[];
|
|
11263
11263
|
/** The new client owner's permissions in that application, chosen with the modules. */
|
|
11264
11264
|
permissions?: string[];
|
|
11265
|
+
/** A Property Management client's Service365 resident app switches, chosen with the modules. */
|
|
11266
|
+
residentAppModules?: Record<string, boolean>;
|
|
11265
11267
|
};
|
|
11266
11268
|
/**
|
|
11267
11269
|
* The one-time code an invitee types to prove they own the mailbox, held on the
|
package/dist/index.js
CHANGED
|
@@ -24198,6 +24198,44 @@ function useMemberController() {
|
|
|
24198
24198
|
// src/controllers/verification.controller.ts
|
|
24199
24199
|
var import_node_server_utils67 = require("@7365admin1/node-server-utils");
|
|
24200
24200
|
var import_joi28 = __toESM(require("joi"));
|
|
24201
|
+
|
|
24202
|
+
// src/utils/resident-app-modules.util.ts
|
|
24203
|
+
var RESIDENT_APP_NATURES = Object.freeze([
|
|
24204
|
+
"property_management_agency",
|
|
24205
|
+
"real_estate_developer"
|
|
24206
|
+
]);
|
|
24207
|
+
function effectiveResidentAppModules(orgModules, siteModules) {
|
|
24208
|
+
const org = asModules(orgModules);
|
|
24209
|
+
const site = asModules(siteModules);
|
|
24210
|
+
const effective = {};
|
|
24211
|
+
for (const key of residentAppModuleKeys) {
|
|
24212
|
+
effective[key] = org[key] !== false && site[key] !== false;
|
|
24213
|
+
}
|
|
24214
|
+
return effective;
|
|
24215
|
+
}
|
|
24216
|
+
function residentAppModulesAboveCeiling(orgModules, requested, stored) {
|
|
24217
|
+
const org = asModules(orgModules);
|
|
24218
|
+
const wanted = asModules(requested);
|
|
24219
|
+
const had = asModules(stored);
|
|
24220
|
+
return residentAppModuleKeys.filter(
|
|
24221
|
+
(key) => org[key] === false && wanted[key] === true && had[key] === false
|
|
24222
|
+
);
|
|
24223
|
+
}
|
|
24224
|
+
function residentAppModulesAboveCeilingMessage(rejected) {
|
|
24225
|
+
return `This client has not been given ${rejected.join(", ")} in the resident app, so a site cannot switch it on. Ask Seven365 to add it to the organisation first.`;
|
|
24226
|
+
}
|
|
24227
|
+
function withoutDerivedSiteMetadata(metadata) {
|
|
24228
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
24229
|
+
return metadata;
|
|
24230
|
+
}
|
|
24231
|
+
const { residentAppModulesEffective: _derived, ...stored } = metadata;
|
|
24232
|
+
return stored;
|
|
24233
|
+
}
|
|
24234
|
+
function asModules(value) {
|
|
24235
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
24236
|
+
}
|
|
24237
|
+
|
|
24238
|
+
// src/controllers/verification.controller.ts
|
|
24201
24239
|
var withoutEmail = (payload) => JSON.stringify({ ...payload, email: payload?.email ? "[redacted]" : void 0 });
|
|
24202
24240
|
function callerId2(req) {
|
|
24203
24241
|
const user = req.user;
|
|
@@ -24279,7 +24317,11 @@ function useVerificationController() {
|
|
|
24279
24317
|
modules: modulesSchema.optional(),
|
|
24280
24318
|
// The new client owner's permissions in that application, chosen with
|
|
24281
24319
|
// the modules (owner, 2026-09-15). Only accepted together with modules.
|
|
24282
|
-
permissions: permissionsSchema.optional()
|
|
24320
|
+
permissions: permissionsSchema.optional(),
|
|
24321
|
+
// The Service365 resident app switches for a Property Management (or
|
|
24322
|
+
// real estate developer) client, same shape the Client details card saves
|
|
24323
|
+
// to `organizations.residentAppModules`. Only accepted with modules.
|
|
24324
|
+
residentAppModules: residentAppModulesSchema.optional()
|
|
24283
24325
|
});
|
|
24284
24326
|
const { error, value } = validation.validate(payload);
|
|
24285
24327
|
if (error) {
|
|
@@ -24299,7 +24341,8 @@ function useVerificationController() {
|
|
|
24299
24341
|
siteId,
|
|
24300
24342
|
siteName,
|
|
24301
24343
|
modules,
|
|
24302
|
-
permissions
|
|
24344
|
+
permissions,
|
|
24345
|
+
residentAppModules
|
|
24303
24346
|
} = value;
|
|
24304
24347
|
const newClient = !org && !app.includes(PLATFORM_STAFF_MEMBER_TYPE);
|
|
24305
24348
|
const role = newClient ? "" : value.role;
|
|
@@ -24329,6 +24372,14 @@ function useVerificationController() {
|
|
|
24329
24372
|
}
|
|
24330
24373
|
clientModules.permissions = chosen;
|
|
24331
24374
|
}
|
|
24375
|
+
if (residentAppModules !== void 0) {
|
|
24376
|
+
if (!clientModules || !RESIDENT_APP_NATURES.includes(app[0])) {
|
|
24377
|
+
throw new import_node_server_utils67.BadRequestError(
|
|
24378
|
+
"Service365 resident app modules can only be chosen with the modules of a new Property Management client."
|
|
24379
|
+
);
|
|
24380
|
+
}
|
|
24381
|
+
clientModules.residentAppModules = residentAppModules;
|
|
24382
|
+
}
|
|
24332
24383
|
await requireInviteReach(req, org, app, role);
|
|
24333
24384
|
const verificationIds = await _createSimpleUserInvite({
|
|
24334
24385
|
email,
|
|
@@ -26145,10 +26196,12 @@ function useOrgController() {
|
|
|
26145
26196
|
const invitedBy = invite.metadata?.invitedBy;
|
|
26146
26197
|
if (chosen.length && invitedBy && invite.metadata?.app === body.nature) {
|
|
26147
26198
|
const permissions = clientInviteOwnerPermissionsOn() ? normalisePermissions(invite.metadata?.permissions) : [];
|
|
26199
|
+
const residentApp = RESIDENT_APP_NATURES.includes(body.nature) ? residentAppModulesSchema.validate(invite.metadata?.residentAppModules) : null;
|
|
26148
26200
|
invitedModules = {
|
|
26149
26201
|
modules: chosen,
|
|
26150
26202
|
invitedBy: String(invitedBy),
|
|
26151
|
-
permissions: permissionsOutsideModules(permissions, chosen).length ? [] : permissions
|
|
26203
|
+
permissions: permissionsOutsideModules(permissions, chosen).length ? [] : permissions,
|
|
26204
|
+
...residentApp?.value && !residentApp.error ? { residentAppModules: residentApp.value } : {}
|
|
26152
26205
|
};
|
|
26153
26206
|
}
|
|
26154
26207
|
} else {
|
|
@@ -26171,7 +26224,10 @@ function useOrgController() {
|
|
|
26171
26224
|
createdBy,
|
|
26172
26225
|
invitedFrom,
|
|
26173
26226
|
invitedRole,
|
|
26174
|
-
...invitedModules && { modules: invitedModules.modules }
|
|
26227
|
+
...invitedModules && { modules: invitedModules.modules },
|
|
26228
|
+
...invitedModules?.residentAppModules && {
|
|
26229
|
+
residentAppModules: invitedModules.residentAppModules
|
|
26230
|
+
}
|
|
26175
26231
|
});
|
|
26176
26232
|
if (invitedModules) {
|
|
26177
26233
|
await recordConsoleAction({
|
|
@@ -26185,7 +26241,10 @@ function useOrgController() {
|
|
|
26185
26241
|
moduleCount: invitedModules.modules.length,
|
|
26186
26242
|
gateListHash: moduleListHash(invitedModules.modules),
|
|
26187
26243
|
acknowledged: false,
|
|
26188
|
-
impactMemberCount: 0
|
|
26244
|
+
impactMemberCount: 0,
|
|
26245
|
+
...invitedModules.residentAppModules && {
|
|
26246
|
+
residentAppModulesOff: Object.keys(invitedModules.residentAppModules).filter((key) => invitedModules.residentAppModules[key] === false).join(", ")
|
|
26247
|
+
}
|
|
26189
26248
|
})
|
|
26190
26249
|
});
|
|
26191
26250
|
}
|
|
@@ -34788,40 +34847,6 @@ function useSiteService() {
|
|
|
34788
34847
|
|
|
34789
34848
|
// src/controllers/site.controller.ts
|
|
34790
34849
|
var import_node_server_utils109 = require("@7365admin1/node-server-utils");
|
|
34791
|
-
|
|
34792
|
-
// src/utils/resident-app-modules.util.ts
|
|
34793
|
-
function effectiveResidentAppModules(orgModules, siteModules) {
|
|
34794
|
-
const org = asModules(orgModules);
|
|
34795
|
-
const site = asModules(siteModules);
|
|
34796
|
-
const effective = {};
|
|
34797
|
-
for (const key of residentAppModuleKeys) {
|
|
34798
|
-
effective[key] = org[key] !== false && site[key] !== false;
|
|
34799
|
-
}
|
|
34800
|
-
return effective;
|
|
34801
|
-
}
|
|
34802
|
-
function residentAppModulesAboveCeiling(orgModules, requested, stored) {
|
|
34803
|
-
const org = asModules(orgModules);
|
|
34804
|
-
const wanted = asModules(requested);
|
|
34805
|
-
const had = asModules(stored);
|
|
34806
|
-
return residentAppModuleKeys.filter(
|
|
34807
|
-
(key) => org[key] === false && wanted[key] === true && had[key] === false
|
|
34808
|
-
);
|
|
34809
|
-
}
|
|
34810
|
-
function residentAppModulesAboveCeilingMessage(rejected) {
|
|
34811
|
-
return `This client has not been given ${rejected.join(", ")} in the resident app, so a site cannot switch it on. Ask Seven365 to add it to the organisation first.`;
|
|
34812
|
-
}
|
|
34813
|
-
function withoutDerivedSiteMetadata(metadata) {
|
|
34814
|
-
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
34815
|
-
return metadata;
|
|
34816
|
-
}
|
|
34817
|
-
const { residentAppModulesEffective: _derived, ...stored } = metadata;
|
|
34818
|
-
return stored;
|
|
34819
|
-
}
|
|
34820
|
-
function asModules(value) {
|
|
34821
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
34822
|
-
}
|
|
34823
|
-
|
|
34824
|
-
// src/controllers/site.controller.ts
|
|
34825
34850
|
var import_joi51 = __toESM(require("joi"));
|
|
34826
34851
|
var import_mongodb74 = require("mongodb");
|
|
34827
34852
|
async function requireSiteWrite(req, siteId) {
|
|
@@ -56330,7 +56355,7 @@ var import_node_server_utils149 = require("@7365admin1/node-server-utils");
|
|
|
56330
56355
|
var import_node_server_utils150 = require("@7365admin1/node-server-utils");
|
|
56331
56356
|
|
|
56332
56357
|
// src/utils/people-create-gate.util.ts
|
|
56333
|
-
var PEOPLE_CREATE_REACH_MODE_DEFAULT = "
|
|
56358
|
+
var PEOPLE_CREATE_REACH_MODE_DEFAULT = "enforce";
|
|
56334
56359
|
function peopleCreateReachMode(env2 = process.env) {
|
|
56335
56360
|
return gateMode(
|
|
56336
56361
|
env2.PEOPLE_CREATE_REACH_MODE,
|