@7365admin1/core 3.52.11 → 3.52.12-staging.260

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.
@@ -0,0 +1,17 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Scope the building, unit and level lists to the caller's own sites
6
+
7
+ `GET /api/buildings`, `GET /api/building-units` and `GET /api/building-levels`
8
+ took an optional `site` and applied it as a plain filter, so a request that
9
+ named none was answered from the whole collection — every client's estate. An
10
+ explicit site was never authorised either. `GET /api/building-units/site/:site`,
11
+ which returns units together with their owners, took the site from the URL and
12
+ checked nothing.
13
+
14
+ All four now use the same rule the vehicle, visitor, document and camera lists
15
+ use: an explicit site goes through `requireSiteReach`, and no site falls back to
16
+ `entitledSites`. The restriction is part of the Redis cache key as well as the
17
+ query, so one caller's page is not served to another.
@@ -0,0 +1,5 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Reconcile the camera site-reach rule with the site-list rule: an organisation-level role reaches every site of its own organisation even when its membership row also names a site.
package/dist/index.d.ts CHANGED
@@ -2379,13 +2379,14 @@ declare const buildings_namespace_collection = "buildings";
2379
2379
  declare function useBuildingRepo(): {
2380
2380
  createIndexes: () => Promise<void>;
2381
2381
  add: (value: TBuilding, session?: ClientSession) => Promise<ObjectId>;
2382
- getAll: ({ search, page, limit, sort, site, status, }?: {
2382
+ getAll: ({ search, page, limit, sort, site, status, siteScope, }?: {
2383
2383
  search?: string | undefined;
2384
2384
  page?: number | undefined;
2385
2385
  limit?: number | undefined;
2386
- sort?: {} | undefined;
2386
+ sort?: Record<string, any> | undefined;
2387
2387
  site?: string | undefined;
2388
2388
  status?: BuildingStatus | undefined;
2389
+ siteScope?: string[] | null | undefined;
2389
2390
  }) => Promise<Record<string, any>>;
2390
2391
  getAllBuildingForResident: ({ search, page, limit, sort, site, status, }?: {
2391
2392
  search?: string | undefined;
@@ -2454,14 +2455,15 @@ declare const building_units_namespace_collection = "building-units";
2454
2455
  declare function useBuildingUnitRepo(): {
2455
2456
  createIndexes: () => Promise<void>;
2456
2457
  add: (value: TBuildingUnit, session?: ClientSession) => Promise<ObjectId>;
2457
- getAll: ({ search, page, limit, sort, site, building, status, }?: {
2458
+ getAll: ({ search, page, limit, sort, site, building, status, siteScope, }?: {
2458
2459
  search?: string | undefined;
2459
2460
  page?: number | undefined;
2460
2461
  limit?: number | undefined;
2461
- sort?: {} | undefined;
2462
+ sort?: Record<string, any> | undefined;
2462
2463
  site?: string | undefined;
2463
2464
  building?: string | undefined;
2464
2465
  status?: string | undefined;
2466
+ siteScope?: string[] | null | undefined;
2465
2467
  }) => Promise<Record<string, any>>;
2466
2468
  getById: (_id: string | ObjectId, session?: ClientSession) => Promise<TBuildingUnit>;
2467
2469
  getByBuildingLevel: (building: string | ObjectId, level: string) => Promise<TBuildingUnit | null>;
@@ -11331,13 +11333,14 @@ declare const building_level_namespace_collection = "building-levels";
11331
11333
  declare function useBuildingLevelRepo(): {
11332
11334
  createIndexes: () => Promise<void>;
11333
11335
  add: (value: TBuildingLevel, session?: ClientSession) => Promise<ObjectId>;
11334
- getAll: ({ search, page, limit, sort, site, status, }?: {
11336
+ getAll: ({ search, page, limit, sort, site, status, siteScope, }?: {
11335
11337
  search?: string | undefined;
11336
11338
  page?: number | undefined;
11337
11339
  limit?: number | undefined;
11338
- sort?: {} | undefined;
11340
+ sort?: Record<string, any> | undefined;
11339
11341
  site?: string | undefined;
11340
11342
  status?: string | undefined;
11343
+ siteScope?: string[] | null | undefined;
11341
11344
  }) => Promise<Record<string, any>>;
11342
11345
  getById: (_id: string | ObjectId, session?: ClientSession) => Promise<TBuildingLevel>;
11343
11346
  updateLevelById: (_id: string | ObjectId, value: TBuildingLevel, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
package/dist/index.js CHANGED
@@ -34878,7 +34878,17 @@ function useBuildingUnitRepo() {
34878
34878
  sort = {},
34879
34879
  site = "",
34880
34880
  building = "",
34881
- status = "active"
34881
+ status = "active",
34882
+ /**
34883
+ * The sites this caller may be shown, or `null` for no restriction. Set only
34884
+ * when the request named NO site — see `entitledSites`. Applied inside the
34885
+ * query so the page counts describe what the caller can actually see, and
34886
+ * folded into the cache key so one caller's page is never served to another.
34887
+ *
34888
+ * An EMPTY array means "this caller reaches no site" and must still be
34889
+ * applied: `$in: []` matches nothing, which is the fail-closed answer.
34890
+ */
34891
+ siteScope = null
34882
34892
  } = {}) {
34883
34893
  page = page > 0 ? page - 1 : 0;
34884
34894
  const searchText = search.trim();
@@ -34903,6 +34913,11 @@ function useBuildingUnitRepo() {
34903
34913
  building_units_namespace_collection,
34904
34914
  cacheParams
34905
34915
  );
34916
+ if (siteScope) {
34917
+ const scoped = siteScope.filter((id) => import_mongodb67.ObjectId.isValid(id));
34918
+ query2.site = { $in: scoped.map((id) => new import_mongodb67.ObjectId(id)) };
34919
+ cacheParams.siteScope = scoped.length ? [...scoped].sort().join(",") : "no-site";
34920
+ }
34906
34921
  import_node_server_utils98.logger.log({
34907
34922
  level: "info",
34908
34923
  message: `Cache key for getAll building units: ${cacheKey}`
@@ -37682,7 +37697,17 @@ function useBuildingRepo() {
37682
37697
  limit = 10,
37683
37698
  sort = {},
37684
37699
  site = "",
37685
- status = "active" /* ACTIVE */
37700
+ status = "active" /* ACTIVE */,
37701
+ /**
37702
+ * The sites this caller may be shown, or `null` for no restriction. Set only
37703
+ * when the request named NO site — see `entitledSites`. Applied inside the
37704
+ * query so the page counts describe what the caller can actually see, and
37705
+ * folded into the cache key so one caller's page is never served to another.
37706
+ *
37707
+ * An EMPTY array means "this caller reaches no site" and must still be
37708
+ * applied: `$in: []` matches nothing, which is the fail-closed answer.
37709
+ */
37710
+ siteScope = null
37686
37711
  } = {}) {
37687
37712
  page = page > 0 ? page - 1 : 0;
37688
37713
  let siteId;
@@ -37716,6 +37741,11 @@ function useBuildingRepo() {
37716
37741
  ...status && { status }
37717
37742
  };
37718
37743
  const cacheKey = (0, import_node_server_utils105.makeCacheKey)(buildings_namespace_collection, cacheParams);
37744
+ if (siteScope) {
37745
+ const scoped = siteScope.filter((id) => import_mongodb70.ObjectId.isValid(id));
37746
+ query2.site = { $in: scoped.map((id) => new import_mongodb70.ObjectId(id)) };
37747
+ cacheParams.siteScope = scoped.length ? [...scoped].sort().join(",") : "no-site";
37748
+ }
37719
37749
  import_node_server_utils105.logger.log({
37720
37750
  level: "info",
37721
37751
  message: `Cache key for getAll buildings: ${cacheKey}`
@@ -38375,7 +38405,17 @@ function useBuildingLevelRepo() {
38375
38405
  limit = 10,
38376
38406
  sort = {},
38377
38407
  site = "",
38378
- status = "active"
38408
+ status = "active",
38409
+ /**
38410
+ * The sites this caller may be shown, or `null` for no restriction. Set only
38411
+ * when the request named NO site — see `entitledSites`. Applied inside the
38412
+ * query so the page counts describe what the caller can actually see, and
38413
+ * folded into the cache key so one caller's page is never served to another.
38414
+ *
38415
+ * An EMPTY array means "this caller reaches no site" and must still be
38416
+ * applied: `$in: []` matches nothing, which is the fail-closed answer.
38417
+ */
38418
+ siteScope = null
38379
38419
  } = {}) {
38380
38420
  page = page > 0 ? page - 1 : 0;
38381
38421
  const query2 = {
@@ -38395,6 +38435,11 @@ function useBuildingLevelRepo() {
38395
38435
  building_level_namespace_collection,
38396
38436
  cacheParams
38397
38437
  );
38438
+ if (siteScope) {
38439
+ const scoped = siteScope.filter((id) => import_mongodb72.ObjectId.isValid(id));
38440
+ query2.site = { $in: scoped.map((id) => new import_mongodb72.ObjectId(id)) };
38441
+ cacheParams.siteScope = scoped.length ? [...scoped].sort().join(",") : "no-site";
38442
+ }
38398
38443
  import_node_server_utils108.logger.log({
38399
38444
  level: "info",
38400
38445
  message: `Cache key for getAll building levels: ${cacheKey}`
@@ -39372,13 +39417,17 @@ function useBuildingController() {
39372
39417
  const search = value.search ?? "";
39373
39418
  const sortObj = sort ? { [sort]: order === "asc" /* ASC */ ? 1 : -1 } : {};
39374
39419
  try {
39420
+ const siteScope = site ? null : await entitledSites(req);
39421
+ if (site)
39422
+ await requireSiteReach(req, site);
39375
39423
  const buildings = await _getAll({
39376
39424
  page,
39377
39425
  limit,
39378
39426
  sort: sortObj,
39379
39427
  status,
39380
39428
  site,
39381
- search
39429
+ search,
39430
+ siteScope
39382
39431
  });
39383
39432
  res.json(buildings);
39384
39433
  return;
@@ -40010,6 +40059,9 @@ function useBuildingUnitController() {
40010
40059
  const site = value.site;
40011
40060
  const building = value.building;
40012
40061
  const search = value.search;
40062
+ const siteScope = site ? null : await entitledSites(req);
40063
+ if (site)
40064
+ await requireSiteReach(req, site);
40013
40065
  const buildings = await _getAll({
40014
40066
  page,
40015
40067
  limit,
@@ -40017,7 +40069,8 @@ function useBuildingUnitController() {
40017
40069
  status,
40018
40070
  site,
40019
40071
  search,
40020
- building
40072
+ building,
40073
+ siteScope
40021
40074
  });
40022
40075
  res.json(buildings);
40023
40076
  return;
@@ -40131,6 +40184,7 @@ function useBuildingUnitController() {
40131
40184
  }
40132
40185
  const site = req.params.site;
40133
40186
  try {
40187
+ await requireSiteReach(req, site);
40134
40188
  const data = await _getBuildingUnitsWithOwner(site);
40135
40189
  res.json(data);
40136
40190
  return;
@@ -52406,7 +52460,7 @@ function useVisitorTransactionService() {
52406
52460
  unitName: unit?.name,
52407
52461
  org: inviter?.org?.toString(),
52408
52462
  site: inviter?.site.toString(),
52409
- status: value?.type === "contractor" ? isAutoApprovedInvitation ? "approved" /* APPROVED */ : "pending" /* PENDING */ : "pending" /* PENDING */,
52463
+ status: value?.type === "contractor" ? isAutoApprovedInvitation ? "approved" /* APPROVED */ : "pending" /* PENDING */ : "approved" /* APPROVED */,
52410
52464
  inviterId: userId
52411
52465
  };
52412
52466
  const leadId = new import_mongodb86.ObjectId();
@@ -89908,12 +89962,16 @@ function useBuildingLevelController() {
89908
89962
  return;
89909
89963
  }
89910
89964
  const { page, limit, status, site, search } = value;
89965
+ const siteScope = site ? null : await entitledSites(req);
89966
+ if (site)
89967
+ await requireSiteReach(req, site);
89911
89968
  const result = await _getAll({
89912
89969
  page,
89913
89970
  limit,
89914
89971
  status,
89915
89972
  site,
89916
- search
89973
+ search,
89974
+ siteScope
89917
89975
  });
89918
89976
  res.json(result);
89919
89977
  return;