@7365admin1/layer-common 3.2.1-staging.72 → 3.2.2
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 +39 -0
- package/components/EntryPassInformation.vue +4 -4
- package/components/FeedbackMain.vue +7 -7
- package/components/HidAccessLogDashboard.vue +44 -119
- package/components/HidIdentityMapping.vue +975 -0
- package/components/HidIntercomManagement.vue +201 -808
- package/components/HidQrCodeConfiguration.vue +95 -907
- package/components/HidServiceSettingsPanel.vue +1 -20
- package/components/HidUserEnrollment.vue +81 -392
- package/components/Layout/NavigationDrawer.vue +2 -43
- package/components/NavigationItem.vue +0 -9
- package/components/Nfc/NFCPatrolRouteMain.vue +7 -52
- package/components/OnlineFormConfigurationForm.vue +224 -620
- package/components/OnlineFormFill.vue +8 -36
- package/components/OnlineFormsConfiguration.vue +2 -6
- package/components/QrTemplate/CreditCardLandscape.vue +12 -19
- package/components/QrTemplate/PrintDialog.vue +196 -209
- package/components/SiteSettings.vue +2 -4
- package/components/VisitorForm.vue +78 -201
- package/components/VisitorManagement.vue +2 -1
- package/composables/useComment.ts +3 -3
- package/composables/useHidAmico.ts +0 -127
- package/composables/useHidNavigation.ts +7 -0
- package/composables/useOnlineFormPages.ts +0 -2
- package/composables/useSiteSettings.ts +0 -50
- package/composables/useWebUsb.ts +37 -127
- package/middleware/member.ts +4 -0
- package/package.json +1 -2
- package/pages/[org]/[site]/access-mgmt/identity-mapping/index.vue +23 -0
- package/pages/[org]/[site]/access-mgmt/intercom/index.vue +1 -1
- package/plugins/secure-member.client.ts +56 -21
- package/plugins/vuetify.ts +9 -37
- package/types/site.d.ts +0 -71
- package/.changeset/camera-wall-gated-endpoint.md +0 -47
- package/.changeset/camera-wall-plain-english.md +0 -60
- package/.changeset/camera-wall-selection-and-guidance.md +0 -65
- package/.changeset/dark-primary-contrast.md +0 -39
- package/components/CameraWall.vue +0 -1034
- package/components/CameraWallTile.vue +0 -818
- package/components/HidCameraCaptureDialog.vue +0 -199
- package/composables/useSipWebPhone.ts +0 -311
- package/utils/camera-wall.test.ts +0 -571
- package/utils/camera-wall.ts +0 -926
- package/utils/theme.test.ts +0 -201
- package/utils/theme.ts +0 -136
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 3.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d81dc2e: Camera-fault alerts get their own snackbar instead of riding the visitor one
|
|
8
|
+
|
|
9
|
+
Camera health was being sent through `showTransientMessage`, the same path as
|
|
10
|
+
unregistered-visitor plate alerts. That path returns early when the site has
|
|
11
|
+
the unregistered-visitor snackbar switched off, so **two of the five ANPR sites
|
|
12
|
+
were being told nothing at all when a camera went down** — the setting that
|
|
13
|
+
silenced them has nothing to do with cameras. The old snackbar was also hidden
|
|
14
|
+
whenever the operator was on the Unregistered tab.
|
|
15
|
+
|
|
16
|
+
Camera health is now its own alert, gated only on the permission to view
|
|
17
|
+
visitor data. It cannot be silenced by the unregistered-visitor switch and is
|
|
18
|
+
not hidden on that tab.
|
|
19
|
+
|
|
20
|
+
Several cameras failing at once collapse into a single line — "N cameras at
|
|
21
|
+
this site are not responding … Open Site Settings > Cameras to see which" —
|
|
22
|
+
rather than one snackbar per camera. Faults are keyed by camera id, so a repeat
|
|
23
|
+
for the same camera replaces its line instead of stacking another.
|
|
24
|
+
|
|
25
|
+
When a camera comes back, the operator who was told it was down is told it
|
|
26
|
+
recovered; the alert clears on its own.
|
|
27
|
+
|
|
28
|
+
Reads the optional `event` (`camera-fault` / `camera-recovered`) and `camera`
|
|
29
|
+
fields added to the socket payload in `@7365admin1/core`. Both are optional —
|
|
30
|
+
against an older API-core that sends a bare `message`, this behaves as it does
|
|
31
|
+
today and treats it as a fault.
|
|
32
|
+
|
|
33
|
+
**Expect an alert burst on first release** from the sites that were silent.
|
|
34
|
+
Warn the client before shipping.
|
|
35
|
+
|
|
36
|
+
## 3.2.1
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- 413272f: 08122026 new release
|
|
41
|
+
|
|
3
42
|
## 3.2.0
|
|
4
43
|
|
|
5
44
|
### Minor Changes
|
|
@@ -168,13 +168,13 @@
|
|
|
168
168
|
<template v-if="passType === 'HID_QR'">
|
|
169
169
|
<v-alert
|
|
170
170
|
v-if="!hidQrPrinterConfigured"
|
|
171
|
-
type="
|
|
171
|
+
type="warning"
|
|
172
172
|
variant="tonal"
|
|
173
173
|
density="compact"
|
|
174
174
|
class="mt-3"
|
|
175
|
-
icon="mdi-
|
|
175
|
+
icon="mdi-printer-alert"
|
|
176
176
|
>
|
|
177
|
-
|
|
177
|
+
No printer is configured on HID settings. QR Pass may not print.
|
|
178
178
|
</v-alert>
|
|
179
179
|
<v-alert
|
|
180
180
|
v-else
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
class="mt-3"
|
|
185
185
|
icon="mdi-qrcode-scan"
|
|
186
186
|
>
|
|
187
|
-
HID QR Code will be generated and
|
|
187
|
+
HID QR Code will be generated and printed when you continue.
|
|
188
188
|
</v-alert>
|
|
189
189
|
</template>
|
|
190
190
|
</template>
|
|
@@ -721,9 +721,9 @@ const {
|
|
|
721
721
|
_getFeedbacks({
|
|
722
722
|
page: page.value,
|
|
723
723
|
site: route.params.site as string,
|
|
724
|
-
provider: currentUser.value
|
|
725
|
-
...(currentUser.value
|
|
726
|
-
userId: currentUser.value
|
|
724
|
+
provider: currentUser.value.serviceProvider,
|
|
725
|
+
...(currentUser.value.type != "site" && {
|
|
726
|
+
userId: currentUser.value._id,
|
|
727
727
|
}),
|
|
728
728
|
service: "Security",
|
|
729
729
|
dateFrom: moment(startDate.value, "DD/MM/YYYY").startOf("day"),
|
|
@@ -998,9 +998,9 @@ async function handleAccept() {
|
|
|
998
998
|
_id: feedbackData.value._id,
|
|
999
999
|
statusUpdate: {
|
|
1000
1000
|
status: "In-Progress",
|
|
1001
|
-
updatedById: currentUser.value
|
|
1002
|
-
updatedByName: `${currentUser.value
|
|
1003
|
-
assignee: currentUser.value
|
|
1001
|
+
updatedById: currentUser.value._id,
|
|
1002
|
+
updatedByName: `${currentUser.value.givenName} ${currentUser.value.surname}`,
|
|
1003
|
+
assignee: currentUser.value._id,
|
|
1004
1004
|
provider: currentUser.value?.serviceProvider,
|
|
1005
1005
|
},
|
|
1006
1006
|
};
|
|
@@ -1158,7 +1158,7 @@ async function submit() {
|
|
|
1158
1158
|
isSubmitting.value = true;
|
|
1159
1159
|
|
|
1160
1160
|
const result = await createFeedback({
|
|
1161
|
-
createdBy: currentUser.value
|
|
1161
|
+
createdBy: currentUser.value._id,
|
|
1162
1162
|
description: _feedback.value.description,
|
|
1163
1163
|
attachments: _feedback.value.attachments,
|
|
1164
1164
|
site: route.params.site as string,
|
|
@@ -327,8 +327,6 @@ type AccessTab = "resident" | "visitor" | "administrator";
|
|
|
327
327
|
type AccessRow = {
|
|
328
328
|
key: string;
|
|
329
329
|
identityKey: string;
|
|
330
|
-
identityType?: string;
|
|
331
|
-
visitorId?: string;
|
|
332
330
|
name: string;
|
|
333
331
|
facialData: string;
|
|
334
332
|
faceImage?: string;
|
|
@@ -353,7 +351,6 @@ const { getVisitors } = useVisitor();
|
|
|
353
351
|
|
|
354
352
|
const readers = ref<Record<string, any>[]>([]);
|
|
355
353
|
const identities = ref<Record<string, any>[]>([]);
|
|
356
|
-
const allIdentities = ref<Record<string, any>[]>([]);
|
|
357
354
|
const visitorRecords = ref<Record<string, any>>({});
|
|
358
355
|
const logs = ref<Record<string, any>[]>([]);
|
|
359
356
|
const liveAccessLogs = ref<Record<string, any>[]>([]);
|
|
@@ -421,17 +418,8 @@ const selectedHistoryRows = computed<AccessRow[]>(() => {
|
|
|
421
418
|
if (!selectedHistoryRow.value) return [];
|
|
422
419
|
|
|
423
420
|
const selectedKey = selectedHistoryRow.value.identityKey;
|
|
424
|
-
const
|
|
425
|
-
const
|
|
426
|
-
selectedIdentity
|
|
427
|
-
? accessLogMatchesIdentity(log, selectedIdentity)
|
|
428
|
-
: getLogIdentityKey(log) === selectedKey,
|
|
429
|
-
);
|
|
430
|
-
const matchedLiveLogs = liveAccessLogs.value.filter((log) =>
|
|
431
|
-
selectedIdentity
|
|
432
|
-
? accessLogMatchesIdentity(log, selectedIdentity)
|
|
433
|
-
: getAccessLogIdentityKey(log) === selectedKey,
|
|
434
|
-
);
|
|
421
|
+
const matchedLogs = logs.value.filter((log) => getLogIdentityKey(log) === selectedKey);
|
|
422
|
+
const matchedLiveLogs = liveAccessLogs.value.filter((log) => getAccessLogIdentityKey(log) === selectedKey);
|
|
435
423
|
|
|
436
424
|
if (!matchedLogs.length && !matchedLiveLogs.length) {
|
|
437
425
|
return rows.value.filter((row) => row.identityKey === selectedKey);
|
|
@@ -561,41 +549,28 @@ async function loadDashboard() {
|
|
|
561
549
|
const isAdministratorTab = activeTab.value === "administrator";
|
|
562
550
|
const isVisitorTab = activeTab.value === "visitor";
|
|
563
551
|
const [identityResponse, logResponse, hidAccessLogs, configurationResponse, roleResponse, visitorResponse, readerUserResponse] = await Promise.all([
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}),
|
|
577
|
-
null,
|
|
578
|
-
"persisted access logs",
|
|
579
|
-
),
|
|
580
|
-
loadDashboardSource(loadLiveAccessLogs(selectedReaderId.value), [], "live access logs"),
|
|
581
|
-
loadDashboardSource(loadReaderConfiguration(selectedReaderId.value), {}, "reader configuration"),
|
|
582
|
-
isAdministratorTab
|
|
583
|
-
? loadDashboardSource(loadAdministratorRoles(selectedReaderId.value), null, "administrator roles")
|
|
584
|
-
: Promise.resolve(null),
|
|
552
|
+
getIdentities(selectedReaderId.value, {
|
|
553
|
+
page: 1,
|
|
554
|
+
limit: 500,
|
|
555
|
+
...(!isAdministratorTab ? { type: getIdentityType(activeTab.value) } : {}),
|
|
556
|
+
}),
|
|
557
|
+
getLogs(selectedReaderId.value, {
|
|
558
|
+
page: 1,
|
|
559
|
+
limit: 500,
|
|
560
|
+
}),
|
|
561
|
+
loadLiveAccessLogs(selectedReaderId.value),
|
|
562
|
+
loadReaderConfiguration(selectedReaderId.value),
|
|
563
|
+
isAdministratorTab ? loadAdministratorRoles(selectedReaderId.value) : Promise.resolve(null),
|
|
585
564
|
isVisitorTab && props.org
|
|
586
|
-
?
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
}),
|
|
594
|
-
null,
|
|
595
|
-
"visitor records",
|
|
596
|
-
)
|
|
565
|
+
? getVisitors({
|
|
566
|
+
org: props.org,
|
|
567
|
+
site: props.site,
|
|
568
|
+
page: 1,
|
|
569
|
+
limit: 500,
|
|
570
|
+
order: "desc",
|
|
571
|
+
})
|
|
597
572
|
: Promise.resolve(null),
|
|
598
|
-
|
|
573
|
+
loadReaderUsers(selectedReaderId.value),
|
|
599
574
|
]);
|
|
600
575
|
|
|
601
576
|
if (sequence !== loadSequence.value) return;
|
|
@@ -603,19 +578,18 @@ async function loadDashboard() {
|
|
|
603
578
|
const loadedIdentities = identityResponse?.items ?? identityResponse?.data?.items ?? identityResponse?.data?.identities ?? [];
|
|
604
579
|
const mergedIdentities = mergeReaderUsersWithIdentities(readerUserResponse, loadedIdentities);
|
|
605
580
|
const loadedVisitors = visitorResponse?.items ?? visitorResponse?.data?.items ?? visitorResponse?.data?.visitors ?? [];
|
|
606
|
-
visitorRecords.value =
|
|
607
|
-
loadedVisitors.map((visitor: Record<string, any>) => [String(visitor._id), visitor])
|
|
608
|
-
|
|
581
|
+
visitorRecords.value = isVisitorTab
|
|
582
|
+
? Object.fromEntries(loadedVisitors.map((visitor: Record<string, any>) => [String(visitor._id), visitor]))
|
|
583
|
+
: {};
|
|
609
584
|
administratorUserIds.value = getAdministratorRoleUserIds(roleResponse);
|
|
610
|
-
allIdentities.value = mergedIdentities;
|
|
611
585
|
identities.value = isAdministratorTab
|
|
612
586
|
? mergedIdentities.filter((identity: Record<string, any>) => {
|
|
613
587
|
const hidUserId = toHidNumericId(identity.hidUserId);
|
|
614
588
|
return Boolean(hidUserId && administratorUserIds.value.has(hidUserId));
|
|
615
589
|
})
|
|
616
|
-
:
|
|
617
|
-
? mergedIdentities.filter(
|
|
618
|
-
|
|
590
|
+
: isVisitorTab
|
|
591
|
+
? mergedIdentities.filter((identity: Record<string, any>) => Boolean(getVisitorRecord(identity)))
|
|
592
|
+
: mergedIdentities;
|
|
619
593
|
logs.value = logResponse?.items ?? logResponse?.data?.items ?? logResponse?.data?.logs ?? [];
|
|
620
594
|
liveAccessLogs.value = hidAccessLogs;
|
|
621
595
|
readerConfiguration.value = normalizeReaderConfiguration(configurationResponse);
|
|
@@ -627,15 +601,6 @@ async function loadDashboard() {
|
|
|
627
601
|
}
|
|
628
602
|
}
|
|
629
603
|
|
|
630
|
-
async function loadDashboardSource<T>(request: Promise<T>, fallback: T, label: string): Promise<T> {
|
|
631
|
-
try {
|
|
632
|
-
return await request;
|
|
633
|
-
} catch (error) {
|
|
634
|
-
console.warn(`Unable to load HID ${label}`, error);
|
|
635
|
-
return fallback;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
604
|
async function loadUserImages(items: Record<string, any>[]) {
|
|
640
605
|
if (!selectedReaderId.value) return;
|
|
641
606
|
|
|
@@ -801,7 +766,6 @@ function mergeReaderUsersWithIdentities(readerUsers: Record<string, any>[], iden
|
|
|
801
766
|
function resetDashboardData() {
|
|
802
767
|
selectedHistoryRow.value = undefined;
|
|
803
768
|
identities.value = [];
|
|
804
|
-
allIdentities.value = [];
|
|
805
769
|
visitorRecords.value = {};
|
|
806
770
|
logs.value = [];
|
|
807
771
|
liveAccessLogs.value = [];
|
|
@@ -809,11 +773,15 @@ function resetDashboardData() {
|
|
|
809
773
|
administratorUserIds.value = new Set();
|
|
810
774
|
}
|
|
811
775
|
|
|
776
|
+
function getIdentityType(tab: AccessTab) {
|
|
777
|
+
if (tab === "administrator") return "admin";
|
|
778
|
+
return tab;
|
|
779
|
+
}
|
|
780
|
+
|
|
812
781
|
function isVisibleForActiveTab(row: AccessRow) {
|
|
813
782
|
const identity = findIdentityByKey(row.identityKey);
|
|
814
|
-
const isVisitor = row.identityType === "visitor" || Boolean(row.visitorId) || isVisitorIdentity(identity);
|
|
815
783
|
if (activeTab.value === "visitor") {
|
|
816
|
-
return
|
|
784
|
+
return Boolean(identity && getVisitorRecord(identity));
|
|
817
785
|
}
|
|
818
786
|
|
|
819
787
|
if (activeTab.value === "administrator") {
|
|
@@ -821,11 +789,7 @@ function isVisibleForActiveTab(row: AccessRow) {
|
|
|
821
789
|
return Boolean(hidUserId && administratorUserIds.value.has(hidUserId));
|
|
822
790
|
}
|
|
823
791
|
|
|
824
|
-
return !
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
function isVisitorIdentity(identity: Record<string, unknown> | undefined) {
|
|
828
|
-
return Boolean(identity && (identity.type === "visitor" || identity.visitor));
|
|
792
|
+
return !identity || !getVisitorRecord(identity);
|
|
829
793
|
}
|
|
830
794
|
|
|
831
795
|
function loadAdministratorRoles(readerId: string) {
|
|
@@ -871,13 +835,13 @@ function getIdentityKey(identity: Record<string, any>) {
|
|
|
871
835
|
return [
|
|
872
836
|
identity.hidUserId,
|
|
873
837
|
identity.registration,
|
|
874
|
-
identity.cardNo
|
|
838
|
+
identity.cardNo,
|
|
875
839
|
].filter(Boolean).join("|");
|
|
876
840
|
}
|
|
877
841
|
|
|
878
842
|
function findIdentityByKey(identityKey: string) {
|
|
879
843
|
if (!identityKey) return undefined;
|
|
880
|
-
return
|
|
844
|
+
return identities.value.find((identity) => getIdentityKey(identity) === identityKey);
|
|
881
845
|
}
|
|
882
846
|
|
|
883
847
|
function getLogIdentityKey(log: Record<string, any>) {
|
|
@@ -887,7 +851,7 @@ function getLogIdentityKey(log: Record<string, any>) {
|
|
|
887
851
|
return [
|
|
888
852
|
identity.hidUserId || lookup.hidUserId || rawLog.user_id || rawLog.userId || rawLog.hidUserId,
|
|
889
853
|
identity.registration || lookup.registration,
|
|
890
|
-
identity.cardNo || lookup.cardNo || rawLog.card_value || rawLog.cardNo
|
|
854
|
+
identity.cardNo || lookup.cardNo || rawLog.card_value || rawLog.cardNo,
|
|
891
855
|
].filter(Boolean).join("|");
|
|
892
856
|
}
|
|
893
857
|
|
|
@@ -1181,15 +1145,12 @@ function getRawAccessLogs(event: Record<string, any>) {
|
|
|
1181
1145
|
|
|
1182
1146
|
function mapAccessLogToRow(rawLog: Record<string, any>, event: Record<string, any>, index: string): AccessRow {
|
|
1183
1147
|
const identity = findIdentityForAccessLog(rawLog, event);
|
|
1184
|
-
const eventIdentity = event.payload?.identity || event.payload?.identityLookup || {};
|
|
1185
1148
|
const rawAccessTime = getAccessLogTime(rawLog, event);
|
|
1186
1149
|
const identityKey = identity ? getIdentityKey(identity) : getLogIdentityKey({ ...event, payload: { ...event.payload, rawAccessLog: rawLog } });
|
|
1187
1150
|
|
|
1188
1151
|
return {
|
|
1189
1152
|
key: `${event._id || event.id || "log"}-${rawLog.id || rawLog.time || index}`,
|
|
1190
1153
|
identityKey,
|
|
1191
|
-
identityType: String(identity?.type || eventIdentity.type || "").toLowerCase() || undefined,
|
|
1192
|
-
visitorId: String(identity?.visitor || eventIdentity.visitor || "") || undefined,
|
|
1193
1154
|
name: identity ? getName(identity) : getRawLogName(rawLog, event),
|
|
1194
1155
|
facialData: identity ? getFacialData(identity) : "N/A",
|
|
1195
1156
|
faceImage: identity ? getUserImageSrc(identity) : "",
|
|
@@ -1205,33 +1166,32 @@ function mapAccessLogToRow(rawLog: Record<string, any>, event: Record<string, an
|
|
|
1205
1166
|
function findIdentityForAccessLog(rawLog: Record<string, any>, event: Record<string, any>) {
|
|
1206
1167
|
const eventIdentityId = event.payload?.identity?._id;
|
|
1207
1168
|
if (eventIdentityId) {
|
|
1208
|
-
const byId =
|
|
1169
|
+
const byId = identities.value.find((identity) => String(identity._id) === String(eventIdentityId));
|
|
1209
1170
|
if (byId) return byId;
|
|
1210
1171
|
}
|
|
1211
1172
|
|
|
1212
1173
|
const hidUserId = rawLog.user_id ?? rawLog.userId ?? rawLog.hidUserId ?? event.payload?.identity?.hidUserId ?? event.payload?.identityLookup?.hidUserId;
|
|
1213
1174
|
const registration = rawLog.registration ?? event.payload?.identity?.registration ?? event.payload?.identityLookup?.registration;
|
|
1214
1175
|
const cardNo = rawLog.card_value || rawLog.cardNo || event.payload?.identity?.cardNo || event.payload?.identityLookup?.cardNo;
|
|
1215
|
-
const qrCodeValue = rawLog.qrcode_value || rawLog.qrCode || rawLog.qrcode;
|
|
1216
1176
|
|
|
1217
|
-
return
|
|
1177
|
+
return identities.value.find((identity) => {
|
|
1218
1178
|
return (
|
|
1219
1179
|
(hidUserId !== undefined && hidUserId !== null && String(identity.hidUserId) === String(hidUserId)) ||
|
|
1220
1180
|
(registration && identity.registration === registration) ||
|
|
1221
|
-
(cardNo && String(identity.cardNo) === String(cardNo))
|
|
1222
|
-
(qrCodeValue && String(identity.metadata?.qrCodeValue || "") === String(qrCodeValue))
|
|
1181
|
+
(cardNo && String(identity.cardNo) === String(cardNo))
|
|
1223
1182
|
);
|
|
1224
1183
|
});
|
|
1225
1184
|
}
|
|
1226
1185
|
|
|
1227
1186
|
function getLatestAccessLogForIdentity(identity: Record<string, any>) {
|
|
1187
|
+
const identityKey = getIdentityKey(identity);
|
|
1228
1188
|
const accessLogs = [
|
|
1229
1189
|
...liveAccessLogs.value,
|
|
1230
1190
|
...logs.value.flatMap((event) => getRawAccessLogs(event)),
|
|
1231
1191
|
];
|
|
1232
1192
|
|
|
1233
1193
|
return accessLogs
|
|
1234
|
-
.filter((log) =>
|
|
1194
|
+
.filter((log) => getAccessLogIdentityKey(log) === identityKey)
|
|
1235
1195
|
.sort((a, b) => {
|
|
1236
1196
|
const aTime = parseDate(getAccessLogTime(a, {}))?.getTime() || 0;
|
|
1237
1197
|
const bTime = parseDate(getAccessLogTime(b, {}))?.getTime() || 0;
|
|
@@ -1239,46 +1199,11 @@ function getLatestAccessLogForIdentity(identity: Record<string, any>) {
|
|
|
1239
1199
|
})[0];
|
|
1240
1200
|
}
|
|
1241
1201
|
|
|
1242
|
-
function toUnknownRecord(value: unknown): Record<string, unknown> {
|
|
1243
|
-
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
1244
|
-
? value as Record<string, unknown>
|
|
1245
|
-
: {};
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
function accessLogMatchesIdentity(log: unknown, identity: unknown) {
|
|
1249
|
-
const logRecord = toUnknownRecord(log);
|
|
1250
|
-
const identityRecord = toUnknownRecord(identity);
|
|
1251
|
-
const payload = toUnknownRecord(logRecord.payload);
|
|
1252
|
-
const rawLog = Object.keys(toUnknownRecord(payload.rawAccessLog)).length
|
|
1253
|
-
? toUnknownRecord(payload.rawAccessLog)
|
|
1254
|
-
: logRecord;
|
|
1255
|
-
const eventIdentity = Object.keys(toUnknownRecord(payload.identity)).length
|
|
1256
|
-
? toUnknownRecord(payload.identity)
|
|
1257
|
-
: toUnknownRecord(payload.identityLookup);
|
|
1258
|
-
const metadata = toUnknownRecord(identityRecord.metadata);
|
|
1259
|
-
const hidUserId = rawLog.user_id ?? rawLog.userId ?? rawLog.hidUserId ?? eventIdentity.hidUserId;
|
|
1260
|
-
const registration = rawLog.registration || eventIdentity.registration;
|
|
1261
|
-
const credential =
|
|
1262
|
-
rawLog.card_value ||
|
|
1263
|
-
rawLog.cardNo ||
|
|
1264
|
-
rawLog.qrcode_value ||
|
|
1265
|
-
rawLog.qrCode ||
|
|
1266
|
-
rawLog.qrcode ||
|
|
1267
|
-
eventIdentity.cardNo;
|
|
1268
|
-
const identityCredential = identityRecord.cardNo || metadata.qrCodeValue;
|
|
1269
|
-
|
|
1270
|
-
return Boolean(
|
|
1271
|
-
(hidUserId !== undefined && hidUserId !== null && String(identityRecord.hidUserId) === String(hidUserId)) ||
|
|
1272
|
-
(registration && identityRecord.registration === registration) ||
|
|
1273
|
-
(credential && identityCredential && String(identityCredential) === String(credential)),
|
|
1274
|
-
);
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
1202
|
function getAccessLogIdentityKey(rawLog: Record<string, any>) {
|
|
1278
1203
|
return [
|
|
1279
1204
|
rawLog.user_id ?? rawLog.userId ?? rawLog.hidUserId,
|
|
1280
1205
|
rawLog.registration,
|
|
1281
|
-
rawLog.card_value || rawLog.cardNo
|
|
1206
|
+
rawLog.card_value || rawLog.cardNo,
|
|
1282
1207
|
].filter(Boolean).join("|");
|
|
1283
1208
|
}
|
|
1284
1209
|
|