@7365admin1/core 3.47.1-staging.139 → 3.47.1-staging.140
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/.changeset/estate-structure-write-scope.md +51 -0
- package/dist/index.js +2871 -2833
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +56 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/estate-structure-scope.e2e.test.mjs +346 -0
- package/test/e2e/harness.mjs +40 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope the estate-structure writes to the site they act on.
|
|
6
|
+
|
|
7
|
+
`POST/PATCH/PUT` on `/api/buildings`, `/api/building-levels` and
|
|
8
|
+
`/api/building-units` all carried `requireAuth` and nothing more. The site came
|
|
9
|
+
from the request body on the creates and the record id came from the URL on the
|
|
10
|
+
edits and deletes, and neither was checked against the caller. So any signed-in
|
|
11
|
+
account on the platform could add a block to another client's estate, rename its
|
|
12
|
+
levels in bulk, or delete its units — the records residents, visitor passes,
|
|
13
|
+
billing and access rights are all hung off.
|
|
14
|
+
|
|
15
|
+
Ten routes now decide from the site:
|
|
16
|
+
|
|
17
|
+
- `POST /api/buildings/`, `POST /api/building-levels/`,
|
|
18
|
+
`POST /api/building-units/` — from the site named in the body, which is where
|
|
19
|
+
the new record lands.
|
|
20
|
+
- `PATCH /api/buildings/id/:id`, `PUT /api/buildings/:id`,
|
|
21
|
+
`PUT /api/building-levels/id/:id`, `PUT /api/building-levels/:id`,
|
|
22
|
+
`PATCH /api/building-units/id/:id`, `PUT /api/building-units/:id` — the stored
|
|
23
|
+
record is loaded first and its own site decides. The id in the URL selects the
|
|
24
|
+
record; it never authorises it.
|
|
25
|
+
- `PATCH /api/building-levels/batch` — EVERY id in the batch is checked, not
|
|
26
|
+
just the first, and only the distinct sites are looked up so renaming twelve
|
|
27
|
+
levels of one block stays one check.
|
|
28
|
+
|
|
29
|
+
The rule is `entitleSite`, the site-reach rule the camera, HID and people
|
|
30
|
+
modules already use: a membership pinned to the site, an org-wide membership at
|
|
31
|
+
the site's owning organisation, or an ACTIVE `customer.sites` engagement. The
|
|
32
|
+
engagement branch is required, not incidental — the estate structure is
|
|
33
|
+
maintained from the property-management and service-provider apps, whose users
|
|
34
|
+
may hold no membership in the estate's own organisation.
|
|
35
|
+
|
|
36
|
+
The shared four lines live in a new `src/utils/site-reach.util.ts` so the same
|
|
37
|
+
check is not written out in three controllers. It introduces no second
|
|
38
|
+
mechanism: it resolves the caller with `resolveInviteActor` and defers to
|
|
39
|
+
`entitleSite`, exactly as `person.controller.ts` does.
|
|
40
|
+
|
|
41
|
+
A site the caller cannot reach answers as a site that does not exist, so site
|
|
42
|
+
ids cannot be enumerated by watching the difference. A record with no site at
|
|
43
|
+
all is refused rather than waved through.
|
|
44
|
+
|
|
45
|
+
The READS on these three routers are deliberately unchanged. Six of them share
|
|
46
|
+
a controller function with a pre-login signup alias
|
|
47
|
+
(`/buildings/list/site/resident/:siteId`, `/building-levels/list/site/resident/:siteId`,
|
|
48
|
+
`/building-units/resident/site/:site/block/:block/level/:level` and the three
|
|
49
|
+
`resident` variants), which the resident mobile app calls before an account
|
|
50
|
+
exists. Guarding the handler would break registration on a shipped client, so
|
|
51
|
+
those need the alias split first.
|