@7365admin1/core 3.47.1-staging.138 → 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.
@@ -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.
@@ -0,0 +1,46 @@
1
+ ---
2
+ "@7365admin1/core": minor
3
+ ---
4
+
5
+ Scope `/api/sites` to the organisation that owns the site.
6
+
7
+ Every route on this router except the pre-login resident picker carried
8
+ `requireAuth` and nothing more (`site.controller.ts`), and took the
9
+ organisation from the query string or the site id from the URL. `requireAuth`
10
+ proves a session exists and makes no organisation or site decision, so any
11
+ signed-in account on the platform — a resident, a cleaner, an agency guard —
12
+ could `DELETE /api/sites/:id` any site belonging to any client, rename it,
13
+ re-block it, move its guard posts, rewrite its information page, create a site
14
+ inside any organisation, and page through any client's estate list.
15
+
16
+ The caller is now resolved from the session and the decision made before
17
+ anything is read or written:
18
+
19
+ - `POST /` uses `requireOrgAccess` on the body's `orgId` — that is where the new
20
+ site lands.
21
+ - `GET /` uses `requireOrgAccess` on the `org` filter the caller sends.
22
+ - `PUT /:id/block`, `PATCH /id/:id`, `PATCH /guard-post/id/:id`,
23
+ `PATCH /information/id/:id` and `DELETE /:id` use `entitleSite` — a
24
+ membership pinned to the site, an org-wide membership at the site's owning
25
+ organisation, or an ACTIVE `customer.sites` engagement. The engagement branch
26
+ is required, not incidental: Site Settings lives in the SERVICE-PROVIDER apps
27
+ (`web-app-security` and the five module apps, each
28
+ `pages/[org]/[site]/settings.vue` via `layer-common useSiteSettings.ts`), and
29
+ those users hold no membership in the estate's organisation at all.
30
+ - `GET /:id` is deliberately one notch wider than the writes: it also passes
31
+ for any live membership in the site's OWNING organisation. Three shipped
32
+ mobile clients read this route, and the resident app reads
33
+ `org.defaultSite` — which in a multi-site organisation need not be the
34
+ resident's own site, and a resident's membership carries a `siteId`. The
35
+ wider read closes the cross-CLIENT read, which is the defect, and leaves
36
+ site-to-site partitioning inside one client where it is today.
37
+
38
+ A site the caller cannot reach answers exactly as a site that does not exist,
39
+ so site ids cannot be enumerated by watching the difference.
40
+
41
+ `GET /site/resident` is unchanged and still pre-login: the resident mobile app
42
+ needs a site picker before an account exists.
43
+
44
+ No new authorization mechanism is introduced — `requireOrgAccess` and
45
+ `entitleSite` are the helpers the member, role, people, camera and HID paths
46
+ already use.
package/dist/index.d.ts CHANGED
@@ -10153,7 +10153,6 @@ declare function useHidAmicoService(): {
10153
10153
  location?: string | undefined;
10154
10154
  enabled?: boolean | undefined;
10155
10155
  username: string;
10156
- serial?: string | undefined;
10157
10156
  capabilities?: {
10158
10157
  card: boolean;
10159
10158
  facial: boolean;
@@ -10161,6 +10160,7 @@ declare function useHidAmicoService(): {
10161
10160
  pin: boolean;
10162
10161
  intercom: boolean;
10163
10162
  } | undefined;
10163
+ serial?: string | undefined;
10164
10164
  baseUrl: string;
10165
10165
  deviceId?: string | undefined;
10166
10166
  firmwareVersion?: string | undefined;