@7365admin1/layer-common 4.0.3-staging.232 → 4.0.3-staging.233

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.
@@ -311,9 +311,7 @@ type HidSyncUser = HidRecord & {
311
311
  };
312
312
 
313
313
  type HidSyncPayload = {
314
- objects: Array<{ object: "users"; values: HidSyncUser[] }>;
315
314
  users: HidSyncUser[];
316
- unmappedCount: number;
317
315
  stats: { newEnrolled: number; updatedInformation: number; facialData: number };
318
316
  defaultMessage: string;
319
317
  };
@@ -331,12 +329,10 @@ const {
331
329
  updateReader,
332
330
  deleteReader,
333
331
  testReader,
334
- syncReaderFacialData,
335
332
  configureReaderIntegration,
336
333
  setReaderMonitor,
337
334
  setReaderOperatingMode,
338
- getIdentities,
339
- runObjectOperation,
335
+ getReaderUsers,
340
336
  } = useHidAmico();
341
337
 
342
338
  const readers = ref<HidRecord[]>([]);
@@ -594,48 +590,11 @@ async function runConfirmedAction() {
594
590
 
595
591
  actionStage.value = "loading";
596
592
  const payload = syncPreviewPayload.value;
597
- const unmappedCount = Number(payload.unmappedCount || 0);
598
-
599
- if (!payload.objects.length) {
600
- const facialSync = await syncReaderFacialData(selectedReader.value._id);
601
- const facialStats = toFacialSyncStats(facialSync);
602
- if (unmappedCount) {
603
- const message = [
604
- syncMessage.value || `Found ${unmappedCount} HID user(s) that must be linked from the HID User Mapping screen.`,
605
- facialStats.message,
606
- ].filter(Boolean).join(" ");
607
- await applyReaderSyncState(selectedReader.value._id, "completed", message);
608
- showResult(true, "Sync Review Required", message, {
609
- readerName: selectedReader.value.name || "HID Reader",
610
- stats: { ...syncPreviewStats.value, facialData: facialStats.syncedCount },
611
- });
612
- confirmDialog.value = false;
613
- resetActionFlow();
614
- await loadReaders();
615
- return;
616
- }
617
-
618
- const message = syncMessage.value || "No active HID users found to sync.";
619
- await applyReaderSyncState(selectedReader.value._id, "failed", message);
620
- showResult(false, "Sync Device Failed", message);
621
- confirmDialog.value = false;
622
- resetActionFlow();
623
- await loadReaders();
624
- return;
625
- }
626
- const result = await syncHidUsers(selectedReader.value._id, payload.users);
627
- const facialSync = await syncReaderFacialData(selectedReader.value._id);
628
- const facialStats = toFacialSyncStats(facialSync);
629
- const mappingMessage = unmappedCount
630
- ? `${unmappedCount} HID user(s) still need to be linked from the HID User Mapping screen.`
631
- : "";
632
- const message = [syncMessage.value, result.message, facialStats.message, mappingMessage]
633
- .filter(Boolean)
634
- .join(" ");
593
+ const message = syncMessage.value || `Read ${payload.users.length} HID user(s) directly from Amico.`;
635
594
  await applyReaderSyncState(selectedReader.value._id, "completed", message);
636
595
  showResult(true, "Sync Successful", message, {
637
596
  readerName: selectedReader.value.name || "HID Reader",
638
- stats: { ...syncPreviewStats.value, facialData: facialStats.syncedCount },
597
+ stats: syncPreviewStats.value,
639
598
  });
640
599
  }
