@7365admin1/core 3.32.2-staging.74 → 3.32.2-staging.76

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,19 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Stop logging camera and mailer credentials
6
+
7
+ Six places wrote a secret or a resident's details to stdout on an ordinary code
8
+ path. `getTrafficJunction` dumped the whole `TSiteCamera` object — including the
9
+ camera's `username` and plaintext `password` — on every reconnect, and
10
+ `addPlateNumber` logged its argument, which carries the same password plus a
11
+ resident's plate number and owner name. `checkOutBySiteAndPlate` logged the
12
+ matched visitor transaction. `siteCameraRepo.updateById` logged the re-read
13
+ camera document, and `vehicleService.add` logged the whole array of a site's
14
+ cameras, both with credentials in them. `sendEmail` printed `MAILER_PASSWORD`
15
+ itself on every message sent.
16
+
17
+ All now log identifiers, counts and outcomes only, through the module's logger
18
+ rather than `console.log`; the mailer line is removed outright because it
19
+ carried nothing but the secret.
package/dist/index.js CHANGED
@@ -22700,7 +22700,6 @@ async function sendEmail({ to, subject, text, html }) {
22700
22700
  pass: MAILER_PASSWORD
22701
22701
  }
22702
22702
  });
22703
- console.log(MAILER_EMAIL, MAILER_PASSWORD, MAILER_TRANSPORT_HOST, MAILER_TRANSPORT_PORT);
22704
22703
  const mailOptions = {
22705
22704
  from: `Seven 365 <${MAILER_EMAIL}>`,
22706
22705
  to,
@@ -24737,6 +24736,47 @@ var loggerDahua = winston.createLogger({
24737
24736
  ]
24738
24737
  });
24739
24738
 
24739
+ // src/utils/camera-alert.util.ts
24740
+ var DIRECTION_WORDS = {
24741
+ entry: "entry",
24742
+ exit: "exit",
24743
+ both: "entry and exit",
24744
+ visitors: "visitor",
24745
+ residents: "resident"
24746
+ };
24747
+ function describeCamera(camera) {
24748
+ const site = String(camera?.siteName ?? "").trim();
24749
+ const name = String(camera?.name ?? "").trim();
24750
+ const at = site ? ` at ${site}` : "";
24751
+ if (name)
24752
+ return `Camera "${name}"${at}`;
24753
+ const words = DIRECTION_WORDS[String(camera?.direction ?? "").trim().toLowerCase()];
24754
+ return words ? `The ${words} ANPR camera${at}` : `The ANPR camera${at}`;
24755
+ }
24756
+ function cameraUnreachableMessage(camera) {
24757
+ return `${describeCamera(camera)} is not responding. Plate reads and automatic barrier opening are stopped while it is down. The server keeps trying to reconnect on its own. If it does not come back, ask your site technician or the security-system installer to check the camera's power and network.`;
24758
+ }
24759
+ function cameraRecoveredMessage(camera) {
24760
+ return `${describeCamera(camera)} is responding again. Plate reads have resumed.`;
24761
+ }
24762
+ function cameraCredentialsMessage(camera) {
24763
+ return `${describeCamera(camera)} refused the login, so it cannot read plates. The username or password saved for it is wrong. An administrator can correct them in Site Settings > Cameras; if they are already correct, the camera's own account needs checking by your site technician.`;
24764
+ }
24765
+ function cameraNotAuthorisedMessage(camera) {
24766
+ return `${describeCamera(camera)} rejected our connection, so it cannot read plates. This usually means its account is not allowed to use the plate-reading feed. Please ask your site technician or the security-system installer to check the camera's account permissions.`;
24767
+ }
24768
+ var CAMERA_ALERT_AT_ATTEMPT = [1, 6, 30, 90];
24769
+ var CAMERA_ALERT_EVERY_AFTER = 90;
24770
+ function shouldAlertOnFailure(consecutiveFailures) {
24771
+ if (!Number.isInteger(consecutiveFailures) || consecutiveFailures < 1)
24772
+ return false;
24773
+ if (CAMERA_ALERT_AT_ATTEMPT.includes(consecutiveFailures))
24774
+ return true;
24775
+ if (consecutiveFailures < CAMERA_ALERT_EVERY_AFTER)
24776
+ return false;
24777
+ return (consecutiveFailures - CAMERA_ALERT_EVERY_AFTER) % CAMERA_ALERT_EVERY_AFTER === 0;
24778
+ }
24779
+
24740
24780
  // src/services/dahua.service.ts
