@7365admin1/core 3.53.3 → 3.53.5
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 +26 -0
- package/dist/index.d.ts +197 -1
- package/dist/index.js +519 -477
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -185
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/invite-org-scope.test.mjs +7 -1
- package/test/role-member-org-scope.test.mjs +4 -1
- package/test/sp-approvals-console-gate.test.mjs +117 -0
- package/test/staff-bypass-tenant-scope.test.mjs +38 -0
package/dist/index.mjs
CHANGED
|
@@ -10496,7 +10496,7 @@ import {
|
|
|
10496
10496
|
BadRequestError as BadRequestError29,
|
|
10497
10497
|
NotFoundError as NotFoundError11,
|
|
10498
10498
|
InternalServerError as InternalServerError15,
|
|
10499
|
-
UnauthorizedError as
|
|
10499
|
+
UnauthorizedError as UnauthorizedError3,
|
|
10500
10500
|
useAtlas as useAtlas20
|
|
10501
10501
|
} from "@7365admin1/node-server-utils";
|
|
10502
10502
|
|
|
@@ -13430,9 +13430,13 @@ async function resolveInviteActor(userId) {
|
|
|
13430
13430
|
const members = await db2.collection("members").find({ user: new ObjectId25(id), status: { $ne: "deleted" } }).toArray();
|
|
13431
13431
|
const adminMember = members.find((m) => m.type === "admin");
|
|
13432
13432
|
let isSuperAdmin2 = false;
|
|
13433
|
+
let staffPermissions;
|
|
13433
13434
|
if (adminMember?.role && ObjectId25.isValid(adminMember.role.toString())) {
|
|
13434
13435
|
const role = await db2.collection("roles").findOne({ _id: new ObjectId25(adminMember.role.toString()), ...LIVE_ROLE });
|
|
13435
13436
|
isSuperAdmin2 = role?.type === "admin";
|
|
13437
|
+
if (isSuperAdmin2) {
|
|
13438
|
+
staffPermissions = Array.isArray(role?.permissions) ? role?.permissions : [];
|
|
13439
|
+
}
|
|
13436
13440
|
}
|
|
13437
13441
|
const orgIds = Array.from(
|
|
13438
13442
|
new Set(
|
|
@@ -13455,6 +13459,7 @@ async function resolveInviteActor(userId) {
|
|
|
13455
13459
|
id,
|
|
13456
13460
|
name: user?.name ?? adminMember?.name ?? "",
|
|
13457
13461
|
isSuperAdmin: isSuperAdmin2,
|
|
13462
|
+
staffPermissions,
|
|
13458
13463
|
orgIds,
|
|
13459
13464
|
propertyManagementOrgIds,
|
|
13460
13465
|
memberships: members.map((m) => ({
|
|
@@ -13557,7 +13562,7 @@ async function holdsRole(userId, roleId) {
|
|
|
13557
13562
|
// src/services/service-provider-invite.service.ts
|
|
13558
13563
|
import {
|
|
13559
13564
|
BadRequestError as BadRequestError28,
|
|
13560
|
-
UnauthorizedError,
|
|
13565
|
+
UnauthorizedError as UnauthorizedError2,
|
|
13561
13566
|
NotFoundError as NotFoundError10,
|
|
13562
13567
|
compileHandlebar,
|
|
13563
13568
|
getDirectory,
|
|
@@ -14796,6 +14801,169 @@ var NotificationService = class {
|
|
|
14796
14801
|
}
|
|
14797
14802
|
};
|
|
14798
14803
|
|
|
14804
|
+
// src/utils/console-authz.util.ts
|
|
14805
|
+
import { UnauthorizedError } from "@7365admin1/node-server-utils";
|
|
14806
|
+
|
|
14807
|
+
// src/utils/console-permission.util.ts
|
|
14808
|
+
var CONSOLE_PERMISSIONS = Object.freeze({
|
|
14809
|
+
organizations: Object.freeze([
|
|
14810
|
+
"see-all-organizations",
|
|
14811
|
+
"see-organization-details"
|
|
14812
|
+
]),
|
|
14813
|
+
"promo-codes": Object.freeze([
|
|
14814
|
+
"create-promo-code",
|
|
14815
|
+
"see-promo-code-details",
|
|
14816
|
+
"edit-promo-code-details",
|
|
14817
|
+
"change-promo-code-status",
|
|
14818
|
+
"delete-promo-code"
|
|
14819
|
+
]),
|
|
14820
|
+
users: Object.freeze(["see-all-users", "see-user-details"]),
|
|
14821
|
+
invitations: Object.freeze([
|
|
14822
|
+
"create-invitation",
|
|
14823
|
+
"view-invitations",
|
|
14824
|
+
"cancel-invitation"
|
|
14825
|
+
]),
|
|
14826
|
+
subscriptions: Object.freeze([
|
|
14827
|
+
"see-all-subscriptions",
|
|
14828
|
+
"see-subscription-details",
|
|
14829
|
+
"manage-subscription"
|
|
14830
|
+
]),
|
|
14831
|
+
"sp-approvals": Object.freeze([
|
|
14832
|
+
"see-all-sp-approvals",
|
|
14833
|
+
"approve-sp",
|
|
14834
|
+
"reject-sp",
|
|
14835
|
+
"delete-sp-approval"
|
|
14836
|
+
]),
|
|
14837
|
+
"marketplace-vendors": Object.freeze([
|
|
14838
|
+
"see-all-marketplace-vendors",
|
|
14839
|
+
"see-marketplace-vendor-details"
|
|
14840
|
+
]),
|
|
14841
|
+
"platform-terms": Object.freeze([
|
|
14842
|
+
"see-platform-terms",
|
|
14843
|
+
"edit-platform-terms"
|
|
14844
|
+
]),
|
|
14845
|
+
"activity-history": Object.freeze(["see-activity-history"]),
|
|
14846
|
+
members: Object.freeze([
|
|
14847
|
+
"view-members",
|
|
14848
|
+
"assign-member-role",
|
|
14849
|
+
"suspend-member",
|
|
14850
|
+
"activate-member",
|
|
14851
|
+
"delete-member"
|
|
14852
|
+
]),
|
|
14853
|
+
"roles-and-permissions": Object.freeze([
|
|
14854
|
+
"add-role",
|
|
14855
|
+
"see-all-roles",
|
|
14856
|
+
"see-role-details",
|
|
14857
|
+
"update-role",
|
|
14858
|
+
"delete-role"
|
|
14859
|
+
])
|
|
14860
|
+
});
|
|
14861
|
+
var RESOURCE_SPELLINGS = Object.freeze({
|
|
14862
|
+
"roles-and-permissions": Object.freeze([
|
|
14863
|
+
"roles-and-permissions",
|
|
14864
|
+
"roles"
|
|
14865
|
+
]),
|
|
14866
|
+
roles: Object.freeze(["roles", "roles-and-permissions"])
|
|
14867
|
+
});
|
|
14868
|
+
function consoleSpellings(resource, action) {
|
|
14869
|
+
const resources = RESOURCE_SPELLINGS[resource] ?? [resource];
|
|
14870
|
+
return resources.map((name) => `${name}:${action}`);
|
|
14871
|
+
}
|
|
14872
|
+
function consoleRoleAllowsAll(held) {
|
|
14873
|
+
if (!Array.isArray(held) || held.length === 0)
|
|
14874
|
+
return true;
|
|
14875
|
+
return held.includes("*");
|
|
14876
|
+
}
|
|
14877
|
+
function consoleRoleAllows(held, resource, action) {
|
|
14878
|
+
if (consoleRoleAllowsAll(held))
|
|
14879
|
+
return true;
|
|
14880
|
+
const actions = CONSOLE_PERMISSIONS[resource];
|
|
14881
|
+
if (!actions?.length)
|
|
14882
|
+
return false;
|
|
14883
|
+
const wanted = action ? actions.includes(action) ? [action] : [] : actions;
|
|
14884
|
+
return wanted.some(
|
|
14885
|
+
(name) => consoleSpellings(resource, name).some(
|
|
14886
|
+
(spelling) => held.includes(spelling)
|
|
14887
|
+
)
|
|
14888
|
+
);
|
|
14889
|
+
}
|
|
14890
|
+
var CROSS_CLIENT_GRANT = {
|
|
14891
|
+
resource: "organizations"
|
|
14892
|
+
};
|
|
14893
|
+
function staffMayBypass(actor, grant = CROSS_CLIENT_GRANT) {
|
|
14894
|
+
if (!actor.isSuperAdmin)
|
|
14895
|
+
return false;
|
|
14896
|
+
return consoleRoleAllows(actor.staffPermissions, grant.resource, grant.action);
|
|
14897
|
+
}
|
|
14898
|
+
|
|
14899
|
+
// src/utils/console-authz.util.ts
|
|
14900
|
+
function callerId(req) {
|
|
14901
|
+
const user = req.user;
|
|
14902
|
+
return user?.user?.toString?.() || user?._id?.toString?.() || "";
|
|
14903
|
+
}
|
|
14904
|
+
async function requirePlatformStaff(req, grant) {
|
|
14905
|
+
const id = callerId(req);
|
|
14906
|
+
const role = id ? await resolveStaffRole(id) : null;
|
|
14907
|
+
if (!role) {
|
|
14908
|
+
throw new UnauthorizedError("Not authorized.");
|
|
14909
|
+
}
|
|
14910
|
+
if (grant && !consoleRoleAllows(role.permissions, grant.resource, grant.action)) {
|
|
14911
|
+
throw new UnauthorizedError("Not authorized.");
|
|
14912
|
+
}
|
|
14913
|
+
return id;
|
|
14914
|
+
}
|
|
14915
|
+
async function requireConsolePermission(req, resource, action) {
|
|
14916
|
+
return await requirePlatformStaff(req, { resource, action });
|
|
14917
|
+
}
|
|
14918
|
+
async function requireSelfOrPlatformStaff(req, userId, grant) {
|
|
14919
|
+
const id = callerId(req);
|
|
14920
|
+
const target = userId?.toString() ?? "";
|
|
14921
|
+
if (id && target && target === id)
|
|
14922
|
+
return id;
|
|
14923
|
+
return await requirePlatformStaff(req, grant);
|
|
14924
|
+
}
|
|
14925
|
+
async function requireOrgAccess(req, orgId) {
|
|
14926
|
+
return await requireOrgReach(req, orgId);
|
|
14927
|
+
}
|
|
14928
|
+
async function requirePlatformOwner(req, grant) {
|
|
14929
|
+
const id = callerId(req);
|
|
14930
|
+
if (!id || !await isPlatformOwner(id)) {
|
|
14931
|
+
throw new UnauthorizedError("Not authorized.");
|
|
14932
|
+
}
|
|
14933
|
+
if (grant)
|
|
14934
|
+
await requirePlatformStaff(req, grant);
|
|
14935
|
+
return id;
|
|
14936
|
+
}
|
|
14937
|
+
async function requireOrgReach(req, orgId) {
|
|
14938
|
+
const id = callerId(req);
|
|
14939
|
+
if (!id)
|
|
14940
|
+
throw new UnauthorizedError("Not authorized.");
|
|
14941
|
+
const org = orgId?.toString() ?? "";
|
|
14942
|
+
const actor = await resolveInviteActor(id);
|
|
14943
|
+
if (staffMayBypass(actor))
|
|
14944
|
+
return id;
|
|
14945
|
+
if (org && actor.orgIds.includes(org))
|
|
14946
|
+
return id;
|
|
14947
|
+
if (org && await hasOrgInvitation(id, org))
|
|
14948
|
+
return id;
|
|
14949
|
+
if (org && await hasOrgOwnership(id, org))
|
|
14950
|
+
return id;
|
|
14951
|
+
throw new UnauthorizedError("Not authorized.");
|
|
14952
|
+
}
|
|
14953
|
+
async function requireInviteReach(req, org, app) {
|
|
14954
|
+
const apps = Array.isArray(app) ? app : [app];
|
|
14955
|
+
if (apps.some((a) => a === PLATFORM_STAFF_MEMBER_TYPE)) {
|
|
14956
|
+
await requirePlatformStaff(req);
|
|
14957
|
+
}
|
|
14958
|
+
if (org)
|
|
14959
|
+
await requireOrgReach(req, org);
|
|
14960
|
+
}
|
|
14961
|
+
async function requireUserFieldWrite(req, userId, field, grant) {
|
|
14962
|
+
if (field === "email")
|
|
14963
|
+
return await requirePlatformStaff(req, grant);
|
|
14964
|
+
return await requireSelfOrPlatformStaff(req, userId, grant);
|
|
14965
|
+
}
|
|
14966
|
+
|
|
14799
14967
|
// src/services/service-provider-invite.service.ts
|
|
14800
14968
|
var INVITE_VALID_HOURS = 72;
|
|
14801
14969
|
function useServiceProviderInviteService() {
|
|
@@ -14886,18 +15054,18 @@ function useServiceProviderInviteService() {
|
|
|
14886
15054
|
return invite;
|
|
14887
15055
|
}
|
|
14888
15056
|
function assertOwnerOrSuperAdmin(actor, invite) {
|
|
14889
|
-
if (actor
|
|
15057
|
+
if (staffMayBypass(actor))
|
|
14890
15058
|
return;
|
|
14891
15059
|
const org = inviteOrgId(invite);
|
|
14892
15060
|
if (org && actor.orgIds.includes(org))
|
|
14893
15061
|
return;
|
|
14894
|
-
throw new
|
|
15062
|
+
throw new UnauthorizedError2(
|
|
14895
15063
|
"This invitation belongs to another organisation."
|
|
14896
15064
|
);
|
|
14897
15065
|
}
|
|
14898
15066
|
function assertSuperAdmin(actor) {
|
|
14899
|
-
if (!actor
|
|
14900
|
-
throw new
|
|
15067
|
+
if (!staffMayBypass(actor)) {
|
|
15068
|
+
throw new UnauthorizedError2(
|
|
14901
15069
|
"Only a Seven365 administrator can approve or reject invitations."
|
|
14902
15070
|
);
|
|
14903
15071
|
}
|
|
@@ -14910,7 +15078,7 @@ function useServiceProviderInviteService() {
|
|
|
14910
15078
|
async function actorFor(userId) {
|
|
14911
15079
|
const actor = await resolveInviteActor(userId);
|
|
14912
15080
|
if (!actor.id)
|
|
14913
|
-
throw new
|
|
15081
|
+
throw new UnauthorizedError2("Sign in to continue.");
|
|
14914
15082
|
return actor;
|
|
14915
15083
|
}
|
|
14916
15084
|
async function listApprovals({
|
|
@@ -14946,8 +15114,8 @@ function useServiceProviderInviteService() {
|
|
|
14946
15114
|
const actor = await actorFor(userId);
|
|
14947
15115
|
let scope = actor.orgIds;
|
|
14948
15116
|
if (orgId) {
|
|
14949
|
-
if (!actor
|
|
14950
|
-
throw new
|
|
15117
|
+
if (!staffMayBypass(actor) && !actor.orgIds.includes(orgId)) {
|
|
15118
|
+
throw new UnauthorizedError2(
|
|
14951
15119
|
"You are not a member of that organisation."
|
|
14952
15120
|
);
|
|
14953
15121
|
}
|
|
@@ -14957,7 +15125,7 @@ function useServiceProviderInviteService() {
|
|
|
14957
15125
|
statuses: statuses ?? [],
|
|
14958
15126
|
// A super admin asking for everything passes no scope; everyone else is
|
|
14959
15127
|
// pinned to their own organisations even if they ask for more.
|
|
14960
|
-
orgIds: actor
|
|
15128
|
+
orgIds: staffMayBypass(actor) && !orgId ? void 0 : scope,
|
|
14961
15129
|
search,
|
|
14962
15130
|
page,
|
|
14963
15131
|
limit
|
|
@@ -15106,7 +15274,7 @@ function useServiceProviderInviteService() {
|
|
|
15106
15274
|
);
|
|
15107
15275
|
const invitedUserId = user?._id?.toString();
|
|
15108
15276
|
if (!invitedUserId || invitedUserId !== userId) {
|
|
15109
|
-
throw new
|
|
15277
|
+
throw new UnauthorizedError2("This invitation was sent to someone else.");
|
|
15110
15278
|
}
|
|
15111
15279
|
}
|
|
15112
15280
|
async function decline({ id, userId }) {
|
|
@@ -15407,10 +15575,10 @@ function useVerificationService() {
|
|
|
15407
15575
|
const org = await getOrgById(orgId);
|
|
15408
15576
|
const actor = await resolveInviteActor(invitedBy);
|
|
15409
15577
|
if (!actor.id) {
|
|
15410
|
-
throw new
|
|
15578
|
+
throw new UnauthorizedError3("Sign in to continue.");
|
|
15411
15579
|
}
|
|
15412
|
-
if (!actor
|
|
15413
|
-
throw new
|
|
15580
|
+
if (!staffMayBypass(actor) && !actor.orgIds.includes(orgId)) {
|
|
15581
|
+
throw new UnauthorizedError3(
|
|
15414
15582
|
"You can only invite service providers to your own organisation's sites."
|
|
15415
15583
|
);
|
|
15416
15584
|
}
|
|
@@ -18059,161 +18227,6 @@ function usePersonRepo() {
|
|
|
18059
18227
|
};
|
|
18060
18228
|
}
|
|
18061
18229
|
|
|
18062
|
-
// src/utils/console-authz.util.ts
|
|
18063
|
-
import { UnauthorizedError as UnauthorizedError3 } from "@7365admin1/node-server-utils";
|
|
18064
|
-
|
|
18065
|
-
// src/utils/console-permission.util.ts
|
|
18066
|
-
var CONSOLE_PERMISSIONS = Object.freeze({
|
|
18067
|
-
organizations: Object.freeze([
|
|
18068
|
-
"see-all-organizations",
|
|
18069
|
-
"see-organization-details"
|
|
18070
|
-
]),
|
|
18071
|
-
"promo-codes": Object.freeze([
|
|
18072
|
-
"create-promo-code",
|
|
18073
|
-
"see-promo-code-details",
|
|
18074
|
-
"edit-promo-code-details",
|
|
18075
|
-
"change-promo-code-status",
|
|
18076
|
-
"delete-promo-code"
|
|
18077
|
-
]),
|
|
18078
|
-
users: Object.freeze(["see-all-users", "see-user-details"]),
|
|
18079
|
-
invitations: Object.freeze([
|
|
18080
|
-
"create-invitation",
|
|
18081
|
-
"view-invitations",
|
|
18082
|
-
"cancel-invitation"
|
|
18083
|
-
]),
|
|
18084
|
-
subscriptions: Object.freeze([
|
|
18085
|
-
"see-all-subscriptions",
|
|
18086
|
-
"see-subscription-details",
|
|
18087
|
-
"manage-subscription"
|
|
18088
|
-
]),
|
|
18089
|
-
"sp-approvals": Object.freeze([
|
|
18090
|
-
"see-all-sp-approvals",
|
|
18091
|
-
"approve-sp",
|
|
18092
|
-
"reject-sp",
|
|
18093
|
-
"delete-sp-approval"
|
|
18094
|
-
]),
|
|
18095
|
-
"marketplace-vendors": Object.freeze([
|
|
18096
|
-
"see-all-marketplace-vendors",
|
|
18097
|
-
"see-marketplace-vendor-details"
|
|
18098
|
-
]),
|
|
18099
|
-
"platform-terms": Object.freeze([
|
|
18100
|
-
"see-platform-terms",
|
|
18101
|
-
"edit-platform-terms"
|
|
18102
|
-
]),
|
|
18103
|
-
"activity-history": Object.freeze(["see-activity-history"]),
|
|
18104
|
-
members: Object.freeze([
|
|
18105
|
-
"view-members",
|
|
18106
|
-
"assign-member-role",
|
|
18107
|
-
"suspend-member",
|
|
18108
|
-
"activate-member",
|
|
18109
|
-
"delete-member"
|
|
18110
|
-
]),
|
|
18111
|
-
"roles-and-permissions": Object.freeze([
|
|
18112
|
-
"add-role",
|
|
18113
|
-
"see-all-roles",
|
|
18114
|
-
"see-role-details",
|
|
18115
|
-
"update-role",
|
|
18116
|
-
"delete-role"
|
|
18117
|
-
])
|
|
18118
|
-
});
|
|
18119
|
-
var RESOURCE_SPELLINGS = Object.freeze({
|
|
18120
|
-
"roles-and-permissions": Object.freeze([
|
|
18121
|
-
"roles-and-permissions",
|
|
18122
|
-
"roles"
|
|
18123
|
-
]),
|
|
18124
|
-
roles: Object.freeze(["roles", "roles-and-permissions"])
|
|
18125
|
-
});
|
|
18126
|
-
function consoleSpellings(resource, action) {
|
|
18127
|
-
const resources = RESOURCE_SPELLINGS[resource] ?? [resource];
|
|
18128
|
-
return resources.map((name) => `${name}:${action}`);
|
|
18129
|
-
}
|
|
18130
|
-
function consoleRoleAllowsAll(held) {
|
|
18131
|
-
if (!Array.isArray(held) || held.length === 0)
|
|
18132
|
-
return true;
|
|
18133
|
-
return held.includes("*");
|
|
18134
|
-
}
|
|
18135
|
-
function consoleRoleAllows(held, resource, action) {
|
|
18136
|
-
if (consoleRoleAllowsAll(held))
|
|
18137
|
-
return true;
|
|
18138
|
-
const actions = CONSOLE_PERMISSIONS[resource];
|
|
18139
|
-
if (!actions?.length)
|
|
18140
|
-
return false;
|
|
18141
|
-
const wanted = action ? actions.includes(action) ? [action] : [] : actions;
|
|
18142
|
-
return wanted.some(
|
|
18143
|
-
(name) => consoleSpellings(resource, name).some(
|
|
18144
|
-
(spelling) => held.includes(spelling)
|
|
18145
|
-
)
|
|
18146
|
-
);
|
|
18147
|
-
}
|
|
18148
|
-
|
|
18149
|
-
// src/utils/console-authz.util.ts
|
|
18150
|
-
function callerId(req) {
|
|
18151
|
-
const user = req.user;
|
|
18152
|
-
return user?.user?.toString?.() || user?._id?.toString?.() || "";
|
|
18153
|
-
}
|
|
18154
|
-
async function requirePlatformStaff(req, grant) {
|
|
18155
|
-
const id = callerId(req);
|
|
18156
|
-
const role = id ? await resolveStaffRole(id) : null;
|
|
18157
|
-
if (!role) {
|
|
18158
|
-
throw new UnauthorizedError3("Not authorized.");
|
|
18159
|
-
}
|
|
18160
|
-
if (grant && !consoleRoleAllows(role.permissions, grant.resource, grant.action)) {
|
|
18161
|
-
throw new UnauthorizedError3("Not authorized.");
|
|
18162
|
-
}
|
|
18163
|
-
return id;
|
|
18164
|
-
}
|
|
18165
|
-
async function requireConsolePermission(req, resource, action) {
|
|
18166
|
-
return await requirePlatformStaff(req, { resource, action });
|
|
18167
|
-
}
|
|
18168
|
-
async function requireSelfOrPlatformStaff(req, userId, grant) {
|
|
18169
|
-
const id = callerId(req);
|
|
18170
|
-
const target = userId?.toString() ?? "";
|
|
18171
|
-
if (id && target && target === id)
|
|
18172
|
-
return id;
|
|
18173
|
-
return await requirePlatformStaff(req, grant);
|
|
18174
|
-
}
|
|
18175
|
-
async function requireOrgAccess(req, orgId) {
|
|
18176
|
-
return await requireOrgReach(req, orgId);
|
|
18177
|
-
}
|
|
18178
|
-
async function requirePlatformOwner(req, grant) {
|
|
18179
|
-
const id = callerId(req);
|
|
18180
|
-
if (!id || !await isPlatformOwner(id)) {
|
|
18181
|
-
throw new UnauthorizedError3("Not authorized.");
|
|
18182
|
-
}
|
|
18183
|
-
if (grant)
|
|
18184
|
-
await requirePlatformStaff(req, grant);
|
|
18185
|
-
return id;
|
|
18186
|
-
}
|
|
18187
|
-
async function requireOrgReach(req, orgId) {
|
|
18188
|
-
const id = callerId(req);
|
|
18189
|
-
if (!id)
|
|
18190
|
-
throw new UnauthorizedError3("Not authorized.");
|
|
18191
|
-
const org = orgId?.toString() ?? "";
|
|
18192
|
-
const actor = await resolveInviteActor(id);
|
|
18193
|
-
if (actor.isSuperAdmin)
|
|
18194
|
-
return id;
|
|
18195
|
-
if (org && actor.orgIds.includes(org))
|
|
18196
|
-
return id;
|
|
18197
|
-
if (org && await hasOrgInvitation(id, org))
|
|
18198
|
-
return id;
|
|
18199
|
-
if (org && await hasOrgOwnership(id, org))
|
|
18200
|
-
return id;
|
|
18201
|
-
throw new UnauthorizedError3("Not authorized.");
|
|
18202
|
-
}
|
|
18203
|
-
async function requireInviteReach(req, org, app) {
|
|
18204
|
-
const apps = Array.isArray(app) ? app : [app];
|
|
18205
|
-
if (apps.some((a) => a === PLATFORM_STAFF_MEMBER_TYPE)) {
|
|
18206
|
-
await requirePlatformStaff(req);
|
|
18207
|
-
}
|
|
18208
|
-
if (org)
|
|
18209
|
-
await requireOrgReach(req, org);
|
|
18210
|
-
}
|
|
18211
|
-
async function requireUserFieldWrite(req, userId, field, grant) {
|
|
18212
|
-
if (field === "email")
|
|
18213
|
-
return await requirePlatformStaff(req, grant);
|
|
18214
|
-
return await requireSelfOrPlatformStaff(req, userId, grant);
|
|
18215
|
-
}
|
|
18216
|
-
|
|
18217
18230
|
// src/utils/user-response.util.ts
|
|
18218
18231
|
function publicIdentity(user) {
|
|
18219
18232
|
if (!user || typeof user !== "object")
|
|
@@ -26186,7 +26199,7 @@ async function requireSiteReach(req, site, permission) {
|
|
|
26186
26199
|
if (!siteId)
|
|
26187
26200
|
throw new UnauthorizedError6("Not authorized.");
|
|
26188
26201
|
const actor = await resolveInviteActor(callerId(req));
|
|
26189
|
-
if (actor
|
|
26202
|
+
if (staffMayBypass(actor))
|
|
26190
26203
|
return;
|
|
26191
26204
|
if (permission) {
|
|
26192
26205
|
await useCameraViewService().authorizeSite({
|
|
@@ -26201,8 +26214,9 @@ async function requireSiteReach(req, site, permission) {
|
|
|
26201
26214
|
async function siteReachOf(req) {
|
|
26202
26215
|
const actor = await resolveInviteActor(callerId(req));
|
|
26203
26216
|
const reachable = /* @__PURE__ */ new Map();
|
|
26217
|
+
const bypass = staffMayBypass(actor);
|
|
26204
26218
|
function canReach(record) {
|
|
26205
|
-
if (
|
|
26219
|
+
if (bypass)
|
|
26206
26220
|
return Promise.resolve(true);
|
|
26207
26221
|
if (!record)
|
|
26208
26222
|
return Promise.resolve(false);
|
|
@@ -26223,7 +26237,7 @@ async function siteReachOf(req) {
|
|
|
26223
26237
|
return reachable.get(site);
|
|
26224
26238
|
}
|
|
26225
26239
|
async function only(records) {
|
|
26226
|
-
if (
|
|
26240
|
+
if (bypass)
|
|
26227
26241
|
return records;
|
|
26228
26242
|
const verdicts = await Promise.all(records.map((r) => canReach(r)));
|
|
26229
26243
|
return records.filter((_, i) => verdicts[i]);
|
|
@@ -26237,7 +26251,7 @@ async function requireSiteReachIfSignedIn(req, site) {
|
|
|
26237
26251
|
}
|
|
26238
26252
|
async function entitledSites(req) {
|
|
26239
26253
|
const actor = await resolveInviteActor(callerId(req));
|
|
26240
|
-
if (actor
|
|
26254
|
+
if (staffMayBypass(actor))
|
|
26241
26255
|
return null;
|
|
26242
26256
|
if (actor.memberships.length === 0)
|
|
26243
26257
|
return [];
|
|
@@ -36942,13 +36956,13 @@ import { BadRequestError as BadRequestError91, logger as logger65 } from "@7365a
|
|
|
36942
36956
|
import Joi50 from "joi";
|
|
36943
36957
|
async function requireSiteWrite(req, siteId) {
|
|
36944
36958
|
const actor = await resolveInviteActor(callerId(req));
|
|
36945
|
-
if (actor
|
|
36959
|
+
if (staffMayBypass(actor))
|
|
36946
36960
|
return;
|
|
36947
36961
|
await useCameraViewService().entitleSite({ siteId, userId: actor.id });
|
|
36948
36962
|
}
|
|
36949
36963
|
async function requireSiteRead(req, siteId, site) {
|
|
36950
36964
|
const actor = await resolveInviteActor(callerId(req));
|
|
36951
|
-
if (actor
|
|
36965
|
+
if (staffMayBypass(actor))
|
|
36952
36966
|
return;
|
|
36953
36967
|
const owner = (site?.orgId ?? site?.org)?.toString?.() ?? "";
|
|
36954
36968
|
if (owner && actor.orgIds.includes(owner))
|
|
@@ -41818,7 +41832,7 @@ import {
|
|
|
41818
41832
|
async function requireEitherOrg(req, ...orgs) {
|
|
41819
41833
|
const wanted = orgs.map((org) => org?.toString?.() ?? "").filter((org) => Boolean(org));
|
|
41820
41834
|
const actor = await resolveInviteActor(callerId(req));
|
|
41821
|
-
if (actor
|
|
41835
|
+
if (staffMayBypass(actor))
|
|
41822
41836
|
return;
|
|
41823
41837
|
if (wanted.length === 0 || !wanted.some((org) => actor.orgIds.includes(org))) {
|
|
41824
41838
|
throw new UnauthorizedError10("Not authorized.");
|
|
@@ -41914,7 +41928,7 @@ function useCustomerSiteController() {
|
|
|
41914
41928
|
try {
|
|
41915
41929
|
await requireOrgAccess(req, org);
|
|
41916
41930
|
const actor = await resolveInviteActor(callerId(req));
|
|
41917
|
-
const siteScope = actor
|
|
41931
|
+
const siteScope = staffMayBypass(actor) ? null : orgSiteScope({ memberships: actor.memberships, org });
|
|
41918
41932
|
const data = await _getAll({
|
|
41919
41933
|
search,
|
|
41920
41934
|
page,
|
|
@@ -41948,7 +41962,7 @@ function useCustomerSiteController() {
|
|
|
41948
41962
|
}
|
|
41949
41963
|
try {
|
|
41950
41964
|
const actor = await resolveInviteActor(callerId(req));
|
|
41951
|
-
if (!actor
|
|
41965
|
+
if (!staffMayBypass(actor)) {
|
|
41952
41966
|
await useCameraViewService().entitleSite({
|
|
41953
41967
|
siteId: site,
|
|
41954
41968
|
userId: actor.id
|
|
@@ -57952,7 +57966,7 @@ function usePersonController() {
|
|
|
57952
57966
|
} = usePersonService();
|
|
57953
57967
|
async function entitlePerson(req, _id) {
|
|
57954
57968
|
const actor = await resolveInviteActor(callerId(req));
|
|
57955
|
-
if (actor
|
|
57969
|
+
if (staffMayBypass(actor))
|
|
57956
57970
|
return actor;
|
|
57957
57971
|
const person = await _getById(_id);
|
|
57958
57972
|
if (!person)
|
|
@@ -64621,7 +64635,7 @@ function useDocumentManagementController() {
|
|
|
64621
64635
|
return;
|
|
64622
64636
|
}
|
|
64623
64637
|
const actor = await resolveInviteActor(callerId(req));
|
|
64624
|
-
if (actor
|
|
64638
|
+
if (staffMayBypass(actor))
|
|
64625
64639
|
return;
|
|
64626
64640
|
const org = doc?.org?.toString() ?? "";
|
|
64627
64641
|
if (!org || !actor.orgIds.includes(org)) {
|
|
@@ -68652,7 +68666,7 @@ import { ObjectId as ObjectId123 } from "mongodb";
|
|
|
68652
68666
|
import { UnauthorizedError as UnauthorizedError17, useAtlas as useAtlas94 } from "@7365admin1/node-server-utils";
|
|
68653
68667
|
async function requireOwnUnit(req, site, unitId) {
|
|
68654
68668
|
const actor = await resolveInviteActor(callerId(req));
|
|
68655
|
-
if (actor
|
|
68669
|
+
if (staffMayBypass(actor))
|
|
68656
68670
|
return;
|
|
68657
68671
|
const unit = unitId?.toString?.() ?? "";
|
|
68658
68672
|
const siteId = site?.toString?.() ?? "";
|
|
@@ -77292,10 +77306,10 @@ function useOnlineFormController() {
|
|
|
77292
77306
|
const { actor } = await siteReachOf(req);
|
|
77293
77307
|
if (site) {
|
|
77294
77308
|
await requireSiteReach(req, site);
|
|
77295
|
-
} else if (!actor
|
|
77309
|
+
} else if (!staffMayBypass(actor)) {
|
|
77296
77310
|
throw new UnauthorizedError18("Not authorized.");
|
|
77297
77311
|
}
|
|
77298
|
-
if (org && !actor
|
|
77312
|
+
if (org && !staffMayBypass(actor) && !actor.orgIds.includes(org)) {
|
|
77299
77313
|
throw new UnauthorizedError18("Not authorized.");
|
|
77300
77314
|
}
|
|
77301
77315
|
const data = await _getAll({ search, page, limit, status, org, site });
|
|
@@ -77360,7 +77374,7 @@ function useOnlineFormController() {
|
|
|
77360
77374
|
}
|
|
77361
77375
|
if (payload.org) {
|
|
77362
77376
|
const { actor } = await siteReachOf(req);
|
|
77363
|
-
if (!actor
|
|
77377
|
+
if (!staffMayBypass(actor) && !actor.orgIds.includes(payload.org)) {
|
|
77364
77378
|
throw new UnauthorizedError18("Not authorized.");
|
|
77365
77379
|
}
|
|
77366
77380
|
}
|
|
@@ -84878,7 +84892,7 @@ function useVerificationServiceV2() {
|
|
|
84878
84892
|
if (!actor.id) {
|
|
84879
84893
|
throw new UnauthorizedError19("Sign in to continue.");
|
|
84880
84894
|
}
|
|
84881
|
-
if (!actor
|
|
84895
|
+
if (!staffMayBypass(actor) && !actor.orgIds.includes(orgId)) {
|
|
84882
84896
|
throw new UnauthorizedError19(
|
|
84883
84897
|
"You can only invite service providers to your own organisation's sites."
|
|
84884
84898
|
);
|
|
@@ -85380,6 +85394,11 @@ function useServiceProviderInviteController() {
|
|
|
85380
85394
|
}
|
|
85381
85395
|
async function approvals(req, res, next) {
|
|
85382
85396
|
try {
|
|
85397
|
+
await requireConsolePermission(
|
|
85398
|
+
req,
|
|
85399
|
+
"sp-approvals",
|
|
85400
|
+
"see-all-sp-approvals"
|
|
85401
|
+
);
|
|
85383
85402
|
const schema2 = Joi143.object({
|
|
85384
85403
|
status: Joi143.string().valid(
|
|
85385
85404
|
"awaiting-approval",
|
|
@@ -85406,6 +85425,11 @@ function useServiceProviderInviteController() {
|
|
|
85406
85425
|
}
|
|
85407
85426
|
async function pendingApprovalCount(req, res, next) {
|
|
85408
85427
|
try {
|
|
85428
|
+
await requireConsolePermission(
|
|
85429
|
+
req,
|
|
85430
|
+
"sp-approvals",
|
|
85431
|
+
"see-all-sp-approvals"
|
|
85432
|
+
);
|
|
85409
85433
|
res.json(await approvalCount({ userId: callerId5(req) }));
|
|
85410
85434
|
} catch (error) {
|
|
85411
85435
|
next(error);
|
|
@@ -85413,6 +85437,7 @@ function useServiceProviderInviteController() {
|
|
|
85413
85437
|
}
|
|
85414
85438
|
async function approve(req, res, next) {
|
|
85415
85439
|
try {
|
|
85440
|
+
await requireConsolePermission(req, "sp-approvals", "approve-sp");
|
|
85416
85441
|
res.json(await _approve({ id: inviteId(req), userId: callerId5(req) }));
|
|
85417
85442
|
} catch (error) {
|
|
85418
85443
|
logger198.log({ level: "error", message: `${error.message}` });
|
|
@@ -85421,6 +85446,7 @@ function useServiceProviderInviteController() {
|
|
|
85421
85446
|
}
|
|
85422
85447
|
async function reject(req, res, next) {
|
|
85423
85448
|
try {
|
|
85449
|
+
await requireConsolePermission(req, "sp-approvals", "reject-sp");
|
|
85424
85450
|
const { error, value } = Joi143.object({
|
|
85425
85451
|
reason: Joi143.string().trim().min(1).max(1e3).required()
|
|
85426
85452
|
}).validate(req.body ?? {});
|
|
@@ -92228,7 +92254,9 @@ export {
|
|
|
92228
92254
|
CLIENT_ACTIONS,
|
|
92229
92255
|
CLOCK_DRIFT_WARN_SECONDS,
|
|
92230
92256
|
CONSOLE_AUDIT_LABELS,
|
|
92257
|
+
CONSOLE_PERMISSIONS,
|
|
92231
92258
|
CONTRACTOR_TYPE_LABELS,
|
|
92259
|
+
CROSS_CLIENT_GRANT,
|
|
92232
92260
|
CURRENT_TIME_ENDPOINT,
|
|
92233
92261
|
CameraType,
|
|
92234
92262
|
ConsoleAuditAction,
|
|
@@ -92440,6 +92468,9 @@ export {
|
|
|
92440
92468
|
chatSchema,
|
|
92441
92469
|
clampPtzSpeed,
|
|
92442
92470
|
clockDriftSeconds,
|
|
92471
|
+
consoleRoleAllows,
|
|
92472
|
+
consoleRoleAllowsAll,
|
|
92473
|
+
consoleSpellings,
|
|
92443
92474
|
console_audit_namespace_collection,
|
|
92444
92475
|
createManpowerRemarksDaily,
|
|
92445
92476
|
customerSchema,
|
|
@@ -92539,6 +92570,8 @@ export {
|
|
|
92539
92570
|
relayForRecorder,
|
|
92540
92571
|
remarksSchema,
|
|
92541
92572
|
renderPagePdf,
|
|
92573
|
+
requireConsolePermission,
|
|
92574
|
+
requirePlatformStaff,
|
|
92542
92575
|
resetCameraTransports,
|
|
92543
92576
|
residentAppModuleKeys,
|
|
92544
92577
|
residentFormEntry,
|
|
@@ -92710,6 +92743,7 @@ export {
|
|
|
92710
92743
|
site_people_namespace_collection,
|
|
92711
92744
|
snapshotEndpoint,
|
|
92712
92745
|
snapshotRefusalReason,
|
|
92746
|
+
staffMayBypass,
|
|
92713
92747
|
stringifyHidJson,
|
|
92714
92748
|
stripFacialImageMetadata,
|
|
92715
92749
|
subscriptionPlanSchema,
|