@iobroker/socket-classes 2.6.1 → 2.7.0

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.
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ var _a;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.SocketCommands = exports.COMMANDS_PERMISSIONS = void 0;
4
5
  const adapter_core_1 = require("@iobroker/adapter-core"); // Get common adapter utils
@@ -74,6 +75,11 @@ class SocketCommands {
74
75
  adapterName;
75
76
  _sendToHost;
76
77
  states;
78
+ /**
79
+ * Finish the authentication of a socket with an access token the client announced.
80
+ * Set by `SocketCommon`, which is the only one that knows how to calculate the ACL of a user.
81
+ */
82
+ authenticateSocket = null;
77
83
  constructor(adapter, updateSession, context) {
78
84
  this.adapter = adapter;
79
85
  this.#updateSession = updateSession || (() => true);
@@ -191,41 +197,41 @@ class SocketCommands {
191
197
  if (socket._acl?.user !== 'system.user.admin') {
192
198
  // type: file, object, state, other
193
199
  // operation: create, read, write, list, delete, sendto, execute, sendToHost, readLogs
194
- if (SocketCommands.COMMANDS_PERMISSIONS[_command]) {
200
+ if (_a.COMMANDS_PERMISSIONS[_command]) {
195
201
  // If permission required
196
- const commandType = SocketCommands.COMMANDS_PERMISSIONS[_command].type;
202
+ const commandType = _a.COMMANDS_PERMISSIONS[_command].type;
197
203
  if (commandType) {
198
204
  if (commandType === 'object') {
199
- const operation = SocketCommands.COMMANDS_PERMISSIONS[_command].operation;
205
+ const operation = _a.COMMANDS_PERMISSIONS[_command].operation;
200
206
  if (socket._acl?.object?.[operation]) {
201
207
  return true;
202
208
  }
203
209
  }
204
210
  else if (commandType === 'state') {
205
- const operation = SocketCommands.COMMANDS_PERMISSIONS[_command].operation;
211
+ const operation = _a.COMMANDS_PERMISSIONS[_command].operation;
206
212
  if (socket._acl?.state?.[operation]) {
207
213
  return true;
208
214
  }
209
215
  }
210
216
  else if (commandType === 'users') {
211
- const operation = SocketCommands.COMMANDS_PERMISSIONS[_command].operation;
217
+ const operation = _a.COMMANDS_PERMISSIONS[_command].operation;
212
218
  if (socket._acl?.users?.[operation]) {
213
219
  return true;
214
220
  }
215
221
  }
216
222
  else if (commandType === 'other') {
217
- const operation = SocketCommands.COMMANDS_PERMISSIONS[_command].operation;
223
+ const operation = _a.COMMANDS_PERMISSIONS[_command].operation;
218
224
  if (socket._acl?.other?.[operation]) {
219
225
  return true;
220
226
  }
221
227
  }
222
228
  else if (commandType === 'file') {
223
- const operation = SocketCommands.COMMANDS_PERMISSIONS[_command].operation;
229
+ const operation = _a.COMMANDS_PERMISSIONS[_command].operation;
224
230
  if (socket._acl?.file?.[operation]) {
225
231
  return true;
226
232
  }
227
233
  }
228
- this.adapter.log.warn(`No permission for "${socket._acl?.user}" to call ${_command}. Need "${commandType}"."${SocketCommands.COMMANDS_PERMISSIONS[_command].operation}"`);
234
+ this.adapter.log.warn(`No permission for "${socket._acl?.user}" to call ${_command}. Need "${commandType}"."${_a.COMMANDS_PERMISSIONS[_command].operation}"`);
229
235
  }
230
236
  else {
231
237
  return true;
@@ -235,19 +241,19 @@ class SocketCommands {
235
241
  this.adapter.log.warn(`No rule for command: ${_command}`);
236
242
  }
237
243
  if (typeof callback === 'function') {
238
- callback(SocketCommands.ERROR_PERMISSION);
244
+ callback(_a.ERROR_PERMISSION);
239
245
  }
240
246
  else {
241
- if (SocketCommands.COMMANDS_PERMISSIONS[_command]) {
242
- socket.emit(SocketCommands.ERROR_PERMISSION, {
247
+ if (_a.COMMANDS_PERMISSIONS[_command]) {
248
+ socket.emit(_a.ERROR_PERMISSION, {
243
249
  command,
244
- type: SocketCommands.COMMANDS_PERMISSIONS[_command].type,
245
- operation: SocketCommands.COMMANDS_PERMISSIONS[_command].operation,
250
+ type: _a.COMMANDS_PERMISSIONS[_command].type,
251
+ operation: _a.COMMANDS_PERMISSIONS[_command].operation,
246
252
  args,
247
253
  });
248
254
  }
249
255
  else {
250
- socket.emit(SocketCommands.ERROR_PERMISSION, { command: _command, args });
256
+ socket.emit(_a.ERROR_PERMISSION, { command: _command, args });
251
257
  }
252
258
  }
253
259
  return false;
@@ -283,17 +289,29 @@ class SocketCommands {
283
289
  }
284
290
  return false;
285
291
  }
292
+ /**
293
+ * The send options for a message triggered by this socket: the user it is sent on behalf of.
294
+ *
295
+ * Objects, states and files have always been read and written with `{ user }` so the database
296
+ * applies the ACLs of the logged-in user. A message had no such channel: the receiving instance saw
297
+ * `from` and nothing else, so every adapter reachable over `sendTo` had to act with its own rights,
298
+ * and could not tell one caller from another. The user travels with the message now, for the
299
+ * controller versions that support it - older ones ignore the option, so nothing breaks, but a
300
+ * receiver must treat `obj.user` as optional (`adapter.supportsFeature('ADAPTER_MESSAGE_USER_CONTEXT')`).
301
+ *
302
+ * @param socket the socket the command came in on
303
+ */
304
+ static sendOptionsOf(socket) {
305
+ const user = socket?._acl?.user;
306
+ return user ? { user } : undefined;
307
+ }
286
308
  publishInstanceMessage(socket, sourceInstance, messageType, data) {
287
309
  if (this.#clientSubscribes[socket.id]?.[sourceInstance]?.includes(messageType)) {
288
310
  socket.emit('im', messageType, sourceInstance, data);
289
311
  return true;
290
312
  }
291
313
  // inform instance about missing subscription
292
- this.adapter.sendTo(sourceInstance, 'clientSubscribeError', {
293
- type: messageType,
294
- sid: socket.id,
295
- reason: 'no one subscribed',
296
- });
314
+ this.adapter.sendTo(sourceInstance, 'clientSubscribeError', { type: messageType, sid: socket.id, reason: 'no one subscribed' }, undefined, _a.sendOptionsOf(socket));
297
315
  return false;
298
316
  }
299
317
  _showSubscribes(socket, type) {
@@ -545,7 +563,7 @@ class SocketCommands {
545
563
  return;
546
564
  }
547
565
  // inform all instances about disconnected socket, also if the socket has never subscribed to anything
548
- this.#informAboutDisconnect(socket.id);
566
+ this.#informAboutDisconnect(socket);
549
567
  if (!socket.subscribe) {
550
568
  return;
551
569
  }
@@ -743,6 +761,14 @@ class SocketCommands {
743
761
  * @param callback Callback `(isUserAuthenticated: boolean, isAuthenticationUsed: boolean) => void`
744
762
  */
745
763
  this.commands.authenticate = (socket, callback) => {
764
+ // Authentication is in use and the access token of this socket was not accepted. The client
765
+ // was asked to bring a new one and is fetching it right now, so the answer waits for that
766
+ // instead of starting the GUI on a socket that may do nothing.
767
+ if (socket._secure && !socket._acl?.user) {
768
+ this.adapter.log.debug(`${new Date().toISOString()} Request authenticate: waiting for the announced access token`);
769
+ socket._authPending = callback;
770
+ return;
771
+ }
746
772
  if (socket._acl?.user !== null) {
747
773
  this.adapter.log.debug(`${new Date().toISOString()} Request authenticate [${socket._acl?.user}]`);
748
774
  if (typeof callback === 'function') {
@@ -787,6 +813,13 @@ class SocketCommands {
787
813
  if (socket.conn.request.query?.token) {
788
814
  socket.conn.request.query.token = accessToken;
789
815
  }
816
+ // The socket was opened with a token the server did not accept, so it has no user
817
+ // yet. The announced token finishes the authentication, and the connection carries
818
+ // on instead of being thrown away and opened again with the next refresh token.
819
+ if (!socket._acl?.user && this.authenticateSocket) {
820
+ this.authenticateSocket(socket, token.user, token.aExp, success => callback(success ? null : 'Cannot authenticate the socket', success));
821
+ return;
822
+ }
790
823
  socket._sessionExpiresAt = token.aExp;
791
824
  socket.emit('tokenInfo', { expiresAt: token.aExp });
792
825
  callback(null, true);
@@ -839,18 +872,18 @@ class SocketCommands {
839
872
  */
840
873
  this.commands.checkFeatureSupported = (_socket, feature, callback) => {
841
874
  if (feature === 'INSTANCE_MESSAGES') {
842
- SocketCommands._fixCallback(callback, null, true);
875
+ _a._fixCallback(callback, null, true);
843
876
  }
844
877
  else if (feature === 'PARTIAL_OBJECT_TREE') {
845
- SocketCommands._fixCallback(callback, null, true);
878
+ _a._fixCallback(callback, null, true);
846
879
  }
847
880
  else if (feature === 'OBJECTS_COUNT') {
848
881
  // only the admin variant of these commands has it, and a client that asks must not
849
882
  // send a command that nobody answers - it would sit there until its timeout
850
- SocketCommands._fixCallback(callback, null, !!this.commands.getObjectsCount);
883
+ _a._fixCallback(callback, null, !!this.commands.getObjectsCount);
851
884
  }
852
885
  else {
853
- SocketCommands._fixCallback(callback, null, this.adapter.supportsFeature(feature));
886
+ _a._fixCallback(callback, null, this.adapter.supportsFeature(feature));
854
887
  }
855
888
  };
856
889
  /**
@@ -874,11 +907,11 @@ class SocketCommands {
874
907
  options.user = socket._acl?.user;
875
908
  options.aggregate ||= 'none';
876
909
  try {
877
- this.adapter.getHistory(id, options, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
910
+ this.adapter.getHistory(id, options, (error, ...args) => _a._fixCallback(callback, error, ...args));
878
911
  }
879
912
  catch (error) {
880
913
  this.adapter.log.error(`[getHistory] ERROR: ${error.toString()}`);
881
- SocketCommands._fixCallback(callback, error);
914
+ _a._fixCallback(callback, error);
882
915
  }
883
916
  }
884
917
  };
@@ -916,7 +949,7 @@ class SocketCommands {
916
949
  this.commands.sendTo = (socket, adapterInstance, command, message, callback) => {
917
950
  if (this._checkPermissions(socket, 'sendTo', callback, command)) {
918
951
  try {
919
- this.adapter.sendTo(adapterInstance, command, message, res => typeof callback === 'function' && setImmediate(() => callback(res)));
952
+ this.adapter.sendTo(adapterInstance, command, message, res => typeof callback === 'function' && setImmediate(() => callback(res)), _a.sendOptionsOf(socket));
920
953
  }
921
954
  catch (error) {
922
955
  if (typeof callback === 'function') {
@@ -951,7 +984,7 @@ class SocketCommands {
951
984
  * @param callback callback `(result: { error?: string; result?: any }) => void`
952
985
  */
953
986
  this.commands.sendToHost = (socket, host, command, message, callback) => {
954
- if (this._checkPermissions(socket, protectedCommands.includes(command) ? 'cmdExec' : 'sendToHost', (error) => callback({ error: error || SocketCommands.ERROR_PERMISSION }), command)) {
987
+ if (this._checkPermissions(socket, protectedCommands.includes(command) ? 'cmdExec' : 'sendToHost', (error) => callback({ error: error || _a.ERROR_PERMISSION }), command)) {
955
988
  // Try to decode this file locally as redis has a limitation for files bigger than 20MB
956
989
  if (command === 'writeDirAsZip' && message && message.data.length > 1024 * 1024) {
957
990
  let buffer;
@@ -982,7 +1015,10 @@ class SocketCommands {
982
1015
  }
983
1016
  else {
984
1017
  try {
985
- this.adapter.sendToHost(host, command, message, callback);
1018
+ // the 5th parameter exists from the controller version that reports
1019
+ // `ADAPTER_MESSAGE_USER_CONTEXT`; an older one ignores the extra argument
1020
+ const sendToHost = this.adapter.sendToHost;
1021
+ sendToHost.call(this.adapter, host, command, message, callback, _a.sendOptionsOf(socket));
986
1022
  }
987
1023
  catch (error) {
988
1024
  if (callback) {
@@ -1081,7 +1117,7 @@ class SocketCommands {
1081
1117
  */
1082
1118
  this.commands.listPermissions = (_socket, callback) => {
1083
1119
  if (typeof callback === 'function') {
1084
- callback(SocketCommands.COMMANDS_PERMISSIONS);
1120
+ callback(_a.COMMANDS_PERMISSIONS);
1085
1121
  }
1086
1122
  else {
1087
1123
  this.adapter.log.warn('[listPermissions] Invalid callback');
@@ -1153,11 +1189,11 @@ class SocketCommands {
1153
1189
  this.commands.readFile = (socket, adapter, fileName, callback) => {
1154
1190
  if (this._checkPermissions(socket, 'readFile', callback, fileName)) {
1155
1191
  try {
1156
- this.adapter.readFile(adapter, fileName, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1192
+ this.adapter.readFile(adapter, fileName, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1157
1193
  }
1158
1194
  catch (error) {
1159
1195
  this.adapter.log.error(`[readFile] ERROR: ${error.toString()}`);
1160
- SocketCommands._fixCallback(callback, error);
1196
+ _a._fixCallback(callback, error);
1161
1197
  }
1162
1198
  }
1163
1199
  };
@@ -1206,7 +1242,7 @@ class SocketCommands {
1206
1242
  }
1207
1243
  catch (error) {
1208
1244
  this.adapter.log.error(`[readFile64] ERROR: ${error.toString()}`);
1209
- SocketCommands._fixCallback(callback, error);
1245
+ _a._fixCallback(callback, error);
1210
1246
  }
1211
1247
  }
1212
1248
  };
@@ -1235,16 +1271,16 @@ class SocketCommands {
1235
1271
  }
1236
1272
  if (this._checkPermissions(socket, 'writeFile64', callback, fileName)) {
1237
1273
  if (!data64) {
1238
- return SocketCommands._fixCallback(callback, 'No data provided');
1274
+ return _a._fixCallback(callback, 'No data provided');
1239
1275
  }
1240
1276
  // Convert base 64 to buffer
1241
1277
  try {
1242
1278
  const buffer = Buffer.from(data64, 'base64');
1243
- this.adapter.writeFile(adapter, fileName, buffer, _options, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1279
+ this.adapter.writeFile(adapter, fileName, buffer, _options, (error, ...args) => _a._fixCallback(callback, error, ...args));
1244
1280
  }
1245
1281
  catch (error) {
1246
1282
  this.adapter.log.error(`[writeFile64] Cannot convert data: ${error.toString()}`);
1247
- SocketCommands._fixCallback(callback, `Cannot convert data: ${error.toString()}`);
1283
+ _a._fixCallback(callback, `Cannot convert data: ${error.toString()}`);
1248
1284
  }
1249
1285
  }
1250
1286
  };
@@ -1277,11 +1313,11 @@ class SocketCommands {
1277
1313
  }
1278
1314
  this.adapter.log.debug('writeFile deprecated. Please use writeFile64');
1279
1315
  try {
1280
- this.adapter.writeFile(adapter, fileName, data, _options, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1316
+ this.adapter.writeFile(adapter, fileName, data, _options, (error, ...args) => _a._fixCallback(callback, error, ...args));
1281
1317
  }
1282
1318
  catch (error) {
1283
1319
  this.adapter.log.error(`[writeFile] ERROR: ${error.toString()}`);
1284
- SocketCommands._fixCallback(callback, error);
1320
+ _a._fixCallback(callback, error);
1285
1321
  }
1286
1322
  }
1287
1323
  };
@@ -1298,12 +1334,12 @@ class SocketCommands {
1298
1334
  if (this._checkPermissions(socket, 'unlink', callback, name)) {
1299
1335
  try {
1300
1336
  this.#unlink(adapter, name, { user: socket._acl?.user })
1301
- .then(() => SocketCommands._fixCallback(callback, undefined))
1302
- .catch(error => SocketCommands._fixCallback(callback, error));
1337
+ .then(() => _a._fixCallback(callback, undefined))
1338
+ .catch(error => _a._fixCallback(callback, error));
1303
1339
  }
1304
1340
  catch (error) {
1305
1341
  this.adapter.log.error(`[unlink] ERROR: ${error.toString()}`);
1306
- SocketCommands._fixCallback(callback, error);
1342
+ _a._fixCallback(callback, error);
1307
1343
  }
1308
1344
  }
1309
1345
  };
@@ -1319,11 +1355,11 @@ class SocketCommands {
1319
1355
  this.commands.deleteFile = (socket, adapter, name, callback) => {
1320
1356
  if (this._checkPermissions(socket, 'unlink', callback, name)) {
1321
1357
  try {
1322
- this.adapter.unlink(adapter, name, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1358
+ this.adapter.unlink(adapter, name, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1323
1359
  }
1324
1360
  catch (error) {
1325
1361
  this.adapter.log.error(`[deleteFile] ERROR: ${error.toString()}`);
1326
- SocketCommands._fixCallback(callback, error);
1362
+ _a._fixCallback(callback, error);
1327
1363
  }
1328
1364
  }
1329
1365
  };
@@ -1340,12 +1376,12 @@ class SocketCommands {
1340
1376
  if (this._checkPermissions(socket, 'unlink', callback, name)) {
1341
1377
  try {
1342
1378
  this.#unlink(adapter, name, { user: socket._acl?.user })
1343
- .then(() => SocketCommands._fixCallback(callback, null))
1344
- .catch(error => SocketCommands._fixCallback(callback, error));
1379
+ .then(() => _a._fixCallback(callback, null))
1380
+ .catch(error => _a._fixCallback(callback, error));
1345
1381
  }
1346
1382
  catch (error) {
1347
1383
  this.adapter.log.error(`[deleteFolder] ERROR: ${error.toString()}`);
1348
- SocketCommands._fixCallback(callback, error);
1384
+ _a._fixCallback(callback, error);
1349
1385
  }
1350
1386
  }
1351
1387
  };
@@ -1362,11 +1398,11 @@ class SocketCommands {
1362
1398
  this.commands.renameFile = (socket, adapter, oldName, newName, callback) => {
1363
1399
  if (this._checkPermissions(socket, 'rename', callback, oldName)) {
1364
1400
  try {
1365
- this.adapter.rename(adapter, oldName, newName, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1401
+ this.adapter.rename(adapter, oldName, newName, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1366
1402
  }
1367
1403
  catch (error) {
1368
1404
  this.adapter.log.error(`[renameFile] ERROR: ${error.toString()}`);
1369
- SocketCommands._fixCallback(callback, error);
1405
+ _a._fixCallback(callback, error);
1370
1406
  }
1371
1407
  }
1372
1408
  };
@@ -1384,12 +1420,12 @@ class SocketCommands {
1384
1420
  if (this._checkPermissions(socket, 'rename', callback, oldName)) {
1385
1421
  try {
1386
1422
  this.#rename(adapter, oldName, newName, { user: socket._acl?.user })
1387
- .then(() => SocketCommands._fixCallback(callback, undefined))
1388
- .catch(error => SocketCommands._fixCallback(callback, error));
1423
+ .then(() => _a._fixCallback(callback, undefined))
1424
+ .catch(error => _a._fixCallback(callback, error));
1389
1425
  }
1390
1426
  catch (error) {
1391
1427
  this.adapter.log.error(`[rename] ERROR: ${error.toString()}`);
1392
- SocketCommands._fixCallback(callback, error);
1428
+ _a._fixCallback(callback, error);
1393
1429
  }
1394
1430
  }
1395
1431
  };
@@ -1405,11 +1441,11 @@ class SocketCommands {
1405
1441
  this.commands.mkdir = (socket, adapter, dirName, callback) => {
1406
1442
  if (this._checkPermissions(socket, 'mkdir', callback, dirName)) {
1407
1443
  try {
1408
- this.adapter.mkdir(adapter, dirName, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1444
+ this.adapter.mkdir(adapter, dirName, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1409
1445
  }
1410
1446
  catch (error) {
1411
1447
  this.adapter.log.error(`[mkdir] ERROR: ${error.toString()}`);
1412
- SocketCommands._fixCallback(callback, error);
1448
+ _a._fixCallback(callback, error);
1413
1449
  }
1414
1450
  }
1415
1451
  };
@@ -1429,11 +1465,11 @@ class SocketCommands {
1429
1465
  }
1430
1466
  if (this._checkPermissions(socket, 'readDir', callback, dirName)) {
1431
1467
  try {
1432
- this.adapter.readDir(adapter, dirName, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1468
+ this.adapter.readDir(adapter, dirName, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1433
1469
  }
1434
1470
  catch (error) {
1435
1471
  this.adapter.log.error(`[readDir] ERROR: ${error.toString()}`);
1436
- SocketCommands._fixCallback(callback, error);
1472
+ _a._fixCallback(callback, error);
1437
1473
  }
1438
1474
  }
1439
1475
  };
@@ -1455,16 +1491,16 @@ class SocketCommands {
1455
1491
  }
1456
1492
  else {
1457
1493
  this.adapter.log.error(`[chownFile] ERROR: no options`);
1458
- SocketCommands._fixCallback(callback, 'no options');
1494
+ _a._fixCallback(callback, 'no options');
1459
1495
  return;
1460
1496
  }
1461
1497
  if (this._checkPermissions(socket, 'chmodFile', callback, fileName)) {
1462
1498
  try {
1463
- this.adapter.chmodFile(adapter, fileName, _options, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1499
+ this.adapter.chmodFile(adapter, fileName, _options, (error, ...args) => _a._fixCallback(callback, error, ...args));
1464
1500
  }
1465
1501
  catch (error) {
1466
1502
  this.adapter.log.error(`[chmodFile] ERROR: ${error.toString()}`);
1467
- SocketCommands._fixCallback(callback, error);
1503
+ _a._fixCallback(callback, error);
1468
1504
  }
1469
1505
  }
1470
1506
  };
@@ -1487,16 +1523,16 @@ class SocketCommands {
1487
1523
  }
1488
1524
  else {
1489
1525
  this.adapter.log.error(`[chownFile] ERROR: no options`);
1490
- SocketCommands._fixCallback(callback, 'no options');
1526
+ _a._fixCallback(callback, 'no options');
1491
1527
  return;
1492
1528
  }
1493
1529
  if (this._checkPermissions(socket, 'chownFile', callback, fileName)) {
1494
1530
  try {
1495
- this.adapter.chownFile(adapter, fileName, _options, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1531
+ this.adapter.chownFile(adapter, fileName, _options, (error, ...args) => _a._fixCallback(callback, error, ...args));
1496
1532
  }
1497
1533
  catch (error) {
1498
1534
  this.adapter.log.error(`[chownFile] ERROR: ${error.toString()}`);
1499
- SocketCommands._fixCallback(callback, error);
1535
+ _a._fixCallback(callback, error);
1500
1536
  }
1501
1537
  }
1502
1538
  };
@@ -1512,11 +1548,11 @@ class SocketCommands {
1512
1548
  this.commands.fileExists = (socket, adapter, fileName, callback) => {
1513
1549
  if (this._checkPermissions(socket, 'fileExists', callback, fileName)) {
1514
1550
  try {
1515
- this.adapter.fileExists(adapter, fileName, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1551
+ this.adapter.fileExists(adapter, fileName, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1516
1552
  }
1517
1553
  catch (error) {
1518
1554
  this.adapter.log.error(`[fileExists] ERROR: ${error.toString()}`);
1519
- SocketCommands._fixCallback(callback, error);
1555
+ _a._fixCallback(callback, error);
1520
1556
  }
1521
1557
  }
1522
1558
  };
@@ -1583,7 +1619,7 @@ class SocketCommands {
1583
1619
  }
1584
1620
  catch (error) {
1585
1621
  this.adapter.log.error(`[getAdapterInstances] ERROR: ${error.toString()}`);
1586
- SocketCommands._fixCallback(callback, error);
1622
+ _a._fixCallback(callback, error);
1587
1623
  }
1588
1624
  }
1589
1625
  }
@@ -1607,11 +1643,11 @@ class SocketCommands {
1607
1643
  }
1608
1644
  if (typeof callback === 'function') {
1609
1645
  try {
1610
- this.adapter.getForeignStates(pattern || '*', { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1646
+ this.adapter.getForeignStates(pattern || '*', { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1611
1647
  }
1612
1648
  catch (error) {
1613
1649
  this.adapter.log.error(`[getStates] ERROR: ${error.toString()}`);
1614
- SocketCommands._fixCallback(callback, error);
1650
+ _a._fixCallback(callback, error);
1615
1651
  }
1616
1652
  }
1617
1653
  else {
@@ -1649,15 +1685,15 @@ class SocketCommands {
1649
1685
  try {
1650
1686
  void this.adapter
1651
1687
  .getForeignStateAsync(id, { user: socket._acl?.user })
1652
- .then(state => SocketCommands._fixCallback(callback, null, state))
1688
+ .then(state => _a._fixCallback(callback, null, state))
1653
1689
  .catch(error => {
1654
1690
  this.adapter.log.error(`[getState] ERROR: ${error.toString()}`);
1655
- SocketCommands._fixCallback(callback, error);
1691
+ _a._fixCallback(callback, error);
1656
1692
  });
1657
1693
  }
1658
1694
  catch (error) {
1659
1695
  this.adapter.log.error(`[getState] ERROR: ${error.toString()}`);
1660
- SocketCommands._fixCallback(callback, error);
1696
+ _a._fixCallback(callback, error);
1661
1697
  }
1662
1698
  }
1663
1699
  }
@@ -1685,11 +1721,11 @@ class SocketCommands {
1685
1721
  delete this.states[id];
1686
1722
  }
1687
1723
  try {
1688
- this.adapter.setForeignState(id, state, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
1724
+ this.adapter.setForeignState(id, state, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
1689
1725
  }
1690
1726
  catch (error) {
1691
1727
  this.adapter.log.error(`[setState] ERROR: ${error.toString()}`);
1692
- SocketCommands._fixCallback(callback, error);
1728
+ _a._fixCallback(callback, error);
1693
1729
  }
1694
1730
  }
1695
1731
  };
@@ -1790,12 +1826,12 @@ class SocketCommands {
1790
1826
  if (this.context.language && id === 'system.config' && obj?.common) {
1791
1827
  obj.common.language = this.context.language;
1792
1828
  }
1793
- SocketCommands._fixCallback(callback, error, obj);
1829
+ _a._fixCallback(callback, error, obj);
1794
1830
  });
1795
1831
  }
1796
1832
  catch (error) {
1797
1833
  this.adapter.log.error(`[getObject] ERROR: ${error.toString()}`);
1798
- SocketCommands._fixCallback(callback, error);
1834
+ _a._fixCallback(callback, error);
1799
1835
  }
1800
1836
  }
1801
1837
  };
@@ -1817,11 +1853,11 @@ class SocketCommands {
1817
1853
  if (this._checkPermissions(socket, 'getObject', callback)) {
1818
1854
  if (typeof callback === 'function') {
1819
1855
  try {
1820
- this.adapter.getForeignObjects(list, { user: socket._acl?.user }, (error, objs) => SocketCommands._fixCallback(callback, error, objs));
1856
+ this.adapter.getForeignObjects(list, { user: socket._acl?.user }, (error, objs) => _a._fixCallback(callback, error, objs));
1821
1857
  }
1822
1858
  catch (error) {
1823
1859
  this.adapter.log.error(`[getObjects] ERROR: ${error.toString()}`);
1824
- SocketCommands._fixCallback(callback, error);
1860
+ _a._fixCallback(callback, error);
1825
1861
  }
1826
1862
  }
1827
1863
  else {
@@ -1859,7 +1895,7 @@ class SocketCommands {
1859
1895
  if (this.context.language && result['system.config']?.common) {
1860
1896
  result['system.config'].common.language = this.context.language;
1861
1897
  }
1862
- SocketCommands._fixCallback(callback, error, result);
1898
+ _a._fixCallback(callback, error, result);
1863
1899
  });
1864
1900
  }
1865
1901
  else {
@@ -1868,7 +1904,7 @@ class SocketCommands {
1868
1904
  }
1869
1905
  catch (error) {
1870
1906
  this.adapter.log.error(`[getObjects] ERROR: ${error.toString()}`);
1871
- SocketCommands._fixCallback(callback, error);
1907
+ _a._fixCallback(callback, error);
1872
1908
  }
1873
1909
  }
1874
1910
  };
@@ -2025,7 +2061,7 @@ class SocketCommands {
2025
2061
  }
2026
2062
  catch (error) {
2027
2063
  this.adapter.log.error(`[getObjectView] ERROR: ${error.toString()}`);
2028
- SocketCommands._fixCallback(callback, error);
2064
+ _a._fixCallback(callback, error);
2029
2065
  }
2030
2066
  }
2031
2067
  }
@@ -2045,11 +2081,11 @@ class SocketCommands {
2045
2081
  this.commands.setObject = (socket, id, obj, callback) => {
2046
2082
  if (this._checkPermissions(socket, 'setObject', callback, id)) {
2047
2083
  try {
2048
- void this.adapter.setForeignObject(id, obj, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
2084
+ void this.adapter.setForeignObject(id, obj, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
2049
2085
  }
2050
2086
  catch (error) {
2051
2087
  this.adapter.log.error(`[setObject] ERROR: ${error.toString()}`);
2052
- SocketCommands._fixCallback(callback, error);
2088
+ _a._fixCallback(callback, error);
2053
2089
  }
2054
2090
  }
2055
2091
  };
@@ -2067,16 +2103,16 @@ class SocketCommands {
2067
2103
  if (id.startsWith('flot.') || id.startsWith('fullcalendar.')) {
2068
2104
  if (this._checkPermissions(socket, 'delObject', callback, id)) {
2069
2105
  try {
2070
- this.adapter.delForeignObject(id, { user: socket._acl?.user }, (error, ...args) => SocketCommands._fixCallback(callback, error, ...args));
2106
+ this.adapter.delForeignObject(id, { user: socket._acl?.user }, (error, ...args) => _a._fixCallback(callback, error, ...args));
2071
2107
  }
2072
2108
  catch (error) {
2073
2109
  this.adapter.log.error(`[delObject] ERROR: ${error.toString()}`);
2074
- SocketCommands._fixCallback(callback, error);
2110
+ _a._fixCallback(callback, error);
2075
2111
  }
2076
2112
  }
2077
2113
  }
2078
2114
  else {
2079
- SocketCommands._fixCallback(callback, SocketCommands.ERROR_PERMISSION);
2115
+ _a._fixCallback(callback, _a.ERROR_PERMISSION);
2080
2116
  }
2081
2117
  };
2082
2118
  /**
@@ -2111,7 +2147,7 @@ class SocketCommands {
2111
2147
  this.#clientSubscribes[sid][targetInstance].push(messageType);
2112
2148
  }
2113
2149
  // inform instance about new subscription
2114
- this.adapter.sendTo(targetInstance, 'clientSubscribe', { type: messageType, sid, data }, result => SocketCommands._fixCallback(callback, null, result));
2150
+ this.adapter.sendTo(targetInstance, 'clientSubscribe', { type: messageType, sid, data }, result => _a._fixCallback(callback, null, result), _a.sendOptionsOf(socket));
2115
2151
  };
2116
2152
  /**
2117
2153
  * #DOCUMENTATION commands
@@ -2137,16 +2173,12 @@ class SocketCommands {
2137
2173
  if (pos !== -1) {
2138
2174
  this.#clientSubscribes[sid][targetInstance].splice(pos, 1);
2139
2175
  // inform instance about unsubscription
2140
- this.adapter.sendTo(targetInstance, 'clientUnsubscribe', {
2141
- type: [messageType],
2142
- sid,
2143
- reason: 'client',
2144
- });
2145
- SocketCommands._fixCallback(callback, null, true);
2176
+ this.adapter.sendTo(targetInstance, 'clientUnsubscribe', { type: [messageType], sid, reason: 'client' }, undefined, _a.sendOptionsOf(socket));
2177
+ _a._fixCallback(callback, null, true);
2146
2178
  return;
2147
2179
  }
2148
2180
  }
2149
- SocketCommands._fixCallback(callback, null, false);
2181
+ _a._fixCallback(callback, null, false);
2150
2182
  };
2151
2183
  /**
2152
2184
  * #DOCUMENTATION commands
@@ -2170,7 +2202,7 @@ class SocketCommands {
2170
2202
  obj.native ||= {};
2171
2203
  obj.native.vendor = vendor;
2172
2204
  }
2173
- SocketCommands._fixCallback(callback, error, obj);
2205
+ _a._fixCallback(callback, error, obj);
2174
2206
  });
2175
2207
  }
2176
2208
  };
@@ -2182,15 +2214,26 @@ class SocketCommands {
2182
2214
  this._initCommandsStates();
2183
2215
  this._initCommandsFiles();
2184
2216
  }
2185
- #informAboutDisconnect(socketId) {
2217
+ /**
2218
+ * Tell every instance this socket had subscribed to that it is gone.
2219
+ *
2220
+ * Carries the user of the connection like the explicit `clientUnsubscribe` does: an instance that
2221
+ * keeps something per user - a recording, a session, a pending request - learns whose it was,
2222
+ * instead of only which socket id disappeared.
2223
+ *
2224
+ * @param socket the socket that went away
2225
+ */
2226
+ #informAboutDisconnect(socket) {
2227
+ const socketId = socket.id;
2186
2228
  // say to all instances that this socket was disconnected
2187
2229
  if (this.#clientSubscribes[socketId]) {
2230
+ const options = _a.sendOptionsOf(socket);
2188
2231
  Object.keys(this.#clientSubscribes[socketId]).forEach(targetInstance => {
2189
2232
  this.adapter.sendTo(targetInstance, 'clientUnsubscribe', {
2190
2233
  type: this.#clientSubscribes[socketId][targetInstance],
2191
2234
  sid: socketId,
2192
2235
  reason: 'disconnect',
2193
- });
2236
+ }, undefined, options);
2194
2237
  });
2195
2238
  delete this.#clientSubscribes[socketId];
2196
2239
  }
@@ -2200,7 +2243,7 @@ class SocketCommands {
2200
2243
  // Check if the authentication is still valid. Announcing a new access token is the only way
2201
2244
  // to make an expired session valid again, so that command must pass the check - otherwise
2202
2245
  // a client whose token has expired could never recover without reloading the page.
2203
- if (SocketCommands.COMMANDS_WITHOUT_SESSION_CHECK.includes(command) || this.#updateSession(socket)) {
2246
+ if (_a.COMMANDS_WITHOUT_SESSION_CHECK.includes(command) || this.#updateSession(socket)) {
2204
2247
  this.commands[command](socket, ...args);
2205
2248
  }
2206
2249
  else {
@@ -2216,4 +2259,5 @@ class SocketCommands {
2216
2259
  }
2217
2260
  }
2218
2261
  exports.SocketCommands = SocketCommands;
2262
+ _a = SocketCommands;
2219
2263
  //# sourceMappingURL=socketCommands.js.map