24741
24781
  var cameraRegistry = /* @__PURE__ */ new Map();
24742
24782
  var _savedOnDetected;
@@ -24929,7 +24969,9 @@ function useDahuaService() {
24929
24969
  return;
24930
24970
  try {
24931
24971
  const result = await _checkOutBySiteAndPlate(site, plateNumber2);
24932
- console.log("checkOutBySiteAndPlate result", result);
24972
+ loggerDahua.info(
24973
+ `checkOutBySiteAndPlate matched=${Boolean(result)} type=${result?.type ?? "none"}`
24974
+ );
24933
24975
  if (onDetected2 && result?.type != "resident" && result?.site) {
24934
24976
  onDetected2({ reload: true, site: result?.site?.toString(), siteName: camera?.siteName, cameraDirection: camera?.direction, direction });
24935
24977
  }
@@ -25228,8 +25270,12 @@ function useDahuaService() {
25228
25270
  );
25229
25271
  }
25230
25272
  async function getTrafficJunction(camera, signal, onDetected) {
25231
- console.log(`getTrafficJunction camera object`, camera);
25273
+ loggerDahua.info(
25274
+ `getTrafficJunction starting for camera ${camera?._id} [${camera?.siteName}-${camera?.direction}] host ${camera?.host}`
25275
+ );
25232
25276
  let authFailureCount = 0;
25277
+ let connectionFailureCount = 0;
25278
+ let alertedFailureCount = 0;
25233
25279
  const MAX_AUTH_RETRIES = 10;
25234
25280
  while (!signal.aborted) {
25235
25281
  let bufferQueue = null;
@@ -25257,19 +25303,33 @@ function useDahuaService() {
25257
25303
  onDetected({
25258
25304
  site: camera?.site,
25259
25305
  direction: camera?.direction,
25260
- messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password and try after 10 minutes.`
25306
+ messagePermanent: cameraCredentialsMessage(camera)
25261
25307
  });
25262
25308
  }
25263
25309
  return;
25264
25310
  } else if ([400, 500].includes(statusCode)) {
25265
25311
  loggerDahua.error(`[${camera?.siteName}-${camera?.direction}] Connection error: ${statusCode}`);
25266
25312
  if (onDetected) {
25267
- onDetected({ site: camera?.site, messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Possible Not Authorized.` });
25313
+ onDetected({ site: camera?.site, messagePermanent: cameraNotAuthorisedMessage(camera) });
25268
25314
  }
25269
25315
  return;
25270
25316
  }
25271
25317
  authFailureCount = 0;
25272
25318
  isAuthFailure = false;
25319
+ if (alertedFailureCount > 0 && onDetected) {
25320
+ onDetected({
25321
+ site: camera?.site,
25322
+ direction: camera?.direction,
25323
+ // `event` and `camera` let a client group or clear an alert per
25324
+ // camera instead of matching on the message text. Older clients
25325
+ // ignore them and just render `message`, as they always have.
25326
+ event: "camera-recovered",
25327
+ camera: camera?._id?.toString(),
25328
+ message: cameraRecoveredMessage(camera)
25329
+ });
25330
+ }
25331
+ connectionFailureCount = 0;
25332
+ alertedFailureCount = 0;
25273
25333
  loggerDahua.info(`[${camera?.siteName}-${camera?.direction}] Successfully connected to ANPR.`);
25274
25334
  const contentType = response.res.headers["content-type"];
25275
25335
  const boundaryMatch = contentType?.match(/boundary=(.*)$/i);
@@ -25323,7 +25383,7 @@ function useDahuaService() {
25323
25383
  onDetected({
25324
25384
  site: camera?.site,
25325
25385
  direction: camera?.direction,
25326
- messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password and try after 10 minutes.`
25386
+ messagePermanent: cameraCredentialsMessage(camera)
25327
25387
  });
25328
25388
  }
25329
25389
  return;
@@ -25343,7 +25403,7 @@ function useDahuaService() {
25343
25403
  onDetected({
25344
25404
  site: camera?.site,
25345
25405
  direction: camera?.direction,
25346
- messagePermanent: `Camera [${camera?.siteName}-${camera?.direction}]. Connection Error. Check username and password.`
25406
+ messagePermanent: cameraCredentialsMessage(camera)
25347
25407
  });
25348
25408
  }
25349
25409
  return;
@@ -25351,14 +25411,18 @@ function useDahuaService() {
25351
25411
  } else {
25352
25412
  authFailureCount = 0;
25353
25413
  isAuthFailure = false;
25414
+ connectionFailureCount++;
25354
25415
  loggerDahua.error(
25355
- `[${camera?.siteName}-${camera?.direction}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds...`
25416
+ `[${camera?.siteName}-${camera?.direction}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds... (failure ${connectionFailureCount})`
25356
25417
  );
25357
- if (onDetected) {
25418
+ if (onDetected && shouldAlertOnFailure(connectionFailureCount)) {
25419
+ alertedFailureCount = connectionFailureCount;
25358
25420
  onDetected({
25359
25421
  site: camera?.site,
25360
25422
  direction: camera?.direction,
25361
- message: `Camera in [${camera?.siteName}-${camera?.direction}] Connection Lost. Retrying in 10 seconds. Check the camera if this issue persists, Or set the camera to Inactive to stop this notification.`
25423
+ event: "camera-fault",
25424
+ camera: camera?._id?.toString(),
25425
+ message: cameraUnreachableMessage(camera)
25362
25426
  });
25363
25427
  }
25364
25428
  }
@@ -25395,7 +25459,9 @@ function useDahuaService() {
25395
25459
  return match ? match[1] : null;
25396
25460
  }
25397
25461
  async function addPlateNumber(value) {
25398
- console.log("addPlateNumber called with value:", value);
25462
+ loggerDahua.info(
25463
+ `addPlateNumber called for host ${value?.host} mode ${value?.mode}`
25464
+ );
25399
25465
  let recno = null;
25400
25466
  const validation = import_joi40.default.object({
25401
25467
  host: import_joi40.default.string().required(),
@@ -26055,7 +26121,7 @@ function useSiteCameraRepo() {
26055
26121
  }
26056
26122
  if (result?._id) {
26057
26123
  const result2 = await findOne({ _id: new import_mongodb46.ObjectId(result._id) }, void 0, { session });
26058
- console.log("updateById result2", result2);
26124
+ import_node_server_utils74.logger.info(`Site camera ${result2?._id} re-read after update; reconnecting listener`);
26059
26125
  if (result2?._id) {
26060
26126
  const { listenToCamera } = useDahuaService();
26061
26127
  await listenToCamera(result2);
@@ -27581,7 +27647,9 @@ function useVehicleService() {
27581
27647
  siteCameras.push(...siteCameraReq.items);
27582
27648
  page++;
27583
27649
  } while (page <= pages);
27584
- console.log("add vehicle service siteCameras", siteCameras);
27650
+ import_node_server_utils78.logger.info(
27651
+ `addVehicle resolved ${siteCameras.length} site camera(s) for site ${value?.site}`
27652
+ );
27585
27653
  }
27586
27654
  for (const plateNumber of plateNumbers) {
27587
27655
  const vehicleValue = {