feat: release passwordless hierarchical APT v1.2.5
This commit is contained in:
@@ -6,6 +6,7 @@ const {
|
||||
MAX_PROJECTED_PAYLOAD_BYTES,
|
||||
projectDeviceHierarchy,
|
||||
} = require('../src/device-projection');
|
||||
const { buildDeviceTree } = require('../device-tree');
|
||||
|
||||
function uuid(index) {
|
||||
return `00000000-0000-4000-8000-${index.toString(16).padStart(12, '0')}`;
|
||||
@@ -18,7 +19,7 @@ function rawDevice(index, overrides = {}) {
|
||||
type: 'camera',
|
||||
model: 'Synthetic',
|
||||
address: `10.0.${Math.floor(index / 255)}.${index % 255}`,
|
||||
server_group_id: 'site-1',
|
||||
server_group_id: 'server-group-1',
|
||||
device_group_id: 'group-1',
|
||||
capabilities: { localStorage: index % 2 === 0, secretCapability: 'drop-me' },
|
||||
live: { display_status: 'online', private: 'drop-me' },
|
||||
@@ -29,25 +30,68 @@ function rawDevice(index, overrides = {}) {
|
||||
|
||||
test('projects only allowlisted fields and honestly diagnoses ineligible devices', () => {
|
||||
const payload = projectDeviceHierarchy({
|
||||
devices: [rawDevice(1), rawDevice(2, { guid: 'not-a-uuid' })],
|
||||
devices: [
|
||||
rawDevice(1),
|
||||
rawDevice(2, { guid: 'not-a-uuid' }),
|
||||
rawDevice(4),
|
||||
],
|
||||
sites: [{ id: 'site-1', name: 'HQ', pending_deletion_start: null, secret: 'drop-me' }],
|
||||
groups: [{ id: 'group-1', name: 'Lobby', parent_id: null, pending_deletion_start: null, secret: 'drop-me' }],
|
||||
});
|
||||
|
||||
assert.deepEqual(payload.devices, [{
|
||||
id: uuid(1), name: 'Camera 1', type: 'camera', model: 'Synthetic', address: '10.0.0.1',
|
||||
siteId: 'site-1', deviceGroupId: 'group-1', displayStatus: 'online', localStorage: false,
|
||||
siteId: null, deviceGroupId: 'group-1', displayStatus: 'online', localStorage: false,
|
||||
}]);
|
||||
assert.deepEqual(payload.sites, [{ id: 'site-1', name: 'HQ', pendingDeletionStart: null }]);
|
||||
assert.deepEqual(payload.groups, [{ id: 'group-1', name: 'Lobby', parentId: null, pendingDeletionStart: null }]);
|
||||
assert.deepEqual(payload.diagnostics.devices, { received: 2, eligible: 1, invalid: 1 });
|
||||
assert.deepEqual(payload.diagnostics.devices, {
|
||||
received: 3, eligible: 1, invalid: 1, cloudNativeExcluded: 1,
|
||||
});
|
||||
assert.doesNotMatch(JSON.stringify(payload), /drop-me|cookie|secretCapability|private/);
|
||||
});
|
||||
|
||||
test('infers camera sites from device-group parents instead of server groups', () => {
|
||||
const payload = projectDeviceHierarchy({
|
||||
devices: [rawDevice(3, {
|
||||
name: 'Front Door',
|
||||
server_group_id: 'cloud-connector-server-group',
|
||||
device_group_id: 'entrances',
|
||||
})],
|
||||
sites: [{ id: 'test-site', name: 'Test Site' }],
|
||||
groups: [{ id: 'entrances', name: 'Entrances', parent_id: 'test-site' }],
|
||||
});
|
||||
const model = buildDeviceTree(payload);
|
||||
const camera = [...model.cameraByKey.values()][0];
|
||||
|
||||
assert.equal(payload.devices[0].siteId, null);
|
||||
assert.equal(camera.site.canonicalId, 'test-site');
|
||||
assert.equal(camera.group.canonicalId, 'entrances');
|
||||
assert.equal(camera.hierarchyStatus, 'inferred-site');
|
||||
assert.deepEqual(model.diagnostics, []);
|
||||
});
|
||||
|
||||
test('excludes cloud-native cameras while retaining Cloud Connector and unknown-storage devices', () => {
|
||||
const payload = projectDeviceHierarchy({
|
||||
devices: [
|
||||
rawDevice(10, { name: 'Cloud Native', capabilities: { localStorage: true } }),
|
||||
rawDevice(11, { name: 'Cloud Connector', capabilities: { localStorage: false } }),
|
||||
rawDevice(12, { name: 'Unknown Storage', capabilities: {} }),
|
||||
],
|
||||
});
|
||||
|
||||
assert.deepEqual(payload.devices.map((device) => device.name), ['Cloud Connector', 'Unknown Storage']);
|
||||
assert.deepEqual(payload.diagnostics.devices, {
|
||||
received: 3, eligible: 2, invalid: 0, cloudNativeExcluded: 1,
|
||||
});
|
||||
});
|
||||
|
||||
test('projects synthetic 1,500 and 10,000 camera deployments below the 8 MiB IPC cap', () => {
|
||||
for (const count of [1_500, 10_000]) {
|
||||
const payload = projectDeviceHierarchy({
|
||||
devices: Array.from({ length: count }, (_, index) => rawDevice(index)),
|
||||
devices: Array.from({ length: count }, (_, index) => rawDevice(index, {
|
||||
capabilities: { localStorage: false },
|
||||
})),
|
||||
sites: [],
|
||||
groups: [],
|
||||
});
|
||||
@@ -80,6 +124,7 @@ test('repairs lone UTF-16 surrogates without changing valid Unicode or hiding ca
|
||||
address: 'Hall \ud800\udc00 / \udc00',
|
||||
server_group_id: 'site-\ud800',
|
||||
device_group_id: 'group-\udc00',
|
||||
capabilities: { localStorage: false },
|
||||
})],
|
||||
sites: [{ id: 'site-\ud800', name: 'Valid \ud83d\udcf7 \udc00', pending_deletion_start: '\ud800' }],
|
||||
groups: [{ id: 'group-\udc00', name: 'Group \ud83d\udcf7 \ud800', parent_id: 'site-\ud800' }],
|
||||
@@ -90,7 +135,7 @@ test('repairs lone UTF-16 surrogates without changing valid Unicode or hiding ca
|
||||
assert.equal(payload.devices[0].name, 'Front \ufffd camera');
|
||||
assert.equal(payload.devices[0].model, 'Model \ufffd');
|
||||
assert.equal(payload.devices[0].address, 'Hall \ud800\udc00 / \ufffd');
|
||||
assert.equal(payload.devices[0].siteId, 'site-\ufffd');
|
||||
assert.equal(payload.devices[0].siteId, null);
|
||||
assert.equal(payload.devices[0].deviceGroupId, 'group-\ufffd');
|
||||
assert.deepEqual(payload.sites, [{ id: 'site-\ufffd', name: 'Valid \ud83d\udcf7 \ufffd', pendingDeletionStart: '\ufffd' }]);
|
||||
assert.deepEqual(payload.groups, [{ id: 'group-\ufffd', name: 'Group \ud83d\udcf7 \ufffd', parentId: 'site-\ufffd', pendingDeletionStart: null }]);
|
||||
@@ -101,6 +146,7 @@ test('repairs lone UTF-16 surrogates without changing valid Unicode or hiding ca
|
||||
test('rejects a projected hierarchy payload above 8 MiB', () => {
|
||||
const devices = Array.from({ length: 10_000 }, (_, index) => rawDevice(index, {
|
||||
name: `Camera ${index} ${'x'.repeat(900)}`,
|
||||
capabilities: { localStorage: false },
|
||||
}));
|
||||
assert.throws(
|
||||
() => projectDeviceHierarchy({ devices, sites: [], groups: [] }),
|
||||
|
||||
Reference in New Issue
Block a user