641
600
  if (pendingAction.value === "delete") {
@@ -698,163 +657,31 @@ async function applyReaderSyncState(readerId: string, status: "completed" | "fai
698
657
  }
699
658
 
700
659
  async function buildSyncPayload(readerId: string) {
701
- const response = await getIdentities(readerId, {
660
+ const readerResponse = await getReaderUsers(readerId, {
702
661
  page: 1,
703
- limit: 500,
704
- status: "active",
662
+ limit: 100,
663
+ includeVisitors: true,
705
664
  });
706
- let identities = response?.items ?? response?.data?.items ?? response?.data?.identities ?? [];
707
-
708
- if (!identities.length) {
709
- const hidResponse = await runObjectOperation(readerId, {
710
- operation: "load",
711
- object: "users",
712
- limit: 500,
713
- offset: 0,
714
- });
715
- const hidUsers = normalizeHidUsers(hidResponse);
716
- return {
717
- objects: [],
718
- users: [],
719
- unmappedCount: hidUsers.length,
720
- stats: {
721
- newEnrolled: 0,
722
- updatedInformation: 0,
723
- facialData: countFacialData(hidUsers),
724
- },
725
- defaultMessage: hidUsers.length
726
- ? `Found ${hidUsers.length} HID user(s) that must be linked from the HID User Mapping screen.`
727
- : "",
728
- };
729
- }
730
-
731
- const allLinkedIds = new Set(
732
- identities
733
- .map((identity) => Number(identity.hidUserId))
734
- .filter((id: number) => Number.isInteger(id) && id > 0),
735
- );
736
- const users = identities
737
- .filter((identity) => (
738
- identity.type !== "visitor"
739
- && (identity.metadata as Record<string, unknown> | undefined)?.temporary !== true
740
- ))
741
- .map(toHidUserObject)
665
+ const readerData = readerResponse?.data ?? readerResponse;
666
+ const directUsers = Array.isArray(readerResponse?.items)
667
+ ? readerResponse.items
668
+ : Array.isArray(readerData?.items) ? readerData.items : [];
669
+ const users = directUsers
670
+ .map((user) => toHidUserObject(user as HidRecord))
742
671
  .filter((user): user is HidSyncUser => user !== null);
743
- const existingHidUsers = await getExistingHidUsers(readerId);
744
- const existingIds = new Set(existingHidUsers.map((user) => Number(user.hidUserId)));
745
- const hidUsersToImport = existingHidUsers.filter((user) => {
746
- const hidUserId = Number(user.hidUserId);
747
- return Number.isInteger(hidUserId) && hidUserId > 0 && !allLinkedIds.has(hidUserId);
748
- });
749
- const newEnrolled = users.filter((user) => !existingIds.has(Number(user.id))).length;
750
- const updatedInformation = users.filter((user) => existingIds.has(Number(user.id))).length;
751
- const totalUsersToSync = users.length;
752
672
 
753
673
  return {
754
- objects: users.length
755
- ? [
756
- {
757
- object: "users",
758
- values: users,
759
- },
760
- ]
761
- : [],
762
674
  users,
763
- unmappedCount: hidUsersToImport.length,
764
675
  stats: {
765
- newEnrolled,
766
- updatedInformation,
767
- facialData: countFacialData([...users, ...hidUsersToImport]),
676
+ newEnrolled: users.length,
677
+ updatedInformation: 0,
678
+ facialData: countFacialData(directUsers as HidRecord[]),
768
679
  },
769
- defaultMessage: [
770
- totalUsersToSync ? `Ready to sync ${totalUsersToSync} linked HID user(s).` : "",
771
- hidUsersToImport.length
772
- ? `${hidUsersToImport.length} HID user(s) must be linked from the HID User Mapping screen.`
773
- : "",
774
- ].filter(Boolean).join(" "),
775
- };
776
- }
777
-
778
- async function syncHidUsers(readerId: string, users: HidSyncUser[]) {
779
- const existingIds = await getExistingHidUserIds(readerId);
780
- const usersToCreate = users.filter((user) => !existingIds.has(Number(user.id)));
781
- const usersToModify = users.filter((user) => existingIds.has(Number(user.id)));
782
- const results: HidRecord[] = [];
783
-
784
- if (usersToModify.length) {
785
- const modifyResults = [];
786
- for (const user of usersToModify) {
787
- const result = await runObjectOperation(readerId, {
788
- operation: "modify",
789
- object: "users",
790
- where: {
791
- users: {
792
- id: user.id,
793
- },
794
- },
795
- values: toHidUserValues(user),
796
- });
797
- modifyResults.push(result);
798
- }
799
- results.push({ operation: "modify", count: usersToModify.length, result: modifyResults });
800
- }
801
-
802
- if (usersToCreate.length) {
803
- const result = await runObjectOperation(readerId, {
804
- operation: "create",
805
- object: "users",
806
- values: usersToCreate.map(toHidUserCreateValues),
807
- });
808
- results.push({ operation: "create", count: usersToCreate.length, result });
809
- }
810
-
811
- for (const user of users) {
812
- await syncHidUserRole(readerId, user.id, user._identityType === "admin");
813
- }
814
-
815
- return {
816
- results,
817
- message: `Synced ${users.length} HID user(s). ${usersToModify.length} updated, ${usersToCreate.length} created.`,
680
+ defaultMessage: users.length
681
+ ? `Read ${users.length} HID user(s) directly from Amico.`
682
+ : "No HID users found on this reader.",
818
683
  };
819
- }
820
-
821
- async function getExistingHidUserIds(readerId: string) {
822
- const users = await getExistingHidUsers(readerId);
823
- return new Set(users.map((user) => Number(user.hidUserId)));
824
- }
825
684
 
826
- async function getExistingHidUsers(readerId: string) {
827
- const hidResponse = await runObjectOperation(readerId, {
828
- operation: "load",
829
- object: "users",
830
- limit: 500,
831
- offset: 0,
832
- });
833
- return normalizeHidUsers(hidResponse);
834
- }
835
-
836
- function normalizeHidUsers(response: HidRecord) {
837
- const users =
838
- response?.data?.users ||
839
- response?.data?.data?.users ||
840
- response?.users ||
841
- [];
842
-
843
- return Array.isArray(users)
844
- ? users
845
- // Visitor QR passes are linked by their visitor transaction and must not
846
- // be offered for manual HID user mapping or counted as unmapped users.
847
- .filter((user) => Number(user?.user_type_id) !== 1)
848
- .map((user) => ({
849
- hidUserId: user.id,
850
- registration: user.registration,
851
- cardNo: user.card_value || user.cardNo,
852
- name: user.name,
853
- metadata: {
854
- name: user.name,
855
- },
856
- }))
857
- : [];
858
685
  }
859
686
 
860
687
  function toHidUserObject(identity: HidRecord): HidSyncUser | null {
@@ -872,89 +699,6 @@ function toHidUserObject(identity: HidRecord): HidSyncUser | null {
872
699
  };
873
700
  }
874
701
 
875
- function toHidUserCreateValues(user: HidSyncUser) {
876
- return {
877
- id: user.id,
878
- ...toHidUserValues(user),
879
- };
880
- }
881
-
882
- function toHidUserValues(user: HidSyncUser) {
883
- return {
884
- name: user.name,
885
- registration: user.registration || "",
886
- };
887
- }
888
-
889
- async function syncHidUserRole(readerId: string, hidUserId: unknown, isAdministrator: boolean) {
890
- const userId = toHidNumericId(hidUserId);
891
- if (!readerId || !userId) return;
892
-
893
- const existingRole = await getHidUserRole(readerId, userId);
894
- if (isAdministrator) {
895
- if (existingRole) {
896
- await runObjectOperation(readerId, {
897
- operation: "modify",
898
- object: "user_roles",
899
- where: {
900
- user_roles: {
901
- user_id: userId,
902
- },
903
- },
904
- values: {
905
- role: 1,
906
- },
907
- });
908
- return;
909
- }
910
-
911
- await runObjectOperation(readerId, {
912
- operation: "create",
913
- object: "user_roles",
914
- values: [
915
- {
916
- user_id: userId,
917
- role: 1,
918
- },
919
- ],
920
- });
921
- return;
922
- }
923
-
924
- if (existingRole) {
925
- await runObjectOperation(readerId, {
926
- operation: "destroy",
927
- object: "user_roles",
928
- where: {
929
- user_roles: {
930
- user_id: userId,
931
- },
932
- },
933
- });
934
- }
935
- }
936
-
937
- async function getHidUserRole(readerId: string, userId: number) {
938
- const response = await runObjectOperation(readerId, {
939
- operation: "load",
940
- object: "user_roles",
941
- where: {
942
- user_roles: {
943
- user_id: userId,
944
- },
945
- },
946
- limit: 1,
947
- offset: 0,
948
- });
949
- const data = response?.data || response || {};
950
- const roles =
951
- data?.user_roles ||
952
- data?.data?.user_roles ||
953
- data?.result?.user_roles ||
954
- [];
955
- return Array.isArray(roles) ? roles[0] : undefined;
956
- }
957
-
958
702
  function toHidNumericId(value: unknown) {
959
703
  const raw = String(value ?? "").trim();
960
704
  if (!raw) return undefined;
@@ -983,16 +727,6 @@ function countFacialData(users: HidRecord[]) {
983
727
  return users.filter((user) => user.face || user.photo || user.image || user.imageUrl || user.faceImage).length;
984
728
  }
985
729
 
986
- function toFacialSyncStats(response: unknown) {
987
- const root = asHidRecord(response);
988
- const data = asHidRecord(root.data ?? root);
989
- const syncedCount = Number(data.syncedCount);
990
- return {
991
- syncedCount: Number.isSafeInteger(syncedCount) && syncedCount >= 0 ? syncedCount : 0,
992
- message: String(data.message || "").trim(),
993
- };
994
- }
995
-
996
730
  function getFriendlyHidError(error: unknown) {
997
731
  const message = getHidErrorMessage(error);
998
732
  const lowerMessage = message.toLowerCase();