@7365admin1/core 3.48.1-staging.172 → 3.48.1-staging.173

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,10 @@
1
+ ---
2
+ "@7365admin1/core": patch
3
+ ---
4
+
5
+ Let Seven365 staff switch a client's faulty camera off, and record it
6
+
7
+ `PATCH /api/site-cameras/id/:id` now falls back to a Seven365 staff check when
8
+ the ordinary site rule refuses. The fallback writes `status` only and is
9
+ recorded in the console audit trail. Reads, `add` and `deleteById` are
10
+ unchanged, so staff have gained no access to any organisation's camera list.
package/dist/index.d.ts CHANGED
@@ -11598,7 +11598,16 @@ declare enum ConsoleAuditAction {
11598
11598
  PLAN_CREATED = "plan.created",
11599
11599
  PLAN_UPDATED = "plan.updated",
11600
11600
  PLAN_STATUS_CHANGED = "plan.status-changed",
11601
- TERMS_PUBLISHED = "terms.published"
11601
+ TERMS_PUBLISHED = "terms.published",
11602
+ /**
11603
+ * Seven365 staff switching a client's camera on or off.
11604
+ *
11605
+ * The only tenant-owned object on this list, and it is here because it is the
11606
+ * only one staff may touch: a faulty camera at a client's site has to be
11607
+ * switchable off by us. See `updateById` in `site-camera.controller.ts` for
11608
+ * the boundary that allows it and nothing else.
11609
+ */
11610
+ CAMERA_STATUS_CHANGED = "camera.status-changed"
11602
11611
  }
11603
11612
  /**
11604
11613
  * The three actions that live in `organization.controller.ts`.
@@ -11618,7 +11627,8 @@ declare enum ConsoleAuditTarget {
11618
11627
  SUBSCRIPTION = "subscription",
11619
11628
  PROMO_CODE = "promo-code",
11620
11629
  PLAN = "plan",
11621
- TERMS = "terms"
11630
+ TERMS = "terms",
11631
+ CAMERA = "camera"
11622
11632
  }
11623
11633
  /** A stored value is a primitive or it is not stored. */
11624
11634
  declare const AUDIT_VALUE_MAX_LENGTH = 120;
package/dist/index.js CHANGED
@@ -27289,6 +27289,7 @@ var ConsoleAuditAction = /* @__PURE__ */ ((ConsoleAuditAction3) => {
27289
27289
  ConsoleAuditAction3["PLAN_UPDATED"] = "plan.updated";
27290
27290
  ConsoleAuditAction3["PLAN_STATUS_CHANGED"] = "plan.status-changed";
27291
27291
  ConsoleAuditAction3["TERMS_PUBLISHED"] = "terms.published";
27292
+ ConsoleAuditAction3["CAMERA_STATUS_CHANGED"] = "camera.status-changed";
27292
27293
  return ConsoleAuditAction3;
27293
27294
  })(ConsoleAuditAction || {});
