@7365admin1/layer-common 4.149.1 → 4.150.0
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/CHANGELOG.md +16 -4
- package/components/EntryPassInformation.vue +13 -0
- package/components/HidAccessPermissions.vue +202 -40
- package/components/HidEnabledGate.vue +29 -10
- package/components/HidIntercomManagement.vue +26 -13
- package/components/HidProfileQrCode.vue +6 -2
- package/components/HidQrCodeConfiguration.vue +2 -2
- package/components/HidReaderForm.vue +239 -1
- package/components/HidReaderManagement.vue +26 -8
- package/components/HidReaderUserRoster.vue +3 -1
- package/components/HidServiceSettingsPanel.vue +2 -2
- package/components/HidUserEnrollment.vue +1662 -162
- package/components/MemberMain.vue +1 -1
- package/components/OvernightParkingAvailability.vue +123 -11
- package/components/SiteSettings.vue +5 -2
- package/components/VisitorForm.vue +39 -11
- package/composables/useCleaningPermission.ts +11 -0
- package/composables/useHidAccessPermission.ts +176 -81
- package/composables/useHidAmico.ts +37 -0
- package/composables/useHidNavigation.ts +44 -23
- package/composables/useLandscapingPermission.ts +11 -0
- package/composables/useMechanicalElectricalPermission.ts +5 -0
- package/composables/usePestControlPermission.ts +11 -0
- package/composables/usePoolMaintenancePermission.ts +11 -0
- package/composables/usePropertyPermission.ts +31 -7
- package/composables/useSecurityPermission.ts +33 -13
- package/composables/useServiceProvider.ts +9 -4
- package/constants/permissions.ts +73 -21
- package/package.json +1 -1
- package/pages/[org]/[site]/access-mgmt/hid-qr-code/index.vue +3 -0
- package/types/overnight-parking.d.ts +14 -0
- package/types/site.d.ts +7 -1
- package/utils/hid-enrolment-subject.ts +226 -4
- package/utils/hid-permission-assignments.ts +75 -6
- package/utils/hid-qr-validity.ts +25 -0
- package/utils/hid-reader-audiences.ts +557 -0
- package/utils/hid-registration.ts +24 -0
- package/utils/module-routes.ts +15 -2
- package/utils/nav-sections.ts +1 -1
|
@@ -204,6 +204,22 @@ export default function useHidAmico() {
|
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* The readers a member may enrol THEMSELVES on: the site's enabled readers
|
|
209
|
+
* with a portal, each with its credential capabilities, and nothing else.
|
|
210
|
+
*
|
|
211
|
+
* The self service screens (own QR, face, PIN, card) load this instead of
|
|
212
|
+
* `getReaders`: that one is an admin list behind the HID view right, and a
|
|
213
|
+
* member holding only `hid-mgmt:use-hid-access` is refused on it. This route
|
|
214
|
+
* asks for site membership and the use right. Response: `{ data: { items } }`.
|
|
215
|
+
*/
|
|
216
|
+
function getEnrollmentReaders(siteId: string) {
|
|
217
|
+
return useNuxtApp().$api<{ data: { items: HidApiRecord[] } }>(
|
|
218
|
+
`${basePath}/sites/${siteId}/enrollment-readers`,
|
|
219
|
+
{ method: "GET" },
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
207
223
|
/**
|
|
208
224
|
* The signed-in member's own QR code on one reader.
|
|
209
225
|
*
|
|
@@ -398,6 +414,25 @@ export default function useHidAmico() {
|
|
|
398
414
|
}
|
|
399
415
|
|
|
400
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Put a person's STORED enrolment photo on a reader.
|
|
419
|
+
*
|
|
420
|
+
* No body: the image is the one already on file from when they were first
|
|
421
|
+
* captured. This is what makes a reader that was offline during an enrolment
|
|
422
|
+
* retryable WITHOUT the person coming back - a face template lives on one
|
|
423
|
+
* device and cannot be copied, so the alternative is a fresh capture at every
|
|
424
|
+
* reader.
|
|
425
|
+
*
|
|
426
|
+
* Keyed by the iService account, not a HID user id: the caller does not know
|
|
427
|
+
* which number the person carries on which reader, and the server looks it up.
|
|
428
|
+
*/
|
|
429
|
+
function pushStoredFace(readerId: string, userId: string) {
|
|
430
|
+
return useNuxtApp().$api<{ data: HidFacialEnrollmentResult; message?: string }>(
|
|
431
|
+
`${basePath}/readers/${readerId}/accounts/${userId}/stored-face`,
|
|
432
|
+
{ method: "POST" },
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
401
436
|
function setUserImage(
|
|
402
437
|
readerId: string,
|
|
403
438
|
hidUserId: string | number,
|
|
@@ -660,6 +695,7 @@ export default function useHidAmico() {
|
|
|
660
695
|
|
|
661
696
|
return {
|
|
662
697
|
getReaders,
|
|
698
|
+
getEnrollmentReaders,
|
|
663
699
|
getProfileQr,
|
|
664
700
|
issueProfileQr,
|
|
665
701
|
deleteProfileQr,
|
|
@@ -681,6 +717,7 @@ export default function useHidAmico() {
|
|
|
681
717
|
reconcileReaderIdentificationMethods,
|
|
682
718
|
getLogs,
|
|
683
719
|
setUserImage,
|
|
720
|
+
pushStoredFace,
|
|
684
721
|
deleteUserImage,
|
|
685
722
|
getUserCards,
|
|
686
723
|
assignUserCard,
|
|
@@ -3,23 +3,23 @@ import type { ComputedRef, Ref } from "vue";
|
|
|
3
3
|
/**
|
|
4
4
|
* THE HID FACE READER MENU IS A PERMISSION, NOT A SERVICE FLAG.
|
|
5
5
|
*
|
|
6
|
-
* This composable used to draw the
|
|
7
|
-
* `getHidServiceEnabled(site)` was true. That is a SITE SERVICE FLAG
|
|
8
|
-
* the estate bought HID, not that this member may use it.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* be in the menu at all.
|
|
6
|
+
* This composable used to draw the six item "HID Reader" group whenever
|
|
7
|
+
* `getHidServiceEnabled(site)` was true. That is a SITE SERVICE FLAG: it says
|
|
8
|
+
* the estate bought HID, not that this member may use it. A module a member
|
|
9
|
+
* cannot use should not be in the menu at all, so the menu asks the same
|
|
10
|
+
* questions the pages ask (`useHidAccessPermission`), ANDed with the service
|
|
11
|
+
* flag: no HID service still means no menu.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* Decision of 2026-10-16: the admin entries (Face Reader, HID Reader Users, HID
|
|
14
|
+
* Cards, Intercom, Access Logs) follow `canViewHid`; the member's own "HID QR
|
|
15
|
+
* Code" entry follows `canUseHid`. The group is drawn when at least one entry
|
|
16
|
+
* is, so a member holding only `use-hid-access` still finds their QR page, and
|
|
17
|
+
* a member holding only the admin rights does not see a page the server would
|
|
18
|
+
* refuse them. `site-settings:manage-entry-pass` no longer draws anything here.
|
|
17
19
|
*
|
|
18
|
-
* `Layout/NavigationDrawer.vue`
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
21
|
-
* here therefore WIDENS — nobody who could see the menu can lose it — and
|
|
22
|
-
* leaves one list in one place.
|
|
20
|
+
* `Layout/NavigationDrawer.vue` keeps no permission list of its own: it takes
|
|
21
|
+
* `menuItem` from here and runs it through `withoutDeniedRoutes`, where the
|
|
22
|
+
* client's module list (`hid-mgmt`) can take the whole group away again.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
type HidNavigationParams = {
|
|
@@ -32,14 +32,21 @@ type HidNavigationSite = Record<string, unknown>;
|
|
|
32
32
|
export default function useHidNavigation() {
|
|
33
33
|
const { getSiteById } = useSiteSettings();
|
|
34
34
|
const { getHidServiceEnabled } = useOptionalServices();
|
|
35
|
-
const {
|
|
35
|
+
const { canViewHid, canUseHid } = useHidAccessPermission();
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* The whole group, unfiltered. Exported for callers that compose their own
|
|
39
|
+
* menus; `useHidFaceReaderMenu` below is the one that applies the rights.
|
|
40
|
+
* Each entry says which right draws it so the filter cannot drift from the
|
|
41
|
+
* list.
|
|
42
|
+
*/
|
|
37
43
|
function getHidFaceReaderMenu({ org, site }: HidNavigationParams) {
|
|
38
44
|
return {
|
|
39
|
-
title: "HID
|
|
45
|
+
title: "HID Reader",
|
|
40
46
|
children: [
|
|
41
47
|
{
|
|
42
48
|
title: "Face Reader",
|
|
49
|
+
hidRight: "view" as const,
|
|
43
50
|
route: {
|
|
44
51
|
name: "org-site-access-mgmt-hid-readers",
|
|
45
52
|
params: { org, site },
|
|
@@ -61,6 +68,7 @@ export default function useHidNavigation() {
|
|
|
61
68
|
// `hid-users` is left in place and simply unlisted - the same state
|
|
62
69
|
// `administrator` was in - so any existing link to it still resolves.
|
|
63
70
|
title: "HID Reader Users",
|
|
71
|
+
hidRight: "view" as const,
|
|
64
72
|
route: {
|
|
65
73
|
name: "org-site-access-mgmt-administrator",
|
|
66
74
|
params: { org, site },
|
|
@@ -71,6 +79,7 @@ export default function useHidNavigation() {
|
|
|
71
79
|
// entry in this group acts on a resident or a visitor; this one has
|
|
72
80
|
// no subject but the caller.
|
|
73
81
|
title: "HID QR Code",
|
|
82
|
+
hidRight: "use" as const,
|
|
74
83
|
route: {
|
|
75
84
|
name: "org-site-access-mgmt-hid-qr-code",
|
|
76
85
|
params: { org, site },
|
|
@@ -78,6 +87,7 @@ export default function useHidNavigation() {
|
|
|
78
87
|
},
|
|
79
88
|
{
|
|
80
89
|
title: "HID Cards",
|
|
90
|
+
hidRight: "view" as const,
|
|
81
91
|
route: {
|
|
82
92
|
name: "org-site-access-mgmt-hid-cards",
|
|
83
93
|
params: { org, site },
|
|
@@ -85,6 +95,7 @@ export default function useHidNavigation() {
|
|
|
85
95
|
},
|
|
86
96
|
{
|
|
87
97
|
title: "Intercom",
|
|
98
|
+
hidRight: "view" as const,
|
|
88
99
|
route: {
|
|
89
100
|
name: "org-site-access-mgmt-intercom",
|
|
90
101
|
params: { org, site },
|
|
@@ -92,6 +103,7 @@ export default function useHidNavigation() {
|
|
|
92
103
|
},
|
|
93
104
|
{
|
|
94
105
|
title: "Access Logs",
|
|
106
|
+
hidRight: "view" as const,
|
|
95
107
|
route: {
|
|
96
108
|
name: "org-site-access-mgmt-access-logs",
|
|
97
109
|
params: { org, site },
|
|
@@ -138,14 +150,23 @@ export default function useHidNavigation() {
|
|
|
138
150
|
getHidServiceEnabled(site.value, siteDetails.value || fallbackSite?.value),
|
|
139
151
|
);
|
|
140
152
|
|
|
141
|
-
// ...AND this member may open
|
|
142
|
-
// name and its meaning for callers: "should the HID menu be drawn".
|
|
143
|
-
const enabled = computed(
|
|
144
|
-
|
|
145
|
-
const menuItem = computed(() =>
|
|
146
|
-
enabled.value ? getHidFaceReaderMenu({ org: org.value, site: site.value }) : null,
|
|
153
|
+
// ...AND this member may open at least one screen behind it. `enabled`
|
|
154
|
+
// keeps its name and its meaning for callers: "should the HID menu be drawn".
|
|
155
|
+
const enabled = computed(
|
|
156
|
+
() => serviceEnabled.value && (canViewHid.value || canUseHid.value),
|
|
147
157
|
);
|
|
148
158
|
|
|
159
|
+
// Only the entries this member's rights draw. The admin entries need
|
|
160
|
+
// `canViewHid`; the member's own QR page needs `canUseHid`.
|
|
161
|
+
const menuItem = computed(() => {
|
|
162
|
+
if (!enabled.value) return null;
|
|
163
|
+
const group = getHidFaceReaderMenu({ org: org.value, site: site.value });
|
|
164
|
+
const children = group.children.filter((child) =>
|
|
165
|
+
child.hidRight === "use" ? canUseHid.value : canViewHid.value,
|
|
166
|
+
);
|
|
167
|
+
return children.length ? { ...group, children } : null;
|
|
168
|
+
});
|
|
169
|
+
|
|
149
170
|
return {
|
|
150
171
|
enabled,
|
|
151
172
|
serviceEnabled,
|
|
@@ -285,6 +285,17 @@ export default function useLandscapingPermission() {
|
|
|
285
285
|
description: "Allows the user to manage site settings.",
|
|
286
286
|
},
|
|
287
287
|
},
|
|
288
|
+
// HID access, user side only (decision of 2026-10-16). The service apps
|
|
289
|
+
// have no HID admin screens yet, so a role here can be prepared with the
|
|
290
|
+
// one string that lets a member use their own QR code, face, PIN, card and
|
|
291
|
+
// intercom. Mirrored from core `src/utils/hid-access.util.ts`.
|
|
292
|
+
"hid-mgmt": {
|
|
293
|
+
"use-hid-access": {
|
|
294
|
+
check: true,
|
|
295
|
+
description:
|
|
296
|
+
"Allows the user to see HID Access in the app and use their own QR code, face, PIN, card and intercom at this site.",
|
|
297
|
+
},
|
|
298
|
+
},
|
|
288
299
|
};
|
|
289
300
|
|
|
290
301
|
return {
|
|
@@ -52,6 +52,11 @@ export default function useMechanicalElectricalPermission() {
|
|
|
52
52
|
"area-mgmt": schedulePermissions["area-mgmt"],
|
|
53
53
|
"unit-mgmt": schedulePermissions["unit-mgmt"],
|
|
54
54
|
"site-settings": schedulePermissions["site-settings"],
|
|
55
|
+
// HID access, user side only (2026-10-19): the M&E mobile app gains the
|
|
56
|
+
// HID user side, so an M&E role must be able to hold `use-hid-access`.
|
|
57
|
+
// Taken from the cleaning catalogue like the keys above (one action, same
|
|
58
|
+
// description), so the two cannot drift. Catalogue-only: grants nothing.
|
|
59
|
+
"hid-mgmt": schedulePermissions["hid-mgmt"],
|
|
55
60
|
"cleaning-schedule-mgmt": schedulePermissions["cleaning-schedule-mgmt"],
|
|
56
61
|
"schedule-task-mgmt": schedulePermissions["schedule-task-mgmt"],
|
|
57
62
|
"attendance-mgmt": schedulePermissions["attendance-mgmt"],
|
|
@@ -93,6 +93,17 @@ export default function usePestControlPermission() {
|
|
|
93
93
|
description: "Allows the user to manage and update site settings.",
|
|
94
94
|
},
|
|
95
95
|
},
|
|
96
|
+
// HID access, user side only (decision of 2026-10-16). The service apps
|
|
97
|
+
// have no HID admin screens yet, so a role here can be prepared with the
|
|
98
|
+
// one string that lets a member use their own QR code, face, PIN, card and
|
|
99
|
+
// intercom. Mirrored from core `src/utils/hid-access.util.ts`.
|
|
100
|
+
"hid-mgmt": {
|
|
101
|
+
"use-hid-access": {
|
|
102
|
+
check: true,
|
|
103
|
+
description:
|
|
104
|
+
"Allows the user to see HID Access in the app and use their own QR code, face, PIN, card and intercom at this site.",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
96
107
|
// area management permissions
|
|
97
108
|
"area-mgmt": {
|
|
98
109
|
"see-all-areas": {
|
|
@@ -93,6 +93,17 @@ export default function usePoolMaintenancePermission() {
|
|
|
93
93
|
description: "Allows the user to manage and update site settings.",
|
|
94
94
|
},
|
|
95
95
|
},
|
|
96
|
+
// HID access, user side only (decision of 2026-10-16). The service apps
|
|
97
|
+
// have no HID admin screens yet, so a role here can be prepared with the
|
|
98
|
+
// one string that lets a member use their own QR code, face, PIN, card and
|
|
99
|
+
// intercom. Mirrored from core `src/utils/hid-access.util.ts`.
|
|
100
|
+
"hid-mgmt": {
|
|
101
|
+
"use-hid-access": {
|
|
102
|
+
check: true,
|
|
103
|
+
description:
|
|
104
|
+
"Allows the user to see HID Access in the app and use their own QR code, face, PIN, card and intercom at this site.",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
96
107
|
// area management permissions
|
|
97
108
|
"area-mgmt": {
|
|
98
109
|
"see-all-areas": {
|
|
@@ -14,7 +14,8 @@ import { useCommonPermissions } from "./useCommonPermission";
|
|
|
14
14
|
* Two copies is how they drift. On 2026-09-05 the `-org` copy was found to be a
|
|
15
15
|
* strict SUBSET of `-property-management`'s — **32 permissions short**, nine
|
|
16
16
|
* whole families plus all six `access-card-mgmt` strings that
|
|
17
|
-
* `core/utils/hid-access.util.ts`
|
|
17
|
+
* `core/utils/hid-access.util.ts` enforced at the time (HID reads its own
|
|
18
|
+
* `hid-mgmt` family since 2026-10-16) — so a role built through
|
|
18
19
|
* the onboarding wizard could never be granted them, and the modules were
|
|
19
20
|
* unreachable for anybody who joined that way. web-app-org #189 closed it by
|
|
20
21
|
* copying the file across, which left two identical copies and the same trap
|
|
@@ -256,10 +257,6 @@ export default function usePropertyPermission() {
|
|
|
256
257
|
description:
|
|
257
258
|
"Allows the user to remove an access card from the system permanently.",
|
|
258
259
|
},
|
|
259
|
-
view: {
|
|
260
|
-
check: true,
|
|
261
|
-
description: "Allows the user to view an access card's details.",
|
|
262
|
-
},
|
|
263
260
|
"assign-access-card": {
|
|
264
261
|
check: true,
|
|
265
262
|
description: "Allows the user to assign an access card to a person.",
|
|
@@ -269,10 +266,37 @@ export default function usePropertyPermission() {
|
|
|
269
266
|
description:
|
|
270
267
|
"Allows the user to replace a lost or damaged access card with a new one.",
|
|
271
268
|
},
|
|
272
|
-
|
|
269
|
+
},
|
|
270
|
+
// HID access management (decision of 2026-10-16). Five strings under one
|
|
271
|
+
// resource, mirrored from core `src/utils/hid-access.util.ts`; the HID
|
|
272
|
+
// screens, menu and buttons (`useHidAccessPermission`) and every
|
|
273
|
+
// `/api/access-management/hid` route read them. Wildcard passes all five,
|
|
274
|
+
// an empty list passes none, either manage right implies view.
|
|
275
|
+
"hid-mgmt": {
|
|
276
|
+
"use-hid-access": {
|
|
277
|
+
check: true,
|
|
278
|
+
description:
|
|
279
|
+
"Allows the user to see HID Access in the app and use their own QR code, face, PIN, card and intercom at this site.",
|
|
280
|
+
},
|
|
281
|
+
"see-all-hid": {
|
|
282
|
+
check: true,
|
|
283
|
+
description:
|
|
284
|
+
"Allows the user to view the site's HID readers, enrolled people, cards and access logs.",
|
|
285
|
+
},
|
|
286
|
+
"manage-hid-readers": {
|
|
287
|
+
check: true,
|
|
288
|
+
description:
|
|
289
|
+
"Allows the user to add, configure, test, sync and remove HID readers. Includes viewing.",
|
|
290
|
+
},
|
|
291
|
+
"manage-hid-users": {
|
|
292
|
+
check: true,
|
|
293
|
+
description:
|
|
294
|
+
"Allows the user to enrol and remove people, cards and PINs, and assign HID access groups. Includes viewing.",
|
|
295
|
+
},
|
|
296
|
+
"manage-hid-settings": {
|
|
273
297
|
check: true,
|
|
274
298
|
description:
|
|
275
|
-
"Allows the user to
|
|
299
|
+
"Allows the user to switch HID on or off for the site and configure the HID QR code.",
|
|
276
300
|
},
|
|
277
301
|
},
|
|
278
302
|
"service-provider-mgmt": {
|
|
@@ -575,12 +575,10 @@ export default function useSecurityPermission() {
|
|
|
575
575
|
description: "Allows the user to delete/remove a unit.",
|
|
576
576
|
},
|
|
577
577
|
},
|
|
578
|
-
//
|
|
579
|
-
//
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
// call. Offering them here does not open any gate; it makes the server's
|
|
583
|
-
// existing rule grantable.
|
|
578
|
+
// Access cards. Until 2026-10 this family was also what every
|
|
579
|
+
// `/api/access-management/hid` route read; HID now has `hid-mgmt` below and
|
|
580
|
+
// the card strings here mean cards again (the server still accepts them
|
|
581
|
+
// for HID during the alias period, see `useHidAccessPermission`).
|
|
584
582
|
"access-card-mgmt": {
|
|
585
583
|
"see-all-card": {
|
|
586
584
|
check: true,
|
|
@@ -590,11 +588,6 @@ export default function useSecurityPermission() {
|
|
|
590
588
|
check: true,
|
|
591
589
|
description: "Allows the user to view QR tagging.",
|
|
592
590
|
},
|
|
593
|
-
view: {
|
|
594
|
-
check: true,
|
|
595
|
-
description:
|
|
596
|
-
"Allows the user to view access card management, including HID readers and access logs.",
|
|
597
|
-
},
|
|
598
591
|
"add-access-card": {
|
|
599
592
|
check: true,
|
|
600
593
|
description: "Allows the user to add a new access card to the system.",
|
|
@@ -616,10 +609,37 @@ export default function useSecurityPermission() {
|
|
|
616
609
|
check: true,
|
|
617
610
|
description: "Allows the user to replace a lost or damaged access card.",
|
|
618
611
|
},
|
|
619
|
-
|
|
612
|
+
},
|
|
613
|
+
// HID access management (decision of 2026-10-16). Five strings under one
|
|
614
|
+
// resource, mirrored from core `src/utils/hid-access.util.ts`; the HID
|
|
615
|
+
// screens, menu and buttons (`useHidAccessPermission`) and every
|
|
616
|
+
// `/api/access-management/hid` route read them. Wildcard passes all five,
|
|
617
|
+
// an empty list passes none, either manage right implies view.
|
|
618
|
+
"hid-mgmt": {
|
|
619
|
+
"use-hid-access": {
|
|
620
|
+
check: true,
|
|
621
|
+
description:
|
|
622
|
+
"Allows the user to see HID Access in the app and use their own QR code, face, PIN, card and intercom at this site.",
|
|
623
|
+
},
|
|
624
|
+
"see-all-hid": {
|
|
625
|
+
check: true,
|
|
626
|
+
description:
|
|
627
|
+
"Allows the user to view the site's HID readers, enrolled people, cards and access logs.",
|
|
628
|
+
},
|
|
629
|
+
"manage-hid-readers": {
|
|
630
|
+
check: true,
|
|
631
|
+
description:
|
|
632
|
+
"Allows the user to add, configure, test, sync and remove HID readers. Includes viewing.",
|
|
633
|
+
},
|
|
634
|
+
"manage-hid-users": {
|
|
635
|
+
check: true,
|
|
636
|
+
description:
|
|
637
|
+
"Allows the user to enrol and remove people, cards and PINs, and assign HID access groups. Includes viewing.",
|
|
638
|
+
},
|
|
639
|
+
"manage-hid-settings": {
|
|
620
640
|
check: true,
|
|
621
641
|
description:
|
|
622
|
-
"Allows the user to
|
|
642
|
+
"Allows the user to switch HID on or off for the site and configure the HID QR code.",
|
|
623
643
|
},
|
|
624
644
|
},
|
|
625
645
|
// Two resources below are checked ONLY by the iSecure365 mobile app, which
|
|
@@ -19,10 +19,15 @@ export type TSiteProviderMember = {
|
|
|
19
19
|
unit?: string | null;
|
|
20
20
|
unitName?: string;
|
|
21
21
|
/**
|
|
22
|
-
* The person's user account.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* The person's user account. Anything acting on the PERSON needs this rather
|
|
23
|
+
* than `_id`, which identifies the membership: an access card carries it as
|
|
24
|
+
* `userId`, and HID reader access is bound by it -
|
|
25
|
+
* `resolvePermissionUserBindings` drops every subject without one.
|
|
26
|
+
*
|
|
27
|
+
* Returned from core 3.130. Before that the repository projected it and the
|
|
28
|
+
* service layer dropped it, so against an older API it is absent on every
|
|
29
|
+
* row - `providerAccountsKnown` is how the HID enrolment screen tells the two
|
|
30
|
+
* apart rather than reading an absence as "nobody has an account".
|
|
26
31
|
*/
|
|
27
32
|
user?: string | null;
|
|
28
33
|
};
|
package/constants/permissions.ts
CHANGED
|
@@ -380,16 +380,38 @@ export const PERMISSIONS = {
|
|
|
380
380
|
"add-service-provider",
|
|
381
381
|
"invite-service-provider",
|
|
382
382
|
],
|
|
383
|
+
// Access cards and QR tagging: the Property Management screens of those
|
|
384
|
+
// names. Until 2026-10 the HID screens borrowed this family (core
|
|
385
|
+
// `hid-access.util.ts` read nine of its strings); HID now has `hid-mgmt`
|
|
386
|
+
// below. `view` and `manage-hid` were only ever HID rights, so they left with
|
|
387
|
+
// it: see `RETIRED_PERMISSIONS` for how they are still read during the alias
|
|
388
|
+
// period.
|
|
383
389
|
"access-card-mgmt": [
|
|
384
390
|
"see-all-card",
|
|
385
391
|
"see-all-qr-tagging",
|
|
386
|
-
"view",
|
|
387
392
|
"add-access-card",
|
|
388
393
|
"update-access-card",
|
|
389
394
|
"replace-access-card",
|
|
390
395
|
"delete-access-card",
|
|
391
396
|
"assign-access-card",
|
|
392
|
-
|
|
397
|
+
],
|
|
398
|
+
// HID access management (decision of 2026-10-16). The five strings are
|
|
399
|
+
// defined in core `src/utils/hid-access.util.ts` (`HID_RESOURCE` and the
|
|
400
|
+
// `HID_*_PERMISSIONS` lists); this package does not depend on `@7365admin1/core`,
|
|
401
|
+
// so it keeps its own copy and `test/hid-access-gate.test.mjs` pins the five.
|
|
402
|
+
// use-hid-access user side: own QR, face, PIN, card, intercom
|
|
403
|
+
// see-all-hid read any HID admin screen
|
|
404
|
+
// manage-hid-readers add, configure, test, sync, remove readers
|
|
405
|
+
// manage-hid-users enrol and remove people, cards, PINs, groups
|
|
406
|
+
// manage-hid-settings HID on or off and the QR configuration for a site
|
|
407
|
+
// Wildcard passes all five; an empty list passes none; either manage right
|
|
408
|
+
// implies view. The module deny list key is the resource name.
|
|
409
|
+
"hid-mgmt": [
|
|
410
|
+
"use-hid-access",
|
|
411
|
+
"see-all-hid",
|
|
412
|
+
"manage-hid-readers",
|
|
413
|
+
"manage-hid-users",
|
|
414
|
+
"manage-hid-settings",
|
|
393
415
|
],
|
|
394
416
|
|
|
395
417
|
// ---- security ----
|
|
@@ -659,12 +681,14 @@ export const LEGACY_PERMISSION_ALIASES: Readonly<
|
|
|
659
681
|
/**
|
|
660
682
|
* Strings the SERVER enforces that no UI checks and no role editor can grant.
|
|
661
683
|
*
|
|
662
|
-
* `core/src/utils/hid-access.util.ts
|
|
663
|
-
*
|
|
664
|
-
* whole estate spells visitor rights
|
|
665
|
-
* `:update-visitor` and so on; a bare `visitor`
|
|
666
|
-
* in any repo, so no role can hold these and
|
|
667
|
-
*
|
|
684
|
+
* `core/src/utils/hid-access.util.ts` keeps `visitor:create`, `visitor:update`
|
|
685
|
+
* and `visitor:check-out` in `HID_VISITOR_PERMISSIONS` (the visitor pass revoke
|
|
686
|
+
* routes) until the alias drop. The whole estate spells visitor rights
|
|
687
|
+
* `visitor-mgmt:add-visitor`, `:update-visitor` and so on; a bare `visitor`
|
|
688
|
+
* resource appears in no catalogue in any repo, so no role can hold these and
|
|
689
|
+
* the branch is reachable only through `*`, through
|
|
690
|
+
* `visitor-mgmt:update-visitor` (which the same list now also accepts) or
|
|
691
|
+
* through the HID manage users strings it unions in.
|
|
668
692
|
*
|
|
669
693
|
* They are NOT aliased to `visitor-mgmt:*` here, because doing so would be a
|
|
670
694
|
* decision with a real consequence in both directions:
|
|
@@ -695,19 +719,47 @@ export const SERVER_ONLY_UNGRANTABLE: readonly string[] = Object.freeze([
|
|
|
695
719
|
* Canonical strings that are CHECKED -- by this package and by the server -- and
|
|
696
720
|
* that no role editor can GRANT.
|
|
697
721
|
*
|
|
698
|
-
*
|
|
699
|
-
* the HID menu and
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
722
|
+
* Empty since 2026-10-16. It used to hold `access-card-mgmt:view`,
|
|
723
|
+
* `:assign-access-card` and `:manage-hid`, which the HID menu accepted and
|
|
724
|
+
* `core/src/utils/hid-access.util.ts` enforced while no app's catalogue offered
|
|
725
|
+
* them. HID now has its own `hid-mgmt` family, offered in full by the property
|
|
726
|
+
* and security catalogues and as `use-hid-access` by the five service
|
|
727
|
+
* catalogues (M&E joined on 2026-10-19); `assign-access-card` is offered by
|
|
728
|
+
* both card catalogues; `view` and `manage-hid` are retired (below). Kept,
|
|
729
|
+
* and still pinned by the drift test, so the next string of this shape is
|
|
730
|
+
* recorded here rather than found by somebody staring at a blank screen.
|
|
704
731
|
*/
|
|
705
732
|
export const CHECKED_BUT_UNGRANTABLE: readonly TPermissionString[] =
|
|
706
|
-
Object.freeze([
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
733
|
+
Object.freeze([]);
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Strings that are no longer canonical and have no canonical equivalent, but
|
|
737
|
+
* that this package and the server STILL READ for one release.
|
|
738
|
+
*
|
|
739
|
+
* `access-card-mgmt:view` and `access-card-mgmt:manage-hid` were the HID
|
|
740
|
+
* rights before `hid-mgmt` existed. Core `hid-access.util.ts` keeps them in
|
|
741
|
+
* `HID_LEGACY_VIEW_PERMISSIONS` and `HID_LEGACY_MANAGE_PERMISSIONS` until the
|
|
742
|
+
* live roles are backfilled onto the five `hid-mgmt` strings, and
|
|
743
|
+
* `useHidAccessPermission` reads them at the same levels during that period.
|
|
744
|
+
* No role editor offers them any more, and nothing new may be written against
|
|
745
|
+
* them.
|
|
746
|
+
*
|
|
747
|
+
* They are NOT legacy aliases: an alias joins two spellings of ONE grant into
|
|
748
|
+
* an equivalence class (`utils/permission-spellings.ts`) and joins the two
|
|
749
|
+
* resources into one module spelling group (`utils/org-modules.ts`). Access
|
|
750
|
+
* cards and HID are two modules, and `manage-hid` meant three HID levels at
|
|
751
|
+
* once, so neither of those is true here.
|
|
752
|
+
*
|
|
753
|
+
* `isKnownPermission` answers true for these; `canonicalPermission` does not
|
|
754
|
+
* resolve them. The alias drop deletes this list and the composable's legacy
|
|
755
|
+
* branches together.
|
|
756
|
+
*/
|
|
757
|
+
export const RETIRED_PERMISSIONS: Readonly<Record<string, string>> = Object.freeze({
|
|
758
|
+
"access-card-mgmt:view":
|
|
759
|
+
"HID view right before hid-mgmt:see-all-hid; read until the alias drop",
|
|
760
|
+
"access-card-mgmt:manage-hid":
|
|
761
|
+
"HID manage right before hid-mgmt:manage-hid-*; read until the alias drop",
|
|
762
|
+
});
|
|
711
763
|
|
|
712
764
|
const CANONICAL = new Set<string>(PERMISSION_STRINGS);
|
|
713
765
|
|
|
@@ -724,7 +776,7 @@ export function canonicalPermission(
|
|
|
724
776
|
return LEGACY_PERMISSION_ALIASES[value];
|
|
725
777
|
}
|
|
726
778
|
|
|
727
|
-
/** Is this string one the catalogue knows
|
|
779
|
+
/** Is this string one the catalogue knows: canonical, legacy, or retired but still read? */
|
|
728
780
|
export function isKnownPermission(value: string): boolean {
|
|
729
|
-
return canonicalPermission(value) !== undefined;
|
|
781
|
+
return canonicalPermission(value) !== undefined || value in RETIRED_PERMISSIONS;
|
|
730
782
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.150.0",
|
|
6
6
|
"author": "7365admin1",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
8
8
|
"//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-container fluid>
|
|
3
|
+
<!-- The member's own pass, so the gate asks for the use right, not the
|
|
4
|
+
admin view right every other HID page asks for. -->
|
|
3
5
|
<HidEnabledGate
|
|
4
6
|
:site="siteId"
|
|
5
7
|
:org="orgId"
|
|
8
|
+
level="use"
|
|
6
9
|
message="Enable HID as a service for this site before generating a QR code."
|
|
7
10
|
>
|
|
8
11
|
<HidProfileQrCode :site="siteId" />
|
|
@@ -14,6 +14,20 @@ declare type TOvernightParkingAvailability = {
|
|
|
14
14
|
sunday: TOvernightParkingDay;
|
|
15
15
|
isAllowPlateNumberOpenBarrier?: boolean;
|
|
16
16
|
autoApproveOvernightParking?: boolean;
|
|
17
|
+
visitorQrCodes?: TVisitorQrCode[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
declare type TVisitorQrCodeType = "hid" | "entryPass" | "security";
|
|
21
|
+
|
|
22
|
+
// How long an HID visitor pass lasts: until the end of the visit day, or
|
|
23
|
+
// until the visitor's first entry.
|
|
24
|
+
declare type TVisitorQrUsage = "wholeDay" | "singleUse";
|
|
25
|
+
|
|
26
|
+
declare type TVisitorQrCode = {
|
|
27
|
+
type: TVisitorQrCodeType;
|
|
28
|
+
isEnabled: boolean;
|
|
29
|
+
// HID only.
|
|
30
|
+
usage?: TVisitorQrUsage;
|
|
17
31
|
};
|
|
18
32
|
|
|
19
33
|
declare type TOvernightParkingRequestStatus =
|
package/types/site.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ declare type THidQrCodeFormat = "0" | "1" | "2";
|
|
|
5
5
|
declare type THidPermissionCategory =
|
|
6
6
|
| "resident"
|
|
7
7
|
| "property_management"
|
|
8
|
-
|
|
8
|
+
/** A provider COMPANY - granting one admits every active member of that org. */
|
|
9
|
+
| "service_provider"
|
|
10
|
+
/** ONE PERSON from a provider company, by their membership at this site. */
|
|
11
|
+
| "service_provider_member";
|
|
9
12
|
|
|
10
13
|
declare type THidPermissionAssignment = {
|
|
11
14
|
subjectId: string;
|
|
@@ -27,7 +30,10 @@ declare type THidSitePermissions = {
|
|
|
27
30
|
counts: {
|
|
28
31
|
resident: number;
|
|
29
32
|
propertyManagement: number;
|
|
33
|
+
/** Provider COMPANIES granted. */
|
|
30
34
|
serviceProvider: number;
|
|
35
|
+
/** Named provider people granted. Counted apart from the companies. */
|
|
36
|
+
serviceProviderMember: number;
|
|
31
37
|
intercom: number;
|
|
32
38
|
};
|
|
33
39
|
};
|