@7365admin1/core 3.74.0 → 3.75.1
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.js +48 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +48 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/test/backfill-org-owner-roles.test.mjs +6 -1
- package/test/default-staff-role.test.mjs +1 -1
- package/test/e2e/client-invite-service365.e2e.test.mjs +107 -1
- package/test/org-default-roles.test.mjs +11 -0
- package/test/service-app-type.test.mjs +35 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @iservice365/core
|
|
2
2
|
|
|
3
|
+
## 3.75.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- da435e7: Membership and role lookups by type match every stored spelling of an application: a Property Management lookup finds rows stored as `real_estate_developer` (written before 3.75.0) as well as `property_management_agency`, including the module deny list and the owner-grant cap.
|
|
8
|
+
|
|
9
|
+
## 3.75.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 75fb139: Real Estate Developer clients use the Property Management application: membership and role types `real_estate_developer` are stored and looked up as `property_management_agency`, so a developer's owner can open the Property Management app and the owner grant caps their roles.
|
|
14
|
+
|
|
3
15
|
## 3.74.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -3974,6 +3974,30 @@ function useUserRepo() {
|
|
|
3974
3974
|
var import_node_server_utils17 = require("@7365admin1/node-server-utils");
|
|
3975
3975
|
var import_uuid = require("uuid");
|
|
3976
3976
|
|
|
3977
|
+
// src/utils/service-app-type.util.ts
|
|
3978
|
+
var APP_TYPE_ALIASES = Object.freeze({
|
|
3979
|
+
real_estate_developer: "property_management_agency"
|
|
3980
|
+
});
|
|
3981
|
+
function serviceAppType(type) {
|
|
3982
|
+
if (typeof type !== "string")
|
|
3983
|
+
return type;
|
|
3984
|
+
return APP_TYPE_ALIASES[type] ?? type;
|
|
3985
|
+
}
|
|
3986
|
+
function storedAppTypes(type) {
|
|
3987
|
+
const app = serviceAppType(type);
|
|
3988
|
+
return [
|
|
3989
|
+
app,
|
|
3990
|
+
...Object.keys(APP_TYPE_ALIASES).filter((alias) => APP_TYPE_ALIASES[alias] === app)
|
|
3991
|
+
];
|
|
3992
|
+
}
|
|
3993
|
+
function appTypeQuery(type) {
|
|
3994
|
+
const types = storedAppTypes(type);
|
|
3995
|
+
return types.length === 1 ? types[0] : { $in: types };
|
|
3996
|
+
}
|
|
3997
|
+
function sameAppType(a, b) {
|
|
3998
|
+
return !!a && !!b && serviceAppType(a) === serviceAppType(b);
|
|
3999
|
+
}
|
|
4000
|
+
|
|
3977
4001
|
// src/repositories/member.repo.ts
|
|
3978
4002
|
var import_node_server_utils14 = require("@7365admin1/node-server-utils");
|
|
3979
4003
|
|
|
@@ -4126,7 +4150,7 @@ function useMemberRepo() {
|
|
|
4126
4150
|
}
|
|
4127
4151
|
async function add(value, session) {
|
|
4128
4152
|
try {
|
|
4129
|
-
value = MMember(value);
|
|
4153
|
+
value = MMember({ ...value, type: serviceAppType(value.type) });
|
|
4130
4154
|
await collection.insertOne(value, { session });
|
|
4131
4155
|
delNamespace().then(() => {
|
|
4132
4156
|
import_node_server_utils14.logger.info(`Cache cleared for namespace: ${namespace_collection3}`);
|
|
@@ -4254,6 +4278,7 @@ function useMemberRepo() {
|
|
|
4254
4278
|
}
|
|
4255
4279
|
}
|
|
4256
4280
|
async function getByUserIdType(user, type) {
|
|
4281
|
+
type = serviceAppType(type);
|
|
4257
4282
|
try {
|
|
4258
4283
|
user = new import_mongodb13.ObjectId(user);
|
|
4259
4284
|
} catch (error) {
|
|
@@ -4269,7 +4294,7 @@ function useMemberRepo() {
|
|
|
4269
4294
|
return cachedData;
|
|
4270
4295
|
}
|
|
4271
4296
|
try {
|
|
4272
|
-
const data = await collection.findOne({ user, type });
|
|
4297
|
+
const data = await collection.findOne({ user, type: appTypeQuery(type) });
|
|
4273
4298
|
if (!data) {
|
|
4274
4299
|
throw new import_node_server_utils14.NotFoundError("Member not found.");
|
|
4275
4300
|
}
|
|
@@ -4413,7 +4438,7 @@ function useMemberRepo() {
|
|
|
4413
4438
|
search = search || "";
|
|
4414
4439
|
page = page > 0 ? page - 1 : 0;
|
|
4415
4440
|
const query2 = {
|
|
4416
|
-
type,
|
|
4441
|
+
type: type ? appTypeQuery(type) : type,
|
|
4417
4442
|
status
|
|
4418
4443
|
};
|
|
4419
4444
|
const cacheOptions = {
|
|
@@ -4542,7 +4567,7 @@ function useMemberRepo() {
|
|
|
4542
4567
|
const query2 = {
|
|
4543
4568
|
user,
|
|
4544
4569
|
org: { $nin: [null, ""] },
|
|
4545
|
-
type
|
|
4570
|
+
type: appTypeQuery(type)
|
|
4546
4571
|
};
|
|
4547
4572
|
const cacheOptions = {
|
|
4548
4573
|
page,
|
|
@@ -4935,6 +4960,7 @@ function useMemberRepo() {
|
|
|
4935
4960
|
}
|
|
4936
4961
|
}
|
|
4937
4962
|
async function getByUserIdTypeOrg(user, type, org) {
|
|
4963
|
+
type = serviceAppType(type);
|
|
4938
4964
|
try {
|
|
4939
4965
|
user = new import_mongodb13.ObjectId(user);
|
|
4940
4966
|
} catch {
|
|
@@ -4958,7 +4984,7 @@ function useMemberRepo() {
|
|
|
4958
4984
|
try {
|
|
4959
4985
|
const data = await collection.findOne({
|
|
4960
4986
|
user,
|
|
4961
|
-
type,
|
|
4987
|
+
type: appTypeQuery(type),
|
|
4962
4988
|
org
|
|
4963
4989
|
});
|
|
4964
4990
|
if (!data) {
|
|
@@ -10536,7 +10562,7 @@ function pickSiteMembership(rows, type, site, org = "") {
|
|
|
10536
10562
|
if (!site)
|
|
10537
10563
|
return null;
|
|
10538
10564
|
const live = rows.filter(
|
|
10539
|
-
(m) => m.type
|
|
10565
|
+
(m) => sameAppType(m.type, type) && isLiveMembership(m) && (!org || idOf2(m.org) === org)
|
|
10540
10566
|
);
|
|
10541
10567
|
const atSite = live.find((m) => idOf2(m.siteId) === site);
|
|
10542
10568
|
if (atSite)
|
|
@@ -10550,10 +10576,10 @@ function pickLookupMembership(rows, type, site = "", org = "") {
|
|
|
10550
10576
|
const atSite = site ? pickSiteMembership(list, type, site, org) : null;
|
|
10551
10577
|
if (atSite)
|
|
10552
10578
|
return atSite;
|
|
10553
|
-
const inOrg = org ? list.find((m) => m.type
|
|
10579
|
+
const inOrg = org ? list.find((m) => sameAppType(m.type, type) && idOf2(m.org) === org.toLowerCase()) : void 0;
|
|
10554
10580
|
if (inOrg && isLiveMembership(inOrg))
|
|
10555
10581
|
return inOrg;
|
|
10556
|
-
return list.find((m) => m.type
|
|
10582
|
+
return list.find((m) => sameAppType(m.type, type)) ?? null;
|
|
10557
10583
|
}
|
|
10558
10584
|
function memberListSiteScope(memberships, org) {
|
|
10559
10585
|
const inOrg = (memberships ?? []).filter((m) => idOf2(m.org) === idOf2(org));
|
|
@@ -12442,7 +12468,7 @@ function useRoleRepo() {
|
|
|
12442
12468
|
const { delNamespace, setCache, getCache } = (0, import_node_server_utils42.useCache)(namespace_collection3);
|
|
12443
12469
|
const { delNamespace: _delDashboardNameSpace } = (0, import_node_server_utils42.useCache)("dashboard");
|
|
12444
12470
|
async function addRole(value, session) {
|
|
12445
|
-
value = new MRole(value);
|
|
12471
|
+
value = new MRole({ ...value, type: serviceAppType(value.type) });
|
|
12446
12472
|
try {
|
|
12447
12473
|
const res = await collection.insertOne(value, { session });
|
|
12448
12474
|
delNamespace().then(() => {
|
|
@@ -12506,7 +12532,7 @@ function useRoleRepo() {
|
|
|
12506
12532
|
return cachedData;
|
|
12507
12533
|
}
|
|
12508
12534
|
try {
|
|
12509
|
-
const data = await collection.find({ org, permissions: "*", type, status: "active" }).toArray();
|
|
12535
|
+
const data = await collection.find({ org, permissions: "*", type: appTypeQuery(type), status: "active" }).toArray();
|
|
12510
12536
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
12511
12537
|
import_node_server_utils42.logger.info(`Cache set for key: ${cacheKey}`);
|
|
12512
12538
|
}).catch((err) => {
|
|
@@ -12545,7 +12571,8 @@ function useRoleRepo() {
|
|
|
12545
12571
|
if (!name) {
|
|
12546
12572
|
throw new import_node_server_utils42.BadRequestError("Role name is required.");
|
|
12547
12573
|
}
|
|
12548
|
-
|
|
12574
|
+
type = serviceAppType(type);
|
|
12575
|
+
const query2 = type ? { name, type: appTypeQuery(type) } : { name };
|
|
12549
12576
|
try {
|
|
12550
12577
|
const cacheKey = (0, import_node_server_utils42.makeCacheKey)(namespace_collection3, query2);
|
|
12551
12578
|
const cachedData = await getCache(cacheKey);
|
|
@@ -12601,8 +12628,8 @@ function useRoleRepo() {
|
|
|
12601
12628
|
cacheOptions.search = search;
|
|
12602
12629
|
}
|
|
12603
12630
|
if (type) {
|
|
12604
|
-
query2.type = type;
|
|
12605
|
-
cacheOptions.type = type;
|
|
12631
|
+
query2.type = appTypeQuery(type);
|
|
12632
|
+
cacheOptions.type = serviceAppType(type);
|
|
12606
12633
|
}
|
|
12607
12634
|
const cacheKey = (0, import_node_server_utils42.makeCacheKey)(namespace_collection3, cacheOptions);
|
|
12608
12635
|
const cachedData = await getCache(cacheKey);
|
|
@@ -15216,13 +15243,14 @@ function defaultOwnerRoles(org, nature, appOwnerPermissions) {
|
|
|
15216
15243
|
{ ...owner, type: "organization" },
|
|
15217
15244
|
{ ...administrator, type: "organization" }
|
|
15218
15245
|
];
|
|
15219
|
-
|
|
15246
|
+
const appType = serviceAppType(nature);
|
|
15247
|
+
if (appType && APP_SERVICE_TYPES.has(appType)) {
|
|
15220
15248
|
roles.push({
|
|
15221
15249
|
...owner,
|
|
15222
|
-
type:
|
|
15250
|
+
type: appType,
|
|
15223
15251
|
...appOwnerPermissions?.length && { permissions: [...appOwnerPermissions] }
|
|
15224
15252
|
});
|
|
15225
|
-
roles.push({ ...administrator, type:
|
|
15253
|
+
roles.push({ ...administrator, type: appType });
|
|
15226
15254
|
}
|
|
15227
15255
|
return roles;
|
|
15228
15256
|
}
|
|
@@ -15307,15 +15335,16 @@ async function moduleCeiling(org, site) {
|
|
|
15307
15335
|
}
|
|
15308
15336
|
async function ownerGrantCeiling(org, type) {
|
|
15309
15337
|
const orgId = org?.toString() ?? "";
|
|
15338
|
+
type = serviceAppType(type);
|
|
15310
15339
|
if (!orgId || !type)
|
|
15311
15340
|
return null;
|
|
15312
15341
|
try {
|
|
15313
15342
|
const orgDoc = await useOrgRepo().getById(orgId).catch(() => null);
|
|
15314
|
-
if (!orgDoc?.invitedRole || orgDoc
|
|
15343
|
+
if (!orgDoc?.invitedRole || !sameAppType(orgDoc?.nature, type))
|
|
15315
15344
|
return null;
|
|
15316
15345
|
const role = await useRoleRepo().getRoleById(String(orgDoc.invitedRole)).catch(() => null);
|
|
15317
15346
|
const permissions = role?.permissions;
|
|
15318
|
-
const chosen = role && String(role.org ?? "") === orgId && role.default === true && role.type
|
|
15347
|
+
const chosen = role && String(role.org ?? "") === orgId && role.default === true && sameAppType(role.type, type) && Array.isArray(permissions) && permissions.length > 0 && !permissions.includes("*");
|
|
15319
15348
|
return chosen ? permissions.map(String) : null;
|
|
15320
15349
|
} catch {
|
|
15321
15350
|
return null;
|
|
@@ -26267,7 +26296,7 @@ function useOrgController() {
|
|
|
26267
26296
|
invitedModules?.permissions
|
|
26268
26297
|
);
|
|
26269
26298
|
const appOwnerRole = invitedModules?.permissions.length ? seededRoles.find(
|
|
26270
|
-
(role) => role.type
|
|
26299
|
+
(role) => sameAppType(role.type, body.nature) && role.name === "owner"
|
|
26271
26300
|
) : void 0;
|
|
26272
26301
|
if (appOwnerRole) {
|
|
26273
26302
|
try {
|