@7365admin1/core 3.47.1-staging.145 → 3.47.1-staging.147

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.d.ts CHANGED
@@ -2654,6 +2654,7 @@ declare function useVehicleRepo(): {
2654
2654
  }>;
2655
2655
  getSeasonPassTypes: (site: string | ObjectId) => Promise<bson.Document[]>;
2656
2656
  getVehicleById: (_id: string | ObjectId) => Promise<bson.Document>;
2657
+ getVehicleSite: (_id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
2657
2658
  updateVehicleById: (_id: string | ObjectId, value: TVehicleUpdate, session?: ClientSession) => Promise<number>;
2658
2659
  deleteVehicle: (_id: string | ObjectId, session?: ClientSession) => Promise<number>;
2659
2660
  getByPlaceNumber: (value: string) => Promise<mongodb.WithId<bson.Document>>;
@@ -5471,6 +5472,7 @@ declare function useDocumentManagementRepo(): {
5471
5472
  pageRange: string;
5472
5473
  } | TDocumentManagement>;
5473
5474
  getDocumentById: (_id: string | ObjectId) => Promise<bson.Document>;
5475
+ getDocumentScope: (_id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
5474
5476
  updateDocumentById: (_id: string | ObjectId, value: TDocumentManagement) => Promise<number>;
5475
5477
  updateFolderById: (_id: string | ObjectId, value: TFolderUpdate) => Promise<number>;
5476
5478
  deleteDocumentById: (_id: string | ObjectId, session?: ClientSession) => Promise<number>;
package/dist/index.js CHANGED
@@ -29008,7 +29008,10 @@ function useVehicleRepo() {
29008
29008
  recNo: 1,
29009
29009
  nric: 1,
29010
29010
  status: 1,
29011
- type: 1
29011
+ type: 1,
29012
+ // needed by the caller to drop rows on sites it cannot reach;
29013
+ // this lookup takes an NRIC and names no site of its own.
29014
+ site: 1
29012
29015
  }
29013
29016
  }
29014
29017
  ]).toArray();
@@ -29239,6 +29242,19 @@ function useVehicleRepo() {
29239
29242
  throw error;
29240
29243
  }
29241
29244
  }
