@7365admin1/core 3.47.1-staging.137 → 3.47.1-staging.139
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/customer-site-org-scope.md +48 -0
- package/.changeset/site-org-scope.md +46 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5378 -5329
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5397 -5344
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/test/e2e/customer-site-scope.e2e.test.mjs +337 -0
- package/test/e2e/harness.mjs +46 -2
- package/test/e2e/site-scope.e2e.test.mjs +321 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
"@7365admin1/core": minor
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Scope `/api/customer-sites` to the organisations on the record.
|
|
6
|
+
|
|
7
|
+
Every route on this module except the pre-login invite acceptance carried
|
|
8
|
+
`requireAuth` and nothing more, and took the organisation straight out of the
|
|
9
|
+
query string or the body (`customer-site.controller.ts`). Two things followed
|
|
10
|
+
from that, and both are closed here.
|
|
11
|
+
|
|
12
|
+
`POST /api/customer-sites` is not merely an engagement record: it CREATES A SITE
|
|
13
|
+
inside whatever `siteOrg` the body names, and writes that site onto the
|
|
14
|
+
organisation as its default when it has none
|
|
15
|
+
(`customer-site.service.ts:77-111`). Any signed-in account on the platform — a
|
|
16
|
+
resident, a cleaner, a guard — could therefore plant a site inside any client.
|
|
17
|
+
|
|
18
|
+
A `customer.sites` row is also the cross-organisation access grant itself: the
|
|
19
|
+
"engaged agency" branch of `resolveSiteAccess` reads it to decide who may reach
|
|
20
|
+
a site's cameras, HID readers and residents
|
|
21
|
+
(`camera-view.service.ts:325-341`). Being able to write, edit or delete those
|
|
22
|
+
rows by id was being able to grant yourself reach into another client's estate,
|
|
23
|
+
or revoke a contractor's.
|
|
24
|
+
|
|
25
|
+
The caller is now resolved from the session and the decision made before
|
|
26
|
+
anything is read or written:
|
|
27
|
+
|
|
28
|
+
- `POST /` requires `requireOrgAccess` on the body's `org`, and on `siteOrg`
|
|
29
|
+
too when it names a different organisation — because that is where the new
|
|
30
|
+
site lands. The Add / Edit Site form sends the same id for both
|
|
31
|
+
(`web-app-org components/SiteForm.vue:397-402`).
|
|
32
|
+
- `GET /` requires `requireOrgAccess` on the `org` filter the caller sends.
|
|
33
|
+
- `GET /:id`, `PUT /:id` and `DELETE /:id` load the row first and decide from
|
|
34
|
+
the row's own `org` and `siteOrg` — Seven365 staff, or a live member of
|
|
35
|
+
EITHER side of the engagement. Either, not one: the estate's manager reaches
|
|
36
|
+
the row through `siteOrg` and the contracted agency reaches the same row
|
|
37
|
+
through `org`, so scoping to one side would break the other's screen.
|
|
38
|
+
- `GET /service-provider/:id` takes a SITE id, and uses `entitleSite` — the
|
|
39
|
+
same site-reach rule the camera, HID and people modules already use, so an
|
|
40
|
+
agency contracted to a site still lists who else works there.
|
|
41
|
+
|
|
42
|
+
`POST /invite/:id` is unchanged and still reachable with no session: an invited
|
|
43
|
+
organisation accepts before it has an account (`web-app-main pages/sign-in.vue:182`).
|
|
44
|
+
|
|
45
|
+
No new authorization mechanism is introduced. `requireOrgAccess` and
|
|
46
|
+
`entitleSite` are the helpers the member, role, people, camera and HID paths
|
|
47
|
+
already use, and the "either side" test is `resolveInviteActor` asked about two
|
|
48
|
+
organisations in one round trip rather than two.
|
|
@@ -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;
|