27294
27295
  var CLIENT_ACTIONS = [
@@ -27309,7 +27310,8 @@ var CONSOLE_AUDIT_LABELS = {
27309
27310
  ["plan.created" /* PLAN_CREATED */]: "Plan created",
27310
27311
  ["plan.updated" /* PLAN_UPDATED */]: "Plan edited",
27311
27312
  ["plan.status-changed" /* PLAN_STATUS_CHANGED */]: "Plan enabled or disabled",
27312
- ["terms.published" /* TERMS_PUBLISHED */]: "Platform Terms published"
27313
+ ["terms.published" /* TERMS_PUBLISHED */]: "Platform Terms published",
27314
+ ["camera.status-changed" /* CAMERA_STATUS_CHANGED */]: "Camera switched on or off by Seven365 staff"
27313
27315
  };
27314
27316
  var ConsoleAuditTarget = /* @__PURE__ */ ((ConsoleAuditTarget2) => {
27315
27317
  ConsoleAuditTarget2["ORGANIZATION"] = "organization";
@@ -27317,6 +27319,7 @@ var ConsoleAuditTarget = /* @__PURE__ */ ((ConsoleAuditTarget2) => {
27317
27319
  ConsoleAuditTarget2["PROMO_CODE"] = "promo-code";
27318
27320
  ConsoleAuditTarget2["PLAN"] = "plan";
27319
27321
  ConsoleAuditTarget2["TERMS"] = "terms";
27322
+ ConsoleAuditTarget2["CAMERA"] = "camera";
27320
27323
  return ConsoleAuditTarget2;
27321
27324
  })(ConsoleAuditTarget || {});
27322
27325
  var AUDIT_FIELDS = {
@@ -27380,7 +27383,11 @@ var AUDIT_FIELDS = {
27380
27383
  "status"
27381
27384
  ],
27382
27385
  ["plan.status-changed" /* PLAN_STATUS_CHANGED */]: ["status"],
27383
- ["terms.published" /* TERMS_PUBLISHED */]: ["version"]
27386
+ ["terms.published" /* TERMS_PUBLISHED */]: ["version"],
27387
+ // `status` only. Not the host, not the username, not the password - the whole
27388
+ // point of the staff camera path is that it may change nothing else, and the
27389
+ // audit row must not become the place a device credential is copied to.
27390
+ ["camera.status-changed" /* CAMERA_STATUS_CHANGED */]: ["status"]
27384
27391
  };
27385
27392
  var AUDIT_VALUE_MAX_LENGTH = 120;
27386
27393
  function auditValue(value) {
@@ -39302,10 +39309,29 @@ function useSiteCameraController() {
39302
39309
  throw error;
39303
39310
  }
39304
39311
  }
39312
+ async function staffStatusChange(params) {
39313
+ const status = params.value?.status;
39314
+ if (typeof status !== "string" || !status.trim())
39315
+ return null;
39316
+ const id = callerId4(params.req);
39317
+ if (!id || !await isSuperAdmin(id))
39318
+ return null;
39319
+ return id;
39320
+ }
39305
39321
  async function loadForWrite(id) {
39306
39322
  if (!import_mongodb72.ObjectId.isValid(id))
39307
39323
  return null;
39308
- return await _findOne({ _id: new import_mongodb72.ObjectId(id) }, { site: 1, type: 1 });
39324
+ return await _findOne(
39325
+ { _id: new import_mongodb72.ObjectId(id) },
39326
+ { site: 1, type: 1, host: 1, category: 1 }
39327
+ );
39328
+ }
39329
+ function staffUpdate(camera, status) {
39330
+ return {
39331
+ host: camera.host ?? "",
39332
+ category: camera.category ?? "standard",
39333
+ status
39334
+ };
39309
39335
  }
39310
39336
  function applyDerivedHost(body) {
39311
39337
  const { recorderHost, recorderPort, channel, ...rest } = body ?? {};
@@ -39406,13 +39432,32 @@ function useSiteCameraController() {
39406
39432
  const camera = await loadForWrite(id);
39407
39433
  if (!camera)
39408
39434
  throw new import_node_server_utils114.NotFoundError("Camera not found.");
39409
- await authorizeWrite({
39410
- req,
39411
- site: camera.site,
39412
- type: camera.type,
39413
- notFound: "Camera not found."
39414
- });
39415
- const message = await _updateById(id, value);
39435
+ let staffId = null;
39436
+ try {
39437
+ await authorizeWrite({
39438
+ req,
39439
+ site: camera.site,
39440
+ type: camera.type,
39441
+ notFound: "Camera not found."
39442
+ });
39443
+ } catch (error2) {
39444
+ staffId = await staffStatusChange({ req, value });
39445
+ if (!staffId)
39446
+ throw error2;
39447
+ }
39448
+ const update = staffId ? staffUpdate(camera, value.status) : value;
39449
+ const message = await _updateById(id, update);
39450
+ if (staffId) {
39451
+ await recordConsoleAction({
39452
+ action: "camera.status-changed" /* CAMERA_STATUS_CHANGED */,
39453
+ actor: staffId,
39454
+ target: id,
39455
+ targetType: "camera" /* CAMERA */,
39456
+ after: pickAuditFields("camera.status-changed" /* CAMERA_STATUS_CHANGED */, {
39457
+ status: value.status
39458
+ })
39459
+ });
39460
+ }
39416
39461
  res.json({
39417
39462
  message
39418
39463
  });