29245
+ async function getVehicleSite(_id) {
29246
+ let id;
29247
+ try {
29248
+ id = new import_mongodb60.ObjectId(_id);
29249
+ } catch (error) {
29250
+ throw new import_node_server_utils90.BadRequestError("Invalid vehicle ID format.");
29251
+ }
29252
+ const doc = await collection.findOne(
29253
+ { _id: id },
29254
+ { projection: { site: 1, org: 1 } }
29255
+ );
29256
+ return doc ?? null;
29257
+ }
29242
29258
  return {
29243
29259
  createIndex,
29244
29260
  createTextIndex,
@@ -29246,6 +29262,7 @@ function useVehicleRepo() {
29246
29262
  getVehicles,
29247
29263
  getSeasonPassTypes,
29248
29264
  getVehicleById,
29265
+ getVehicleSite,
29249
29266
  updateVehicleById,
29250
29267
  deleteVehicle,
29251
29268
  getByPlaceNumber,
@@ -37327,6 +37344,38 @@ async function requireSiteReach(req, site) {
37327
37344
  return;
37328
37345
  await useCameraViewService().entitleSite({ siteId, userId: actor.id });
37329
37346
  }
37347
+ async function siteReachOf(req) {
37348
+ const actor = await resolveInviteActor(callerId(req));
37349
+ const reachable = /* @__PURE__ */ new Map();
37350
+ function canReach(record) {
37351
+ if (actor.isSuperAdmin)
37352
+ return Promise.resolve(true);
37353
+ if (!record)
37354
+ return Promise.resolve(false);
37355
+ const site = record.site?.toString() ?? "";
37356
+ if (!site) {
37357
+ const org = record.org?.toString() ?? "";
37358
+ return Promise.resolve(Boolean(org) && actor.orgIds.includes(org));
37359
+ }
37360
+ if (!reachable.has(site)) {
37361
+ reachable.set(
37362
+ site,
37363
+ useCameraViewService().entitleSite({ siteId: site, userId: actor.id }).then(
37364
+ () => true,
37365
+ () => false
37366
+ )
37367
+ );
37368
+ }
37369
+ return reachable.get(site);
37370
+ }
37371
+ async function only(records) {
37372
+ if (actor.isSuperAdmin)
37373
+ return records;
37374
+ const verdicts = await Promise.all(records.map((r) => canReach(r)));
37375
+ return records.filter((_, i) => verdicts[i]);
37376
+ }
37377
+ return { actor, canReach, only };
37378
+ }
37330
37379
 
37331
37380
  // src/controllers/building.controller.ts
37332
37381
  var import_exceljs = __toESM(require("exceljs"));
@@ -38324,8 +38373,13 @@ function useVehicleController() {
38324
38373
  getVehiclesByNRIC: _getVehiclesByNRIC,
38325
38374
  getAllVehiclesByUnitId: _getAllVehiclesByUnitId,
38326
38375
  getSpecificVehicleById: _getSpecificVehicleById,
38327
- getBlocklistedVehicles: _getBlocklistedVehicles
38376
+ getBlocklistedVehicles: _getBlocklistedVehicles,
38377
+ getVehicleSite: _getVehicleSite
38328
38378
  } = useVehicleRepo();
38379
+ async function requireVehicleReach(req, _id) {
38380
+ const vehicle = await _getVehicleSite(_id);
38381
+ await requireSiteReach(req, vehicle?.site);
38382
+ }
38329
38383
  function normalizeRow(row) {
38330
38384
  return Object.fromEntries(
38331
38385
  Object.entries(row).map(([key, value]) => [
@@ -38518,6 +38572,7 @@ function useVehicleController() {
38518
38572
  return;
38519
38573
  }
38520
38574
  try {
38575
+ await requireSiteReach(req, value.site);
38521
38576
  const user = req.user?.user || req.user?._id;
38522
38577
  const data = await _add(value, void 0, user);
38523
38578
  res.status(201).json({
@@ -38561,6 +38616,8 @@ function useVehicleController() {
38561
38616
  };
38562
38617
  }
38563
38618
  try {
38619
+ if (site)
38620
+ await requireSiteReach(req, site);
38564
38621
  const data = await _getVehicles({
38565
38622
  search,
38566
38623
  page,
@@ -38595,6 +38652,7 @@ function useVehicleController() {
38595
38652
  }
38596
38653
  const { site } = value;
38597
38654
  try {
38655
+ await requireSiteReach(req, site);
38598
38656
  const data = await _getSeasonPassTypes(site);
38599
38657
  res.json(data);
38600
38658
  return;
@@ -38620,6 +38678,7 @@ function useVehicleController() {
38620
38678
  }
38621
38679
  const { _id } = value;
38622
38680
  try {
38681
+ await requireVehicleReach(req, _id);
38623
38682
  const site = await _getVehicleById(_id);
38624
38683
  res.json(site);
38625
38684
  return;
@@ -38645,6 +38704,7 @@ function useVehicleController() {
38645
38704
  }
38646
38705
  const { _id } = value;
38647
38706
  try {
38707
+ await requireVehicleReach(req, _id);
38648
38708
  const site = await _getSpecificVehicleById(_id);
38649
38709
  res.json(site);
38650
38710
  return;
@@ -38688,12 +38748,15 @@ function useVehicleController() {
38688
38748
  return;
38689
38749
  }
38690
38750
  const { _id, ...rest } = value;
38751
+ await requireVehicleReach(req, _id);
38691
38752
  await _updateVehicleById(_id, rest);
38692
38753
  res.json({ message: "Successfully updated vehicle." });
38693
38754
  return;
38694
38755
  } catch (error) {
38695
38756
  import_node_server_utils112.logger.log({ level: "error", message: error.message });
38696
- if (error?.message) {
38757
+ if (error?.statusCode) {
38758
+ next(error);
38759
+ } else if (error?.message) {
38697
38760
  next(new import_node_server_utils112.BadRequestError(error?.message));
38698
38761
  } else {
38699
38762
  next(error);
@@ -38721,6 +38784,7 @@ function useVehicleController() {
38721
38784
  }
38722
38785
  const { recno, site, type, bypass, _id } = value;
38723
38786
  try {
38787
+ await requireVehicleReach(req, _id);
38724
38788
  const data = await _deleteVehicle(_id, recno, site, type, bypass);
38725
38789
  res.json({
38726
38790
  message: "Vehicle deleted successfully.",
@@ -38748,6 +38812,7 @@ function useVehicleController() {
38748
38812
  return;
38749
38813
  }
38750
38814
  const { _id, org, site } = value;
38815
+ await requireVehicleReach(req, _id);
38751
38816
  await _approveVehicleById(_id, org, site);
38752
38817
  res.json({ message: "Successfully approved and updated vehicle." });
38753
38818
  return;
@@ -38793,6 +38858,8 @@ function useVehicleController() {
38793
38858
  limit,
38794
38859
  sort: sortObj
38795
38860
  });
38861
+ const { only } = await siteReachOf(req);
38862
+ data.items = await only(data.items ?? []);
38796
38863
  res.json(data);
38797
38864
  return;
38798
38865
  } catch (error2) {
@@ -38818,6 +38885,7 @@ function useVehicleController() {
38818
38885
  }
38819
38886
  const { _id, org, site } = value;
38820
38887
  try {
38888
+ await requireVehicleReach(req, _id);
38821
38889
  const data = await _reactivateVehicleById(_id, org, site);
38822
38890
  res.status(200).json({
38823
38891
  message: data
@@ -38859,6 +38927,8 @@ function useVehicleController() {
38859
38927
  limit,
38860
38928
  sort: sortObj
38861
38929
  });
38930
+ const { only } = await siteReachOf(req);
38931
+ data.items = await only(data.items ?? []);
38862
38932
  res.json(data);
38863
38933
  return;
38864
38934
  } catch (error2) {
@@ -38885,6 +38955,8 @@ function useVehicleController() {
38885
38955
  }
38886
38956
  const { search, page, limit, site } = value;
38887
38957
  try {
38958
+ if (site)
38959
+ await requireSiteReach(req, site);
38888
38960
  const data = await _getBlocklistedVehicles({
38889
38961
  search,
38890
38962
  page,
@@ -38921,6 +38993,7 @@ function useVehicleController() {
38921
38993
  return;
38922
38994
  }
38923
38995
  const { _id, ...rest } = value;
38996
+ await requireVehicleReach(req, _id);
38924
38997
  await _blocklistVehicles(_id, rest);
38925
38998
  res.json({ message: "Successfully blocked vehicle." });
38926
38999
  return;
@@ -38952,6 +39025,7 @@ function useVehicleController() {
38952
39025
  return;
38953
39026
  }
38954
39027
  const { _id, ...rest } = value;
39028
+ await requireVehicleReach(req, _id);
38955
39029
  await _removeFromBlocklist(_id, rest);
38956
39030
  res.json({ message: "Successfully removed vehicle from blocklist." });
38957
39031
  return;
@@ -50370,38 +50444,6 @@ function usePersonController() {
50370
50444
  }
50371
50445
  return actor;
50372
50446
  }
50373
- async function siteReach(req) {
50374
- const actor = await resolveInviteActor(callerId(req));
50375
- const reachable = /* @__PURE__ */ new Map();
50376
- function canReach(person) {
50377
- if (actor.isSuperAdmin)
50378
- return Promise.resolve(true);
50379
- if (!person)
50380
- return Promise.resolve(false);
50381
- const site = person.site?.toString() ?? "";
50382
- if (!site) {
50383
- const org = person.org?.toString() ?? "";
50384
- return Promise.resolve(Boolean(org) && actor.orgIds.includes(org));
50385
- }
50386
- if (!reachable.has(site)) {
50387
- reachable.set(
50388
- site,
50389
- useCameraViewService().entitleSite({ siteId: site, userId: actor.id }).then(
50390
- () => true,
50391
- () => false
50392
- )
50393
- );
50394
- }
50395
- return reachable.get(site);
50396
- }
50397
- async function only(people) {
50398
- if (actor.isSuperAdmin)
50399
- return people;
50400
- const verdicts = await Promise.all(people.map((p) => canReach(p)));
50401
- return people.filter((_, i) => verdicts[i]);
50402
- }
50403
- return { actor, canReach, only };
50404
- }
50405
50447
  async function add(req, res, next) {
50406
50448
  const payload = { ...req.body };
50407
50449
  const { error } = schemaPerson.validate(payload, {
@@ -50576,7 +50618,7 @@ function usePersonController() {
50576
50618
  }
50577
50619
  try {
50578
50620
  const data = await _getByNRIC(nric);
50579
- const { canReach } = await siteReach(req);
50621
+ const { canReach } = await siteReachOf(req);
50580
50622
  res.json(await canReach(data) ? data : null);
50581
50623
  return;
50582
50624
  } catch (error2) {
@@ -50596,7 +50638,7 @@ function usePersonController() {
50596
50638
  }
50597
50639
  try {
50598
50640
  const data = await _getPersonByPhoneNumber(contact);
50599
- const { canReach } = await siteReach(req);
50641
+ const { canReach } = await siteReachOf(req);
50600
50642
  res.json(await canReach(data) ? data : null);
50601
50643
  return;
50602
50644
  } catch (error2) {
@@ -50641,7 +50683,7 @@ function usePersonController() {
50641
50683
  type,
50642
50684
  unit
50643
50685
  });
50644
- const { only } = await siteReach(req);
50686
+ const { only } = await siteReachOf(req);
50645
50687
  res.json(await only(data));
50646
50688
  return;
50647
50689
  } catch (error) {
@@ -50662,7 +50704,7 @@ function usePersonController() {
50662
50704
  }
50663
50705
  const { search } = value;
50664
50706
  try {
50665
- const { actor } = await siteReach(req);
50707
+ const { actor } = await siteReachOf(req);
50666
50708
  const data = await _getCompany(
50667
50709
  search,
50668
50710
  actor.isSuperAdmin ? void 0 : actor.orgIds
@@ -50686,7 +50728,7 @@ function usePersonController() {
50686
50728
  }
50687
50729
  try {
50688
50730
  const data = await _getPeopleByPlateNumber(plateNumber);
50689
- const { only } = await siteReach(req);
50731
+ const { only } = await siteReachOf(req);
50690
50732
  res.json({ data: await only(data) });
50691
50733
  return;
50692
50734
  } catch (error2) {
@@ -50727,7 +50769,7 @@ function usePersonController() {
50727
50769
  }
50728
50770
  });
50729
50771
  try {
50730
- const { actor } = await siteReach(req);
50772
+ const { actor } = await siteReachOf(req);
50731
50773
  if (!actor.isSuperAdmin) {
50732
50774
  await useCameraViewService().entitleSite({ siteId: site, userId: actor.id });
50733
50775
  }
@@ -50757,7 +50799,7 @@ function usePersonController() {
50757
50799
  }
50758
50800
  try {
50759
50801
  const data = await _getByUserId(userId);
50760
- const { actor, canReach } = await siteReach(req);
50802
+ const { actor, canReach } = await siteReachOf(req);
50761
50803
  const isSelf = Boolean(actor.id) && data?.user?.toString() === actor.id;
50762
50804
  res.json(isSelf || await canReach(data) ? data : null);
50763
50805
  return;
@@ -55438,12 +55480,25 @@ function useDocumentManagementRepo() {
55438
55480
  throw error;
55439
55481
  }
55440
55482
  }
55483
+ async function getDocumentScope(_id) {
55484
+ let id;
55485
+ try {
55486
+ id = new import_mongodb102.ObjectId(_id);
55487
+ } catch (error) {
55488
+ throw new import_node_server_utils164.BadRequestError("Invalid document ID format.");
55489
+ }
55490
+ return await collection.findOne(
55491
+ { _id: id },
55492
+ { projection: { site: 1, org: 1 } }
55493
+ );
55494
+ }
55441
55495
  return {
55442
55496
  createIndex,
55443
55497
  createTextIndex,
55444
55498
  add,
55445
55499
  getAll,
55446
55500
  getDocumentById,
55501
+ getDocumentScope,
55447
55502
  updateDocumentById,
55448
55503
  updateFolderById,
55449
55504
  deleteDocumentById,
@@ -55698,8 +55753,24 @@ function useDocumentManagementController() {
55698
55753
  updateFolderById: _updateFolderById,
55699
55754
  deleteDocumentById: _deleteDocumentById,
55700
55755
  deleteFolderById: _deleteFolderById,
55701
- getDocumentManagementBySiteId: _getDocumentManagementBySiteId
55756
+ getDocumentManagementBySiteId: _getDocumentManagementBySiteId,
55757
+ getDocumentScope: _getDocumentScope
55702
55758
  } = useDocumentManagementRepo();
55759
+ async function requireDocumentReach(req, _id) {
55760
+ const doc = await _getDocumentScope(_id);
55761
+ const site = doc?.site?.toString() ?? "";
55762
+ if (site) {
55763
+ await requireSiteReach(req, site);
55764
+ return;
55765
+ }
55766
+ const actor = await resolveInviteActor(callerId(req));
55767
+ if (actor.isSuperAdmin)
55768
+ return;
55769
+ const org = doc?.org?.toString() ?? "";
55770
+ if (!org || !actor.orgIds.includes(org)) {
55771
+ throw new import_node_server_utils166.NotFoundError("Document not found.");
55772
+ }
55773
+ }
55703
55774
  async function add(req, res, next) {
55704
55775
  const cookies = req.headers.cookie?.split(";").map((cookie) => cookie.trim().split("=")).reduce(
55705
55776
  (acc, [key, value]) => ({ ...acc, [key]: value }),
@@ -55792,6 +55863,7 @@ function useDocumentManagementController() {
55792
55863
  return;
55793
55864
  }
55794
55865
  try {
55866
+ await requireDocumentReach(req, _id);
55795
55867
  const data = await _getDocumentById(_id);
55796
55868
  res.json(data);
55797
55869
  return;
@@ -55833,6 +55905,7 @@ function useDocumentManagementController() {
55833
55905
  return;
55834
55906
  }
55835
55907
  try {
55908
+ await requireDocumentReach(req, _id);
55836
55909
  await _updateDocumentById(_id, payload);
55837
55910
  res.json({ message: "Successfully updated document." });
55838
55911
  return;
@@ -55865,6 +55938,7 @@ function useDocumentManagementController() {
55865
55938
  return;
55866
55939
  }
55867
55940
  try {
55941
+ await requireDocumentReach(req, _id);
55868
55942
  await _updateFolderById(_id, payload);
55869
55943
  res.json({ message: "Successfully updated folder." });
55870
55944
  return;
@@ -55884,6 +55958,7 @@ function useDocumentManagementController() {
55884
55958
  return;
55885
55959
  }
55886
55960
  try {
55961
+ await requireDocumentReach(req, _id);
55887
55962
  await _deleteDocumentById(_id);
55888
55963
  res.json({ message: "Successfully deleted document." });
55889
55964
  return;
@@ -55903,6 +55978,7 @@ function useDocumentManagementController() {
55903
55978
  return;
55904
55979
  }
55905
55980
  try {
55981
+ await requireDocumentReach(req, _id);
55906
55982
  await _deleteFolderById(_id);
55907
55983
  res.json({ message: "Successfully deleted folder." });
55908
55984
  return;
@@ -55923,6 +55999,7 @@ function useDocumentManagementController() {
55923
55999
  return;
55924
56000
  }
55925
56001
  try {
56002
+ await requireSiteReach(req, _id);
55926
56003
  const data = await _getDocumentManagementBySiteId(_id, type);
55927
56004
  res.json(data);
55928
56005
  return;