@7365admin1/core 3.54.0 → 3.56.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/dist/index.mjs CHANGED
@@ -13658,6 +13658,8 @@ var NotificationModule = /* @__PURE__ */ ((NotificationModule2) => {
13658
13658
  NotificationModule2["FACILITY_BOOKING"] = "facilityBooking";
13659
13659
  NotificationModule2["ONLINE_FORM"] = "onlineForm";
13660
13660
  NotificationModule2["PRELOVED_MARKETPLACE"] = "prelovedMarketplace";
13661
+ NotificationModule2["MARKETPLACE_ORDER"] = "marketplace-order";
13662
+ NotificationModule2["MARKETPLACE_VENDOR_ORDER"] = "marketplace-vendor-order";
13661
13663
  NotificationModule2["INCIDENT_REPORT"] = "incidentReport";
13662
13664
  NotificationModule2["EMERGENCY_CONTACT"] = "emergencyContact";
13663
13665
  NotificationModule2["VIRTUAL_PATROL"] = "virtualPatrol";
@@ -14126,7 +14128,7 @@ var NOTIFICATION_CATEGORIES = [
14126
14128
  {
14127
14129
  key: "facilityBooking",
14128
14130
  label: "Facility Bookings",
14129
- description: "When a facility booking is made or its status changes.",
14131
+ description: "When a facility booking is made or its status changes. The confirmation email goes to the address entered on the booking form itself.",
14130
14132
  channels: { inApp: true, push: true, email: false },
14131
14133
  channelNote: {
14132
14134
  email: "Booking confirmations go to the email address entered on the booking form itself. To change where a confirmation lands, change that address when the booking is made."
@@ -14138,7 +14140,7 @@ var NOTIFICATION_CATEGORIES = [
14138
14140
  {
14139
14141
  key: "visitors",
14140
14142
  label: "Visitors",
14141
- description: "When a visitor you invited checks in or checks out.",
14143
+ description: "When a visitor you invited checks in or checks out. The invitation email goes to the address entered for the visitor.",
14142
14144
  channels: { inApp: true, push: true, email: false },
14143
14145
  channelNote: {
14144
14146
  email: "Visitor invitations go to the email address entered for the visitor when they are invited. To change where one lands, change that address on the invitation."
@@ -14212,7 +14214,7 @@ var NOTIFICATION_CATEGORIES = [
14212
14214
  {
14213
14215
  key: "serviceProviderInvite",
14214
14216
  label: "Service Provider Invitations",
14215
- description: "When a property manager invites your company to provide services at a site.",
14217
+ description: "When a property manager invites your company to provide services at a site. The invitation email is the invitation itself and is always sent to the address it was addressed to; these settings control the copy that reaches you inside the app.",
14216
14218
  channels: { inApp: true, push: true, email: false },
14217
14219
  channelNote: {
14218
14220
  email: "The invitation email is the invitation itself \u2014 for a company that has no account here yet it is the only copy, so it is always sent to the address the invitation was addressed to. The switches above control the copy that reaches you inside the app."
@@ -18694,6 +18696,53 @@ function useRoleService() {
18694
18696
  return { deleteRole, getDeletionPreview, deleteWithReassignments };
18695
18697
  }
18696
18698
 
18699
+ // src/utils/role-scope.util.ts
18700
+ import { UnauthorizedError as UnauthorizedError4 } from "@7365admin1/node-server-utils";
18701
+ function roleScope(role) {
18702
+ if ((role?.type ?? "") === PLATFORM_STAFF_ROLE_TYPE)
18703
+ return "platform";
18704
+ return role?.org?.toString() ? "client" : "client-template";
18705
+ }
18706
+ var PLATFORM_ONLY_RESOURCES = [
18707
+ "organizations",
18708
+ "promo-codes",
18709
+ "subscriptions",
18710
+ "sp-approvals",
18711
+ "marketplace-vendors",
18712
+ "platform-terms",
18713
+ "activity-history"
18714
+ ];
18715
+ var PLATFORM_ONLY_PERMISSIONS = new Set(
18716
+ PLATFORM_ONLY_RESOURCES.flatMap(
18717
+ (resource) => (CONSOLE_PERMISSIONS[resource] ?? []).map(
18718
+ (action) => `${resource}:${action}`
18719
+ )
18720
+ )
18721
+ );
18722
+ function platformPermissionsAdded(next, held) {
18723
+ const already = new Set(held ?? []);
18724
+ return (next ?? []).filter(
18725
+ (permission) => PLATFORM_ONLY_PERMISSIONS.has(permission) && !already.has(permission)
18726
+ );
18727
+ }
18728
+ function requireNoPlatformGrant(role, next) {
18729
+ if (roleScope(role) === "platform")
18730
+ return;
18731
+ const added = platformPermissionsAdded(next, role?.permissions);
18732
+ if (added.length === 0)
18733
+ return;
18734
+ throw new UnauthorizedError4(
18735
+ "These are Seven365 console permissions and cannot be granted on a client role: " + added.join(", ")
18736
+ );
18737
+ }
18738
+ function refuseSharedClientTemplate(role) {
18739
+ if (roleScope(role) !== "client-template")
18740
+ return;
18741
+ throw new UnauthorizedError4(
18742
+ "This role is shared by every client that was invited with it and cannot be changed here."
18743
+ );
18744
+ }
18745
+
18697
18746
  // src/controllers/role.controller.ts
18698
18747
  async function requireRoleOrg(req, org) {
18699
18748
  const orgId = org?.toString() ?? "";
@@ -18708,6 +18757,10 @@ async function requireRoleRead(req, roleId, org) {
18708
18757
  return;
18709
18758
  await requireRoleOrg(req, org);
18710
18759
  }
18760
+ async function requireRoleWrite(req, role) {
18761
+ refuseSharedClientTemplate(role);
18762
+ await requireRoleOrg(req, role?.org);
18763
+ }
18711
18764
  function useRoleController() {
18712
18765
  const {
18713
18766
  addRole: _createRole,
@@ -18745,6 +18798,10 @@ function useRoleController() {
18745
18798
  if (payload.org) {
18746
18799
  await requireOrgReach(req, payload.org);
18747
18800
  }
18801
+ requireNoPlatformGrant(
18802
+ { type: payload.type, org: payload.org, permissions: [] },
18803
+ payload.permissions
18804
+ );
18748
18805
  const role = await _createRole(payload);
18749
18806
  res.status(201).json({ message: "Successfully created role.", data: { role } });
18750
18807
  return;
@@ -18848,7 +18905,8 @@ function useRoleController() {
18848
18905
  const existing = await _getRoleById(_id);
18849
18906
  if (!existing)
18850
18907
  throw new NotFoundError14("Role not found.");
18851
- await requireRoleOrg(req, existing.org);
18908
+ await requireRoleWrite(req, existing);
18909
+ requireNoPlatformGrant(existing, permissions);
18852
18910
  const role = await _updateRole(_id, { name, permissions });
18853
18911
  res.json({ message: "Successfully updated role.", data: { role } });
18854
18912
  return;
@@ -18876,7 +18934,8 @@ function useRoleController() {
18876
18934
  const existing = await _getRoleById(_id);
18877
18935
  if (!existing)
18878
18936
  throw new NotFoundError14("Role not found.");
18879
- await requireRoleOrg(req, existing.org);
18937
+ await requireRoleWrite(req, existing);
18938
+ requireNoPlatformGrant(existing, permissions);
18880
18939
  await _updatePermissionsById(_id, permissions);
18881
18940
  res.json({ message: "Successfully updated role permissions." });
18882
18941
  return;
@@ -18899,7 +18958,7 @@ function useRoleController() {
18899
18958
  const existing = await _getRoleById(_id);
18900
18959
  if (!existing)
18901
18960
  throw new NotFoundError14("Role not found.");
18902
- await requireRoleOrg(req, existing.org);
18961
+ await requireRoleWrite(req, existing);
18903
18962
  const message = await _deleteRole(_id);
18904
18963
  res.json({ message });
18905
18964
  return;
@@ -18955,7 +19014,7 @@ function useRoleController() {
18955
19014
  const existing = await _getRoleById(req.params.id);
18956
19015
  if (!existing)
18957
19016
  throw new NotFoundError14("Role not found.");
18958
- await requireRoleOrg(req, existing.org);
19017
+ await requireRoleWrite(req, existing);
18959
19018
  const message = await _deleteWithReassignments(
18960
19019
  req.params.id,
18961
19020
  req.body.reassignments
@@ -18988,12 +19047,12 @@ import { BadRequestError as BadRequestError49, logger as logger33 } from "@7365a
18988
19047
  // src/services/member.service.ts
18989
19048
  import {
18990
19049
  BadRequestError as BadRequestError41,
18991
- UnauthorizedError as UnauthorizedError4,
19050
+ UnauthorizedError as UnauthorizedError5,
18992
19051
  useAtlas as useAtlas27
18993
19052
  } from "@7365admin1/node-server-utils";
18994
19053
  async function requireStaffCaller(callerId5, what) {
18995
19054
  if (!await isSuperAdmin(callerId5)) {
18996
- throw new UnauthorizedError4(
19055
+ throw new UnauthorizedError5(
18997
19056
  `Only Seven365 staff can ${what}.`
18998
19057
  );
18999
19058
  }
@@ -19210,14 +19269,14 @@ function useMemberService() {
19210
19269
  }
19211
19270
 
19212
19271
  // src/utils/site-reach.util.ts
19213
- import { useAtlas as useAtlas34, UnauthorizedError as UnauthorizedError6 } from "@7365admin1/node-server-utils";
19272
+ import { useAtlas as useAtlas34, UnauthorizedError as UnauthorizedError7 } from "@7365admin1/node-server-utils";
19214
19273
  import { ObjectId as ObjectId47 } from "mongodb";
19215
19274
 
19216
19275
  // src/services/camera-view.service.ts
19217
19276
  import {
19218
19277
  BadRequestError as BadRequestError48,
19219
19278
  NotFoundError as NotFoundError16,
19220
- UnauthorizedError as UnauthorizedError5,
19279
+ UnauthorizedError as UnauthorizedError6,
19221
19280
  logger as logger32,
19222
19281
  useAtlas as useAtlas33,
19223
19282
  useCache as useCache19
@@ -25664,7 +25723,7 @@ function useCameraViewService() {
25664
25723
  }
25665
25724
  async function authorizeCamera(params) {
25666
25725
  if (!params.userId || !ObjectId46.isValid(params.userId)) {
25667
- throw new UnauthorizedError5("Not signed in.");
25726
+ throw new UnauthorizedError6("Not signed in.");
25668
25727
  }
25669
25728
  if (!ObjectId46.isValid(params.cameraId)) {
25670
25729
  throw new BadRequestError48("Invalid camera id.");
@@ -25693,7 +25752,7 @@ function useCameraViewService() {
25693
25752
  memberships
25694
25753
  );
25695
25754
  if (!hasAnyPermission(permissions, params.permissions)) {
25696
- throw new UnauthorizedError5(
25755
+ throw new UnauthorizedError6(
25697
25756
  "You do not have permission to use this camera."
25698
25757
  );
25699
25758
  }
@@ -25801,7 +25860,7 @@ function useCameraViewService() {
25801
25860
  }
25802
25861
  async function entitleSite(params) {
25803
25862
  if (!params.userId || !ObjectId46.isValid(params.userId)) {
25804
- throw new UnauthorizedError5("Not signed in.");
25863
+ throw new UnauthorizedError6("Not signed in.");
25805
25864
  }
25806
25865
  if (!ObjectId46.isValid(params.siteId)) {
25807
25866
  throw new BadRequestError48("Invalid site id.");
@@ -25833,7 +25892,7 @@ function useCameraViewService() {
25833
25892
  );
25834
25893
  const required = params.permissions ?? CAMERA_VIEW_PERMISSIONS;
25835
25894
  if (!hasAnyPermission(permissions, required)) {
25836
- throw new UnauthorizedError5(
25895
+ throw new UnauthorizedError6(
25837
25896
  params.message ?? (required === CAMERA_VIEW_PERMISSIONS ? "You do not have permission to view these cameras." : "You do not have permission to set up cameras on this site.")
25838
25897
  );
25839
25898
  }
@@ -26242,7 +26301,7 @@ function idText(value) {
26242
26301
  async function requireSiteReach(req, site, permission) {
26243
26302
  const siteId = site?.toString?.() ?? "";
26244
26303
  if (!siteId)
26245
- throw new UnauthorizedError6("Not authorized.");
26304
+ throw new UnauthorizedError7("Not authorized.");
26246
26305
  const actor = await resolveInviteActor(callerId(req));
26247
26306
  if (staffMayBypass(actor))
26248
26307
  return;
@@ -27228,7 +27287,7 @@ function useVerificationController() {
27228
27287
  // src/controllers/file.controller.ts
27229
27288
  import {
27230
27289
  BadRequestError as BadRequestError51,
27231
- UnauthorizedError as UnauthorizedError7,
27290
+ UnauthorizedError as UnauthorizedError8,
27232
27291
  logger as logger35
27233
27292
  } from "@7365admin1/node-server-utils";
27234
27293
  import Joi27 from "joi";
@@ -27257,7 +27316,7 @@ async function requireFileDelete(req, file) {
27257
27316
  return;
27258
27317
  const caller = callerId(req);
27259
27318
  if (!caller)
27260
- throw new UnauthorizedError7("Not authorized.");
27319
+ throw new UnauthorizedError8("Not authorized.");
27261
27320
  if (caller === ownerId)
27262
27321
  return;
27263
27322
  const [me, owner] = await Promise.all([
@@ -27273,7 +27332,7 @@ async function requireFileDelete(req, file) {
27273
27332
  })) {
27274
27333
  return;
27275
27334
  }
27276
- throw new UnauthorizedError7("Not authorized.");
27335
+ throw new UnauthorizedError8("Not authorized.");
27277
27336
  }
27278
27337
  function useFileController() {
27279
27338
  const { createFile, deleteFile: _deleteFile } = useFileService();
@@ -27346,7 +27405,7 @@ import {
27346
27405
  BadRequestError as BadRequestError55,
27347
27406
  logger as logger38,
27348
27407
  NotFoundError as NotFoundError17,
27349
- UnauthorizedError as UnauthorizedError8
27408
+ UnauthorizedError as UnauthorizedError9
27350
27409
  } from "@7365admin1/node-server-utils";
27351
27410
  import Joi31 from "joi";
27352
27411
 
@@ -28619,7 +28678,7 @@ function useOrgController() {
28619
28678
  try {
28620
28679
  const createdBy = callerId(req);
28621
28680
  if (!createdBy)
28622
- throw new UnauthorizedError8("Not authorized.");
28681
+ throw new UnauthorizedError9("Not authorized.");
28623
28682
  const _id = await _add({ ...req.body, createdBy });
28624
28683
  const data = await _getById(_id);
28625
28684
  res.status(201).json({
@@ -31120,7 +31179,7 @@ function useSubscriptionService() {
31120
31179
  import Joi36 from "joi";
31121
31180
  import {
31122
31181
  BadRequestError as BadRequestError71,
31123
- UnauthorizedError as UnauthorizedError9,
31182
+ UnauthorizedError as UnauthorizedError10,
31124
31183
  logger as logger48
31125
31184
  } from "@7365admin1/node-server-utils";
31126
31185
 
@@ -31541,7 +31600,7 @@ function useSubscriptionController() {
31541
31600
  try {
31542
31601
  const subscription = await _getSubscriptionById(subscriptionId);
31543
31602
  if (!subscription) {
31544
- throw new UnauthorizedError9("Not authorized.");
31603
+ throw new UnauthorizedError10("Not authorized.");
31545
31604
  }
31546
31605
  await requireOrgAccess(req, subscription.org?.toString());
31547
31606
  const _res = await _updateSubscriptionSeats({
@@ -41873,7 +41932,7 @@ function useCustomerSiteService() {
41873
41932
  import Joi59 from "joi";
41874
41933
  import {
41875
41934
  BadRequestError as BadRequestError107,
41876
- UnauthorizedError as UnauthorizedError10,
41935
+ UnauthorizedError as UnauthorizedError11,
41877
41936
  logger as logger78
41878
41937
  } from "@7365admin1/node-server-utils";
41879
41938
  async function requireEitherOrg(req, ...orgs) {
@@ -41882,7 +41941,7 @@ async function requireEitherOrg(req, ...orgs) {
41882
41941
  if (staffMayBypass(actor))
41883
41942
  return;
41884
41943
  if (wanted.length === 0 || !wanted.some((org) => actor.orgIds.includes(org))) {
41885
- throw new UnauthorizedError10("Not authorized.");
41944
+ throw new UnauthorizedError11("Not authorized.");
41886
41945
  }
41887
41946
  }
41888
41947
  function useCustomerSiteController() {
@@ -45094,7 +45153,7 @@ import {
45094
45153
  BadRequestError as BadRequestError121,
45095
45154
  InternalServerError as InternalServerError42,
45096
45155
  NotFoundError as NotFoundError34,
45097
- UnauthorizedError as UnauthorizedError11,
45156
+ UnauthorizedError as UnauthorizedError12,
45098
45157
  logger as logger90
45099
45158
  } from "@7365admin1/node-server-utils";
45100
45159
 
@@ -48628,8 +48687,8 @@ function useHidAmicoService() {
48628
48687
  await siteAccess.authorizeSite({ siteId, userId: value.userId, permissions });
48629
48688
  }
48630
48689
  } catch (error) {
48631
- if (error instanceof UnauthorizedError11) {
48632
- throw new UnauthorizedError11("You do not have permission to manage HID access at this site.");
48690
+ if (error instanceof UnauthorizedError12) {
48691
+ throw new UnauthorizedError12("You do not have permission to manage HID access at this site.");
48633
48692
  }
48634
48693
  throw error;
48635
48694
  }
@@ -48653,7 +48712,7 @@ function useHidAmicoService() {
48653
48712
  try {
48654
48713
  await authorizeSiteForCaller(String(reader.site || ""), userId);
48655
48714
  } catch (error) {
48656
- if (error instanceof UnauthorizedError11)
48715
+ if (error instanceof UnauthorizedError12)
48657
48716
  throw error;
48658
48717
  throw new NotFoundError34(HID_READER_NOT_FOUND);
48659
48718
  }
@@ -48705,10 +48764,10 @@ function useHidAmicoService() {
48705
48764
  async function assertUserReaderPermission(reader, userId, options = {}) {
48706
48765
  const permission = await getReaderPermissionForUser(reader, userId);
48707
48766
  if (!permission.granted) {
48708
- throw new UnauthorizedError11("You do not have HID access permission for this reader.");
48767
+ throw new UnauthorizedError12("You do not have HID access permission for this reader.");
48709
48768
  }
48710
48769
  if (options.intercom && !permission.intercom) {
48711
- throw new UnauthorizedError11("You do not have HID intercom permission for this reader.");
48770
+ throw new UnauthorizedError12("You do not have HID intercom permission for this reader.");
48712
48771
  }
48713
48772
  return permission;
48714
48773
  }
@@ -50046,10 +50105,10 @@ function useHidAmicoService() {
50046
50105
  const hasActiveMembership = memberships.some((membership) => membership.status !== "deleted" && membership.status !== "inactive");
50047
50106
  const resolvedIssuer = issuer || (hasResidentMembership ? "resident" : "property_management");
50048
50107
  if (resolvedIssuer === "resident" && !hasResidentMembership) {
50049
- throw new UnauthorizedError11("Only a Resident account can issue a Resident visitor QR code.");
50108
+ throw new UnauthorizedError12("Only a Resident account can issue a Resident visitor QR code.");
50050
50109
  }
50051
50110
  if (resolvedIssuer === "property_management" && !hasActiveMembership) {
50052
- throw new UnauthorizedError11("Only a site Property Management account can issue this visitor QR code.");
50111
+ throw new UnauthorizedError12("Only a site Property Management account can issue this visitor QR code.");
50053
50112
  }
50054
50113
  const configuredGateIds = site?.metadata?.hidQrCodePass?.qrGatePermissions?.[resolvedIssuer === "resident" ? "resident" : "propertyManagement"] || [];
50055
50114
  const gateReaderIds = configuredGateIds.filter((readerId) => typeof readerId === "string" && /^[a-f0-9]{24}$/i.test(readerId)).map(String);
@@ -52642,7 +52701,7 @@ function useVisitorTransactionService() {
52642
52701
  import Joi68 from "joi";
52643
52702
  import moment5 from "moment-timezone";
52644
52703
  import { ObjectId as ObjectId90 } from "mongodb";
52645
- import { BadRequestError as BadRequestError124, NotFoundError as NotFoundError36, InternalServerError as InternalServerError44, UnauthorizedError as UnauthorizedError12, logger as logger94 } from "@7365admin1/node-server-utils";
52704
+ import { BadRequestError as BadRequestError124, NotFoundError as NotFoundError36, InternalServerError as InternalServerError44, UnauthorizedError as UnauthorizedError13, logger as logger94 } from "@7365admin1/node-server-utils";
52646
52705
 
52647
52706
  // src/models/visitor-invite.model.ts
52648
52707
  import Joi66 from "joi";
@@ -57426,7 +57485,7 @@ function useVisitorTransactionController() {
57426
57485
  }
57427
57486
  const inviterUserId = callerId(req);
57428
57487
  if (!inviterUserId) {
57429
- next(new UnauthorizedError12("Not authorized."));
57488
+ next(new UnauthorizedError13("Not authorized."));
57430
57489
  return;
57431
57490
  }
57432
57491
  try {
@@ -57990,7 +58049,7 @@ function useGuestManagementController() {
57990
58049
  // src/controllers/person.controller.ts
57991
58050
  import Joi71 from "joi";
57992
58051
  import { BadRequestError as BadRequestError127, logger as logger97 } from "@7365admin1/node-server-utils";
57993
- import { NotFoundError as NotFoundError37, UnauthorizedError as UnauthorizedError13 } from "@7365admin1/node-server-utils";
58052
+ import { NotFoundError as NotFoundError37, UnauthorizedError as UnauthorizedError14 } from "@7365admin1/node-server-utils";
57994
58053
  function usePersonController() {
57995
58054
  const {
57996
58055
  getAll: _getAll,
@@ -58024,7 +58083,7 @@ function usePersonController() {
58024
58083
  }
58025
58084
  const org = person.org?.toString() ?? "";
58026
58085
  if (!org || !actor.orgIds.includes(org)) {
58027
- throw new UnauthorizedError13("Not authorized.");
58086
+ throw new UnauthorizedError14("Not authorized.");
58028
58087
  }
58029
58088
  return actor;
58030
58089
  }
@@ -58150,7 +58209,7 @@ function usePersonController() {
58150
58209
  });
58151
58210
  } else if (org) {
58152
58211
  if (!actor.orgIds.includes(org)) {
58153
- throw new UnauthorizedError13("Not authorized.");
58212
+ throw new UnauthorizedError14("Not authorized.");
58154
58213
  }
58155
58214
  } else {
58156
58215
  orgs = actor.orgIds;
@@ -62470,7 +62529,7 @@ function useSiteFacilityService() {
62470
62529
  import {
62471
62530
  BadRequestError as BadRequestError149,
62472
62531
  NotFoundError as NotFoundError43,
62473
- UnauthorizedError as UnauthorizedError14,
62532
+ UnauthorizedError as UnauthorizedError15,
62474
62533
  logger as logger116
62475
62534
  } from "@7365admin1/node-server-utils";
62476
62535
  import Joi83 from "joi";
@@ -62557,7 +62616,7 @@ function useSiteFacilityController() {
62557
62616
  } else {
62558
62617
  const { actor } = await siteReachOf(req);
62559
62618
  if (!actor.isSuperAdmin)
62560
- throw new UnauthorizedError14("Not authorized.");
62619
+ throw new UnauthorizedError15("Not authorized.");
62561
62620
  }
62562
62621
  const data = await _getAll({
62563
62622
  search,
@@ -65592,7 +65651,7 @@ function useBulletinBoardService() {
65592
65651
  import {
65593
65652
  BadRequestError as BadRequestError158,
65594
65653
  NotFoundError as NotFoundError51,
65595
- UnauthorizedError as UnauthorizedError15,
65654
+ UnauthorizedError as UnauthorizedError16,
65596
65655
  logger as logger125
65597
65656
  } from "@7365admin1/node-server-utils";
65598
65657
  import Joi91 from "joi";
@@ -65628,7 +65687,7 @@ function useBulletinBoardController() {
65628
65687
  } else {
65629
65688
  const { canReach } = await siteReachOf(req);
65630
65689
  if (!await canReach(scopeOf(value))) {
65631
- throw new UnauthorizedError15("Not authorized.");
65690
+ throw new UnauthorizedError16("Not authorized.");
65632
65691
  }
65633
65692
  }
65634
65693
  const data = await _add(value);
@@ -66185,7 +66244,7 @@ import { BadRequestError as BadRequestError164, logger as logger131 } from "@736
66185
66244
  import {
66186
66245
  BadRequestError as BadRequestError163,
66187
66246
  logger as logger130,
66188
- UnauthorizedError as UnauthorizedError16,
66247
+ UnauthorizedError as UnauthorizedError17,
66189
66248
  useAtlas as useAtlas89
66190
66249
  } from "@7365admin1/node-server-utils";
66191
66250
 
@@ -66569,7 +66628,7 @@ function useSiteBillingItemService() {
66569
66628
  function assertUnitAtSite(buildingUnit, site) {
66570
66629
  const siteId = site?.toString?.() ?? "";
66571
66630
  if (!siteId || (buildingUnit?.site?.toString() ?? "") !== siteId) {
66572
- throw new UnauthorizedError16("Not authorized.");
66631
+ throw new UnauthorizedError17("Not authorized.");
66573
66632
  }
66574
66633
  }
66575
66634
  async function add(value) {
@@ -66740,7 +66799,7 @@ function useSiteBillingItemService() {
66740
66799
  message: error.message
66741
66800
  });
66742
66801
  await session.abortTransaction();
66743
- if (error instanceof BadRequestError163 || error instanceof UnauthorizedError16) {
66802
+ if (error instanceof BadRequestError163 || error instanceof UnauthorizedError17) {
66744
66803
  throw error;
66745
66804
  }
66746
66805
  throw new BadRequestError163("Failed to update Site Billing Item.");
@@ -68709,7 +68768,7 @@ import Joi99 from "joi";
68709
68768
 
68710
68769
  // src/utils/resident-unit.util.ts
68711
68770
  import { ObjectId as ObjectId124 } from "mongodb";
68712
- import { UnauthorizedError as UnauthorizedError17, useAtlas as useAtlas95 } from "@7365admin1/node-server-utils";
68771
+ import { UnauthorizedError as UnauthorizedError18, useAtlas as useAtlas95 } from "@7365admin1/node-server-utils";
68713
68772
  async function requireOwnUnit(req, site, unitId) {
68714
68773
  const actor = await resolveInviteActor(callerId(req));
68715
68774
  if (staffMayBypass(actor))
@@ -68717,7 +68776,7 @@ async function requireOwnUnit(req, site, unitId) {
68717
68776
  const unit = unitId?.toString?.() ?? "";
68718
68777
  const siteId = site?.toString?.() ?? "";
68719
68778
  if (!ObjectId124.isValid(unit) || !ObjectId124.isValid(siteId) || !actor.id) {
68720
- throw new UnauthorizedError17("Not authorized.");
68779
+ throw new UnauthorizedError18("Not authorized.");
68721
68780
  }
68722
68781
  const db2 = useAtlas95.getDb();
68723
68782
  if (!db2)
@@ -68729,7 +68788,7 @@ async function requireOwnUnit(req, site, unitId) {
68729
68788
  status: { $ne: "deleted" }
68730
68789
  });
68731
68790
  if (!own)
68732
- throw new UnauthorizedError17("Not authorized.");
68791
+ throw new UnauthorizedError18("Not authorized.");
68733
68792
  }
68734
68793
 
68735
68794
  // src/controllers/site-unit-billing.controller.ts
@@ -77281,7 +77340,7 @@ function useOnlineFormRepo() {
77281
77340
  import {
77282
77341
  BadRequestError as BadRequestError204,
77283
77342
  NotFoundError as NotFoundError71,
77284
- UnauthorizedError as UnauthorizedError18,
77343
+ UnauthorizedError as UnauthorizedError19,
77285
77344
  logger as logger169
77286
77345
  } from "@7365admin1/node-server-utils";
77287
77346
  import Joi122 from "joi";
@@ -77353,10 +77412,10 @@ function useOnlineFormController() {
77353
77412
  if (site) {
77354
77413
  await requireSiteReach(req, site);
77355
77414
  } else if (!staffMayBypass(actor)) {
77356
- throw new UnauthorizedError18("Not authorized.");
77415
+ throw new UnauthorizedError19("Not authorized.");
77357
77416
  }
77358
77417
  if (org && !staffMayBypass(actor) && !actor.orgIds.includes(org)) {
77359
- throw new UnauthorizedError18("Not authorized.");
77418
+ throw new UnauthorizedError19("Not authorized.");
77360
77419
  }
77361
77420
  const data = await _getAll({ search, page, limit, status, org, site });
77362
77421
  res.json(data);
@@ -77421,7 +77480,7 @@ function useOnlineFormController() {
77421
77480
  if (payload.org) {
77422
77481
  const { actor } = await siteReachOf(req);
77423
77482
  if (!staffMayBypass(actor) && !actor.orgIds.includes(payload.org)) {
77424
- throw new UnauthorizedError18("Not authorized.");
77483
+ throw new UnauthorizedError19("Not authorized.");
77425
77484
  }
77426
77485
  }
77427
77486
  await _updateOnlineFormById(_id, payload);
@@ -84667,7 +84726,7 @@ import {
84667
84726
  BadRequestError as BadRequestError229,
84668
84727
  NotFoundError as NotFoundError78,
84669
84728
  InternalServerError as InternalServerError81,
84670
- UnauthorizedError as UnauthorizedError19,
84729
+ UnauthorizedError as UnauthorizedError20,
84671
84730
  useAtlas as useAtlas132,
84672
84731
  hashPassword as hashPassword4
84673
84732
  } from "@7365admin1/node-server-utils";
@@ -84936,10 +84995,10 @@ function useVerificationServiceV2() {
84936
84995
  const org = await getOrgById(orgId);
84937
84996
  const actor = await resolveInviteActor(invitedBy);
84938
84997
  if (!actor.id) {
84939
- throw new UnauthorizedError19("Sign in to continue.");
84998
+ throw new UnauthorizedError20("Sign in to continue.");
84940
84999
  }
84941
85000
  if (!staffMayBypass(actor) && !actor.orgIds.includes(orgId)) {
84942
- throw new UnauthorizedError19(
85001
+ throw new UnauthorizedError20(
84943
85002
  "You can only invite service providers to your own organisation's sites."
84944
85003
  );
84945
85004
  }
@@ -89356,7 +89415,7 @@ import Joi158 from "joi";
89356
89415
  import { ObjectId as ObjectId179 } from "mongodb";
89357
89416
  import {
89358
89417
  InternalServerError as InternalServerError93,
89359
- UnauthorizedError as UnauthorizedError20,
89418
+ UnauthorizedError as UnauthorizedError21,
89360
89419
  useAtlas as useAtlas146
89361
89420
  } from "@7365admin1/node-server-utils";
89362
89421
  function db() {
@@ -89372,7 +89431,7 @@ function asObjectId(value) {
89372
89431
  function requireCaller(req) {
89373
89432
  const id = callerId(req);
89374
89433
  if (!id || !ObjectId179.isValid(id)) {
89375
- throw new UnauthorizedError20("Not authorized.");
89434
+ throw new UnauthorizedError21("Not authorized.");
89376
89435
  }
89377
89436
  return id;
89378
89437
  }
@@ -89380,7 +89439,7 @@ function requireSelfId(req, claimed) {
89380
89439
  const caller = requireCaller(req);
89381
89440
  const asked = claimed?.toString?.() ?? "";
89382
89441
  if (!asked || asked !== caller) {
89383
- throw new UnauthorizedError20("Not authorized.");
89442
+ throw new UnauthorizedError21("Not authorized.");
89384
89443
  }
89385
89444
  return caller;
89386
89445
  }
@@ -89388,11 +89447,11 @@ async function requireOwnChannel(req, channelId) {
89388
89447
  const caller = requireCaller(req);
89389
89448
  const _id = asObjectId(channelId);
89390
89449
  if (!_id)
89391
- throw new UnauthorizedError20("Not authorized.");
89450
+ throw new UnauthorizedError21("Not authorized.");
89392
89451
  const channel = await db().collection("channel-preloved").findOne({ _id }, { projection: { senderId: 1, receiverId: 1, postId: 1 } });
89393
89452
  const participants = [channel?.senderId, channel?.receiverId].map((id) => id?.toString?.() ?? "").filter(Boolean);
89394
89453
  if (!channel || !participants.includes(caller)) {
89395
- throw new UnauthorizedError20("Not authorized.");
89454
+ throw new UnauthorizedError21("Not authorized.");
89396
89455
  }
89397
89456
  return { caller, channel };
89398
89457
  }
@@ -89400,10 +89459,10 @@ async function requireOwnChatMessage(req, chatId) {
89400
89459
  const caller = requireCaller(req);
89401
89460
  const _id = asObjectId(chatId);
89402
89461
  if (!_id)
89403
- throw new UnauthorizedError20("Not authorized.");
89462
+ throw new UnauthorizedError21("Not authorized.");
89404
89463
  const message = await db().collection("chat-preloved").findOne({ _id }, { projection: { senderId: 1 } });
89405
89464
  if (!message || message.senderId?.toString?.() !== caller) {
89406
- throw new UnauthorizedError20("Not authorized.");
89465
+ throw new UnauthorizedError21("Not authorized.");
89407
89466
  }
89408
89467
  return caller;
89409
89468
  }
@@ -89829,7 +89888,7 @@ function useBidPrelovedService() {
89829
89888
  // src/controllers/bid-preloved.controller.ts
89830
89889
  import {
89831
89890
  BadRequestError as BadRequestError252,
89832
- UnauthorizedError as UnauthorizedError21,
89891
+ UnauthorizedError as UnauthorizedError22,
89833
89892
  logger as logger212
89834
89893
  } from "@7365admin1/node-server-utils";
89835
89894
  import Joi161 from "joi";
@@ -89881,7 +89940,7 @@ function useBidPrelovedController() {
89881
89940
  const bid = await _getById(params.id);
89882
89941
  const seller = await sellerOfPost(bid?.postId);
89883
89942
  if (!seller || seller !== caller) {
89884
- throw new UnauthorizedError21("Not authorized.");
89943
+ throw new UnauthorizedError22("Not authorized.");
89885
89944
  }
89886
89945
  const data = await _updateStatus(params.id, body.status);
89887
89946
  res.status(200).json(data);
@@ -89905,7 +89964,7 @@ function useBidPrelovedController() {
89905
89964
  const data = await _getById(params.id);
89906
89965
  const seller = await sellerOfPost(data?.postId);
89907
89966
  if (data?.buyerId?.toString?.() !== caller && seller !== caller) {
89908
- throw new UnauthorizedError21("Not authorized.");
89967
+ throw new UnauthorizedError22("Not authorized.");
89909
89968
  }
89910
89969
  res.status(200).json(data);
89911
89970
  } catch (error2) {
@@ -90303,7 +90362,7 @@ function useFormEntryRepo() {
90303
90362
  import {
90304
90363
  BadRequestError as BadRequestError254,
90305
90364
  NotFoundError as NotFoundError89,
90306
- UnauthorizedError as UnauthorizedError22,
90365
+ UnauthorizedError as UnauthorizedError23,
90307
90366
  logger as logger214
90308
90367
  } from "@7365admin1/node-server-utils";
90309
90368
  import Joi163 from "joi";
@@ -90413,7 +90472,7 @@ function useFormEntryController() {
90413
90472
  } else {
90414
90473
  const { actor } = await siteReachOf(req);
90415
90474
  if (!actor.isSuperAdmin)
90416
- throw new UnauthorizedError22("Not authorized.");
90475
+ throw new UnauthorizedError23("Not authorized.");
90417
90476
  }
90418
90477
  const data = await _getAll({ search, page, limit, status, org, site });
90419
90478
  res.json(data);
@@ -90464,7 +90523,7 @@ function useFormEntryController() {
90464
90523
  await requireSiteReach(req, rest.site);
90465
90524
  delete rest.userId;
90466
90525
  if (isOwner && rest.status && rest.status !== "pending") {
90467
- throw new UnauthorizedError22("Not authorized.");
90526
+ throw new UnauthorizedError23("Not authorized.");
90468
90527
  }
90469
90528
  await _updateFormEntryById(_id, rest);
90470
90529
  res.json({ message: "Successfully updated online form." });
@@ -90521,7 +90580,7 @@ function useFormEntryController() {
90521
90580
  async function residentFormSubmission(req, res, next) {
90522
90581
  const userId = callerId(req);
90523
90582
  if (!userId) {
90524
- next(new UnauthorizedError22("Not authorized."));
90583
+ next(new UnauthorizedError23("Not authorized."));
90525
90584
  return;
90526
90585
  }
90527
90586
  const payload = { ...req.body, userId };
@@ -91752,7 +91811,7 @@ function useHidAmicoController() {
91752
91811
  import {
91753
91812
  BadRequestError as BadRequestError257,
91754
91813
  logger as logger216,
91755
- UnauthorizedError as UnauthorizedError23
91814
+ UnauthorizedError as UnauthorizedError24
91756
91815
  } from "@7365admin1/node-server-utils";
91757
91816
  import Joi165 from "joi";
91758
91817
  function usePlatformTermsController() {
@@ -91768,7 +91827,7 @@ function usePlatformTermsController() {
91768
91827
  async function requireOwnRecord(req, user, { staffMayRead = false } = {}) {
91769
91828
  const id = callerId(req);
91770
91829
  if (!id) {
91771
- throw new UnauthorizedError23("Not authorized.");
91830
+ throw new UnauthorizedError24("Not authorized.");
91772
91831
  }
91773
91832
  if (id === user) {
91774
91833
  return id;
@@ -91776,7 +91835,7 @@ function usePlatformTermsController() {
91776
91835
  if (staffMayRead) {
91777
91836
  return await requireConsolePermission(req, "platform-terms", "see-platform-terms");
91778
91837
  }
91779
- throw new UnauthorizedError23("Not authorized.");
91838
+ throw new UnauthorizedError24("Not authorized.");
91780
91839
  }
91781
91840
  async function getLatest(_req, res, next) {
91782
91841
  try {
@@ -91982,7 +92041,7 @@ function useConsoleAuditController() {
91982
92041
  // src/controllers/notification.controller.ts
91983
92042
  import {
91984
92043
  BadRequestError as BadRequestError259,
91985
- UnauthorizedError as UnauthorizedError24,
92044
+ UnauthorizedError as UnauthorizedError25,
91986
92045
  logger as logger218
91987
92046
  } from "@7365admin1/node-server-utils";
91988
92047
  function useNotificationController() {
@@ -92000,10 +92059,10 @@ function useNotificationController() {
92000
92059
  function inboxOwner(req, claimed) {
92001
92060
  const caller = callerId5(req);
92002
92061
  if (!caller) {
92003
- throw new UnauthorizedError24("Not authorized.");
92062
+ throw new UnauthorizedError25("Not authorized.");
92004
92063
  }
92005
92064
  if (claimed && claimed !== caller) {
92006
- throw new UnauthorizedError24("Not authorized.");
92065
+ throw new UnauthorizedError25("Not authorized.");
92007
92066
  }
92008
92067
  return caller;
92009
92068
  }
@@ -92015,7 +92074,7 @@ function useNotificationController() {
92015
92074
  }
92016
92075
  try {
92017
92076
  if (!await isSuperAdmin(callerId5(req))) {
92018
- throw new UnauthorizedError24("Not authorized.");
92077
+ throw new UnauthorizedError25("Not authorized.");
92019
92078
  }
92020
92079
  const inserted = await _addMany(value.to, {
92021
92080
  title: value.title,
@@ -92182,8 +92241,10 @@ function useNotificationPreferenceService() {
92182
92241
  categoriesForUser(id)
92183
92242
  ]);
92184
92243
  const isOff = (category, channel) => off.some((o) => o.category === category && o.channel === channel);
92244
+ const supportedIn = (category) => NOTIFICATION_CHANNELS.filter((channel) => category.channels[channel]);
92245
+ const offered = new Set(categories.flatMap((c) => supportedIn(c)));
92185
92246
  return {
92186
- channels: NOTIFICATION_CHANNELS.map((c) => ({
92247
+ channels: NOTIFICATION_CHANNELS.filter((c) => offered.has(c)).map((c) => ({
92187
92248
  key: c,
92188
92249
  label: NOTIFICATION_CHANNEL_LABELS[c]
92189
92250
  })),
@@ -92192,16 +92253,14 @@ function useNotificationPreferenceService() {
92192
92253
  label: category.label,
92193
92254
  description: category.description,
92194
92255
  safety: Boolean(category.safety),
92195
- channels: NOTIFICATION_CHANNELS.map((channel) => {
92196
- const supported = category.channels[channel];
92197
- return {
92198
- key: channel,
92199
- label: NOTIFICATION_CHANNEL_LABELS[channel],
92200
- supported,
92201
- note: supported ? void 0 : category.channelNote?.[channel],
92202
- enabled: supported && !isOff(category.key, channel)
92203
- };
92204
- })
92256
+ channels: supportedIn(category).map((channel) => ({
92257
+ key: channel,
92258
+ label: NOTIFICATION_CHANNEL_LABELS[channel],
92259
+ // kept so a client written against the old shape still filters
92260
+ // correctly; every channel sent is now a supported one.
92261
+ supported: true,
92262
+ enabled: !isOff(category.key, channel)
92263
+ }))
92205
92264
  }))
92206
92265
  };
92207
92266
  }