@zwave-js/cc 15.23.1 → 15.23.3
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 +203 -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 +237 -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,20 @@ 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. We correlate responses on the targeted (type, slot)
|
|
1563
|
+
// but not on userId, because rejection reports like DuplicateCredential
|
|
1564
|
+
// or WrongUserUniqueIdentifier may legitimately reference a different
|
|
1565
|
+
// user at the same credential location.
|
|
1566
|
+
return (received.reportType
|
|
1567
|
+
!== UserCredentialCredentialReportType.ResponseToGet
|
|
1568
|
+
&& received.credentialType === sent.credentialType
|
|
1569
|
+
&& received.credentialSlot === sent.credentialSlot);
|
|
1570
|
+
}
|
|
1538
1571
|
let UserCredentialCCCredentialSet = (() => {
|
|
1539
|
-
let _classDecorators = [CCCommand(UserCredentialCommand.CredentialSet),
|
|
1572
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.CredentialSet), expectedCCResponse(() => UserCredentialCCCredentialReport, testResponseForUserCredentialCredentialSet)];
|
|
1540
1573
|
let _classDescriptor;
|
|
1541
1574
|
let _classExtraInitializers = [];
|
|
1542
1575
|
let _classThis;
|
|
@@ -1658,12 +1691,16 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1658
1691
|
this.credentialType = options.credentialType;
|
|
1659
1692
|
this.credentialSlot = options.credentialSlot;
|
|
1660
1693
|
this.credentialReadBack = options.credentialReadBack;
|
|
1661
|
-
|
|
1662
|
-
|
|
1694
|
+
if (options.credentialReadBack) {
|
|
1695
|
+
this.credentialData = options.credentialData;
|
|
1696
|
+
}
|
|
1663
1697
|
this.modifierType = options.modifierType;
|
|
1664
1698
|
this.modifierNodeId = options.modifierNodeId;
|
|
1665
|
-
|
|
1666
|
-
|
|
1699
|
+
if (options.reportType
|
|
1700
|
+
=== UserCredentialCredentialReportType.ResponseToGet) {
|
|
1701
|
+
this.nextCredentialType = options.nextCredentialType;
|
|
1702
|
+
this.nextCredentialSlot = options.nextCredentialSlot;
|
|
1703
|
+
}
|
|
1667
1704
|
}
|
|
1668
1705
|
static from(raw, ctx) {
|
|
1669
1706
|
validatePayload(raw.payload.length >= 8);
|
|
@@ -1674,25 +1711,36 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1674
1711
|
const credentialReadBack = !!(raw.payload[6] & 128);
|
|
1675
1712
|
const credentialLength = raw.payload[7];
|
|
1676
1713
|
validatePayload(raw.payload.length >= 8 + credentialLength + 6);
|
|
1677
|
-
const
|
|
1678
|
-
let offset = 8 + credentialLength;
|
|
1714
|
+
const offset = 8 + credentialLength;
|
|
1679
1715
|
const modifierType = raw.payload[offset];
|
|
1680
1716
|
const modifierNodeId = raw.payload.readUInt16BE(offset + 1);
|
|
1681
|
-
const
|
|
1682
|
-
const nextCredentialSlot = raw.payload.readUInt16BE(offset + 4);
|
|
1683
|
-
return new this({
|
|
1717
|
+
const common = {
|
|
1684
1718
|
nodeId: ctx.sourceNodeId,
|
|
1685
|
-
reportType,
|
|
1686
1719
|
userId,
|
|
1687
1720
|
credentialType,
|
|
1688
1721
|
credentialSlot,
|
|
1689
|
-
credentialReadBack,
|
|
1690
|
-
credentialLength,
|
|
1691
|
-
credentialData,
|
|
1692
1722
|
modifierType,
|
|
1693
1723
|
modifierNodeId,
|
|
1694
|
-
|
|
1695
|
-
|
|
1724
|
+
};
|
|
1725
|
+
const dataOptions = credentialReadBack
|
|
1726
|
+
? {
|
|
1727
|
+
credentialReadBack: true,
|
|
1728
|
+
credentialData: Bytes.from(raw.payload.subarray(8, 8 + credentialLength)),
|
|
1729
|
+
}
|
|
1730
|
+
: { credentialReadBack: false };
|
|
1731
|
+
if (reportType === UserCredentialCredentialReportType.ResponseToGet) {
|
|
1732
|
+
return new this({
|
|
1733
|
+
...common,
|
|
1734
|
+
...dataOptions,
|
|
1735
|
+
reportType,
|
|
1736
|
+
nextCredentialType: raw.payload[offset + 3],
|
|
1737
|
+
nextCredentialSlot: raw.payload.readUInt16BE(offset + 4),
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
return new this({
|
|
1741
|
+
...common,
|
|
1742
|
+
...dataOptions,
|
|
1743
|
+
reportType,
|
|
1696
1744
|
});
|
|
1697
1745
|
}
|
|
1698
1746
|
reportType;
|
|
@@ -1700,28 +1748,29 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1700
1748
|
credentialType;
|
|
1701
1749
|
credentialSlot;
|
|
1702
1750
|
credentialReadBack;
|
|
1703
|
-
credentialLength;
|
|
1704
1751
|
credentialData;
|
|
1705
1752
|
modifierType;
|
|
1706
1753
|
modifierNodeId;
|
|
1707
1754
|
nextCredentialType;
|
|
1708
1755
|
nextCredentialSlot;
|
|
1709
1756
|
serialize(ctx) {
|
|
1710
|
-
this.
|
|
1757
|
+
const credentialData = this.credentialData ?? new Bytes();
|
|
1758
|
+
this.payload = Bytes.alloc(14 + credentialData.length);
|
|
1711
1759
|
this.payload[0] = this.reportType;
|
|
1712
1760
|
this.payload.writeUInt16BE(this.userId, 1);
|
|
1713
1761
|
this.payload[3] = this.credentialType;
|
|
1714
1762
|
this.payload.writeUInt16BE(this.credentialSlot, 4);
|
|
1715
1763
|
this.payload[6] = this.credentialReadBack ? 0x80 : 0x00;
|
|
1716
|
-
this.payload[7] =
|
|
1717
|
-
if (
|
|
1718
|
-
this.payload.set(
|
|
1764
|
+
this.payload[7] = credentialData.length;
|
|
1765
|
+
if (credentialData.length > 0) {
|
|
1766
|
+
this.payload.set(credentialData, 8);
|
|
1719
1767
|
}
|
|
1720
|
-
|
|
1768
|
+
const offset = 8 + credentialData.length;
|
|
1721
1769
|
this.payload[offset] = this.modifierType;
|
|
1722
1770
|
this.payload.writeUInt16BE(this.modifierNodeId, offset + 1);
|
|
1723
|
-
this.payload[offset + 3] = this.nextCredentialType
|
|
1724
|
-
|
|
1771
|
+
this.payload[offset + 3] = this.nextCredentialType
|
|
1772
|
+
?? UserCredentialType.None;
|
|
1773
|
+
this.payload.writeUInt16BE(this.nextCredentialSlot ?? 0, offset + 4);
|
|
1725
1774
|
return super.serialize(ctx);
|
|
1726
1775
|
}
|
|
1727
1776
|
persistValues(ctx) {
|
|
@@ -1731,43 +1780,64 @@ let UserCredentialCCCredentialReport = (() => {
|
|
|
1731
1780
|
|| this.credentialSlot === 0) {
|
|
1732
1781
|
return true;
|
|
1733
1782
|
}
|
|
1783
|
+
// A CredentialModifyRejectedLocationEmpty report means we have a stale
|
|
1784
|
+
// cache entry for a credential that no longer exists on the device.
|
|
1734
1785
|
if (this.reportType
|
|
1735
|
-
=== UserCredentialCredentialReportType.CredentialDeleted
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1786
|
+
=== UserCredentialCredentialReportType.CredentialDeleted
|
|
1787
|
+
|| this.reportType
|
|
1788
|
+
=== UserCredentialCredentialReportType
|
|
1789
|
+
.CredentialModifyRejectedLocationEmpty) {
|
|
1790
|
+
this.removeValue(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot));
|
|
1791
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot));
|
|
1792
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialModifierType(this.credentialType, this.credentialSlot));
|
|
1793
|
+
this.removeValue(ctx, UserCredentialCCValues.credentialModifierNodeId(this.credentialType, this.credentialSlot));
|
|
1739
1794
|
return true;
|
|
1740
1795
|
}
|
|
1796
|
+
// A CredentialAddRejectedLocationOccupied report includes the actual
|
|
1797
|
+
// credential data in the read-back field when the device chooses to
|
|
1798
|
+
// reveal it, so we can update our cache with the real state.
|
|
1799
|
+
const isRejectionWithReadback = this.reportType
|
|
1800
|
+
=== UserCredentialCredentialReportType
|
|
1801
|
+
.CredentialAddRejectedLocationOccupied
|
|
1802
|
+
&& this.credentialReadBack;
|
|
1741
1803
|
if (this.reportType
|
|
1742
1804
|
!== UserCredentialCredentialReportType.ResponseToGet
|
|
1743
1805
|
&& this.reportType
|
|
1744
1806
|
!== UserCredentialCredentialReportType.CredentialAdded
|
|
1745
1807
|
&& this.reportType
|
|
1746
|
-
!== UserCredentialCredentialReportType.CredentialModified
|
|
1808
|
+
!== UserCredentialCredentialReportType.CredentialModified
|
|
1809
|
+
&& !isRejectionWithReadback) {
|
|
1747
1810
|
return true;
|
|
1748
1811
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1812
|
+
if (this.credentialData != undefined) {
|
|
1813
|
+
this.ensureMetadata(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot));
|
|
1814
|
+
this.setValue(ctx, UserCredentialCCValues.credential(this.credentialType, this.credentialSlot), normalizeCredentialData(this.credentialType, this.credentialData));
|
|
1815
|
+
}
|
|
1816
|
+
this.setValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot), this.userId);
|
|
1817
|
+
this.setValue(ctx, UserCredentialCCValues.credentialModifierType(this.credentialType, this.credentialSlot), this.modifierType);
|
|
1818
|
+
this.setValue(ctx, UserCredentialCCValues.credentialModifierNodeId(this.credentialType, this.credentialSlot), this.modifierNodeId);
|
|
1753
1819
|
return true;
|
|
1754
1820
|
}
|
|
1755
1821
|
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
|
-
},
|
|
1822
|
+
const message = {
|
|
1823
|
+
"report type": getEnumMemberName(UserCredentialCredentialReportType, this.reportType),
|
|
1824
|
+
"user ID": this.userId,
|
|
1825
|
+
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
1826
|
+
"credential slot": this.credentialSlot,
|
|
1827
|
+
"credential read-back": this.credentialReadBack,
|
|
1770
1828
|
};
|
|
1829
|
+
if (this.credentialData != undefined) {
|
|
1830
|
+
message["credential data"] = credentialToLogString(this.credentialData);
|
|
1831
|
+
}
|
|
1832
|
+
message["modifier type"] = getEnumMemberName(UserCredentialModifierType, this.modifierType);
|
|
1833
|
+
message["modifier node id"] = this.modifierNodeId;
|
|
1834
|
+
if (this.nextCredentialType != undefined) {
|
|
1835
|
+
message["next credential type"] = getEnumMemberName(UserCredentialType, this.nextCredentialType);
|
|
1836
|
+
}
|
|
1837
|
+
if (this.nextCredentialSlot != undefined) {
|
|
1838
|
+
message["next credential slot"] = this.nextCredentialSlot;
|
|
1839
|
+
}
|
|
1840
|
+
return { ...super.toLogEntry(ctx), message };
|
|
1771
1841
|
}
|
|
1772
1842
|
};
|
|
1773
1843
|
return UserCredentialCCCredentialReport = _classThis;
|
|
@@ -1992,18 +2062,18 @@ let UserCredentialCCCredentialLearnReport = (() => {
|
|
|
1992
2062
|
return UserCredentialCCCredentialLearnReport = _classThis;
|
|
1993
2063
|
})();
|
|
1994
2064
|
export { UserCredentialCCCredentialLearnReport };
|
|
1995
|
-
let
|
|
1996
|
-
let _classDecorators = [CCCommand(UserCredentialCommand.
|
|
2065
|
+
let UserCredentialCCAssociationReport = (() => {
|
|
2066
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.UserCredentialAssociationReport)];
|
|
1997
2067
|
let _classDescriptor;
|
|
1998
2068
|
let _classExtraInitializers = [];
|
|
1999
2069
|
let _classThis;
|
|
2000
2070
|
let _classSuper = UserCredentialCC;
|
|
2001
|
-
var
|
|
2071
|
+
var UserCredentialCCAssociationReport = class extends _classSuper {
|
|
2002
2072
|
static { _classThis = this; }
|
|
2003
2073
|
static {
|
|
2004
2074
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2005
2075
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2006
|
-
|
|
2076
|
+
UserCredentialCCAssociationReport = _classThis = _classDescriptor.value;
|
|
2007
2077
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2008
2078
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
2009
2079
|
}
|
|
@@ -2012,29 +2082,45 @@ let UserCredentialCCUserCredentialAssociationSet = (() => {
|
|
|
2012
2082
|
this.credentialType = options.credentialType;
|
|
2013
2083
|
this.credentialSlot = options.credentialSlot;
|
|
2014
2084
|
this.destinationUserId = options.destinationUserId;
|
|
2085
|
+
this.status = options.status;
|
|
2015
2086
|
}
|
|
2016
|
-
credentialType;
|
|
2017
|
-
credentialSlot;
|
|
2018
|
-
destinationUserId;
|
|
2019
2087
|
static from(raw, ctx) {
|
|
2020
|
-
validatePayload(raw.payload.length >=
|
|
2088
|
+
validatePayload(raw.payload.length >= 6);
|
|
2021
2089
|
const credentialType = raw.payload[0];
|
|
2022
2090
|
const credentialSlot = raw.payload.readUInt16BE(1);
|
|
2023
2091
|
const destinationUserId = raw.payload.readUInt16BE(3);
|
|
2092
|
+
const status = raw.payload[5];
|
|
2024
2093
|
return new this({
|
|
2025
2094
|
nodeId: ctx.sourceNodeId,
|
|
2026
2095
|
credentialType,
|
|
2027
2096
|
credentialSlot,
|
|
2028
|
-
destinationUserId,
|
|
2097
|
+
destinationUserId: destinationUserId,
|
|
2098
|
+
status,
|
|
2029
2099
|
});
|
|
2030
2100
|
}
|
|
2101
|
+
credentialType;
|
|
2102
|
+
credentialSlot;
|
|
2103
|
+
destinationUserId;
|
|
2104
|
+
status;
|
|
2031
2105
|
serialize(ctx) {
|
|
2032
|
-
this.payload = Bytes.alloc(
|
|
2106
|
+
this.payload = Bytes.alloc(6);
|
|
2033
2107
|
this.payload[0] = this.credentialType;
|
|
2034
2108
|
this.payload.writeUInt16BE(this.credentialSlot, 1);
|
|
2035
2109
|
this.payload.writeUInt16BE(this.destinationUserId, 3);
|
|
2110
|
+
this.payload[5] = this.status;
|
|
2036
2111
|
return super.serialize(ctx);
|
|
2037
2112
|
}
|
|
2113
|
+
persistValues(ctx) {
|
|
2114
|
+
if (!super.persistValues(ctx))
|
|
2115
|
+
return false;
|
|
2116
|
+
if (this.status !== 0
|
|
2117
|
+
|| this.credentialType === UserCredentialType.None
|
|
2118
|
+
|| this.credentialSlot === 0) {
|
|
2119
|
+
return true;
|
|
2120
|
+
}
|
|
2121
|
+
this.setValue(ctx, UserCredentialCCValues.credentialOwner(this.credentialType, this.credentialSlot), this.destinationUserId);
|
|
2122
|
+
return true;
|
|
2123
|
+
}
|
|
2038
2124
|
toLogEntry(ctx) {
|
|
2039
2125
|
return {
|
|
2040
2126
|
...super.toLogEntry(ctx),
|
|
@@ -2042,25 +2128,30 @@ let UserCredentialCCUserCredentialAssociationSet = (() => {
|
|
|
2042
2128
|
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
2043
2129
|
"credential slot": this.credentialSlot,
|
|
2044
2130
|
"destination user ID": this.destinationUserId,
|
|
2131
|
+
status: this.status,
|
|
2045
2132
|
},
|
|
2046
2133
|
};
|
|
2047
2134
|
}
|
|
2048
2135
|
};
|
|
2049
|
-
return
|
|
2136
|
+
return UserCredentialCCAssociationReport = _classThis;
|
|
2050
2137
|
})();
|
|
2051
|
-
export {
|
|
2052
|
-
|
|
2053
|
-
|
|
2138
|
+
export { UserCredentialCCAssociationReport };
|
|
2139
|
+
function testResponseForUserCredentialAssociationSet(sent, received) {
|
|
2140
|
+
return (sent.credentialType === received.credentialType
|
|
2141
|
+
&& sent.credentialSlot === received.credentialSlot);
|
|
2142
|
+
}
|
|
2143
|
+
let UserCredentialCCAssociationSet = (() => {
|
|
2144
|
+
let _classDecorators = [CCCommand(UserCredentialCommand.UserCredentialAssociationSet), expectedCCResponse(UserCredentialCCAssociationReport, testResponseForUserCredentialAssociationSet)];
|
|
2054
2145
|
let _classDescriptor;
|
|
2055
2146
|
let _classExtraInitializers = [];
|
|
2056
2147
|
let _classThis;
|
|
2057
2148
|
let _classSuper = UserCredentialCC;
|
|
2058
|
-
var
|
|
2149
|
+
var UserCredentialCCAssociationSet = class extends _classSuper {
|
|
2059
2150
|
static { _classThis = this; }
|
|
2060
2151
|
static {
|
|
2061
2152
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2062
2153
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2063
|
-
|
|
2154
|
+
UserCredentialCCAssociationSet = _classThis = _classDescriptor.value;
|
|
2064
2155
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2065
2156
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
2066
2157
|
}
|
|
@@ -2069,32 +2160,27 @@ let UserCredentialCCUserCredentialAssociationReport = (() => {
|
|
|
2069
2160
|
this.credentialType = options.credentialType;
|
|
2070
2161
|
this.credentialSlot = options.credentialSlot;
|
|
2071
2162
|
this.destinationUserId = options.destinationUserId;
|
|
2072
|
-
this.status = options.status;
|
|
2073
2163
|
}
|
|
2164
|
+
credentialType;
|
|
2165
|
+
credentialSlot;
|
|
2166
|
+
destinationUserId;
|
|
2074
2167
|
static from(raw, ctx) {
|
|
2075
|
-
validatePayload(raw.payload.length >=
|
|
2168
|
+
validatePayload(raw.payload.length >= 5);
|
|
2076
2169
|
const credentialType = raw.payload[0];
|
|
2077
2170
|
const credentialSlot = raw.payload.readUInt16BE(1);
|
|
2078
2171
|
const destinationUserId = raw.payload.readUInt16BE(3);
|
|
2079
|
-
const status = raw.payload[5];
|
|
2080
2172
|
return new this({
|
|
2081
2173
|
nodeId: ctx.sourceNodeId,
|
|
2082
2174
|
credentialType,
|
|
2083
2175
|
credentialSlot,
|
|
2084
|
-
destinationUserId
|
|
2085
|
-
status,
|
|
2176
|
+
destinationUserId,
|
|
2086
2177
|
});
|
|
2087
2178
|
}
|
|
2088
|
-
credentialType;
|
|
2089
|
-
credentialSlot;
|
|
2090
|
-
destinationUserId;
|
|
2091
|
-
status;
|
|
2092
2179
|
serialize(ctx) {
|
|
2093
|
-
this.payload = Bytes.alloc(
|
|
2180
|
+
this.payload = Bytes.alloc(5);
|
|
2094
2181
|
this.payload[0] = this.credentialType;
|
|
2095
2182
|
this.payload.writeUInt16BE(this.credentialSlot, 1);
|
|
2096
2183
|
this.payload.writeUInt16BE(this.destinationUserId, 3);
|
|
2097
|
-
this.payload[5] = this.status;
|
|
2098
2184
|
return super.serialize(ctx);
|
|
2099
2185
|
}
|
|
2100
2186
|
toLogEntry(ctx) {
|
|
@@ -2104,14 +2190,13 @@ let UserCredentialCCUserCredentialAssociationReport = (() => {
|
|
|
2104
2190
|
"credential type": getEnumMemberName(UserCredentialType, this.credentialType),
|
|
2105
2191
|
"credential slot": this.credentialSlot,
|
|
2106
2192
|
"destination user ID": this.destinationUserId,
|
|
2107
|
-
status: this.status,
|
|
2108
2193
|
},
|
|
2109
2194
|
};
|
|
2110
2195
|
}
|
|
2111
2196
|
};
|
|
2112
|
-
return
|
|
2197
|
+
return UserCredentialCCAssociationSet = _classThis;
|
|
2113
2198
|
})();
|
|
2114
|
-
export {
|
|
2199
|
+
export { UserCredentialCCAssociationSet };
|
|
2115
2200
|
let UserCredentialCCAllUsersChecksumReport = (() => {
|
|
2116
2201
|
let _classDecorators = [CCCommand(UserCredentialCommand.AllUsersChecksumReport)];
|
|
2117
2202
|
let _classDescriptor;
|