@7365admin1/core 3.47.1-staging.122 → 3.47.1-staging.124

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,12 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Authorize the HID facial-data sync handler in its own body
6
+
7
+ `syncReaderFacialData` reached `staging` with no authorization check inside the
8
+ handler. The API-core router does apply `requireAuth` + `authorizeManage`, so it
9
+ was not reachable by an ordinary signed-in user — but this is a published
10
+ package, and the guard and the handler sat in two different repositories. It now
11
+ runs the same `manage`-level check the router applies, with the site taken from
12
+ the stored reader. The guard test pins it by name.
package/dist/index.d.ts CHANGED
@@ -10199,13 +10199,16 @@ declare function useHidAmicoService(): {
10199
10199
  pages: number;
10200
10200
  pageRange: string;
10201
10201
  }>;
10202
- listReaderUsers: (readerId: string, page?: number, limit?: number, search?: string, status?: "mapped" | "unmapped" | "") => Promise<{
10202
+ listReaderUsers: (readerId: string, page?: number, limit?: number, search?: string, status?: "mapped" | "unmapped" | "", includeVisitors?: boolean) => Promise<{
10203
10203
  items: {
10204
10204
  reader: string;
10205
10205
  hidUserId: string;
10206
10206
  registration: string;
10207
10207
  metadata: {
10208
+ facialData?: string | undefined;
10208
10209
  name: string;
10210
+ hidUserTypeId: unknown;
10211
+ facialEnrolled: boolean;
10209
10212
  };
10210
10213
  isAdministrator: boolean;
10211
10214
  _id?: bson.ObjectId | undefined;
@@ -10217,7 +10220,7 @@ declare function useHidAmicoService(): {
10217
10220
  hasMore: boolean;
10218
10221
  pageRange: string;
10219
10222
  }>;
10220
- listReaderAccessLogs: (readerId: string, page?: number, limit?: number, search?: string, status?: "authorized" | "not_authorized" | "unknown" | "", method?: "facial" | "qr_code" | "id_password" | "pin" | "card" | "", tab?: "resident" | "visitor" | "administrator") => Promise<{
10223
+ listReaderAccessLogs: (readerId: string, page?: number, limit?: number, search?: string, status?: "authorized" | "not_authorized" | "unknown" | "", method?: "facial" | "qr_code" | "id_password" | "pin" | "card" | "", tab?: "all" | "unmapped" | "mapped" | "resident" | "visitor" | "administrator") => Promise<{
10221
10224
  items: unknown[];
10222
10225
  page: number;
10223
10226
  limit: number;
@@ -10331,6 +10334,13 @@ declare function useHidAmicoService(): {
10331
10334
  contentType: any;
10332
10335
  base64: string;
10333
10336
  }>;
10337
+ syncReaderFacialData: (readerId: string) => Promise<{
10338
+ readerId: string;
10339
+ facialDetected: number;
10340
+ syncedCount: number;
10341
+ unmappedCount: number;
10342
+ message: string;
10343
+ }>;
10334
10344
  listUserCards: (readerId: string, hidUserIdValue: string | number) => Promise<{
10335
10345
  readerId: string;
10336
10346
  hidUserId: number;
@@ -10476,6 +10486,7 @@ declare function useHidAmicoController(): {
10476
10486
  deleteReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10477
10487
  testReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10478
10488
  syncReader: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10489
+ syncReaderFacialData: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10479
10490
  configureReaderIntegration: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10480
10491
  setReaderMonitor: (req: Request, res: Response, next: NextFunction) => Promise<void>;
10481
10492
  setOperatingMode: (req: Request, res: Response, next: NextFunction) => Promise<void>;
package/dist/index.js CHANGED
@@ -42850,7 +42850,8 @@ var schemaHidAmicoReaderUserQuery = import_joi64.default.object({
42850
42850
  page: import_joi64.default.number().integer().min(1).default(1),
42851
42851
  limit: import_joi64.default.number().integer().min(1).max(100).default(10),
42852
42852
  search: import_joi64.default.string().trim().max(100).allow("").default(""),
42853
- status: import_joi64.default.string().valid("mapped", "unmapped").allow("").default("")
42853
+ status: import_joi64.default.string().valid("mapped", "unmapped").allow("").default(""),
42854
+ includeVisitors: import_joi64.default.boolean().default(false)
42854
42855
  });
42855
42856
  var schemaHidAmicoAccessLogQuery = import_joi64.default.object({
42856
42857
  page: import_joi64.default.number().integer().min(1).default(1),
@@ -42858,7 +42859,7 @@ var schemaHidAmicoAccessLogQuery = import_joi64.default.object({
42858
42859
  search: import_joi64.default.string().trim().max(100).allow("").default(""),
42859
42860
  status: import_joi64.default.string().valid("authorized", "not_authorized", "unknown").allow("").default(""),
42860
42861
  method: import_joi64.default.string().valid("facial", "qr_code", "id_password", "pin", "card").allow("").default(""),
42861
- tab: import_joi64.default.string().valid("resident", "visitor", "administrator").default("resident")
42862
+ tab: import_joi64.default.string().valid("all", "unmapped", "mapped", "resident", "visitor", "administrator").default("all")
42862
42863
  });
42863
42864
  var schemaHidAmicoOperatingMode = import_joi64.default.object({
42864
42865
  mode: import_joi64.default.string().valid("standalone", "online").required()
@@ -44371,12 +44372,17 @@ function getSecretKey() {
44371
44372
  function getReaderCapabilities(readerModel, firmwareVersion) {
44372
44373
  return {
44373
44374
  card: hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
44374
- facial: hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
44375
+ // VL35LF and VL70LF are biometric readers. Some deployed readers report
44376
+ // their device firmware as 2.x even though their face API is available.
44377
+ facial: readerModel === "VL35LF" || readerModel === "VL70LF",
44375
44378
  qr: hidFirmwareAtLeast(firmwareVersion, "6.5.1"),
44376
44379
  pin: hidFirmwareAtLeast(firmwareVersion, "6.9.0"),
44377
44380
  intercom: readerModel === "VL70LF"
44378
44381
  };
44379
44382
  }
44383
+ function readerSupportsFacial(reader) {
44384
+ return reader.capabilities?.facial === true || reader.readerModel === "VL35LF" || reader.readerModel === "VL70LF";
44385
+ }
44380
44386
  function getMonitorConfiguration(callbackToken) {
44381
44387
  const configured = String(process.env.HID_AMICO_MONITOR_URL || "").trim();
44382
44388
  if (!configured) {
@@ -44839,26 +44845,6 @@ function getHidPortals(response) {
44839
44845
  areaToId: Number(portal.area_to_id)
44840
44846
  })).filter((portal) => Number.isSafeInteger(portal.id) && portal.id > 0 && portal.name);
44841
44847
  }
44842
- function getHidObjectTotal(response, object) {
44843
- const root = isUnknownRecord2(response) ? response : {};
44844
- const data = isUnknownRecord2(root.data) ? root.data : root;
44845
- const nested = isUnknownRecord2(data.data) ? data.data : {};
44846
- const objectData = isUnknownRecord2(data[object]) ? data[object] : {};
44847
- for (const candidate of [
44848
- data.total,
44849
- data.total_count,
44850
- data.count,
44851
- nested.total,
44852
- nested.total_count,
44853
- nested.count,
44854
- objectData.total
44855
- ]) {
44856
- const total = Number(candidate);
44857
- if (Number.isSafeInteger(total) && total >= 0)
44858
- return total;
44859
- }
44860
- return null;
44861
- }
44862
44848
  async function upsertHidObject(client, object, id, values) {
44863
44849
  const existing = await client.loadObjects({
44864
44850
  object,
@@ -45234,6 +45220,18 @@ var HidAmicoClient = class {
45234
45220
  base64: buffer.toString("base64")
45235
45221
  };
45236
45222
  }
45223
+ async listUserImageIds() {
45224
+ if (!this.session) {
45225
+ await this.login();
45226
+ }
45227
+ const path5 = this.url("/user_list_images.fcgi?get_timestamp=0");
45228
+ const response = await this.get(path5, "json").catch(() => this.post(path5, {}));
45229
+ const payload = isUnknownRecord2(response.data) ? response.data : {};
45230
+ const userIds = Array.isArray(payload.user_ids) ? payload.user_ids : [];
45231
+ return [...new Set(
45232
+ userIds.map((value) => Number(value)).filter((value) => Number.isSafeInteger(value) && value > 0)
45233
+ )];
45234
+ }
45237
45235
  async setUserImage(hidUserId, image, timestamp, match) {
45238
45236
  if (!this.session) {
45239
45237
  await this.login();
@@ -45809,8 +45807,9 @@ function useHidAmicoService() {
45809
45807
  return reader;
45810
45808
  }
45811
45809
  function assertReaderCapability(reader, capability) {
45812
- if (reader.capabilities?.[capability])
45810
+ if (reader.capabilities?.[capability] || capability === "facial" && readerSupportsFacial(reader)) {
45813
45811
  return;
45812
+ }
45814
45813
  const requirement = capability === "pin" ? "firmware 6.9.0 or newer" : capability === "intercom" ? "a VL70LF reader" : "firmware 6.5.1 or newer";
45815
45814
  throw new import_node_server_utils131.BadRequestError(
45816
45815
  `This reader has not reported ${capability} support (${requirement}). Reconfigure the reader to refresh its capabilities.`
@@ -46426,7 +46425,7 @@ function useHidAmicoService() {
46426
46425
  async function listIdentities(value) {
46427
46426
  return repo.listIdentities(value);
46428
46427
  }
46429
- async function listReaderUsers(readerId, page = 1, limit = 10, search = "", status = "") {
46428
+ async function listReaderUsers(readerId, page = 1, limit = 10, search = "", status = "", includeVisitors = false) {
46430
46429
  const reader = await getActiveReader(readerId);
46431
46430
  const offset = (page - 1) * limit;
46432
46431
  const client = new HidAmicoClient(reader);
@@ -46434,7 +46433,7 @@ function useHidAmicoService() {
46434
46433
  await client.login();
46435
46434
  const normalizedSearch = search.trim();
46436
46435
  const numericSearch = /^\d{1,15}$/.test(normalizedSearch) ? Number(normalizedSearch) : null;
46437
- const userWhere = { user_type_id: 0 };
46436
+ const userWhere = {};
46438
46437
  if (numericSearch !== null && Number.isSafeInteger(numericSearch)) {
46439
46438
  userWhere.id = numericSearch;
46440
46439
  } else if (normalizedSearch) {
@@ -46447,13 +46446,14 @@ function useHidAmicoService() {
46447
46446
  const response = await client.loadObjects({
46448
46447
  object: "users",
46449
46448
  where: { users: userWhere },
46450
- limit,
46451
- offset,
46449
+ limit: 500,
46450
+ offset: 0,
46452
46451
  order: ["id", "ascending"]
46453
46452
  });
46454
- rows = getHidObjectRows(response, "users");
46455
- reportedTotal = getHidObjectTotal(response, "users");
46456
- hasMore = rows.length === limit && (reportedTotal === null || offset + rows.length < reportedTotal);
46453
+ const deviceRows = getHidObjectRows(response, "users").filter((row) => includeVisitors || Number(row.user_type_id) !== 1);
46454
+ reportedTotal = deviceRows.length;
46455
+ rows = deviceRows.slice(offset, offset + limit);
46456
+ hasMore = offset + rows.length < deviceRows.length;
46457
46457
  } else {
46458
46458
  const linkedIdentities = await repo.listActiveIdentities(readerId);
46459
46459
  const mappedUserIds = new Set(
@@ -46474,6 +46474,8 @@ function useHidAmicoService() {
46474
46474
  });
46475
46475
  const batch = getHidObjectRows(response, "users");
46476
46476
  batch.forEach((row) => {
46477
+ if (!includeVisitors && Number(row.user_type_id) === 1)
46478
+ return;
46477
46479
  const mapped = mappedUserIds.has(String(row.id ?? ""));
46478
46480
  if (status === "mapped" && mapped || status === "unmapped" && !mapped) {
46479
46481
  matchedRows.push(row);
@@ -46486,7 +46488,7 @@ function useHidAmicoService() {
46486
46488
  hasMore = matchedRows.length > offset + limit || !exhausted;
46487
46489
  }
46488
46490
  const userIds = rows.map((row) => String(row.id ?? "")).filter(Boolean);
46489
- const [identities, administratorFlags] = await Promise.all([
46491
+ const [identities, administratorFlags, facialUserIds] = await Promise.all([
46490
46492
  repo.findIdentitiesByHidUserIds(readerId, userIds),
46491
46493
  Promise.all(rows.map(async (row) => {
46492
46494
  const userId = Number(row.id);
@@ -46499,13 +46501,17 @@ function useHidAmicoService() {
46499
46501
  offset: 0
46500
46502
  });
46501
46503
  return getHidObjectRows(roleResponse, "user_roles").length > 0;
46502
- }))
46504
+ })),
46505
+ readerSupportsFacial(reader) ? client.listUserImageIds().catch(() => []) : Promise.resolve([])
46503
46506
  ]);
46504
46507
  const identityMap = new Map(
46505
46508
  identities.map((identity) => [String(identity.hidUserId), identity])
46506
46509
  );
46510
+ const facialUserIdSet = new Set(facialUserIds.map(String));
46507
46511
  const items = rows.map((row, index) => {
46508
46512
  const identity = identityMap.get(String(row.id ?? ""));
46513
+ const identityMetadata = identity && isUnknownRecord2(identity.metadata) ? identity.metadata : {};
46514
+ const facialEnrolled = facialUserIdSet.has(String(row.id ?? "")) || identityMetadata.facialEnrolled === true;
46509
46515
  return {
46510
46516
  ...row,
46511
46517
  ...identity || {},
@@ -46513,8 +46519,11 @@ function useHidAmicoService() {
46513
46519
  hidUserId: String(row.id ?? identity?.hidUserId ?? ""),
46514
46520
  registration: String(row.registration ?? identity?.registration ?? ""),
46515
46521
  metadata: {
46516
- ...isUnknownRecord2(identity?.metadata) ? identity?.metadata : {},
46517
- name: String(row.name ?? identity?.metadata?.name ?? "")
46522
+ ...identityMetadata,
46523
+ name: String(row.name ?? identityMetadata.name ?? ""),
46524
+ hidUserTypeId: row.user_type_id ?? identityMetadata.hidUserTypeId,
46525
+ facialEnrolled,
46526
+ ...facialEnrolled ? { facialData: String(row.id ?? "") } : {}
46518
46527
  },
46519
46528
  isAdministrator: administratorFlags[index]
46520
46529
  };
@@ -46533,7 +46542,7 @@ function useHidAmicoService() {
46533
46542
  await client.logout();
46534
46543
  }
46535
46544
  }
46536
- async function listReaderAccessLogs(readerId, page = 1, limit = 10, search = "", status = "", method = "", tab = "resident") {
46545
+ async function listReaderAccessLogs(readerId, page = 1, limit = 10, search = "", status = "", method = "", tab = "all") {
46537
46546
  const reader = await getActiveReader(readerId);
46538
46547
  const offset = (page - 1) * limit;
46539
46548
  const client = new HidAmicoClient(reader);
@@ -46557,7 +46566,7 @@ function useHidAmicoService() {
46557
46566
  const normalizedSearch = search.trim().toLocaleLowerCase();
46558
46567
  const enrichRows = async (rows) => {
46559
46568
  const userIds = [...new Set(rows.map((row) => toPositiveInteger(row.user_id ?? row.userId)).filter((value) => value !== null))];
46560
- const [identities, roleResponse] = await Promise.all([
46569
+ const [identities, roleResponse, userResponse] = await Promise.all([
46561
46570
  repo.findIdentitiesByHidUserIds(readerId, userIds.map(String)),
46562
46571
  userIds.length ? client.loadObjects({
46563
46572
  object: "user_roles",
@@ -46569,7 +46578,17 @@ function useHidAmicoService() {
46569
46578
  },
46570
46579
  limit: Math.max(1, userIds.length),
46571
46580
  offset: 0
46572
- }) : Promise.resolve({ user_roles: [] })
46581
+ }) : Promise.resolve({ user_roles: [] }),
46582
+ userIds.length ? client.loadObjects({
46583
+ object: "users",
46584
+ where: {
46585
+ users: {
46586
+ id: userIds.length === 1 ? userIds[0] : { IN: userIds }
46587
+ }
46588
+ },
46589
+ limit: Math.max(1, userIds.length),
46590
+ offset: 0
46591
+ }) : Promise.resolve({ users: [] })
46573
46592
  ]);
46574
46593
  const identityMap = new Map(
46575
46594
  identities.map((identity) => [String(identity.hidUserId), identity])
@@ -46577,11 +46596,19 @@ function useHidAmicoService() {
46577
46596
  const administratorIds = new Set(
46578
46597
  getHidObjectRows(roleResponse, "user_roles").map((role) => String(role.user_id ?? "")).filter(Boolean)
46579
46598
  );
46599
+ const readerUserById = new Map(
46600
+ getHidObjectRows(userResponse, "users").map((user) => [String(user.id ?? ""), user]).filter(([userId]) => Boolean(userId))
46601
+ );
46580
46602
  return rows.map((row) => {
46581
46603
  const userId = String(row.user_id ?? row.userId ?? "");
46582
46604
  const identity = identityMap.get(userId) || null;
46605
+ const readerUser = readerUserById.get(userId);
46606
+ const existingName = String(row.user_name ?? row.userName ?? "").trim();
46607
+ const readerUserName = String(readerUser?.name ?? "").trim();
46583
46608
  return {
46584
46609
  ...row,
46610
+ user_name: existingName || readerUserName,
46611
+ user_type_id: row.user_type_id ?? readerUser?.user_type_id ?? "",
46585
46612
  identity,
46586
46613
  isAdministrator: administratorIds.has(userId),
46587
46614
  normalizedMethod: normalizeHidAccessLogMethod(row),
@@ -46592,7 +46619,12 @@ function useHidAmicoService() {
46592
46619
  const matchesRequestedFilters = (item) => {
46593
46620
  const identity = isUnknownRecord2(item.identity) ? item.identity : null;
46594
46621
  const itemTab = normalizeHidAccessLogTab(identity, Boolean(item.isAdministrator));
46595
- if (itemTab !== tab)
46622
+ const isMapped = Boolean(identity);
46623
+ if (tab === "unmapped" && isMapped)
46624
+ return false;
46625
+ if (tab === "mapped" && !isMapped)
46626
+ return false;
46627
+ if (["resident", "visitor", "administrator"].includes(tab) && itemTab !== tab)
46596
46628
  return false;
46597
46629
  if (status && item.normalizedStatus !== status)
46598
46630
  return false;
@@ -47133,6 +47165,98 @@ function useHidAmicoService() {
47133
47165
  await client.logout();
47134
47166
  }
47135
47167
  }
47168
+ async function getReaderFacialUserIds(client) {
47169
+ try {
47170
+ return await client.listUserImageIds();
47171
+ } catch {
47172
+ const usersResponse = await client.loadObjects({
47173
+ object: "users",
47174
+ where: { users: {} },
47175
+ limit: 500,
47176
+ offset: 0,
47177
+ order: ["id", "ascending"]
47178
+ });
47179
+ const userIds = getHidObjectRows(usersResponse, "users").map((user) => Number(user.id)).filter((userId) => Number.isSafeInteger(userId) && userId > 0);
47180
+ const facialUserIds = [];
47181
+ const batchSize = 4;
47182
+ for (let offset = 0; offset < userIds.length; offset += batchSize) {
47183
+ const batch = userIds.slice(offset, offset + batchSize);
47184
+ const results = await Promise.all(batch.map(async (userId) => {
47185
+ try {
47186
+ const image = await client.getUserImage(userId);
47187
+ return image.base64 ? userId : null;
47188
+ } catch {
47189
+ return null;
47190
+ }
47191
+ }));
47192
+ facialUserIds.push(...results.filter((userId) => userId !== null));
47193
+ }
47194
+ return facialUserIds;
47195
+ }
47196
+ }
47197
+ async function syncReaderFacialData(readerId) {
47198
+ const reader = await getActiveReader(readerId);
47199
+ assertReaderCapability(reader, "facial");
47200
+ const client = new HidAmicoClient(reader);
47201
+ try {
47202
+ await client.login();
47203
+ const facialUserIds = await getReaderFacialUserIds(client);
47204
+ const activeIdentities = await repo.listActiveIdentities(readerId);
47205
+ const identitiesByUserId = new Map(
47206
+ activeIdentities.filter((identity) => identity._id && identity.hidUserId !== void 0).map((identity) => [String(identity.hidUserId), identity])
47207
+ );
47208
+ const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
47209
+ let syncedCount = 0;
47210
+ let unmappedCount = 0;
47211
+ for (const hidUserId of facialUserIds) {
47212
+ const identity = identitiesByUserId.get(String(hidUserId));
47213
+ if (!identity?._id) {
47214
+ unmappedCount += 1;
47215
+ continue;
47216
+ }
47217
+ const metadata = isUnknownRecord2(identity.metadata) ? identity.metadata : {};
47218
+ await repo.updateIdentity(identity._id, {
47219
+ metadata: {
47220
+ ...metadata,
47221
+ facialData: String(hidUserId),
47222
+ facialEnrolled: true,
47223
+ facialSyncedAt: syncedAt
47224
+ }
47225
+ });
47226
+ syncedCount += 1;
47227
+ }
47228
+ const message = [
47229
+ facialUserIds.length ? `Detected ${facialUserIds.length} facial enrollment(s) on the HID reader.` : "No facial enrollments found on the HID reader.",
47230
+ syncedCount ? `${syncedCount} mapped HID user(s) updated.` : "",
47231
+ unmappedCount ? `${unmappedCount} facial enrollment(s) still need HID User Mapping.` : ""
47232
+ ].filter(Boolean).join(" ");
47233
+ await repo.updateById(readerId, { status: "active", lastSeenAt: /* @__PURE__ */ new Date() });
47234
+ await repo.addEvent({
47235
+ reader: readerId,
47236
+ site: reader.site,
47237
+ type: "facial_sync",
47238
+ payload: { facialDetected: facialUserIds.length, syncedCount, unmappedCount }
47239
+ });
47240
+ return {
47241
+ readerId,
47242
+ facialDetected: facialUserIds.length,
47243
+ syncedCount,
47244
+ unmappedCount,
47245
+ message
47246
+ };
47247
+ } catch (error) {
47248
+ await repo.addEvent({
47249
+ reader: readerId,
47250
+ site: reader.site,
47251
+ type: "facial_sync_failed",
47252
+ status: "failed",
47253
+ payload: { message: getErrorMessage2(error) }
47254
+ });
47255
+ throw error;
47256
+ } finally {
47257
+ await client.logout();
47258
+ }
47259
+ }
47136
47260
  async function setVisitorImage(readerId, visitorId, image, options = {}) {
47137
47261
  assertHidFacialImage(image);
47138
47262
  const reader = await getActiveReader(readerId);
@@ -48284,6 +48408,7 @@ function useHidAmicoService() {
48284
48408
  setVisitorImage,
48285
48409
  deleteVisitorImage,
48286
48410
  getUserImage,
48411
+ syncReaderFacialData,
48287
48412
  listUserCards,
48288
48413
  assignUserCard,
48289
48414
  enrollUserCard,
@@ -84298,6 +84423,19 @@ function useHidAmicoController() {
84298
84423
  next(error);
84299
84424
  }
84300
84425
  }
84426
+ async function syncReaderFacialData(req, res, next) {
84427
+ const { error, value } = schemaHidAmicoReaderIdParams.validate(req.params);
84428
+ if (error) {
84429
+ next(new import_node_server_utils286.BadRequestError(error.message));
84430
+ return;
84431
+ }
84432
+ try {
84433
+ await authorizeReaderAccess(req, value.readerId, "manage");
84434
+ res.json({ data: await service.syncReaderFacialData(value.readerId) });
84435
+ } catch (error2) {
84436
+ next(error2);
84437
+ }
84438
+ }
84301
84439
  async function listLogs(req, res, next) {
84302
84440
  const params = schemaHidAmicoReaderIdParams.validate(req.params);
84303
84441
  const query2 = schemaHidAmicoLogQuery.validate(req.query);
@@ -84409,7 +84547,8 @@ function useHidAmicoController() {
84409
84547
  query2.value.page,
84410
84548
  query2.value.limit,
84411
84549
  query2.value.search,
84412
- query2.value.status
84550
+ query2.value.status,
84551
+ query2.value.includeVisitors
84413
84552
  ));
84414
84553
  } catch (error) {
84415
84554
  next(error);
@@ -84987,6 +85126,7 @@ function useHidAmicoController() {
84987
85126
  deleteReader,
84988
85127
  testReader,
84989
85128
  syncReader,
85129
+ syncReaderFacialData,
84990
85130
  configureReaderIntegration,
84991
85131
  setReaderMonitor,
84992
85132
  setOperatingMode,