@zwave-js/cc 15.23.1 → 15.23.5
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.
- package/build/cjs/cc/NotificationCC.js +4 -0
- package/build/cjs/cc/NotificationCC.js.map +2 -2
- package/build/cjs/cc/UserCredentialCC._validateArgs.js +4 -4
- package/build/cjs/cc/UserCredentialCC._validateArgs.js.map +2 -2
- package/build/cjs/cc/UserCredentialCC.d.ts +75 -37
- package/build/cjs/cc/UserCredentialCC.js +212 -156
- package/build/cjs/cc/UserCredentialCC.js.map +3 -3
- package/build/cjs/cc/_CCValues.generated.d.ts +62 -6
- package/build/cjs/cc/_CCValues.generated.js +38 -6
- package/build/cjs/cc/_CCValues.generated.js.map +2 -2
- package/build/cjs/cc/index.d.ts +3 -3
- package/build/cjs/cc/index.js +6 -6
- package/build/cjs/cc/index.js.map +1 -1
- package/build/esm/cc/NotificationCC.d.ts.map +1 -1
- package/build/esm/cc/NotificationCC.js +6 -1
- package/build/esm/cc/NotificationCC.js.map +1 -1
- package/build/esm/cc/UserCredentialCC._validateArgs.js +4 -4
- package/build/esm/cc/UserCredentialCC._validateArgs.js.map +1 -1
- package/build/esm/cc/UserCredentialCC.d.ts +75 -37
- package/build/esm/cc/UserCredentialCC.d.ts.map +1 -1
- package/build/esm/cc/UserCredentialCC.js +247 -152
- package/build/esm/cc/UserCredentialCC.js.map +1 -1
- package/build/esm/cc/_CCValues.generated.d.ts +62 -6
- package/build/esm/cc/_CCValues.generated.d.ts.map +1 -1
- package/build/esm/cc/_CCValues.generated.js +41 -6
- package/build/esm/cc/_CCValues.generated.js.map +1 -1
- package/build/esm/cc/index.d.ts +3 -3
- package/build/esm/cc/index.d.ts.map +1 -1
- package/build/esm/cc/index.js +4 -4
- package/build/esm/cc/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -12,6 +12,18 @@ function credentialToLogString(credential) {
|
|
|
12
12
|
return "(empty)";
|
|
13
13
|
return "*".repeat(credential.length);
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns the canonical form of a credential for storage and reporting:
|
|
17
|
+
* text credentials (PIN codes, passwords) are returned as strings, binary
|
|
18
|
+
* credentials (biometric data, BLE/NFC/RFID identifiers, ...) as raw bytes.
|
|
19
|
+
*/
|
|
20
|
+
export function normalizeCredentialData(credentialType, credentialData) {
|
|
21
|
+
if (credentialType === UserCredentialType.PINCode
|
|
22
|
+
|| credentialType === UserCredentialType.Password) {
|
|
23
|
+
return credentialData.toString("utf8");
|
|
24
|
+
}
|
|
25
|
+
return credentialData;
|
|
26
|
+
}
|
|
15
27
|
import { UserCredentialCCValues } from "./_CCValues.generated.js";
|
|
16
28
|
export { UserCredentialCCValues };
|
|
17
29
|
// API class
|
|
@@ -196,6 +208,10 @@ let UserCredentialCCAPI = (() => {
|
|
|
196
208
|
return response?.keyLockerCapabilities;
|
|
197
209
|
}
|
|
198
210
|
// User Management
|
|
211
|
+
/**
|
|
212
|
+
* Applications should not use this method directly. Prefer the
|
|
213
|
+
* `endpoint.accessControl` API for managing users.
|
|
214
|
+
*/
|
|
199
215
|
async setUser(options) {
|
|
200
216
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.UserSet);
|
|
201
217
|
const cc = new UserCredentialCCUserSet({
|
|
@@ -205,6 +221,10 @@ let UserCredentialCCAPI = (() => {
|
|
|
205
221
|
});
|
|
206
222
|
return this.host.sendCommand(cc, this.commandOptions);
|
|
207
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Applications should not use this method directly. Prefer the
|
|
226
|
+
* `endpoint.accessControl` API for querying users.
|
|
227
|
+
*/
|
|
208
228
|
async getUser(userId) {
|
|
209
229
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.UserGet);
|
|
210
230
|
const cc = new UserCredentialCCUserGet({
|
|
@@ -212,23 +232,13 @@ let UserCredentialCCAPI = (() => {
|
|
|
212
232
|
endpointIndex: this.endpoint.index,
|
|
213
233
|
userId,
|
|
214
234
|
});
|
|
215
|
-
|
|
216
|
-
if (response) {
|
|
217
|
-
return pick(response, [
|
|
218
|
-
"nextUserId",
|
|
219
|
-
"modifierType",
|
|
220
|
-
"modifierNodeId",
|
|
221
|
-
"userId",
|
|
222
|
-
"userType",
|
|
223
|
-
"active",
|
|
224
|
-
"credentialRule",
|
|
225
|
-
"expiringTimeoutMinutes",
|
|
226
|
-
"nameEncoding",
|
|
227
|
-
"userName",
|
|
228
|
-
]);
|
|
229
|
-
}
|
|
235
|
+
return this.host.sendCommand(cc, this.commandOptions);
|
|
230
236
|
}
|
|
231
237
|
// Credential Management
|
|
238
|
+
/**
|
|
239
|
+
* Applications should not use this method directly. Prefer the
|
|
240
|
+
* `endpoint.accessControl` API for managing credentials.
|
|
241
|
+
*/
|
|
232
242
|
async setCredential(options) {
|
|
233
243
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.CredentialSet);
|
|
234
244
|
const cc = new UserCredentialCCCredentialSet({
|
|
@@ -238,6 +248,10 @@ let UserCredentialCCAPI = (() => {
|
|
|
238
248
|
});
|
|
239
249
|
return this.host.sendCommand(cc, this.commandOptions);
|
|
240
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* Applications should not use this method directly. Prefer the
|
|
253
|
+
* `endpoint.accessControl` API for querying credentials.
|
|
254
|
+
*/
|
|
241
255
|
async getCredential(userId, credentialType, credentialSlot) {
|
|
242
256
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.CredentialGet);
|
|
243
257
|
const cc = new UserCredentialCCCredentialGet({
|
|
@@ -247,24 +261,7 @@ let UserCredentialCCAPI = (() => {
|
|
|
247
261
|
credentialType,
|
|
248
262
|
credentialSlot,
|
|
249
263
|
});
|
|
250
|
-
|
|
251
|
-
if (response) {
|
|
252
|
-
return pick(response, [
|
|
253
|
-
// UserId, credential type and slot can be zero in the
|
|
254
|
-
// request to return the first credential, so we cannot
|
|
255
|
-
// simply omit them here
|
|
256
|
-
"userId",
|
|
257
|
-
"credentialType",
|
|
258
|
-
"credentialSlot",
|
|
259
|
-
"credentialReadBack",
|
|
260
|
-
"credentialLength",
|
|
261
|
-
"credentialData",
|
|
262
|
-
"modifierType",
|
|
263
|
-
"modifierNodeId",
|
|
264
|
-
"nextCredentialType",
|
|
265
|
-
"nextCredentialSlot",
|
|
266
|
-
]);
|
|
267
|
-
}
|
|
264
|
+
return this.host.sendCommand(cc, this.commandOptions);
|
|
268
265
|
}
|
|
269
266
|
async startCredentialLearn(options) {
|
|
270
267
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.CredentialLearnStart);
|
|
@@ -289,9 +286,13 @@ let UserCredentialCCAPI = (() => {
|
|
|
289
286
|
});
|
|
290
287
|
return this.host.sendCommand(cc, this.commandOptions);
|
|
291
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Applications should not use this method directly. Prefer the
|
|
291
|
+
* `endpoint.accessControl` API for reassigning credentials between users.
|
|
292
|
+
*/
|
|
292
293
|
async setUserCredentialAssociation(options) {
|
|
293
294
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.UserCredentialAssociationSet);
|
|
294
|
-
const cc = new
|
|
295
|
+
const cc = new UserCredentialCCAssociationSet({
|
|
295
296
|
nodeId: this.endpoint.nodeId,
|
|
296
297
|
endpointIndex: this.endpoint.index,
|
|
297
298
|
...options,
|
|
@@ -437,7 +438,7 @@ let UserCredentialCCAPI = (() => {
|
|
|
437
438
|
}
|
|
438
439
|
async sendUserCredentialAssociationReport(options) {
|
|
439
440
|
this.assertSupportsCommand(UserCredentialCommand, UserCredentialCommand.UserCredentialAssociationReport);
|
|
440
|
-
const cc = new
|
|
441
|
+
const cc = new UserCredentialCCAssociationReport({
|
|
441
442
|
nodeId: this.endpoint.nodeId,
|
|
442
443
|
endpointIndex: this.endpoint.index,
|
|
443
444
|
...options,
|
|
@@ -629,7 +630,7 @@ let UserCredentialCC = (() => {
|
|
|
629
630
|
}
|
|
630
631
|
}
|
|
631
632
|
previousUserId = currentUserId;
|
|
632
|
-
nextUserId = user.nextUserId;
|
|
633
|
+
nextUserId = user.nextUserId ?? 0;
|
|
633
634
|
} while (nextUserId > 0);
|
|
634
635
|
}
|
|
635
636
|
// After querying all users, save the checksum for the next refresh.
|
|
@@ -674,18 +675,18 @@ let UserCredentialCC = (() => {
|
|
|
674
675
|
this.removeValue(ctx, UserCredentialCCValues.userChecksum(userId));
|
|
675
676
|
// Remove all credential values for this user
|
|
676
677
|
const valueDB = this.getValueDB(ctx);
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
678
|
+
const credentialOwners = valueDB.findValues((vid) => UserCredentialCCValues.credentialOwner.is(vid)
|
|
679
|
+
&& vid.endpoint === this.endpointIndex);
|
|
680
|
+
for (const { endpoint, propertyKey, value } of credentialOwners) {
|
|
681
|
+
if (value !== userId)
|
|
682
|
+
continue;
|
|
683
|
+
const key = propertyKey;
|
|
684
|
+
const credentialType = key >>> 16;
|
|
685
|
+
const credentialSlot = key & 0xffff;
|
|
686
|
+
valueDB.removeValue(UserCredentialCCValues.credential(credentialType, credentialSlot).endpoint(endpoint));
|
|
687
|
+
valueDB.removeValue(UserCredentialCCValues.credentialOwner(credentialType, credentialSlot).endpoint(endpoint));
|
|
688
|
+
valueDB.removeValue(UserCredentialCCValues.credentialModifierType(credentialType, credentialSlot).endpoint(endpoint));
|
|
689
|
+
valueDB.removeValue(UserCredentialCCValues.credentialModifierNodeId(credentialType, credentialSlot).endpoint(endpoint));
|
|
689
690
|
}
|
|
690
691
|
}
|
|
691
692
|
async queryCredentialsForUser(ctx, api, nodeId, userId) {
|
|
@@ -701,8 +702,8 @@ let UserCredentialCC = (() => {
|
|
|
701
702
|
const cred = await api.getCredential(userId, nextCredType, nextCredSlot);
|
|
702
703
|
if (!cred?.credentialSlot)
|
|
703
704
|
break; // No credential found, stop iterating
|
|
704
|
-
nextCredType = cred.nextCredentialType;
|
|
705
|
-
nextCredSlot = cred.nextCredentialSlot;
|
|
705
|
+
nextCredType = cred.nextCredentialType ?? UserCredentialType.None;
|
|
706
|
+
nextCredSlot = cred.nextCredentialSlot ?? 0;
|
|
706
707
|
} while (nextCredType !== UserCredentialType.None || nextCredSlot !== 0);
|
|
707
708
|
}
|
|
708
709
|
static getSupportedUsersCached(ctx, endpoint) {
|
|
@@ -1139,8 +1140,17 @@ let UserCredentialCCKeyLockerCapabilitiesGet = (() => {
|
|
|
1139
1140
|
return UserCredentialCCKeyLockerCapabilitiesGet = _classThis;
|
|
1140
1141
|
})();
|
|
1141
1142
|
export { UserCredentialCCKeyLockerCapabilitiesGet };
|
|
1143
|
+
function testResponseForUserCredentialUserSet(sent, received) {
|
|
1144
|
+
// CC:0083.01.05.11.010, CC:0083.01.05.11.011, CC:0083.01.05.11.012,
|
|
1145
|
+
// CC:0083.01.05.11.013: UserSet MUST be answered by a UserReport.
|
|
1146
|
+
// Match any report type other than ResponseToGet. For Add/Modify/Delete
|
|
1147
|
+
// the report echoes the requested userId; for DeleteAll (userId 0) the
|
|
1148
|
+
// report contains userId 0.
|
|
1149
|
+
return (received.reportType !== UserCredentialUserReportType.ResponseToGet
|
|
1150
|
+
&& received.userId === sent.userId);
|
|
1151
|
+
}
|
|
1142
1152
|
let UserCredentialCCUserSet = (() => {
|
|
1143
|
-
let _classDecorators = [CCCommand(UserCredentialCommand.UserSet),
|
|
1153
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.UserSet), expectedCCResponse(() => UserCredentialCCUserReport, testResponseForUserCredentialUserSet)];
|
|
1144
1154
|
let _classDescriptor;
|
|
1145
1155
|
let _classExtraInitializers = [];
|
|
1146
1156
|
let _classThis;
|
|
@@ -1335,7 +1345,9 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1335
1345
|
constructor(options) {
|
|
1336
1346
|
super(options);
|
|
1337
1347
|
this.reportType = options.reportType;
|
|
1338
|
-
|
|
1348
|
+
if (options.reportType === UserCredentialUserReportType.ResponseToGet) {
|
|
1349
|
+
this.nextUserId = options.nextUserId;
|
|
1350
|
+
}
|
|
1339
1351
|
this.modifierType = options.modifierType;
|
|
1340
1352
|
this.modifierNodeId = options.modifierNodeId;
|
|
1341
1353
|
this.userId = options.userId;
|
|
@@ -1371,10 +1383,8 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1371
1383
|
.subarray(15, 15 + nameLength)
|
|
1372
1384
|
.toString("ascii");
|
|
1373
1385
|
}
|
|
1374
|
-
|
|
1386
|
+
const common = {
|
|
1375
1387
|
nodeId: ctx.sourceNodeId,
|
|
1376
|
-
reportType,
|
|
1377
|
-
nextUserId,
|
|
1378
1388
|
modifierType,
|
|
1379
1389
|
modifierNodeId,
|
|
1380
1390
|
userId,
|
|
@@ -1384,7 +1394,11 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1384
1394
|
expiringTimeoutMinutes,
|
|
1385
1395
|
nameEncoding,
|
|
1386
1396
|
userName,
|
|
1387
|
-
}
|
|
1397
|
+
};
|
|
1398
|
+
if (reportType === UserCredentialUserReportType.ResponseToGet) {
|
|
1399
|
+
return new this({ ...common, reportType, nextUserId });
|
|
1400
|
+
}
|
|
1401
|
+
return new this({ ...common, reportType });
|
|
1388
1402
|
}
|
|
1389
1403
|
reportType;
|
|
1390
1404
|
nextUserId;
|
|
@@ -1407,7 +1421,7 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1407
1421
|
}
|
|
1408
1422
|
this.payload = Bytes.alloc(15 + nameBuffer.length);
|
|
1409
1423
|
this.payload[0] = this.reportType;
|
|
1410
|
-
this.payload.writeUInt16BE(this.nextUserId, 1);
|
|
1424
|
+
this.payload.writeUInt16BE(this.nextUserId ?? 0, 1);
|
|
1411
1425
|
this.payload[3] = this.modifierType;
|
|
1412
1426
|
this.payload.writeUInt16BE(this.modifierNodeId, 4);
|
|
1413
1427
|
this.payload.writeUInt16BE(this.userId, 6);
|
|
@@ -1427,9 +1441,12 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1427
1441
|
return false;
|
|
1428
1442
|
if (this.userId === 0)
|
|
1429
1443
|
return true;
|
|
1430
|
-
//
|
|
1444
|
+
// A UserModifyRejectedLocationEmpty report means we have a stale cache
|
|
1445
|
+
// entry for a user that no longer exists on the device.
|
|
1431
1446
|
if (this.reportType
|
|
1432
|
-
=== UserCredentialUserReportType.UserDeleted
|
|
1447
|
+
=== UserCredentialUserReportType.UserDeleted
|
|
1448
|
+
|| this.reportType
|
|
1449
|
+
=== UserCredentialUserReportType.UserModifyRejectedLocationEmpty) {
|
|
1433
1450
|
// Remove all values for this user
|
|
1434
1451
|
const userId = this.userId;
|
|
1435
1452
|
this.removeValue(ctx, UserCredentialCCValues.userType(userId));
|
|
@@ -1441,12 +1458,16 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1441
1458
|
this.removeValue(ctx, UserCredentialCCValues.userModifierNodeId(userId));
|
|
1442
1459
|
return true;
|
|
1443
1460
|
}
|
|
1461
|
+
// A UserAddRejectedLocationOccupied report contains the data for the
|
|
1462
|
+
// existing user, so we can update our cache with the actual state.
|
|
1444
1463
|
if (this.reportType
|
|
1445
1464
|
!== UserCredentialUserReportType.ResponseToGet
|
|
1446
1465
|
&& this.reportType
|
|
1447
1466
|
!== UserCredentialUserReportType.UserAdded
|
|
1448
1467
|
&& this.reportType
|
|
1449
|
-
!== UserCredentialUserReportType.UserModified
|
|
1468
|
+
!== UserCredentialUserReportType.UserModified
|
|
1469
|
+
&& this.reportType
|
|
1470
|
+
!== UserCredentialUserReportType.UserAddRejectedLocationOccupied) {
|
|
1450
1471
|
return true;
|
|
1451
1472
|
}
|
|
1452
1473
|
const userId = this.userId;
|
|
@@ -1465,22 +1486,22 @@ let UserCredentialCCUserReport = (() => {
|
|
|
1465
1486
|
return true;
|
|
1466
1487
|
}
|
|
1467
1488
|
toLogEntry(ctx) {
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
message: {
|
|
1471
|
-
"report type": getEnumMemberName(UserCredentialUserReportType, this.reportType),
|
|
1472
|
-
"next user ID": this.nextUserId,
|
|
1473
|
-
"modifier type": getEnumMemberName(UserCredentialModifierType, this.modifierType),
|
|
1474
|
-
"modifier node id": this.modifierNodeId,
|
|
1475
|
-
"user ID": this.userId,
|
|
1476
|
-
"user type": getEnumMemberName(UserCredentialUserType, this.userType),
|
|
1477
|
-
active: this.active,
|
|
1478
|
-
"credential rule": getEnumMemberName(UserCredentialRule, this.credentialRule),
|
|
1479
|
-
"expiring timeout (minutes)": this.expiringTimeoutMinutes,
|
|
1480
|
-
"name encoding": getEnumMemberName(UserCredentialNameEncoding, this.nameEncoding),
|
|
1481
|
-
"user name": this.userName,
|
|
1482
|
-
},
|
|
1489
|
+
const message = {
|
|
1490
|
+
"report type": getEnumMemberName(UserCredentialUserReportType, this.reportType),
|
|
1483
1491
|
};
|
|
1492
|
+
if (this.nextUserId != undefined) {
|
|
1493
|
+
message["next user ID"] = this.nextUserId;
|
|
1494
|
+
}
|
|
1495
|
+
message["modifier type"] = getEnumMemberName(UserCredentialModifierType, this.modifierType);
|
|
1496
|
+
message["modifier node id"] = this.modifierNodeId;
|
|
1497
|
+
message["user ID"] = this.userId;
|
|
1498
|
+
message["user type"] = getEnumMemberName(UserCredentialUserType, this.userType);
|
|
1499
|
+
message.active = this.active;
|
|
1500
|
+
message["credential rule"] = getEnumMemberName(UserCredentialRule, this.credentialRule);
|
|
1501
|
+
message["expiring timeout (minutes)"] = this.expiringTimeoutMinutes;
|
|
1502
|
+
message["name encoding"] = getEnumMemberName(UserCredentialNameEncoding, this.nameEncoding);
|
|
1503
|
+
message["user name"] = this.userName;
|
|
1504
|
+
return { ...super.toLogEntry(ctx), message };
|
|
1484
1505
|
}
|
|
1485
1506
|
};
|
|
1486
1507
|
return UserCredentialCCUserReport = _classThis;
|
|
@@ -1535,8 +1556,30 @@ let UserCredentialCCUserGet = (() => {
|
|
|
1535
1556
|
return UserCredentialCCUserGet = _classThis;
|
|
1536
1557
|
})();
|
|
1537
1558
|
export { UserCredentialCCUserGet };
|
|
1559
|
+
function testResponseForUserCredentialCredentialSet(sent, received) {
|
|
1560
|
+
// CC:0083.01.0A.11.010, CC:0083.01.0A.11.011, CC:0083.01.0A.11.012,
|
|
1561
|
+
// CC:0083.01.0A.11.013: CredentialSet MUST be answered by a
|
|
1562
|
+
// CredentialReport. The credentialType is always echoed, so we use it
|
|
1563
|
+
// as the primary correlation. DuplicateCredential and DuplicateAdminPINCode
|
|
1564
|
+
// reports reference the EXISTING duplicate's (userId, slot) rather than
|
|
1565
|
+
// the requested location, so we cannot correlate them on slot.
|
|
1566
|
+
if (received.reportType
|
|
1567
|
+
=== UserCredentialCredentialReportType.ResponseToGet) {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
if (received.credentialType !== sent.credentialType) {
|
|
1571
|
+
return false;
|
|
1572
|
+
}
|
|
1573
|
+
if (received.reportType
|
|
1574
|
+
=== UserCredentialCredentialReportType.DuplicateCredential
|
|
1575
|
+
|| received.reportType
|
|
1576
|
+
=== UserCredentialCredentialReportType.DuplicateAdminPINCode) {
|
|
1577
|
+
return true;
|
|
1578
|
+
}
|
|
1579
|
+
return received.credentialSlot === sent.credentialSlot;
|
|
1580
|
+
}
|
|
1538
1581
|
let UserCredentialCCCredentialSet = (() => {
|
|
1539
|
-
let _classDecorators = [CCCommand(UserCredentialCommand.CredentialSet),
|
|
1582
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.CredentialSet), expectedCCResponse(() => UserCredentialCCCredentialReport, testResponseForUserCredentialCredentialSet)];
|
|
1540
1583
|
let _classDescriptor;
|
|
1541
1584
|
let _classExtraInitializers = [];
|
|
1542
1585
|
let _classThis;
|
|
@@ -1658,12 +1701,16 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1658
1701
|
this.credentialType = options.credentialType;
|
|
1659
1702
|
this.credentialSlot = options.credentialSlot;
|
|
1660
1703
|
this.credentialReadBack = options.credentialReadBack;
|
|
1661
|
-
|
|
1662
|
-
|
|
1704
|
+
if (options.credentialReadBack) {
|
|
1705
|
+
this.credentialData = options.credentialData;
|
|
1706
|
+
}
|
|
1663
1707
|
this.modifierType = options.modifierType;
|
|
1664
1708
|
this.modifierNodeId = options.modifierNodeId;
|
|
1665
|
-
|
|
1666
|
-
|
|
1709
|
+
if (options.reportType
|
|
1710
|
+
=== UserCredentialCredentialReportType.ResponseToGet) {
|
|
1711
|
+
this.nextCredentialType = options.nextCredentialType;
|
|
1712
|
+
this.nextCredentialSlot = options.nextCredentialSlot;
|
|
1713
|
+
}
|
|
1667
1714
|
}
|
|
1668
1715
|
static from(raw, ctx) {
|
|
1669
1716
|
validatePayload(raw.payload.length >= 8);
|
|
@@ -1674,25 +1721,36 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1674
1721
|
const credentialReadBack = !!(raw.payload[6] & 128);
|
|
1675
1722
|
const credentialLength = raw.payload[7];
|
|
1676
1723
|
validatePayload(raw.payload.length >= 8 + credentialLength + 6);
|
|
1677
|
-
const
|
|
1678
|
-
let offset = 8 + credentialLength;
|
|
1724
|
+
const offset = 8 + credentialLength;
|
|
1679
1725
|
const modifierType = raw.payload[offset];
|
|
1680
1726
|
const modifierNodeId = raw.payload.readUInt16BE(offset + 1);
|
|
1681
|
-
const
|
|
1682
|
-
const nextCredentialSlot = raw.payload.readUInt16BE(offset + 4);
|
|
1683
|
-
return new this({
|
|
1727
|
+
const common = {
|
|
1684
1728
|
nodeId: ctx.sourceNodeId,
|
|
1685
|
-
reportType,
|
|
1686
1729
|
userId,
|
|
1687
1730
|
credentialType,
|
|
1688
1731
|
credentialSlot,
|
|
1689
|
-
credentialReadBack,
|
|
1690
|
-
credentialLength,
|
|
1691
|
-
credentialData,
|
|
1692
1732
|
modifierType,
|
|
1693
1733
|
modifierNodeId,
|
|
1694
|
-
|
|
1695
|
-
|
|
1734
|
+
};
|
|
1735
|
+
const dataOptions = credentialReadBack
|
|
1736
|
+
? {
|
|
1737
|
+
credentialReadBack: true,
|
|
1738
|
+
credentialData: Bytes.from(raw.payload.subarray(8, 8 + credentialLength)),
|
|
1739
|
+
}
|
|
1740
|
+
: { credentialReadBack: false };
|
|
1741
|
+
if (reportType === UserCredentialCredentialReportType.ResponseToGet) {
|
|
1742
|
+
return new this({
|
|
1743
|
+
...common,
|
|
1744
|
+
...dataOptions,
|
|
1745
|
+
reportType,
|
|
1746
|
+
nextCredentialType: raw.payload[offset + 3],
|
|
1747
|
+
nextCredentialSlot: raw.payload.readUInt16BE(offset + 4),
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
return new this({
|
|
1751
|
+
...common,
|
|
1752
|
+
...dataOptions,
|
|
1753
|
+
reportType,
|
|
1696
1754
|
});
|
|
1697
1755
|
}
|
|
1698
1756
|
reportType;
|
|
@@ -1700,28 +1758,29 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1700
1758
|
credentialType;
|
|
1701
1759
|
credentialSlot;
|
|
1702
1760
|
credentialReadBack;
|
|
1703
|
-
credentialLength;
|
|
1704
1761
|
credentialData;
|
|
1705
1762
|
modifierType;
|
|
1706
1763
|
modifierNodeId;
|
|
1707
1764
|
nextCredentialType;
|
|
1708
1765
|
nextCredentialSlot;
|
|
1709
1766
|
serialize(ctx) {
|
|
1710
|
-
this.
|
|
1767
|
+
const credentialData = this.credentialData ?? new Bytes();
|
|
1768
|
+
this.payload = Bytes.alloc(14 + credentialData.length);
|
|
1711
1769
|
this.payload[0] = this.reportType;
|
|
1712
1770
|
this.payload.writeUInt16BE(this.userId, 1);
|
|
1713
1771
|
this.payload[3] = this.credentialType;
|
|
1714
1772
|
this.payload.writeUInt16BE(this.credentialSlot, 4);
|
|
1715
1773
|
this.payload[6] = this.credentialReadBack ? 0x80 : 0x00;
|
|
1716
|
-
this.payload[7] =
|
|
1717
|
-
if (
|
|
1718
|
-
this.payload.set(
|
|
1774
|
+
this.payload[7] = credentialData.length;
|
|
1775
|
+
if (credentialData.length > 0) {
|
|
1776
|
+
this.payload.set(credentialData, 8);
|
|
1719
1777
|
}
|
|
1720
|
-
|
|
1778
|
+
const offset = 8 + credentialData.length;
|
|
1721
1779
|
this.payload[offset] = this.modifierType;
|
|
1722
1780
|
this.payload.writeUInt16BE(this.modifierNodeId, offset + 1);
|
|
1723
|
-
this.payload[offset + 3] = this.nextCredentialType
|
|
1724
|
-
|
|
1781
|
+
this.payload[offset + 3] = this.nextCredentialType
|
|
1782
|
+
?? UserCredentialType.None;
|
|
1783
|
+
this.payload.writeUInt16BE(this.nextCredentialSlot ?? 0, offset + 4);
|
|
1725
1784
|
return super.serialize(ctx);
|
|
1726
1785
|
}
|
|
1727
1786
|
persistValues(ctx) {
|
|
@@ -1731,43 +1790,64 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1731
1790
|
|| this.credentialSlot === 0) {
|
|
1732
1791
|
return true;
|
|
1733
1792
|
}
|
|
1793
|
+
// A CredentialModifyRejectedLocationEmpty report means we have a stale
|
|
1794
|
+
// cache entry for a credential that no longer exists on the device.
|
|
1734
1795
|
if (this.reportType
|
|
1735
|
-
=== UserCredentialCredentialReportType.CredentialDeleted
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1796
|
+
=== UserCredentialCredentialReportType.CredentialDeleted
|
|
1797
|
+
|| this.reportType
|
|
1798
|
+
=== UserCredentialCredentialReportType
|
|
1799
|
+
.CredentialModifyRejectedLocationEmpty) {
|
|
1800
|
+
this.removeValue(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot));
|
|
1801
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot));
|
|
1802
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialModifierType(this.credentialType, this.credentialSlot));
|
|
1803
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialModifierNodeId(this.credentialType, this.credentialSlot));
|
|
1739
1804
|
return true;
|
|
1740
1805
|
}
|
|
1806
|
+
// A CredentialAddRejectedLocationOccupied report includes the actual
|
|
1807
|
+
// credential data in the read-back field when the device chooses to
|
|
1808
|
+
// reveal it, so we can update our cache with the real state.
|
|
1809
|
+
const isRejectionWithReadback = this.reportType
|
|
1810
|
+
=== UserCredentialCredentialReportType
|
|
1811
|
+
.CredentialAddRejectedLocationOccupied
|
|
1812
|
+
&& this.credentialReadBack;
|
|
1741
1813
|
if (this.reportType
|
|
1742
1814
|
!== UserCredentialCredentialReportType.ResponseToGet
|
|
1743
1815
|
&& this.reportType
|
|
1744
1816
|
!== UserCredentialCredentialReportType.CredentialAdded
|
|
1745
1817
|
&& this.reportType
|
|
1746
|
-
!== UserCredentialCredentialReportType.CredentialModified
|
|
1818
|
+
!== UserCredentialCredentialReportType.CredentialModified
|
|
1819
|
+
&& !isRejectionWithReadback) {
|
|
1747
1820
|
return true;
|
|
1748
1821
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1822
|
+
if (this.credentialData != undefined) {
|
|
1823
|
+
this.ensureMetadata(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot));
|
|
1824
|
+
this.setValue(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot), normalizeCredentialData(this.credentialType, this.credentialData));
|
|
1825
|
+
}
|
|
1826
|
+
this.setValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot), this.userId);
|
|
1827
|
+
this.setValue(ctx, UserCredentialCCValues.credentialModifierType(this.credentialType, this.credentialSlot), this.modifierType);
|
|
1828
|
+
this.setValue(ctx, UserCredentialCCValues.credentialModifierNodeId(this.credentialType, this.credentialSlot), this.modifierNodeId);
|
|
1753
1829
|
return true;
|
|
1754
1830
|
}
|
|
1755
1831
|
toLogEntry(ctx) {
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
"credential slot": this.credentialSlot,
|
|
1763
|
-
"credential read-back": this.credentialReadBack,
|
|
1764
|
-
"credential data": credentialToLogString(this.credentialData),
|
|
1765
|
-
"modifier type": getEnumMemberName(UserCredentialModifierType, this.modifierType),
|
|
1766
|
-
"modifier node id": this.modifierNodeId,
|
|
1767
|
-
"next credential type": getEnumMemberName(UserCredentialType, this.nextCredentialType),
|
|
1768
|
-
"next credential slot": this.nextCredentialSlot,
|
|
1769
|
-
},
|
|
1832
|
+
const message = {
|
|
1833
|
+
"report type": getEnumMemberName(UserCredentialCredentialReportType, this.reportType),
|
|
1834
|
+
"user ID": this.userId,
|
|
1835
|
+
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
1836
|
+
"credential slot": this.credentialSlot,
|
|
1837
|
+
"credential read-back": this.credentialReadBack,
|
|
1770
1838
|
};
|
|
1839
|
+
if (this.credentialData != undefined) {
|
|
1840
|
+
message["credential data"] = credentialToLogString(this.credentialData);
|
|
1841
|
+
}
|
|
1842
|
+
message["modifier type"] = getEnumMemberName(UserCredentialModifierType, this.modifierType);
|
|
1843
|
+
message["modifier node id"] = this.modifierNodeId;
|
|
1844
|
+
if (this.nextCredentialType != undefined) {
|
|
1845
|
+
message["next credential type"] = getEnumMemberName(UserCredentialType, this.nextCredentialType);
|
|
1846
|
+
}
|
|
1847
|
+
if (this.nextCredentialSlot != undefined) {
|
|
1848
|
+
message["next credential slot"] = this.nextCredentialSlot;
|
|
1849
|
+
}
|
|
1850
|
+
return { ...super.toLogEntry(ctx), message };
|
|
1771
1851
|
}
|
|
1772
1852
|
};
|
|
1773
1853
|
return UserCredentialCCCredentialReport = _classThis;
|
|
@@ -1992,18 +2072,18 @@ let UserCredentialCCCredentialLearnReport = (() => {
|
|
|
1992
2072
|
return UserCredentialCCCredentialLearnReport = _classThis;
|
|
1993
2073
|
})();
|
|
1994
2074
|
export { UserCredentialCCCredentialLearnReport };
|
|
1995
|
-
let
|
|
1996
|
-
let _classDecorators = [CCCommand(UserCredentialCommand.
|
|
2075
|
+
let UserCredentialCCAssociationReport = (() => {
|
|
2076
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.UserCredentialAssociationReport)];
|
|
1997
2077
|
let _classDescriptor;
|
|
1998
2078
|
let _classExtraInitializers = [];
|
|
1999
2079
|
let _classThis;
|
|
2000
2080
|
let _classSuper = UserCredentialCC;
|
|
2001
|
-
var
|
|
2081
|
+
var UserCredentialCCAssociationReport = class extends _classSuper {
|
|
2002
2082
|
static { _classThis = this; }
|
|
2003
2083
|
static {
|
|
2004
2084
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2005
2085
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2006
|
-
|
|
2086
|
+
UserCredentialCCAssociationReport = _classThis = _classDescriptor.value;
|
|
2007
2087
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2008
2088
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
2009
2089
|
}
|
|
@@ -2012,29 +2092,45 @@ let UserCredentialCCUserCredentialAssociationSet = (() => {
|
|
|
2012
2092
|
this.credentialType = options.credentialType;
|
|
2013
2093
|
this.credentialSlot = options.credentialSlot;
|
|
2014
2094
|
this.destinationUserId = options.destinationUserId;
|
|
2095
|
+
this.status = options.status;
|
|
2015
2096
|
}
|
|
2016
|
-
credentialType;
|
|
2017
|
-
credentialSlot;
|
|
2018
|
-
destinationUserId;
|
|
2019
2097
|
static from(raw, ctx) {
|
|
2020
|
-
validatePayload(raw.payload.length >=
|
|
2098
|
+
validatePayload(raw.payload.length >= 6);
|
|
2021
2099
|
const credentialType = raw.payload[0];
|
|
2022
2100
|
const credentialSlot = raw.payload.readUInt16BE(1);
|
|
2023
2101
|
const destinationUserId = raw.payload.readUInt16BE(3);
|
|
2102
|
+
const status = raw.payload[5];
|
|
2024
2103
|
return new this({
|
|
2025
2104
|
nodeId: ctx.sourceNodeId,
|
|
2026
2105
|
credentialType,
|
|
2027
2106
|
credentialSlot,
|
|
2028
|
-
destinationUserId,
|
|
2107
|
+
destinationUserId: destinationUserId,
|
|
2108
|
+
status,
|
|
2029
2109
|
});
|
|
2030
2110
|
}
|
|
2111
|
+
credentialType;
|
|
2112
|
+
credentialSlot;
|
|
2113
|
+
destinationUserId;
|
|
2114
|
+
status;
|
|
2031
2115
|
serialize(ctx) {
|
|
2032
|
-
this.payload = Bytes.alloc(
|
|
2116
|
+
this.payload = Bytes.alloc(6);
|
|
2033
2117
|
this.payload[0] = this.credentialType;
|
|
2034
2118
|
this.payload.writeUInt16BE(this.credentialSlot, 1);
|
|
2035
2119
|
this.payload.writeUInt16BE(this.destinationUserId, 3);
|
|
2120
|
+
this.payload[5] = this.status;
|
|
2036
2121
|
return super.serialize(ctx);
|
|
2037
2122
|
}
|
|
2123
|
+
persistValues(ctx) {
|
|
2124
|
+
if (!super.persistValues(ctx))
|
|
2125
|
+
return false;
|
|
2126
|
+
if (this.status !== 0
|
|
2127
|
+
|| this.credentialType === UserCredentialType.None
|
|
2128
|
+
|| this.credentialSlot === 0) {
|
|
2129
|
+
return true;
|
|
2130
|
+
}
|
|
2131
|
+
this.setValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot), this.destinationUserId);
|
|
2132
|
+
return true;
|
|
2133
|
+
}
|
|
2038
2134
|
toLogEntry(ctx) {
|
|
2039
2135
|
return {
|
|
2040
2136
|
...super.toLogEntry(ctx),
|
|
@@ -2042,25 +2138,30 @@ let UserCredentialCCUserCredentialAssociationSet = (() => {
|
|
|
2042
2138
|
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
2043
2139
|
"credential slot": this.credentialSlot,
|
|
2044
2140
|
"destination user ID": this.destinationUserId,
|
|
2141
|
+
status: this.status,
|
|
2045
2142
|
},
|
|
2046
2143
|
};
|
|
2047
2144
|
}
|
|
2048
2145
|
};
|
|
2049
|
-
return
|
|
2146
|
+
return UserCredentialCCAssociationReport = _classThis;
|
|
2050
2147
|
})();
|
|
2051
|
-
export {
|
|
2052
|
-
|
|
2053
|
-
|
|
2148
|
+
export { UserCredentialCCAssociationReport };
|
|
2149
|
+
function testResponseForUserCredentialAssociationSet(sent, received) {
|
|
2150
|
+
return (sent.credentialType === received.credentialType
|
|
2151
|
+
&& sent.credentialSlot === received.credentialSlot);
|
|
2152
|
+
}
|
|
2153
|
+
let UserCredentialCCAssociationSet = (() => {
|
|
2154
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.UserCredentialAssociationSet), expectedCCResponse(UserCredentialCCAssociationReport, testResponseForUserCredentialAssociationSet)];
|
|
2054
2155
|
let _classDescriptor;
|
|
2055
2156
|
let _classExtraInitializers = [];
|
|
2056
2157
|
let _classThis;
|
|
2057
2158
|
let _classSuper = UserCredentialCC;
|
|
2058
|
-
var
|
|
2159
|
+
var UserCredentialCCAssociationSet = class extends _classSuper {
|
|
2059
2160
|
static { _classThis = this; }
|
|
2060
2161
|
static {
|
|
2061
2162
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2062
2163
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2063
|
-
|
|
2164
|
+
UserCredentialCCAssociationSet = _classThis = _classDescriptor.value;
|
|
2064
2165
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2065
2166
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
2066
2167
|
}
|
|
@@ -2069,32 +2170,27 @@ let UserCredentialCCUserCredentialAssociationReport = (() => {
|
|
|
2069
2170
|
this.credentialType = options.credentialType;
|
|
2070
2171
|
this.credentialSlot = options.credentialSlot;
|
|
2071
2172
|
this.destinationUserId = options.destinationUserId;
|
|
2072
|
-
this.status = options.status;
|
|
2073
2173
|
}
|
|
2174
|
+
credentialType;
|
|
2175
|
+
credentialSlot;
|
|
2176
|
+
destinationUserId;
|
|
2074
2177
|
static from(raw, ctx) {
|
|
2075
|
-
validatePayload(raw.payload.length >=
|
|
2178
|
+
validatePayload(raw.payload.length >= 5);
|
|
2076
2179
|
const credentialType = raw.payload[0];
|
|
2077
2180
|
const credentialSlot = raw.payload.readUInt16BE(1);
|
|
2078
2181
|
const destinationUserId = raw.payload.readUInt16BE(3);
|
|
2079
|
-
const status = raw.payload[5];
|
|
2080
2182
|
return new this({
|
|
2081
2183
|
nodeId: ctx.sourceNodeId,
|
|
2082
2184
|
credentialType,
|
|
2083
2185
|
credentialSlot,
|
|
2084
|
-
destinationUserId
|
|
2085
|
-
status,
|
|
2186
|
+
destinationUserId,
|
|
2086
2187
|
});
|
|
2087
2188
|
}
|
|
2088
|
-
credentialType;
|
|
2089
|
-
credentialSlot;
|
|
2090
|
-
destinationUserId;
|
|
2091
|
-
status;
|
|
2092
2189
|
serialize(ctx) {
|
|
2093
|
-
this.payload = Bytes.alloc(
|
|
2190
|
+
this.payload = Bytes.alloc(5);
|
|
2094
2191
|
this.payload[0] = this.credentialType;
|
|
2095
2192
|
this.payload.writeUInt16BE(this.credentialSlot, 1);
|
|
2096
2193
|
this.payload.writeUInt16BE(this.destinationUserId, 3);
|
|
2097
|
-
this.payload[5] = this.status;
|
|
2098
2194
|
return super.serialize(ctx);
|
|
2099
2195
|
}
|
|
2100
2196
|
toLogEntry(ctx) {
|
|
@@ -2104,14 +2200,13 @@ let UserCredentialCCUserCredentialAssociationReport = (() => {
|
|
|
2104
2200
|
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
2105
2201
|
"credential slot": this.credentialSlot,
|
|
2106
2202
|
"destination user ID": this.destinationUserId,
|
|
2107
|
-
status: this.status,
|
|
2108
2203
|
},
|
|
2109
2204
|
};
|
|
2110
2205
|
}
|
|
2111
2206
|
};
|
|
2112
|
-
return
|
|
2207
|
+
return UserCredentialCCAssociationSet = _classThis;
|
|
2113
2208
|
})();
|
|
2114
|
-
export {
|
|
2209
|
+
export { UserCredentialCCAssociationSet };
|
|
2115
2210
|
let UserCredentialCCAllUsersChecksumReport = (() => {
|
|
2116
2211
|
let _classDecorators = [CCCommand(UserCredentialCommand.AllUsersChecksumReport)];
|
|
2117
2212
|
let _classDescriptor;
|