@iobroker/socket-classes 1.6.1 → 2.0.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.
- package/LICENSE +1 -1
- package/README.md +840 -821
- package/dist/index.d.ts +7 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/passportSocket.d.ts +37 -0
- package/{lib → dist/lib}/passportSocket.js +25 -42
- package/dist/lib/passportSocket.js.map +1 -0
- package/dist/lib/socketCommands.d.ts +83 -0
- package/dist/lib/socketCommands.js +2024 -0
- package/dist/lib/socketCommands.js.map +1 -0
- package/dist/lib/socketCommandsAdmin.d.ts +139 -0
- package/dist/lib/socketCommandsAdmin.js +1584 -0
- package/dist/lib/socketCommandsAdmin.js.map +1 -0
- package/dist/lib/socketCommon.d.ts +141 -0
- package/dist/lib/socketCommon.js +496 -0
- package/dist/lib/socketCommon.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/package.json +24 -18
- package/index.js +0 -19
- package/lib/socketAdmin.js +0 -201
- package/lib/socketCommands.js +0 -1884
- package/lib/socketCommandsAdmin.js +0 -1492
- package/lib/socketCommon.js +0 -480
|
@@ -1,1492 +0,0 @@
|
|
|
1
|
-
const SocketCommands = require('./socketCommands');
|
|
2
|
-
const axios = require('axios');
|
|
3
|
-
const path = require('node:path');
|
|
4
|
-
const fs = require('node:fs');
|
|
5
|
-
|
|
6
|
-
class SocketCommandsAdmin extends SocketCommands {
|
|
7
|
-
static ALLOW_CACHE = [
|
|
8
|
-
'getRepository',
|
|
9
|
-
'getInstalled',
|
|
10
|
-
'getInstalledAdapter',
|
|
11
|
-
'getVersion',
|
|
12
|
-
'getDiagData',
|
|
13
|
-
'getLocationOnDisk',
|
|
14
|
-
'getDevList',
|
|
15
|
-
'getLogs',
|
|
16
|
-
'getHostInfo'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
constructor(adapter, updateSession, objects, states) {
|
|
20
|
-
super(adapter, updateSession);
|
|
21
|
-
|
|
22
|
-
this.objects = objects;
|
|
23
|
-
this.states = states;
|
|
24
|
-
|
|
25
|
-
this.thersholdInterval = null;
|
|
26
|
-
this.cmdSessions = {};
|
|
27
|
-
|
|
28
|
-
this.eventsThreshold = {
|
|
29
|
-
count: 0,
|
|
30
|
-
timeActivated: 0,
|
|
31
|
-
active: false,
|
|
32
|
-
accidents: 0,
|
|
33
|
-
repeatSeconds: 3, // how many seconds continuously must be number of events > value
|
|
34
|
-
value: parseInt(adapter.config.thresholdValue, 10) || 200, // how many events allowed in one check interval
|
|
35
|
-
checkInterval: 1000 // duration of one check interval
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
this.cache = {};
|
|
39
|
-
this.cacheGB = null; // cache garbage collector
|
|
40
|
-
// do not send too many state updates
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
start(onThresholdChanged) {
|
|
44
|
-
// detect event bursts
|
|
45
|
-
this.thersholdInterval = setInterval(() => {
|
|
46
|
-
if (!this.eventsThreshold.active) {
|
|
47
|
-
if (this.eventsThreshold.count > this.eventsThreshold.value) {
|
|
48
|
-
this.eventsThreshold.accidents++;
|
|
49
|
-
|
|
50
|
-
if (this.eventsThreshold.accidents >= this.eventsThreshold.repeatSeconds) {
|
|
51
|
-
this._enableEventThreshold();
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
this.eventsThreshold.accidents = 0;
|
|
55
|
-
}
|
|
56
|
-
this.eventsThreshold.count = 0;
|
|
57
|
-
} else if (Date.now() - this.eventsThreshold.timeActivated > 60000) {
|
|
58
|
-
this.disableEventThreshold();
|
|
59
|
-
}
|
|
60
|
-
}, this.eventsThreshold.checkInterval);
|
|
61
|
-
|
|
62
|
-
this.onThresholdChanged = onThresholdChanged;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async updateRatings(uuid) {
|
|
66
|
-
if (!uuid) {
|
|
67
|
-
const obj = await this.adapter.getForeignObjectAsync('system.meta.uuid');
|
|
68
|
-
uuid = obj.native.uuid;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
const response = await axios.get(`https://rating.iobroker.net/rating?uuid=${uuid}`, {
|
|
73
|
-
timeout: 15000,
|
|
74
|
-
validateStatus: status => status < 400
|
|
75
|
-
});
|
|
76
|
-
this.adapter._ratings = response.data;
|
|
77
|
-
if (
|
|
78
|
-
!this.adapter._ratings ||
|
|
79
|
-
typeof this.adapter._ratings !== 'object' ||
|
|
80
|
-
Array.isArray(this.adapter._ratings)
|
|
81
|
-
) {
|
|
82
|
-
this.adapter._ratings = {};
|
|
83
|
-
}
|
|
84
|
-
this.adapter._ratings.uuid = uuid;
|
|
85
|
-
|
|
86
|
-
// auto update only in admin
|
|
87
|
-
if (this.adapter.name === 'admin') {
|
|
88
|
-
this.adapter.ratingTimeout && clearTimeout(this.adapter.ratingTimeout);
|
|
89
|
-
this.adapter.ratingTimeout = setTimeout(() => {
|
|
90
|
-
this.adapter.ratingTimeout = null;
|
|
91
|
-
this.updateRatings(uuid, true).then(() => this.adapter.log.info('Adapter rating updated'));
|
|
92
|
-
}, 24 * 3600000);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return this.adapter._ratings;
|
|
96
|
-
} catch (error) {
|
|
97
|
-
this.adapter.log.warn(
|
|
98
|
-
`Cannot update rating: ${error.response ? error.response.data : error.message || error.code}`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
_readInstanceConfig(id, user, isTab, configs) {
|
|
104
|
-
return new Promise(resolve =>
|
|
105
|
-
this.adapter.getForeignObject(`system.adapter.${id}`, { user }, (error, obj) => {
|
|
106
|
-
if (obj && obj.common) {
|
|
107
|
-
const instance = id.split('.').pop();
|
|
108
|
-
const config = {
|
|
109
|
-
id,
|
|
110
|
-
title: obj.common.titleLang || obj.common.title,
|
|
111
|
-
desc: obj.common.desc,
|
|
112
|
-
color: obj.common.color,
|
|
113
|
-
url: `/adapter/${obj.common.name}/${isTab ? 'tab' : 'index'}${
|
|
114
|
-
!isTab && obj.common.materialize ? '_m' : ''
|
|
115
|
-
}.html${instance ? `?${instance}` : ''}`,
|
|
116
|
-
icon: obj.common.icon,
|
|
117
|
-
materialize: obj.common.materialize,
|
|
118
|
-
jsonConfig: obj.common.jsonConfig,
|
|
119
|
-
version: obj.common.version
|
|
120
|
-
};
|
|
121
|
-
if (isTab) {
|
|
122
|
-
config.tab = true;
|
|
123
|
-
} else {
|
|
124
|
-
config.config = true;
|
|
125
|
-
}
|
|
126
|
-
/*if (typeof config.title === 'object') {
|
|
127
|
-
config.title = config.title[adapter.systemConfig.language] || config.title.en;
|
|
128
|
-
}
|
|
129
|
-
if (typeof config.desc === 'object') {
|
|
130
|
-
config.desc = config.desc[adapter.systemConfig.language] || config.desc.en;
|
|
131
|
-
}*/
|
|
132
|
-
configs.push(config);
|
|
133
|
-
}
|
|
134
|
-
resolve();
|
|
135
|
-
})
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
_sendToHost(host, command, message, callback) {
|
|
140
|
-
const hash = `${host}_${command}`;
|
|
141
|
-
if (!message && SocketCommandsAdmin.ALLOW_CACHE.includes(command) && this.cache[hash]) {
|
|
142
|
-
if (Date.now() - this.cache[hash].ts < 500) {
|
|
143
|
-
return (
|
|
144
|
-
typeof callback === 'function' &&
|
|
145
|
-
setImmediate(data => callback(data), JSON.parse(this.cache[hash].res))
|
|
146
|
-
);
|
|
147
|
-
} else {
|
|
148
|
-
delete this.cache[hash];
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
this.adapter.sendToHost(host, command, message, res => {
|
|
154
|
-
if (!message && SocketCommandsAdmin.ALLOW_CACHE.includes(command)) {
|
|
155
|
-
this.cache[hash] = { ts: Date.now(), res: JSON.stringify(res) };
|
|
156
|
-
|
|
157
|
-
this.cacheGB =
|
|
158
|
-
this.cacheGB ||
|
|
159
|
-
setInterval(() => {
|
|
160
|
-
const commands = Object.keys(this.cache);
|
|
161
|
-
commands.forEach(cmd => {
|
|
162
|
-
if (Date.now() - this.cache[cmd].ts > 500) {
|
|
163
|
-
delete this.cache[cmd];
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
if (!commands.length) {
|
|
167
|
-
clearInterval(this.cacheGB);
|
|
168
|
-
this.cacheGB = null;
|
|
169
|
-
}
|
|
170
|
-
}, 2000);
|
|
171
|
-
}
|
|
172
|
-
typeof callback === 'function' && setImmediate(() => callback(res));
|
|
173
|
-
});
|
|
174
|
-
} catch (error) {
|
|
175
|
-
this.adapter.log.error(`[sendToHost] ERROR: ${error.toString()}`);
|
|
176
|
-
typeof callback === 'function' && setImmediate(() => callback({ error }));
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// remove this function when js.controller 4.x will be mainstream
|
|
181
|
-
_readLicenses(login, password) {
|
|
182
|
-
const config = {
|
|
183
|
-
headers: { Authorization: `Basic ${Buffer.from(`${login}:${password}`).toString('base64')}` },
|
|
184
|
-
timeout: 4000,
|
|
185
|
-
validateStatus: status => status < 400
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
return axios
|
|
189
|
-
.get(`https://iobroker.net:3001/api/v1/licenses`, config)
|
|
190
|
-
.then(response => {
|
|
191
|
-
if (response.data && response.data.length) {
|
|
192
|
-
const now = Date.now();
|
|
193
|
-
response.data = response.data.filter(
|
|
194
|
-
license =>
|
|
195
|
-
!license.validTill ||
|
|
196
|
-
license.validTill === '0000-00-00 00:00:00' ||
|
|
197
|
-
new Date(license.validTill).getTime() > now
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
return response.data;
|
|
201
|
-
})
|
|
202
|
-
.catch(error => {
|
|
203
|
-
if (error.response) {
|
|
204
|
-
throw new Error(
|
|
205
|
-
(error.response.data && error.response.data.error) ||
|
|
206
|
-
error.response.data ||
|
|
207
|
-
error.response.status
|
|
208
|
-
);
|
|
209
|
-
} else if (error.request) {
|
|
210
|
-
throw new Error('no response');
|
|
211
|
-
} else {
|
|
212
|
-
throw error;
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// remove this function when js.controller 4.x will be mainstream
|
|
218
|
-
_updateLicenses(login, password, options) {
|
|
219
|
-
// if login and password provided in the message, just try to read without saving it in system.licenses
|
|
220
|
-
if (login && password) {
|
|
221
|
-
return this._readLicenses(login, password);
|
|
222
|
-
} else {
|
|
223
|
-
// get actual object
|
|
224
|
-
return this.adapter.getForeignObjectAsync('system.licenses', options).then(systemLicenses => {
|
|
225
|
-
// If password and login exist
|
|
226
|
-
if (
|
|
227
|
-
systemLicenses &&
|
|
228
|
-
systemLicenses.native &&
|
|
229
|
-
systemLicenses.native.password &&
|
|
230
|
-
systemLicenses.native.login
|
|
231
|
-
) {
|
|
232
|
-
// get the secret to decode the password
|
|
233
|
-
return this.adapter
|
|
234
|
-
.getForeignObjectAsync('system.config', options)
|
|
235
|
-
.then(systemConfig => {
|
|
236
|
-
// decode the password
|
|
237
|
-
let password;
|
|
238
|
-
try {
|
|
239
|
-
password = this.adapter.decrypt(
|
|
240
|
-
systemConfig.native.secret,
|
|
241
|
-
systemLicenses.native.password
|
|
242
|
-
);
|
|
243
|
-
} catch {
|
|
244
|
-
throw new Error('Cannot decode password');
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// read licenses from iobroker.net
|
|
248
|
-
return this._readLicenses(systemLicenses.native.login, password);
|
|
249
|
-
})
|
|
250
|
-
.then(licenses => {
|
|
251
|
-
// save licenses to system.licenses and remember the time
|
|
252
|
-
// merge the information together
|
|
253
|
-
const oldLicenses = systemLicenses.native.licenses || [];
|
|
254
|
-
systemLicenses.native.licenses = licenses;
|
|
255
|
-
oldLicenses.forEach(oldLicense => {
|
|
256
|
-
if (oldLicense.usedBy) {
|
|
257
|
-
const newLicense = licenses.find(item => item.json === oldLicense.json);
|
|
258
|
-
if (newLicense) {
|
|
259
|
-
newLicense.usedBy = oldLicense.usedBy;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
systemLicenses.native.readTime = new Date().toISOString();
|
|
265
|
-
|
|
266
|
-
// save only if an object changed
|
|
267
|
-
return this.adapter
|
|
268
|
-
.setForeignObjectAsync('system.licenses', systemLicenses, options)
|
|
269
|
-
.then(() => licenses);
|
|
270
|
-
})
|
|
271
|
-
.catch(error => {
|
|
272
|
-
// if password is invalid
|
|
273
|
-
if (
|
|
274
|
-
error.message.includes('Authentication required') ||
|
|
275
|
-
error.message.includes('Cannot decode password')
|
|
276
|
-
) {
|
|
277
|
-
// clear existing licenses if exist
|
|
278
|
-
if (
|
|
279
|
-
systemLicenses &&
|
|
280
|
-
systemLicenses.native &&
|
|
281
|
-
systemLicenses.native.licenses &&
|
|
282
|
-
systemLicenses.native.licenses.length
|
|
283
|
-
) {
|
|
284
|
-
systemLicenses.native.licenses = [];
|
|
285
|
-
systemLicenses.native.readTime = new Date().toISOString();
|
|
286
|
-
return this.adapter
|
|
287
|
-
.setForeignObjectAsync('system.licenses', systemLicenses, options)
|
|
288
|
-
.then(() => {
|
|
289
|
-
throw error;
|
|
290
|
-
});
|
|
291
|
-
} else {
|
|
292
|
-
throw error;
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
throw error;
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
} else {
|
|
299
|
-
// if password or login are empty => clear existing licenses if exist
|
|
300
|
-
if (
|
|
301
|
-
systemLicenses &&
|
|
302
|
-
systemLicenses.native &&
|
|
303
|
-
systemLicenses.native.licenses &&
|
|
304
|
-
systemLicenses.native.licenses.length
|
|
305
|
-
) {
|
|
306
|
-
systemLicenses.native.licenses = [];
|
|
307
|
-
systemLicenses.native.readTime = new Date().toISOString();
|
|
308
|
-
return this.adapter
|
|
309
|
-
.setForeignObjectAsync('system.licenses', systemLicenses, options)
|
|
310
|
-
.then(() => {
|
|
311
|
-
throw new Error('No password or login');
|
|
312
|
-
});
|
|
313
|
-
} else {
|
|
314
|
-
throw new Error('No password or login');
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
disableEventThreshold() {
|
|
322
|
-
if (this.eventsThreshold.active) {
|
|
323
|
-
this.eventsThreshold.accidents = 0;
|
|
324
|
-
this.eventsThreshold.count = 0;
|
|
325
|
-
this.eventsThreshold.active = false;
|
|
326
|
-
this.eventsThreshold.timeActivated = 0;
|
|
327
|
-
this.adapter.log.info('Subscribe to all states again');
|
|
328
|
-
|
|
329
|
-
setTimeout(async () => {
|
|
330
|
-
this.onThresholdChanged && this.onThresholdChanged(false);
|
|
331
|
-
try {
|
|
332
|
-
await this.adapter.unsubscribeForeignStatesAsync('system.adapter.*');
|
|
333
|
-
} catch (e) {
|
|
334
|
-
this.adapter.log.error(`Cannot unsubscribe "system.adapter.*": ${e.message}`);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
for (const pattern of Object.keys(this.subscribes.stateChange)) {
|
|
338
|
-
try {
|
|
339
|
-
await this.adapter.subscribeForeignStatesAsync(pattern);
|
|
340
|
-
} catch (e) {
|
|
341
|
-
this.adapter.log.error(`Cannot subscribe "${pattern}": ${e.message}`);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}, 50);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
_enableEventThreshold() {
|
|
349
|
-
if (!this.eventsThreshold.active) {
|
|
350
|
-
this.eventsThreshold.active = true;
|
|
351
|
-
|
|
352
|
-
setTimeout(async () => {
|
|
353
|
-
this.adapter.log.info(
|
|
354
|
-
`Unsubscribe from all states, except system's, because over ${this.eventsThreshold.repeatSeconds} seconds the number of events is over ${this.eventsThreshold.value} (in last second ${this.eventsThreshold.count})`
|
|
355
|
-
);
|
|
356
|
-
this.eventsThreshold.timeActivated = Date.now();
|
|
357
|
-
|
|
358
|
-
this.onThresholdChanged && this.onThresholdChanged(true);
|
|
359
|
-
|
|
360
|
-
for (const pattern of Object.keys(this.subscribes.stateChange)) {
|
|
361
|
-
try {
|
|
362
|
-
await this.adapter.unsubscribeForeignStatesAsync(pattern);
|
|
363
|
-
} catch (e) {
|
|
364
|
-
this.adapter.log.error(`Cannot unsubscribe "${pattern}": ${e.message}`);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
try {
|
|
369
|
-
await this.adapter.subscribeForeignStatesAsync('system.adapter.*');
|
|
370
|
-
} catch (e) {
|
|
371
|
-
this.adapter.log.error(`Cannot subscribe "system.adapter.*": ${e.message}`);
|
|
372
|
-
}
|
|
373
|
-
}, 100);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
_addUser(user, pw, options, callback) {
|
|
378
|
-
if (typeof options === 'function') {
|
|
379
|
-
callback = options;
|
|
380
|
-
options = null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (!user.match(/^[-.A-Za-züäößÖÄÜа-яА-Я@+$§0-9=?!&# ]+$/)) {
|
|
384
|
-
return SocketCommands._fixCallback(
|
|
385
|
-
callback,
|
|
386
|
-
'Invalid characters in the name. Only following special characters are allowed: -@+$§=?!&# and letters'
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
try {
|
|
391
|
-
this.adapter.getForeignObject(`system.user.${user}`, options, (error, obj) => {
|
|
392
|
-
if (obj) {
|
|
393
|
-
SocketCommands._fixCallback(callback, 'User yet exists');
|
|
394
|
-
} else {
|
|
395
|
-
try {
|
|
396
|
-
this.adapter.setForeignObject(
|
|
397
|
-
`system.user.${user}`,
|
|
398
|
-
{
|
|
399
|
-
type: 'user',
|
|
400
|
-
common: {
|
|
401
|
-
name: user,
|
|
402
|
-
enabled: true,
|
|
403
|
-
groups: []
|
|
404
|
-
}
|
|
405
|
-
},
|
|
406
|
-
options,
|
|
407
|
-
() => {
|
|
408
|
-
try {
|
|
409
|
-
this.adapter.setPassword(user, pw, options, callback);
|
|
410
|
-
} catch (error) {
|
|
411
|
-
this.adapter.log.error(`[_addUser] cannot set password: ${error.toString()}`);
|
|
412
|
-
SocketCommands._fixCallback(callback, error);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
);
|
|
416
|
-
} catch (error) {
|
|
417
|
-
this.adapter.log.error(`[_addUser] cannot save user: ${error.toString()}`);
|
|
418
|
-
SocketCommands._fixCallback(callback, error);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
} catch (error) {
|
|
423
|
-
this.adapter.log.error(`[_addUser] cannot read user: ${error.toString()}`);
|
|
424
|
-
SocketCommands._fixCallback(callback, error);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
_delUser(user, options, callback) {
|
|
429
|
-
try {
|
|
430
|
-
this.adapter.getForeignObject(`system.user.${user}`, options, (error, obj) => {
|
|
431
|
-
if (error || !obj) {
|
|
432
|
-
SocketCommands._fixCallback(callback, 'User does not exist');
|
|
433
|
-
} else {
|
|
434
|
-
if (obj.common.dontDelete) {
|
|
435
|
-
SocketCommands._fixCallback(callback, 'Cannot delete user, while is system user');
|
|
436
|
-
} else {
|
|
437
|
-
try {
|
|
438
|
-
this.adapter.delForeignObject(`system.user.${user}`, options, error =>
|
|
439
|
-
// Remove this user from all groups in web client
|
|
440
|
-
SocketCommands._fixCallback(callback, error)
|
|
441
|
-
);
|
|
442
|
-
} catch (error) {
|
|
443
|
-
this.adapter.log.error(`[_delUser] cannot delete user: ${error.toString()}`);
|
|
444
|
-
SocketCommands._fixCallback(callback, error);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
} catch (error) {
|
|
450
|
-
this.adapter.log.error(`[_delUser] cannot read user: ${error.toString()}`);
|
|
451
|
-
SocketCommands._fixCallback(callback, error);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
_addGroup(group, desc, acl, options, callback) {
|
|
456
|
-
let name = group;
|
|
457
|
-
if (typeof acl === 'function') {
|
|
458
|
-
callback = acl;
|
|
459
|
-
acl = null;
|
|
460
|
-
}
|
|
461
|
-
if (typeof desc === 'function') {
|
|
462
|
-
callback = desc;
|
|
463
|
-
desc = null;
|
|
464
|
-
}
|
|
465
|
-
if (typeof options === 'function') {
|
|
466
|
-
callback = options;
|
|
467
|
-
options = null;
|
|
468
|
-
}
|
|
469
|
-
if (name && name.substring(0, 1) !== name.substring(0, 1).toUpperCase()) {
|
|
470
|
-
name = name.substring(0, 1).toUpperCase() + name.substring(1);
|
|
471
|
-
}
|
|
472
|
-
group = group.substring(0, 1).toLowerCase() + group.substring(1);
|
|
473
|
-
|
|
474
|
-
if (!group.match(/^[-.A-Za-züäößÖÄÜа-яА-Я@+$§0-9=?!&#_ ]+$/)) {
|
|
475
|
-
return SocketCommands._fixCallback(
|
|
476
|
-
callback,
|
|
477
|
-
'Invalid characters in the group name. Only following special characters are allowed: -@+$§=?!&# and letters'
|
|
478
|
-
);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
try {
|
|
482
|
-
this.adapter.getForeignObject(`system.group.${group}`, options, (error, obj) => {
|
|
483
|
-
if (obj) {
|
|
484
|
-
SocketCommands._fixCallback(callback, 'Group yet exists');
|
|
485
|
-
} else {
|
|
486
|
-
obj = {
|
|
487
|
-
_id: 'system.group.' + group,
|
|
488
|
-
type: 'group',
|
|
489
|
-
common: {
|
|
490
|
-
name,
|
|
491
|
-
desc,
|
|
492
|
-
members: [],
|
|
493
|
-
acl
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
try {
|
|
497
|
-
this.adapter.setForeignObject(`system.group.${group}`, obj, options, error =>
|
|
498
|
-
SocketCommands._fixCallback(callback, error, obj)
|
|
499
|
-
);
|
|
500
|
-
} catch (error) {
|
|
501
|
-
this.adapter.log.error(`[_addGroup] cannot write group: ${error.toString()}`);
|
|
502
|
-
SocketCommands._fixCallback(callback, error);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
} catch (error) {
|
|
507
|
-
this.adapter.log.error(`[_addGroup] cannot read group: ${error.toString()}`);
|
|
508
|
-
SocketCommands._fixCallback(callback, error);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
_delGroup(group, options, callback) {
|
|
513
|
-
try {
|
|
514
|
-
this.adapter.getForeignObject(`system.group.${group}`, options, (error, obj) => {
|
|
515
|
-
if (error || !obj) {
|
|
516
|
-
SocketCommands._fixCallback(callback, 'Group does not exist');
|
|
517
|
-
} else {
|
|
518
|
-
if (obj.common.dontDelete) {
|
|
519
|
-
SocketCommands._fixCallback(callback, 'Cannot delete group, while is system group');
|
|
520
|
-
} else {
|
|
521
|
-
try {
|
|
522
|
-
this.adapter.delForeignObject(`system.group.${group}`, options, error =>
|
|
523
|
-
// Remove this group from all users in the web client
|
|
524
|
-
SocketCommands._fixCallback(callback, error)
|
|
525
|
-
);
|
|
526
|
-
} catch (error) {
|
|
527
|
-
this.adapter.log.error(`[_delGroup] cannot delete group: ${error.toString()}`);
|
|
528
|
-
SocketCommands._fixCallback(callback, error);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
});
|
|
533
|
-
} catch (error) {
|
|
534
|
-
this.adapter.log.error(`[_delGroup] cannot read group: ${error.toString()}`);
|
|
535
|
-
SocketCommands._fixCallback(callback, error);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
static _checkObject(obj, options, flag) {
|
|
540
|
-
// read rights of the object
|
|
541
|
-
if (!obj || !obj.common || !obj.acl || flag === 'list') {
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
if (options.user !== 'system.user.admin' && !options.groups.includes('system.group.administrator')) {
|
|
546
|
-
if (obj.acl.owner !== options.user) {
|
|
547
|
-
// Check if the user is in the group
|
|
548
|
-
if (options.groups.includes(obj.acl.ownerGroup)) {
|
|
549
|
-
// Check group rights
|
|
550
|
-
if (!(obj.acl.object & (flag << 4))) {
|
|
551
|
-
return false;
|
|
552
|
-
}
|
|
553
|
-
} else {
|
|
554
|
-
// everybody
|
|
555
|
-
if (!(obj.acl.object & flag)) {
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
} else {
|
|
560
|
-
// Check group rights
|
|
561
|
-
if (!(obj.acl.object & (flag << 8))) {
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
return true;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
_getAllObjects(socket, callback) {
|
|
570
|
-
if (typeof callback !== 'function') {
|
|
571
|
-
return this.adapter.log.warn('[_getAllObjects] Invalid callback');
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
if (this._checkPermissions(socket, 'getObjects', callback)) {
|
|
575
|
-
if (this.objects) {
|
|
576
|
-
if (
|
|
577
|
-
socket._acl &&
|
|
578
|
-
socket._acl.user !== 'system.user.admin' &&
|
|
579
|
-
!socket._acl.groups.includes('system.group.administrator')
|
|
580
|
-
) {
|
|
581
|
-
const result = {};
|
|
582
|
-
for (const id in this.objects) {
|
|
583
|
-
if (
|
|
584
|
-
Object.prototype.hasOwnProperty.call(this.objects, id) &&
|
|
585
|
-
SocketCommandsAdmin._checkObject(this.objects[id], socket._acl, 4 /* 'read' */)
|
|
586
|
-
) {
|
|
587
|
-
result[id] = this.objects[id];
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
callback(null, result);
|
|
591
|
-
} else {
|
|
592
|
-
callback(null, this.objects);
|
|
593
|
-
}
|
|
594
|
-
} else {
|
|
595
|
-
try {
|
|
596
|
-
this.adapter.getObjectList({ include_docs: true }, { user: socket._acl.user }, (error, res) => {
|
|
597
|
-
this.adapter.log.info('received all objects');
|
|
598
|
-
res = res.rows;
|
|
599
|
-
const objects = {};
|
|
600
|
-
|
|
601
|
-
if (
|
|
602
|
-
socket._acl &&
|
|
603
|
-
socket._acl.user !== 'system.user.admin' &&
|
|
604
|
-
!socket._acl.groups.includes('system.group.administrator')
|
|
605
|
-
) {
|
|
606
|
-
for (let i = 0; i < res.length; i++) {
|
|
607
|
-
if (SocketCommandsAdmin._checkObject(res[i].doc, socket._acl, 4 /* 'read' */)) {
|
|
608
|
-
objects[res[i].doc._id] = res[i].doc;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
callback(null, objects);
|
|
612
|
-
} else {
|
|
613
|
-
for (let j = 0; j < res.length; j++) {
|
|
614
|
-
objects[res[j].doc._id] = res[j].doc;
|
|
615
|
-
}
|
|
616
|
-
callback(null, objects);
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
} catch (error) {
|
|
620
|
-
this.adapter.log.error(`[_getAllObjects] ERROR: ${error.toString()}`);
|
|
621
|
-
SocketCommands._fixCallback(callback, error);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
_initCommandsUser() {
|
|
628
|
-
this.commands['addUser'] = (socket, user, pass, callback) => {
|
|
629
|
-
// Add new user
|
|
630
|
-
// @param {string} user - user name, like `benjamin`
|
|
631
|
-
// @param {string} pass - user password
|
|
632
|
-
// @param {function} callback - `function (error)`
|
|
633
|
-
if (this._checkPermissions(socket, 'addUser', callback, user)) {
|
|
634
|
-
this._addUser(user, pass, { user: socket._acl.user }, (error, ...args) =>
|
|
635
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
636
|
-
);
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
this.commands['delUser'] = (socket, user, callback) => {
|
|
641
|
-
// Delete existing user. Admin cannot be deleted.
|
|
642
|
-
// @param {string} user - user name, like 'benjamin
|
|
643
|
-
// @param {function} callback - `function (error)`
|
|
644
|
-
if (this._checkPermissions(socket, 'delUser', callback, user)) {
|
|
645
|
-
this._delUser(user, { user: socket._acl.user }, (error, ...args) =>
|
|
646
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
647
|
-
);
|
|
648
|
-
}
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
this.commands['addGroup'] = (socket, group, desc, acl, callback) => {
|
|
652
|
-
// Add a new group.
|
|
653
|
-
// @param {string} group - user name, like 'benjamin
|
|
654
|
-
// @param {string} desc - optional description
|
|
655
|
-
// @param {object} acl - optional access control list object, like `{"object":{"list":true,"read":true,"write":false,"delete":false},"state":{"list":true,"read":true,"write":true,"create":true,"delete":false},"users":{"list":true,"read":true,"write":false,"create":false,"delete":false},"other":{"execute":false,"http":true,"sendto":false},"file":{"list":true,"read":true,"write":false,"create":false,"delete":false}}`
|
|
656
|
-
// @param {function} callback - `function (error)`
|
|
657
|
-
if (this._checkPermissions(socket, 'addGroup', callback, group)) {
|
|
658
|
-
this._addGroup(group, desc, acl, { user: socket._acl.user }, (error, ...args) =>
|
|
659
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
this.commands['delGroup'] = (socket, group, callback) => {
|
|
665
|
-
// Delete the existing group. Administrator group cannot be deleted.
|
|
666
|
-
// @param {string} group - group name, like 'users`
|
|
667
|
-
// @param {function} callback - `function (error)`
|
|
668
|
-
if (this._checkPermissions(socket, 'delGroup', callback, group)) {
|
|
669
|
-
this._delGroup(group, { user: socket._acl.user }, (error, ...args) =>
|
|
670
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
this.commands['changePassword'] = (socket, user, pass, callback) => {
|
|
676
|
-
// Change user password
|
|
677
|
-
// @param {string} user - user name, like 'benjamin`
|
|
678
|
-
// @param {string} pass - new password
|
|
679
|
-
// @param {function} callback - `function (error)`
|
|
680
|
-
if (user === socket._acl.user || this._checkPermissions(socket, 'changePassword', callback, user)) {
|
|
681
|
-
try {
|
|
682
|
-
this.adapter.setPassword(user, pass, { user: socket._acl.user }, (error, ...args) =>
|
|
683
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
684
|
-
);
|
|
685
|
-
} catch (error) {
|
|
686
|
-
this.adapter.log.error(`[_changePassword] ERROR: ${error.toString()}`);
|
|
687
|
-
SocketCommands._fixCallback(callback, error);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
_initCommandsAdmin() {
|
|
694
|
-
this.commands['getHostByIp'] = (socket, ip, callback) => {
|
|
695
|
-
// Read the host object by IP address
|
|
696
|
-
// @param {string} ip - ip address. IPv4 or IPv6
|
|
697
|
-
// @param {function} callback - `function (ip, obj)`. If host is not found, obj is null
|
|
698
|
-
if (typeof callback !== 'function') {
|
|
699
|
-
return this.adapter.log.warn('[getHostByIp] Invalid callback');
|
|
700
|
-
}
|
|
701
|
-
if (this._checkPermissions(socket, 'getHostByIp', ip)) {
|
|
702
|
-
try {
|
|
703
|
-
this.adapter.getObjectView('system', 'host', {}, { user: socket._acl.user }, (error, data) => {
|
|
704
|
-
if (data && data.rows && data.rows.length) {
|
|
705
|
-
for (let i = 0; i < data.rows.length; i++) {
|
|
706
|
-
const obj = data.rows[i].value;
|
|
707
|
-
// if we requested specific name
|
|
708
|
-
if (obj.common.hostname === ip) {
|
|
709
|
-
return callback(ip, obj);
|
|
710
|
-
} else if (obj.native.hardware && obj.native.hardware.networkInterfaces) {
|
|
711
|
-
// try to find this IP in the list
|
|
712
|
-
const net = obj.native.hardware.networkInterfaces;
|
|
713
|
-
for (const eth in net) {
|
|
714
|
-
if (!Object.prototype.hasOwnProperty.call(net, eth)) {
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
for (let j = 0; j < net[eth].length; j++) {
|
|
718
|
-
if (net[eth][j].address === ip) {
|
|
719
|
-
return callback(ip, obj);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
callback(ip, null);
|
|
728
|
-
});
|
|
729
|
-
} catch (error) {
|
|
730
|
-
this.adapter.log.error(`[_changePassword] ERROR: ${error.toString()}`);
|
|
731
|
-
SocketCommands._fixCallback(callback, error);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
};
|
|
735
|
-
|
|
736
|
-
this.commands['requireLog'] = (socket, isEnabled, callback) => {
|
|
737
|
-
// Activate or deactivate logging events. Events will be sent to the socket as `log` event. Adapter must have `common.logTransporter = true`
|
|
738
|
-
// @param {boolean} isEnabled - is logging enabled
|
|
739
|
-
// @param {function} callback - `function (error)`
|
|
740
|
-
if (this._checkPermissions(socket, 'setObject', callback)) {
|
|
741
|
-
if (isEnabled) {
|
|
742
|
-
this.subscribe(socket, 'log', 'dummy');
|
|
743
|
-
} else {
|
|
744
|
-
this.unsubscribe(socket, 'log', 'dummy');
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
this.adapter.log.level === 'debug' && this._showSubscribes(socket, 'log');
|
|
748
|
-
|
|
749
|
-
typeof callback === 'function' && setImmediate(callback, null);
|
|
750
|
-
}
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
this.commands['readLogs'] = (socket, host, callback) => {
|
|
754
|
-
// Get logs file from given host
|
|
755
|
-
// @param {string} host - host id, like 'system.host.raspberrypi'
|
|
756
|
-
// @param {function} callback - `function (error, files)`, where `files` is array of `{fileName: `log/hostname/transport/file`, size: 123}`
|
|
757
|
-
if (this._checkPermissions(socket, 'readLogs', callback)) {
|
|
758
|
-
let timeout = setTimeout(() => {
|
|
759
|
-
if (timeout) {
|
|
760
|
-
let result = { list: [] };
|
|
761
|
-
|
|
762
|
-
// deliver the file list
|
|
763
|
-
try {
|
|
764
|
-
const config = this.adapter.systemConfig;
|
|
765
|
-
// detect file log
|
|
766
|
-
if (config && config.log && config.log.transport) {
|
|
767
|
-
for (const transport in config.log.transport) {
|
|
768
|
-
if (
|
|
769
|
-
Object.prototype.hasOwnProperty.call(config.log.transport, transport) &&
|
|
770
|
-
config.log.transport[transport].type === 'file'
|
|
771
|
-
) {
|
|
772
|
-
let fileName = config.log.transport[transport].filename || 'log/';
|
|
773
|
-
const parts = fileName.replace(/\\/g, '/').split('/');
|
|
774
|
-
parts.pop();
|
|
775
|
-
fileName = parts.join('/');
|
|
776
|
-
if (fileName[0] !== '/' && !fileName.match(/^\W:/)) {
|
|
777
|
-
const _filename = path.normalize(__dirname + '/../../../') + fileName;
|
|
778
|
-
if (!fs.existsSync(_filename)) {
|
|
779
|
-
fileName = path.normalize(__dirname + '/../../') + fileName;
|
|
780
|
-
} else {
|
|
781
|
-
fileName = _filename;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
if (fs.existsSync(fileName)) {
|
|
785
|
-
const files = fs.readdirSync(fileName);
|
|
786
|
-
|
|
787
|
-
for (let f = 0; f < files.length; f++) {
|
|
788
|
-
try {
|
|
789
|
-
if (!files[f].endsWith('-audit.json')) {
|
|
790
|
-
const stat = fs.lstatSync(`${fileName}/${files[f]}`);
|
|
791
|
-
if (!stat.isDirectory()) {
|
|
792
|
-
result.list.push({
|
|
793
|
-
fileName: `log/${transport}/${files[f]}`,
|
|
794
|
-
size: stat.size
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
} catch {
|
|
799
|
-
// push unchecked
|
|
800
|
-
// result.list.push('log/' + transport + '/' + files[f]);
|
|
801
|
-
this.adapter.log.error(
|
|
802
|
-
`Cannot check file: ${fileName}/${files[f]}`
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
} else {
|
|
810
|
-
result = { error: 'no file loggers' };
|
|
811
|
-
}
|
|
812
|
-
} catch (error) {
|
|
813
|
-
this.adapter.log.error(`Cannot read logs: ${error}`);
|
|
814
|
-
result = { error };
|
|
815
|
-
}
|
|
816
|
-
SocketCommands._fixCallback(callback, result.error, result.list);
|
|
817
|
-
}
|
|
818
|
-
}, 500);
|
|
819
|
-
|
|
820
|
-
this._sendToHost(host, 'getLogFiles', null, result => {
|
|
821
|
-
clearTimeout(timeout);
|
|
822
|
-
timeout = null;
|
|
823
|
-
SocketCommands._fixCallback(callback, result.error, result.list);
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
};
|
|
827
|
-
|
|
828
|
-
this.commands['delState'] = (socket, id, callback) => {
|
|
829
|
-
// Delete state. The corresponding object will be deleted too.
|
|
830
|
-
// @param {string} id - state ID
|
|
831
|
-
// @param {function} callback - `function (error)`
|
|
832
|
-
if (this._checkPermissions(socket, 'delState', callback, id)) {
|
|
833
|
-
// clear cache
|
|
834
|
-
if (this.states && this.states[id]) {
|
|
835
|
-
delete this.states[id];
|
|
836
|
-
}
|
|
837
|
-
try {
|
|
838
|
-
this.adapter.delForeignState(id, { user: socket._acl.user }, (error, ...args) =>
|
|
839
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
840
|
-
);
|
|
841
|
-
} catch (error) {
|
|
842
|
-
this.adapter.log.error(`[delState] ERROR: ${error.toString()}`);
|
|
843
|
-
SocketCommands._fixCallback(callback, error);
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
|
|
848
|
-
// commands will be executed on host/controller
|
|
849
|
-
// following response commands are expected: cmdStdout, cmdStderr, cmdExit
|
|
850
|
-
this.commands['cmdExec'] = (socket, host, id, cmd, callback) => {
|
|
851
|
-
// Execute the shell command on host/controller. Following response commands are expected: ´cmdStdout, cmdStderr, cmdExit´
|
|
852
|
-
// @param {string} host - host name, like 'system.host.raspberrypi'
|
|
853
|
-
// @param {string} id - session ID, like `Date.now()´. This session ID will come in events `cmdStdout, cmdStderr, cmdExit`
|
|
854
|
-
// @param {string} cmd - command
|
|
855
|
-
// @param {function} callback - `function (error)`
|
|
856
|
-
if (this._checkPermissions(socket, 'cmdExec', callback, cmd)) {
|
|
857
|
-
this.adapter.log.debug(`cmdExec on ${host}(${id}): ${cmd}`);
|
|
858
|
-
// remember socket for this ID.
|
|
859
|
-
this.cmdSessions[id] = { socket };
|
|
860
|
-
try {
|
|
861
|
-
this.adapter.sendToHost(host, 'cmdExec', { data: cmd, id });
|
|
862
|
-
SocketCommands._fixCallback(callback, null);
|
|
863
|
-
} catch (error) {
|
|
864
|
-
this.adapter.log.error(`[cmdExec] ERROR: ${error.toString()}`);
|
|
865
|
-
SocketCommands._fixCallback(callback, error);
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
|
|
870
|
-
this.commands['eventsThreshold'] = (socket, isActive) => {
|
|
871
|
-
// Used only for admin to the limited number of events to front-end.
|
|
872
|
-
// @param {boolean} isActive - if true, then events will be limited
|
|
873
|
-
if (!isActive) {
|
|
874
|
-
this.disableEventThreshold(true);
|
|
875
|
-
} else {
|
|
876
|
-
this._enableEventThreshold();
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
this.commands['getRatings'] = (socket, update, callback) => {
|
|
881
|
-
// Read ratings of adapters
|
|
882
|
-
// @param {boolean} update - if true, the ratings will be read from central server, if false from local cache
|
|
883
|
-
// @param {function} callback - `function (error, ratings)`, where `ratings` is object like `{accuweather: {rating: {r: 3.33, c: 3}, 1.2.1: {r: 3, c: 1}},…}`
|
|
884
|
-
if (update || !this.adapter._ratings) {
|
|
885
|
-
this.updateRatings().then(() => SocketCommands._fixCallback(callback, null, this.adapter._ratings));
|
|
886
|
-
} else {
|
|
887
|
-
SocketCommands._fixCallback(callback, null, this.adapter._ratings);
|
|
888
|
-
}
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
this.commands['getCurrentInstance'] = (socket, callback) => {
|
|
892
|
-
// Return current instance name like `admin.0`
|
|
893
|
-
// @param {function} callback - `function (error, namespace)`
|
|
894
|
-
SocketCommands._fixCallback(callback, null, this.adapter.namespace);
|
|
895
|
-
};
|
|
896
|
-
|
|
897
|
-
this.commands['decrypt'] = (socket, encryptedText, callback) => {
|
|
898
|
-
// Decrypts text with the system secret key
|
|
899
|
-
// @param {string} encryptedText - encrypted text
|
|
900
|
-
// @param {function} callback - `function (error, decryptedText)`
|
|
901
|
-
if (this.secret) {
|
|
902
|
-
SocketCommands._fixCallback(callback, null, this.adapter.decrypt(this.secret, encryptedText));
|
|
903
|
-
} else {
|
|
904
|
-
try {
|
|
905
|
-
this.adapter.getForeignObject('system.config', { user: socket._acl.user }, (error, obj) => {
|
|
906
|
-
if (obj && obj.native && obj.native.secret) {
|
|
907
|
-
this.secret = obj.native.secret;
|
|
908
|
-
SocketCommands._fixCallback(
|
|
909
|
-
callback,
|
|
910
|
-
null,
|
|
911
|
-
this.adapter.decrypt(this.secret, encryptedText)
|
|
912
|
-
);
|
|
913
|
-
} else {
|
|
914
|
-
this.adapter.log.error(`No system.config found: ${error}`);
|
|
915
|
-
SocketCommands._fixCallback(callback, error);
|
|
916
|
-
}
|
|
917
|
-
});
|
|
918
|
-
} catch (error) {
|
|
919
|
-
this.adapter.log.error(`Cannot decrypt: ${error}`);
|
|
920
|
-
SocketCommands._fixCallback(callback, error);
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
};
|
|
924
|
-
|
|
925
|
-
this.commands['encrypt'] = (socket, plainText, callback) => {
|
|
926
|
-
// Encrypts text with the system secret key
|
|
927
|
-
// @param {string} plainText - normal text
|
|
928
|
-
// @param {function} callback - `function (error, encryptedText)`
|
|
929
|
-
if (this.secret) {
|
|
930
|
-
SocketCommands._fixCallback(callback, null, this.adapter.encrypt(this.secret, plainText));
|
|
931
|
-
} else {
|
|
932
|
-
this.adapter.getForeignObject('system.config', { user: socket._acl.user }, (error, obj) => {
|
|
933
|
-
if (obj && obj.native && obj.native.secret) {
|
|
934
|
-
this.secret = obj.native.secret;
|
|
935
|
-
try {
|
|
936
|
-
const encrypted = this.adapter.encrypt(this.secret, plainText);
|
|
937
|
-
SocketCommands._fixCallback(callback, null, encrypted);
|
|
938
|
-
} catch (error) {
|
|
939
|
-
this.adapter.log.error(`Cannot encrypt: ${error}`);
|
|
940
|
-
SocketCommands._fixCallback(callback, error);
|
|
941
|
-
}
|
|
942
|
-
} else {
|
|
943
|
-
this.adapter.log.error(`No system.config found: ${error}`);
|
|
944
|
-
SocketCommands._fixCallback(callback, error);
|
|
945
|
-
}
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
};
|
|
949
|
-
|
|
950
|
-
this.commands['getIsEasyModeStrict'] = (socket, callback) => {
|
|
951
|
-
// Returns if admin has easy mode enabled
|
|
952
|
-
// @param {function} callback - `function (error, isEasyModeStrict)`
|
|
953
|
-
SocketCommands._fixCallback(callback, null, this.adapter.config.accessLimit);
|
|
954
|
-
};
|
|
955
|
-
|
|
956
|
-
this.commands['getEasyMode'] = (socket, callback) => {
|
|
957
|
-
// Get easy mode configuration
|
|
958
|
-
// @param {function} callback - `function (error, easyModeConfig)`, where `easyModeConfig` is object like `{strict: true, configs: [{_id: 'system.adapter.javascript.0', common: {...}}, {...}]}`
|
|
959
|
-
// }`
|
|
960
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
961
|
-
let user;
|
|
962
|
-
if (this.adapter.config.auth) {
|
|
963
|
-
user = socket._acl.user;
|
|
964
|
-
if (!user.startsWith('system.user.')) {
|
|
965
|
-
user = `system.user.${user}`;
|
|
966
|
-
}
|
|
967
|
-
} else {
|
|
968
|
-
user = this.adapter.config.defaultUser;
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
if (this.adapter.config.accessLimit) {
|
|
972
|
-
const configs = [];
|
|
973
|
-
const promises = [];
|
|
974
|
-
this.adapter.config.accessAllowedConfigs.forEach(id =>
|
|
975
|
-
promises.push(this._readInstanceConfig(id, user, false, configs))
|
|
976
|
-
);
|
|
977
|
-
this.adapter.config.accessAllowedTabs.forEach(id =>
|
|
978
|
-
promises.push(this._readInstanceConfig(id, user, true, configs))
|
|
979
|
-
);
|
|
980
|
-
|
|
981
|
-
Promise.all(promises).then(() => {
|
|
982
|
-
callback(null, {
|
|
983
|
-
strict: true,
|
|
984
|
-
configs
|
|
985
|
-
});
|
|
986
|
-
});
|
|
987
|
-
} else {
|
|
988
|
-
this.adapter.getObjectView(
|
|
989
|
-
'system',
|
|
990
|
-
'instance',
|
|
991
|
-
{ startkey: 'system.adapter.', endkey: 'system.adapter.\u9999' },
|
|
992
|
-
{ user },
|
|
993
|
-
(error, doc) => {
|
|
994
|
-
const promises = [];
|
|
995
|
-
const configs = [];
|
|
996
|
-
if (!error && doc.rows.length) {
|
|
997
|
-
for (let i = 0; i < doc.rows.length; i++) {
|
|
998
|
-
const obj = doc.rows[i].value;
|
|
999
|
-
if (obj.common.noConfig && !obj.common.adminTab) {
|
|
1000
|
-
continue;
|
|
1001
|
-
}
|
|
1002
|
-
if (!obj.common.enabled) {
|
|
1003
|
-
continue;
|
|
1004
|
-
}
|
|
1005
|
-
if (!obj.common.noConfig) {
|
|
1006
|
-
promises.push(
|
|
1007
|
-
this._readInstanceConfig(
|
|
1008
|
-
obj._id.substring('system.adapter.'.length),
|
|
1009
|
-
user,
|
|
1010
|
-
false,
|
|
1011
|
-
configs
|
|
1012
|
-
)
|
|
1013
|
-
);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
Promise.all(promises).then(() =>
|
|
1018
|
-
callback(null, {
|
|
1019
|
-
strict: false,
|
|
1020
|
-
configs
|
|
1021
|
-
})
|
|
1022
|
-
);
|
|
1023
|
-
}
|
|
1024
|
-
);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
|
-
this.commands['getAdapters'] = (socket, adapterName, callback) => {
|
|
1030
|
-
// Read all adapters objects
|
|
1031
|
-
// @param {string} adapterName - optional adapter name
|
|
1032
|
-
// @param {function} callback - `function (error, results)`, where `results` is array of objects like `{_id: 'system.adapter.javascript', common: {...}}`
|
|
1033
|
-
if (typeof callback === 'function' && this._checkPermissions(socket, 'getObject', callback)) {
|
|
1034
|
-
this.adapter.getObjectView(
|
|
1035
|
-
'system',
|
|
1036
|
-
'adapter',
|
|
1037
|
-
{
|
|
1038
|
-
startkey: `system.adapter.${adapterName || ''}`,
|
|
1039
|
-
endkey: `system.adapter.${adapterName || '\u9999'}`
|
|
1040
|
-
},
|
|
1041
|
-
{ user: socket._acl.user },
|
|
1042
|
-
(error, doc) => {
|
|
1043
|
-
if (error) {
|
|
1044
|
-
callback(error);
|
|
1045
|
-
} else {
|
|
1046
|
-
callback(
|
|
1047
|
-
null,
|
|
1048
|
-
doc.rows
|
|
1049
|
-
.filter(
|
|
1050
|
-
obj =>
|
|
1051
|
-
obj &&
|
|
1052
|
-
(!adapterName || (obj.common && obj.common.name === this.adapterName))
|
|
1053
|
-
)
|
|
1054
|
-
.map(item => {
|
|
1055
|
-
const obj = item.value;
|
|
1056
|
-
if (obj.common) {
|
|
1057
|
-
delete obj.common.news;
|
|
1058
|
-
delete obj.native;
|
|
1059
|
-
}
|
|
1060
|
-
this._fixAdminUI(obj);
|
|
1061
|
-
return obj;
|
|
1062
|
-
})
|
|
1063
|
-
);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
);
|
|
1067
|
-
}
|
|
1068
|
-
};
|
|
1069
|
-
|
|
1070
|
-
this.commands['updateLicenses'] = (socket, login, password, callback) => {
|
|
1071
|
-
// Read software licenses (vis, knx, ...) from ioBroker.net cloud for given user
|
|
1072
|
-
// @param {string} login - cloud login
|
|
1073
|
-
// @param {string} password - cloud password
|
|
1074
|
-
// @param {function} callback - `function (error, results)`, where `results` is array of objects like `[{"json":"xxx","id":"ab","email":"dogafox@gmail.com","product":"iobroker.knx.year","version":"2","invoice":"Pxx","uuid":"uuid","time":"2021-11-16T19:53:02.000Z","validTill":"2022-11-16T22:59:59.000Z","datapoints":1000}]`
|
|
1075
|
-
if (this._checkPermissions(socket, 'setObject', callback, login, password)) {
|
|
1076
|
-
if (this.adapter.supportsFeature('CONTROLLER_LICENSE_MANAGER')) {
|
|
1077
|
-
let timeout = setTimeout(() => {
|
|
1078
|
-
if (timeout) {
|
|
1079
|
-
timeout = null;
|
|
1080
|
-
SocketCommands._fixCallback(callback, 'updateLicenses timeout');
|
|
1081
|
-
}
|
|
1082
|
-
}, 7000);
|
|
1083
|
-
|
|
1084
|
-
this._sendToHost(this.adapter.common.host, 'updateLicenses', { login, password }, result => {
|
|
1085
|
-
if (timeout) {
|
|
1086
|
-
clearTimeout(timeout);
|
|
1087
|
-
timeout = null;
|
|
1088
|
-
SocketCommands._fixCallback(callback, result.error, result && result.result);
|
|
1089
|
-
}
|
|
1090
|
-
});
|
|
1091
|
-
} else {
|
|
1092
|
-
// remove this branch when js-controller 4.x will be mainstream
|
|
1093
|
-
this._updateLicenses(login, password, { user: socket._acl.user })
|
|
1094
|
-
.then(licenses => SocketCommands._fixCallback(callback, null, licenses))
|
|
1095
|
-
.catch(error => SocketCommands._fixCallback(callback, error));
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
|
|
1100
|
-
this.commands['getCompactInstances'] = (socket, callback) => {
|
|
1101
|
-
// Read all instances in short form to save bandwidth
|
|
1102
|
-
// @param {function} callback - `function (error, results)`, where `results` is an object like `{'system.adapter.javascript.0': {adminTab, name, icon, enabled}}`
|
|
1103
|
-
if (typeof callback === 'function') {
|
|
1104
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1105
|
-
this.adapter.getObjectView(
|
|
1106
|
-
'system',
|
|
1107
|
-
'instance',
|
|
1108
|
-
{ startkey: `system.adapter.`, endkey: `system.adapter.\u9999` },
|
|
1109
|
-
{ user: socket._acl.user },
|
|
1110
|
-
(error, doc) => {
|
|
1111
|
-
if (error) {
|
|
1112
|
-
callback(error);
|
|
1113
|
-
} else {
|
|
1114
|
-
// calculate
|
|
1115
|
-
const result = {};
|
|
1116
|
-
|
|
1117
|
-
doc.rows.forEach(item => {
|
|
1118
|
-
const obj = item.value;
|
|
1119
|
-
result[item.id] = {
|
|
1120
|
-
adminTab: obj.common.adminTab,
|
|
1121
|
-
name: obj.common.name,
|
|
1122
|
-
icon: obj.common.icon,
|
|
1123
|
-
enabled: obj.common.enabled,
|
|
1124
|
-
version: obj.common.version
|
|
1125
|
-
};
|
|
1126
|
-
});
|
|
1127
|
-
|
|
1128
|
-
callback(null, result);
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
};
|
|
1135
|
-
|
|
1136
|
-
this.commands['getCompactAdapters'] = (socket, callback) => {
|
|
1137
|
-
// Read all adapters in short for to save bandwidth
|
|
1138
|
-
// @param {function} callback - `function (error, results)`, where `results` is an object like `{'javascript': {icon, v: '1.0.1', iv: 'ignoredVersion}}`
|
|
1139
|
-
if (typeof callback === 'function') {
|
|
1140
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1141
|
-
this.adapter.getObjectView(
|
|
1142
|
-
'system',
|
|
1143
|
-
'adapter',
|
|
1144
|
-
{ startkey: `system.adapter.`, endkey: `system.adapter.\u9999` },
|
|
1145
|
-
{ user: socket._acl.user },
|
|
1146
|
-
(error, doc) => {
|
|
1147
|
-
if (error) {
|
|
1148
|
-
callback(error);
|
|
1149
|
-
} else {
|
|
1150
|
-
// calculate
|
|
1151
|
-
const result = {};
|
|
1152
|
-
|
|
1153
|
-
doc.rows.forEach(item => {
|
|
1154
|
-
const obj = item.value;
|
|
1155
|
-
if (obj && obj.common && obj.common.name) {
|
|
1156
|
-
result[obj.common.name] = { icon: obj.common.icon, v: obj.common.version };
|
|
1157
|
-
if (obj.common.ignoreVersion) {
|
|
1158
|
-
result[obj.common.name].iv = obj.common.ignoreVersion;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
});
|
|
1162
|
-
|
|
1163
|
-
callback(null, result);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
);
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
|
|
1171
|
-
this.commands['getCompactInstalled'] = (socket, host, callback) => {
|
|
1172
|
-
// Read all installed adapters in short form to save bandwidth
|
|
1173
|
-
// @param {function} callback - `function (error, results)`, where `results` is an object like `{'javascript': {version: '1.0.1'}}``
|
|
1174
|
-
if (typeof callback === 'function') {
|
|
1175
|
-
if (this._checkPermissions(socket, 'sendToHost', callback)) {
|
|
1176
|
-
this._sendToHost(host, 'getInstalled', null, data => {
|
|
1177
|
-
const result = {};
|
|
1178
|
-
Object.keys(data).forEach(name => (result[name] = { version: data[name].version }));
|
|
1179
|
-
callback(result);
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
};
|
|
1184
|
-
|
|
1185
|
-
this.commands['getCompactSystemConfig'] = (socket, callback) => {
|
|
1186
|
-
// Read system config in short form to save bandwidth
|
|
1187
|
-
// @param {function} callback - `function (error, systemConfig)`, where `systemConfig` is an object like `{common: {...}, native: {secret: 'aaa'}}`
|
|
1188
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1189
|
-
this.adapter.getForeignObject('system.config', { user: socket._acl.user }, (error, obj) => {
|
|
1190
|
-
obj = obj || {};
|
|
1191
|
-
const secret = obj && obj.native && obj.native.secret;
|
|
1192
|
-
delete obj.native;
|
|
1193
|
-
if (secret) {
|
|
1194
|
-
obj.native = { secret };
|
|
1195
|
-
}
|
|
1196
|
-
callback(error, obj);
|
|
1197
|
-
});
|
|
1198
|
-
}
|
|
1199
|
-
};
|
|
1200
|
-
|
|
1201
|
-
this.commands['getCompactSystemRepositories'] = (socket, callback) => {
|
|
1202
|
-
// Read repositories from cache in short form to save bandwidth
|
|
1203
|
-
// @param {function} callback - `function (error, repositories)`, where `repositories` is an object like `{_id: 'system.repositories', common: {...}, native: {repositories: {default: {json: {_repoInfo: {...}}}}}}`
|
|
1204
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1205
|
-
this.adapter.getForeignObject('system.repositories', { user: socket._acl.user }, (error, obj) => {
|
|
1206
|
-
obj &&
|
|
1207
|
-
obj.native &&
|
|
1208
|
-
obj.native.repositories &&
|
|
1209
|
-
Object.keys(obj.native.repositories).forEach(name => {
|
|
1210
|
-
if (obj.native.repositories[name].json) {
|
|
1211
|
-
// limit information to _repoInfo
|
|
1212
|
-
obj.native.repositories[name].json = {
|
|
1213
|
-
_repoInfo: obj.native.repositories[name].json._repoInfo
|
|
1214
|
-
};
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
callback(error, obj);
|
|
1218
|
-
});
|
|
1219
|
-
}
|
|
1220
|
-
};
|
|
1221
|
-
|
|
1222
|
-
this.commands['getCompactRepository'] = (socket, host, callback) => {
|
|
1223
|
-
// Read current repository in short form to save bandwidth
|
|
1224
|
-
// @param {function} callback - `function (error, repository)`, where `repository` is an object like `{'javascript': {version: '1.0.1', icon}, 'admin': {version: '1.0.1', icon}}`
|
|
1225
|
-
if (this._checkPermissions(socket, 'sendToHost', callback)) {
|
|
1226
|
-
this._sendToHost(host, 'getRepository', null, data => {
|
|
1227
|
-
// Extract only the version and icon
|
|
1228
|
-
const result = {};
|
|
1229
|
-
data &&
|
|
1230
|
-
Object.keys(data).forEach(
|
|
1231
|
-
name =>
|
|
1232
|
-
(result[name] = {
|
|
1233
|
-
version: data[name].version,
|
|
1234
|
-
icon: data[name].extIcon
|
|
1235
|
-
})
|
|
1236
|
-
);
|
|
1237
|
-
callback(result);
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
};
|
|
1241
|
-
|
|
1242
|
-
this.commands['getCompactHosts'] = (socket, callback) => {
|
|
1243
|
-
// Read all hosts in short form to save bandwidth
|
|
1244
|
-
// @param {function} callback - `function (error, hosts)`, where `hosts` is an array of objects like `[{_id:'system.host.raspi',common:{name:'raspi',icon:'icon',color:'blue',installedVersion:'2.1.0'},native:{hardware:{networkInterfaces:[...]}}}]`
|
|
1245
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1246
|
-
this.adapter.getObjectView(
|
|
1247
|
-
'system',
|
|
1248
|
-
'host',
|
|
1249
|
-
{ startkey: 'system.host.', endkey: 'system.host.\u9999' },
|
|
1250
|
-
{ user: socket._acl.user },
|
|
1251
|
-
(error, doc) => {
|
|
1252
|
-
if (error) {
|
|
1253
|
-
callback(error);
|
|
1254
|
-
} else {
|
|
1255
|
-
const result = [];
|
|
1256
|
-
doc.rows.map(item => {
|
|
1257
|
-
const host = item.value;
|
|
1258
|
-
if (host) {
|
|
1259
|
-
host.common = host.common || {};
|
|
1260
|
-
result.push({
|
|
1261
|
-
_id: host._id,
|
|
1262
|
-
common: {
|
|
1263
|
-
name: host.common.name,
|
|
1264
|
-
icon: host.common.icon,
|
|
1265
|
-
color: host.common.color,
|
|
1266
|
-
installedVersion: host.common.installedVersion
|
|
1267
|
-
},
|
|
1268
|
-
native: {
|
|
1269
|
-
hardware: {
|
|
1270
|
-
networkInterfaces:
|
|
1271
|
-
(host.native &&
|
|
1272
|
-
host.native.hardware &&
|
|
1273
|
-
host.native.hardware.networkInterfaces) ||
|
|
1274
|
-
undefined
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
});
|
|
1278
|
-
}
|
|
1279
|
-
});
|
|
1280
|
-
callback(null, result);
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
);
|
|
1284
|
-
}
|
|
1285
|
-
};
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
__initCommandsCommon() {
|
|
1289
|
-
super.__initCommandsCommon();
|
|
1290
|
-
|
|
1291
|
-
this._initCommandsAdmin();
|
|
1292
|
-
this._initCommandsUser();
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
__initCommandsFiles() {
|
|
1296
|
-
super.__initCommandsFiles();
|
|
1297
|
-
|
|
1298
|
-
this.commands['writeFile'] = (socket, _adapter, fileName, data64, options, callback) => {
|
|
1299
|
-
// Write file into ioBroker DB as base64 string
|
|
1300
|
-
// @param {string} _adapter - instance name, e.g. `vis.0`
|
|
1301
|
-
// @param {string} fileName - file name, e.g `main/vis-views.json`
|
|
1302
|
-
// @param {string} data64 - file content as base64 string
|
|
1303
|
-
// @param {object} options - optional `{mode: 0x0644}`
|
|
1304
|
-
// @param {function} callback - `function (error)`
|
|
1305
|
-
if (this._checkPermissions(socket, 'writeFile', callback, fileName)) {
|
|
1306
|
-
if (typeof options === 'function') {
|
|
1307
|
-
callback = options;
|
|
1308
|
-
options = { user: socket._acl.user };
|
|
1309
|
-
}
|
|
1310
|
-
options = options || {};
|
|
1311
|
-
options.user = socket._acl.user;
|
|
1312
|
-
|
|
1313
|
-
try {
|
|
1314
|
-
const buffer = Buffer.from(data64, 'base64');
|
|
1315
|
-
this.adapter.writeFile(_adapter, fileName, buffer, { user: socket._acl.user }, (error, ...args) =>
|
|
1316
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1317
|
-
);
|
|
1318
|
-
} catch (error) {
|
|
1319
|
-
this.adapter.log.error(`[writeFile] Cannot convert data: ${error.toString()}`);
|
|
1320
|
-
callback && callback(`Cannot convert data: ${error.toString()}`);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
};
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
__initCommandsObjects() {
|
|
1327
|
-
super.__initCommandsObjects();
|
|
1328
|
-
|
|
1329
|
-
this.commands['getAllObjects'] = (socket, callback) => {
|
|
1330
|
-
// Read absolutely all objects
|
|
1331
|
-
// @param {function} callback - `function (error, objects)`, where `objects` is an object like `{'system.adapter.admin.0': {...}, 'system.adapter.web.0': {...}}`
|
|
1332
|
-
return this._getAllObjects(socket, callback);
|
|
1333
|
-
};
|
|
1334
|
-
|
|
1335
|
-
// Identical to getAllObjects
|
|
1336
|
-
this.commands['getObjects'] = (socket, list, callback) => {
|
|
1337
|
-
// Read absolutely all objects. Same as `getAllObjects`.
|
|
1338
|
-
// @param {string[]} list - optional list of IDs.
|
|
1339
|
-
// @param {function} callback - `function (error, objects)`, where `objects` is an object like `{'system.adapter.admin.0': {...}, 'system.adapter.web.0': {...}}`
|
|
1340
|
-
if (typeof list === 'function') {
|
|
1341
|
-
callback = list;
|
|
1342
|
-
list = null;
|
|
1343
|
-
}
|
|
1344
|
-
if (list && list.length) {
|
|
1345
|
-
if (this._checkPermissions(socket, 'getObject', callback)) {
|
|
1346
|
-
if (typeof callback === 'function') {
|
|
1347
|
-
try {
|
|
1348
|
-
this.adapter.getForeignObjects(list, { user: socket._acl.user }, (error, objs) =>
|
|
1349
|
-
SocketCommands._fixCallback(callback, error, objs)
|
|
1350
|
-
);
|
|
1351
|
-
} catch (error) {
|
|
1352
|
-
this.adapter.log.error(`[getObjects] ERROR: ${error.toString()}`);
|
|
1353
|
-
SocketCommands._fixCallback(callback, error);
|
|
1354
|
-
}
|
|
1355
|
-
} else {
|
|
1356
|
-
this.adapter.log.warn('[getObjects] Invalid callback');
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
} else {
|
|
1360
|
-
return this._getAllObjects(socket, callback);
|
|
1361
|
-
}
|
|
1362
|
-
};
|
|
1363
|
-
|
|
1364
|
-
this.commands['extendObject'] = (socket, id, obj, callback) => {
|
|
1365
|
-
// Extend the existing object
|
|
1366
|
-
// @param {string} id - object ID
|
|
1367
|
-
// @param {object} obj - new parts of the object, like `{common: {name: 'new name'}}`
|
|
1368
|
-
// @param {function} callback - `function (error)`
|
|
1369
|
-
if (this._checkPermissions(socket, 'extendObject', callback, id)) {
|
|
1370
|
-
try {
|
|
1371
|
-
this.adapter.extendForeignObject(id, obj, { user: socket._acl.user }, (error, ...args) =>
|
|
1372
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1373
|
-
);
|
|
1374
|
-
} catch (error) {
|
|
1375
|
-
this.adapter.log.error(`[extendObject] ERROR: ${error}`);
|
|
1376
|
-
SocketCommands._fixCallback(callback, error);
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
};
|
|
1380
|
-
|
|
1381
|
-
this.commands['getForeignObjects'] = (socket, pattern, type, callback) => {
|
|
1382
|
-
// Read objects by pattern
|
|
1383
|
-
// @param {string} pattern - pattern like `system.adapter.admin.0.*`
|
|
1384
|
-
// @param {string} type - type of objects to delete, like `state`, `channel`, `device`, `host`, `adapter`. Default - `state`
|
|
1385
|
-
// @param {function} callback - `function (error, objects)`, where `objects` is an object like `{'system.adapter.admin.0': {...}, 'system.adapter.web.0': {...}}`
|
|
1386
|
-
if (this._checkPermissions(socket, 'getObjects', callback)) {
|
|
1387
|
-
if (typeof type === 'function') {
|
|
1388
|
-
callback = type;
|
|
1389
|
-
type = undefined;
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
|
-
if (typeof callback === 'function') {
|
|
1393
|
-
try {
|
|
1394
|
-
this.adapter.getForeignObjects(pattern, type, { user: socket._acl.user }, (error, ...args) =>
|
|
1395
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1396
|
-
);
|
|
1397
|
-
} catch (error) {
|
|
1398
|
-
this.adapter.log.error(`[extendObject] ERROR: ${error}`);
|
|
1399
|
-
SocketCommands._fixCallback(callback, error);
|
|
1400
|
-
}
|
|
1401
|
-
} else {
|
|
1402
|
-
this.adapter.log.warn('[getObjects] Invalid callback');
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
};
|
|
1406
|
-
|
|
1407
|
-
this.commands['delObject'] = (socket, id, options, callback) => {
|
|
1408
|
-
// Delete an object or objects recursively. Objects with `dontDelete` cannot be deleted.
|
|
1409
|
-
// @param {string} id - Object ID like, 'adapterName.0.channel'
|
|
1410
|
-
// @param {string} options - `{recursive: true}`
|
|
1411
|
-
// @param {function} callback - `function (error)`
|
|
1412
|
-
if (this._checkPermissions(socket, 'delObject', callback, id)) {
|
|
1413
|
-
if (typeof options === 'function') {
|
|
1414
|
-
callback = options;
|
|
1415
|
-
options = null;
|
|
1416
|
-
}
|
|
1417
|
-
if (!options || typeof options !== 'object') {
|
|
1418
|
-
options = {};
|
|
1419
|
-
}
|
|
1420
|
-
options.user = socket._acl.user;
|
|
1421
|
-
try {
|
|
1422
|
-
// options.recursive = true; // the only difference between delObject and delObjects is this line
|
|
1423
|
-
this.adapter.delForeignObject(id, options, (error, ...args) =>
|
|
1424
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1425
|
-
);
|
|
1426
|
-
} catch (error) {
|
|
1427
|
-
this.adapter.log.error(`[delObject] ERROR: ${error}`);
|
|
1428
|
-
SocketCommands._fixCallback(callback, error);
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
};
|
|
1432
|
-
|
|
1433
|
-
this.commands['delObjects'] = (socket, id, options, callback) => {
|
|
1434
|
-
// Delete objects recursively. Objects with `dontDelete` cannot be deleted. Same as `delObject` but with `recursive: true`.
|
|
1435
|
-
// @param {string} id - Object ID like, 'adapterName.0.channel'
|
|
1436
|
-
// @param {string} options - optional
|
|
1437
|
-
// @param {function} callback - `function (error)`
|
|
1438
|
-
if (this._checkPermissions(socket, 'delObject', callback, id)) {
|
|
1439
|
-
if (!options || typeof options !== 'object') {
|
|
1440
|
-
options = {};
|
|
1441
|
-
}
|
|
1442
|
-
options.user = socket._acl.user;
|
|
1443
|
-
options.recursive = true; // the only difference between delObject and delObjects is this line
|
|
1444
|
-
try {
|
|
1445
|
-
this.adapter.delForeignObject(id, options, (error, ...args) =>
|
|
1446
|
-
SocketCommands._fixCallback(callback, error, ...args)
|
|
1447
|
-
);
|
|
1448
|
-
} catch (error) {
|
|
1449
|
-
this.adapter.log.error(`[delObjects] ERROR: ${error}`);
|
|
1450
|
-
SocketCommands._fixCallback(callback, error);
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
stateChange(id, state) {
|
|
1457
|
-
if (this.states) {
|
|
1458
|
-
if (!state) {
|
|
1459
|
-
if (this.states[id]) {
|
|
1460
|
-
delete this.states[id];
|
|
1461
|
-
}
|
|
1462
|
-
} else {
|
|
1463
|
-
this.states[id] = state;
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
if (!this.eventsThreshold.active) {
|
|
1468
|
-
this.eventsThreshold.count++;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
sendCommand(obj) {
|
|
1473
|
-
if (this.cmdSessions[obj.message.id]) {
|
|
1474
|
-
if (obj.command === 'cmdExit') {
|
|
1475
|
-
delete this.cmdSessions[obj.message.id];
|
|
1476
|
-
}
|
|
1477
|
-
return true;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
destroy() {
|
|
1482
|
-
this.thersholdInterval && clearInterval(this.thersholdInterval);
|
|
1483
|
-
this.thersholdInterval = null;
|
|
1484
|
-
|
|
1485
|
-
this.cacheGB && clearInterval(this.cacheGB);
|
|
1486
|
-
this.cacheGB = null;
|
|
1487
|
-
|
|
1488
|
-
super.destroy();
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
|
|
1492
|
-
module.exports = SocketCommandsAdmin;
|