@iobroker/db-objects-file 4.0.21 → 4.1.0-alpha.0-20220819-74ceeddc

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.
@@ -6,20 +6,17 @@
6
6
  * MIT License
7
7
  *
8
8
  */
9
-
10
9
  /* jshint -W097 */
11
10
  /* jshint strict: false */
12
11
  /* jslint node: true */
13
12
  /* jshint -W061 */
14
13
  'use strict';
15
-
16
14
  const fs = require('fs-extra');
17
15
  const path = require('path');
18
- const InMemoryFileDB = require('@iobroker/db-base').inMemoryFileDB;
16
+ const { InMemoryFileDB } = require('@iobroker/db-base');
19
17
  const tools = require('@iobroker/db-base').tools;
20
18
  const utils = require('@iobroker/db-objects-redis').objectsUtils;
21
19
  const deepClone = require('deep-clone');
22
-
23
20
  /**
24
21
  * This class inherits InMemoryFileDB class and adds all relevant logic for objects
25
22
  * including the available methods for use by js-controller directly
@@ -32,7 +29,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
32
29
  backupDirName: 'backup-objects'
33
30
  };
34
31
  super(settings);
35
-
36
32
  if (!this.change) {
37
33
  this.change = id => {
38
34
  this.log.silly(`${this.namespace} objects change: ${id} ${JSON.stringify(this.change)}`);
@@ -52,12 +48,9 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
52
48
  if (!settings.jsonlDB) {
53
49
  this.log.silly(`${this.namespace} Objects DB uses file write interval of ${this.writeFileInterval} ms`);
54
50
  }
55
-
56
51
  this.objectsDir = path.join(this.dataDir, 'files');
57
-
58
52
  // cached meta information for file operations
59
53
  this.existingMetaObjects = {};
60
-
61
54
  // Handle some < js-controller 2.0 broken objects and correct them
62
55
  for (const key of Object.keys(this.dataset)) {
63
56
  const obj = this.dataset[key];
@@ -67,19 +60,16 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
67
60
  this.dataset[key] = obj;
68
61
  }
69
62
  }
70
-
71
63
  // init default new acl
72
64
  const configObj = this.dataset['system.config'];
73
65
  if (configObj && configObj.common && configObj.common.defaultNewAcl) {
74
66
  this.defaultNewAcl = deepClone(configObj.common.defaultNewAcl);
75
67
  }
76
68
  }
77
-
78
69
  // internal functionality
79
70
  _normalizeFilename(name) {
80
71
  return name ? name.replace(/[/\\]+/g, '/') : name;
81
72
  }
82
-
83
73
  // -------------- FILE FUNCTIONS -------------------------------------------
84
74
  // internal functionality
85
75
  _saveFileSettings(id, force) {
@@ -87,11 +77,8 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
87
77
  force = id;
88
78
  id = undefined;
89
79
  }
90
-
91
80
  id !== undefined && !this.writeIds.includes(id) && this.writeIds.push(id);
92
-
93
81
  this.writeTimer && clearTimeout(this.writeTimer);
94
-
95
82
  // if store immediately
96
83
  if (force) {
97
84
  this.writeTimer = null;
@@ -102,19 +89,22 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
102
89
  if (fs.existsSync(path.join(this.objectsDir, this.writeIds[_id]))) {
103
90
  fs.writeFileSync(location, JSON.stringify(this.fileOptions[this.writeIds[_id]]));
104
91
  }
105
- } catch (e) {
92
+ }
93
+ catch (e) {
106
94
  this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`);
107
95
  }
108
96
  }
109
97
  this.writeIds = [];
110
- } else {
98
+ }
99
+ else {
111
100
  this.writeTimer = setTimeout(() => {
112
101
  // Store dirs description
113
102
  for (let id = 0; id < this.writeIds.length; id++) {
114
103
  const location = path.join(this.objectsDir, this.writeIds[id], '_data.json');
115
104
  try {
116
105
  fs.writeFileSync(location, JSON.stringify(this.fileOptions[this.writeIds[id]]));
117
- } catch (e) {
106
+ }
107
+ catch (e) {
118
108
  this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`);
119
109
  }
120
110
  }
@@ -122,7 +112,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
122
112
  }, 1000);
123
113
  }
124
114
  }
125
-
126
115
  // internal functionality
127
116
  _loadFileSettings(id) {
128
117
  if (!this.fileOptions[id]) {
@@ -130,7 +119,8 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
130
119
  if (fs.existsSync(location)) {
131
120
  try {
132
121
  this.fileOptions[id] = fs.readJSONSync(location);
133
- } catch (e) {
122
+ }
123
+ catch (e) {
134
124
  this.log.error(`${this.namespace} Cannot parse ${location}: ${e.message}`);
135
125
  this.fileOptions[id] = {};
136
126
  }
@@ -146,22 +136,22 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
146
136
  if (corrected) {
147
137
  try {
148
138
  fs.writeFileSync(location, JSON.stringify(this.fileOptions[id]));
149
- } catch (e) {
139
+ }
140
+ catch (e) {
150
141
  this.log.error(`${this.namespace} Cannot write files: ${location}: ${e.message}`);
151
142
  }
152
143
  }
153
144
  });
154
- } else {
145
+ }
146
+ else {
155
147
  this.fileOptions[id] = {};
156
148
  }
157
149
  }
158
150
  }
159
-
160
151
  // server only functionality
161
152
  syncFileDirectory(limitId) {
162
153
  const resNotifies = [];
163
154
  let resSynced = 0;
164
-
165
155
  function getAllFiles(dir) {
166
156
  let results = [];
167
157
  const list = fs.readdirSync(dir);
@@ -171,19 +161,17 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
171
161
  if (stat && stat.isDirectory()) {
172
162
  /* Recurse into a subdirectory */
173
163
  results = results.concat(getAllFiles(file));
174
- } else {
164
+ }
165
+ else {
175
166
  /* Is a file */
176
167
  results.push(file);
177
168
  }
178
169
  });
179
170
  return results;
180
171
  }
181
-
182
172
  const res = this._getObjectView('system', 'meta', null);
183
-
184
173
  // collect meta ids to generate warning if non existing
185
174
  const metaIds = res.rows.map(obj => obj.id).filter(id => !limitId || limitId === id);
186
-
187
175
  if (!fs.existsSync(this.objectsDir)) {
188
176
  return {
189
177
  numberSuccess: resSynced,
@@ -205,9 +193,7 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
205
193
  return;
206
194
  }
207
195
  if (!metaIds.includes(dir)) {
208
- resNotifies.push(
209
- `Ignoring Directory "${dir}" because officially not created as meta object. Please remove directory!`
210
- );
196
+ resNotifies.push(`Ignoring Directory "${dir}" because officially not created as meta object. Please remove directory!`);
211
197
  return;
212
198
  }
213
199
  this._loadFileSettings(dir);
@@ -223,16 +209,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
223
209
  const mime = utils.getMimeType(ext);
224
210
  const _mimeType = mime.mimeType;
225
211
  const isBinary = mime.isBinary;
226
-
227
212
  this.fileOptions[dir][localFile] = {
228
213
  createdAt: fileStat.ctimeMs,
229
214
  acl: {
230
215
  owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
231
- ownerGroup:
232
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
216
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
233
217
  utils.CONSTS.SYSTEM_ADMIN_GROUP,
234
- permissions:
235
- (this.defaultNewAcl && this.defaultNewAcl.file) ||
218
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file) ||
236
219
  utils.CONSTS.ACCESS_USER_RW |
237
220
  utils.CONSTS.ACCESS_GROUP_READ |
238
221
  utils.CONSTS.ACCESS_EVERY_READ // 0x644
@@ -253,7 +236,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
253
236
  notifications: resNotifies
254
237
  };
255
238
  }
256
-
257
239
  // needed by server
258
240
  _writeFile(id, name, data, options) {
259
241
  if (typeof options === 'string') {
@@ -262,17 +244,12 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
262
244
  if (options && options.acl) {
263
245
  options.acl = null;
264
246
  }
265
-
266
247
  const _path = utils.sanitizePath(id, name);
267
248
  id = _path.id;
268
249
  name = _path.name;
269
-
270
250
  options = options || {};
271
-
272
251
  this._loadFileSettings(id);
273
-
274
252
  this.files[id] = this.files[id] || {};
275
-
276
253
  try {
277
254
  if (!fs.existsSync(this.objectsDir)) {
278
255
  fs.mkdirSync(this.objectsDir);
@@ -280,42 +257,33 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
280
257
  if (!fs.existsSync(path.join(this.objectsDir, id))) {
281
258
  fs.mkdirSync(path.join(this.objectsDir, id));
282
259
  }
283
- } catch (e) {
284
- this.log.error(
285
- `${this.namespace} Cannot create directories: ${path.join(this.objectsDir, id)}: ${e.message}`
286
- );
287
- this.log.error(
288
- `${this.namespace} Check the permissions! Or run installation fixer or "iobroker fix" command!`
289
- );
260
+ }
261
+ catch (e) {
262
+ this.log.error(`${this.namespace} Cannot create directories: ${path.join(this.objectsDir, id)}: ${e.message}`);
263
+ this.log.error(`${this.namespace} Check the permissions! Or run installation fixer or "iobroker fix" command!`);
290
264
  throw e;
291
265
  }
292
-
293
266
  const ext = path.extname(name);
294
267
  const mime = utils.getMimeType(ext);
295
268
  const _mimeType = mime.mimeType;
296
269
  const isBinary = mime.isBinary;
297
-
298
270
  this.fileOptions[id][name] = this.fileOptions[id][name] || { createdAt: Date.now() };
299
271
  this.fileOptions[id][name].acl = this.fileOptions[id][name].acl || {
300
272
  owner: options.user || (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
301
- ownerGroup:
302
- options.group ||
273
+ ownerGroup: options.group ||
303
274
  (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
304
275
  utils.CONSTS.SYSTEM_ADMIN_GROUP,
305
- permissions:
306
- options.mode ||
276
+ permissions: options.mode ||
307
277
  (this.defaultNewAcl && this.defaultNewAcl.file) ||
308
278
  utils.CONSTS.ACCESS_USER_RW | utils.CONSTS.ACCESS_GROUP_READ | utils.CONSTS.ACCESS_EVERY_READ // 0x644
309
279
  };
310
-
311
280
  this.fileOptions[id][name].mimeType = options.mimeType || _mimeType;
312
281
  this.fileOptions[id][name].binary = isBinary;
313
282
  this.fileOptions[id][name].acl.ownerGroup =
314
283
  this.fileOptions[id][name].acl.ownerGroup ||
315
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
316
- utils.CONSTS.SYSTEM_ADMIN_GROUP;
284
+ (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
285
+ utils.CONSTS.SYSTEM_ADMIN_GROUP;
317
286
  this.fileOptions[id][name].modifiedAt = Date.now();
318
-
319
287
  try {
320
288
  // Create directories if complex structure
321
289
  fs.ensureDirSync(path.join(this.objectsDir, id, path.dirname(name)));
@@ -324,40 +292,38 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
324
292
  flag: 'w',
325
293
  encoding: isBinary ? 'binary' : 'utf8'
326
294
  });
327
-
328
295
  if (isBinary) {
329
296
  // Reload by read
330
297
  delete this.files[id][name];
331
- } else {
298
+ }
299
+ else {
332
300
  this.files[id][name] = data;
333
301
  }
334
-
335
302
  // Store dir description
336
303
  this._saveFileSettings(id);
337
- } catch (e) {
338
- this.log.error(
339
- `${this.namespace} Cannot write files: ${path.join(this.objectsDir, id, name)}: ${e.message}`
340
- );
304
+ }
305
+ catch (e) {
306
+ this.log.error(`${this.namespace} Cannot write files: ${path.join(this.objectsDir, id, name)}: ${e.message}`);
341
307
  throw e;
342
308
  }
309
+ setImmediate((name, size) => {
310
+ // publish event in states
311
+ this.log.silly(`${this.namespace} memory publish ${id} ${JSON.stringify({ name, file: true, size })}`);
312
+ this.publishAll('files', `${id}$%$${name}`, size);
313
+ }, name, data.byteLength);
343
314
  }
344
-
345
315
  // needed by server
346
316
  _readFile(id, name, options) {
347
317
  if (options && options.acl) {
348
318
  options.acl = null;
349
319
  }
350
-
351
320
  const _path = utils.sanitizePath(id, name);
352
321
  id = _path.id;
353
322
  name = _path.name;
354
-
355
323
  options = options || {};
356
324
  try {
357
325
  this._loadFileSettings(id);
358
-
359
326
  this.files[id] = this.files[id] || {};
360
-
361
327
  if (!this.files[id][name] || this.settings.connection.noFileCache || options.noFileCache) {
362
328
  const location = path.join(this.objectsDir, id, name);
363
329
  if (fs.existsSync(location)) {
@@ -365,11 +331,9 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
365
331
  this.fileOptions[id][name] = this.fileOptions[id][name] || {
366
332
  acl: {
367
333
  owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
368
- ownerGroup:
369
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
334
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
370
335
  utils.CONSTS.SYSTEM_ADMIN_GROUP,
371
- permissions:
372
- (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
336
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
373
337
  utils.CONSTS.ACCESS_USER_ALL |
374
338
  utils.CONSTS.ACCESS_GROUP_ALL |
375
339
  utils.CONSTS.ACCESS_EVERY_ALL // 777
@@ -379,20 +343,16 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
379
343
  this.fileOptions[id][name] = {
380
344
  mimeType: this.fileOptions[id][name],
381
345
  acl: {
382
- owner:
383
- (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
384
- ownerGroup:
385
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
346
+ owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
347
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
386
348
  utils.CONSTS.SYSTEM_ADMIN_GROUP,
387
- permissions:
388
- (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
349
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
389
350
  utils.CONSTS.ACCESS_USER_ALL |
390
351
  utils.CONSTS.ACCESS_GROUP_ALL |
391
352
  utils.CONSTS.ACCESS_EVERY_ALL // 777
392
353
  }
393
354
  };
394
355
  }
395
-
396
356
  this.files[id][name] = fs.readFileSync(location);
397
357
  if (this.fileOptions[id][name].binary === undefined) {
398
358
  const ext = path.extname(name);
@@ -400,13 +360,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
400
360
  this.fileOptions[id][name].binary = mimeType.isBinary;
401
361
  this.fileOptions[id][name].mimeType = mimeType.mimeType;
402
362
  }
403
-
404
363
  if (!this.fileOptions[id][name].binary) {
405
364
  if (this.files[id][name]) {
406
365
  this.files[id][name] = this.files[id][name].toString();
407
366
  }
408
367
  }
409
- } else {
368
+ }
369
+ else {
410
370
  if (this.fileOptions[id][name] !== undefined) {
411
371
  delete this.fileOptions[id][name];
412
372
  }
@@ -415,19 +375,15 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
415
375
  }
416
376
  }
417
377
  }
418
-
419
378
  if (this.fileOptions[id][name] && !this.fileOptions[id][name].acl) {
420
379
  // all files belongs to admin by default, but everyone can edit it
421
380
  this.fileOptions[id][name].acl = {
422
381
  owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
423
- ownerGroup:
424
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) || utils.CONSTS.SYSTEM_ADMIN_GROUP,
425
- permissions:
426
- (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
382
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) || utils.CONSTS.SYSTEM_ADMIN_GROUP,
383
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
427
384
  utils.CONSTS.ACCESS_USER_ALL | utils.CONSTS.ACCESS_GROUP_ALL | utils.CONSTS.ACCESS_EVERY_RW // 776
428
385
  };
429
386
  }
430
-
431
387
  if (this.fileOptions[id][name] !== null && this.fileOptions[id][name] !== undefined) {
432
388
  if (!this.fileOptions[id][name].mimeType) {
433
389
  const _ext = path.extname(name);
@@ -439,13 +395,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
439
395
  fileMime: this.fileOptions[id][name].mimeType
440
396
  };
441
397
  }
442
- } catch (e) {
398
+ }
399
+ catch (e) {
443
400
  this.log.warn(`${this.namespace} Cannot read file ${id} / ${name}: ${e.message}`);
444
401
  throw e;
445
402
  }
446
403
  throw new Error(utils.ERRORS.ERROR_NOT_FOUND);
447
404
  }
448
-
449
405
  /**
450
406
  * Check if given object exists
451
407
  *
@@ -458,16 +414,15 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
458
414
  if (!id || typeof id !== 'string') {
459
415
  throw new Error(`invalid id ${JSON.stringify(id)}`);
460
416
  }
461
-
462
417
  try {
463
418
  // check if the id exists
464
419
  return Object.prototype.hasOwnProperty.call(this.dataset, id);
465
- } catch (e) {
420
+ }
421
+ catch (e) {
466
422
  this.log.error(`${this.namespace} Cannot check object existence of "${id}": ${e.message}`);
467
423
  throw new Error(`Cannot check object existence of "${id}": ${e.message}`);
468
424
  }
469
425
  }
470
-
471
426
  /**
472
427
  * Check if given file exists
473
428
  *
@@ -480,13 +435,12 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
480
435
  if (typeof name !== 'string') {
481
436
  name = '';
482
437
  }
483
-
484
438
  const location = path.join(this.objectsDir, id, name);
485
-
486
439
  try {
487
440
  const stat = fs.statSync(location);
488
441
  return stat.isFile();
489
- } catch (e) {
442
+ }
443
+ catch (e) {
490
444
  if (e.code !== 'ENOENT') {
491
445
  this.log.error(`${this.namespace} Cannot check file existence of "${location}": ${e.message}`);
492
446
  throw new Error(`Cannot check file existence of "${location}": ${e.message}`);
@@ -494,7 +448,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
494
448
  return false;
495
449
  }
496
450
  }
497
-
498
451
  /**
499
452
  * Check if given directory exists
500
453
  *
@@ -507,13 +460,12 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
507
460
  if (typeof name !== 'string') {
508
461
  name = '';
509
462
  }
510
-
511
463
  const location = path.join(this.objectsDir, id, name);
512
-
513
464
  try {
514
465
  const stat = fs.statSync(location);
515
466
  return stat.isDirectory();
516
- } catch (e) {
467
+ }
468
+ catch (e) {
517
469
  if (e.code !== 'ENOENT') {
518
470
  this.log.error(`${this.namespace} Cannot check directory existence of "${location}": ${e.message}`);
519
471
  throw new Error(`Cannot check directory existence of "${location}": ${e.message}`);
@@ -521,59 +473,58 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
521
473
  return false;
522
474
  }
523
475
  }
524
-
525
476
  // needed by server
526
477
  _unlink(id, name) {
527
478
  const _path = utils.sanitizePath(id, name);
528
479
  id = _path.id;
529
480
  name = _path.name;
530
-
531
481
  this._loadFileSettings(id);
532
-
533
482
  const location = path.join(this.objectsDir, id, name);
534
483
  if (fs.existsSync(location)) {
535
484
  const stat = fs.statSync(location);
536
-
537
485
  if (stat.isDirectory()) {
538
486
  // read all entries and delete every one
539
487
  fs.readdirSync(location).forEach(dir => this._unlink(id, name + '/' + dir));
540
-
541
488
  this.log.debug('Delete directory ' + path.join(id, name));
542
489
  try {
543
490
  fs.removeSync(location);
544
- } catch (e) {
491
+ }
492
+ catch (e) {
545
493
  this.log.error(`${this.namespace} Cannot delete directory "${path.join(id, name)}": ${e.message}`);
546
494
  throw e;
547
495
  }
548
-
549
496
  if (this.fileOptions[id]) {
550
497
  delete this.fileOptions[id];
551
498
  }
552
499
  if (this.files[id] && this.files[id]) {
553
500
  delete this.files[id];
554
501
  }
555
- } else {
502
+ }
503
+ else {
556
504
  this.log.debug('Delete file ' + path.join(id, name));
557
505
  try {
558
506
  fs.removeSync(location);
559
- } catch (e) {
507
+ }
508
+ catch (e) {
560
509
  this.log.error(`${this.namespace} Cannot delete file "${path.join(id, name)}": ${e.message}`);
561
510
  throw e;
562
511
  }
563
-
564
512
  if (this.fileOptions[id][name]) {
565
513
  delete this.fileOptions[id][name];
566
514
  }
567
515
  if (this.files[id] && this.files[id][name]) {
568
516
  delete this.files[id][name];
569
517
  }
570
-
571
518
  // Store dir description
572
519
  this._saveFileSettings(id, true);
573
520
  }
521
+ setImmediate((id, name) => {
522
+ // publish event in states
523
+ this.log.silly(`${this.namespace} memory publish ${id} ${JSON.stringify({ name, file: true, size: null })}`);
524
+ this.publishAll('files', `${id}$%$${name}`, null);
525
+ }, id, name);
574
526
  }
575
527
  }
576
-
577
528
  // needed by server
578
529
  _readDir(id, name, options) {
579
530
  if (options && options.acl) {
@@ -581,25 +532,22 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
581
532
  }
582
533
  if ((id === '' || id === '/' || id === '*') && (name === '' || name === '*')) {
583
534
  // read root of xxx-data/files
584
- } else {
535
+ }
536
+ else {
585
537
  const _path = utils.sanitizePath(id, name);
586
538
  id = _path.id;
587
539
  name = _path.name;
588
540
  }
589
-
590
541
  options = options || {};
591
542
  // Find all files and directories starts with name
592
543
  const _files = [];
593
-
594
544
  if (id && id === '*') {
595
545
  id = '';
596
546
  }
597
547
  if (name && name[name.length - 1] !== '/') {
598
548
  name += '/';
599
549
  }
600
-
601
550
  this._loadFileSettings(id);
602
-
603
551
  const len = name ? name.length : 0;
604
552
  for (const f of Object.keys(this.fileOptions[id])) {
605
553
  if (!name || f.substring(0, len) === name) {
@@ -611,7 +559,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
611
559
  }
612
560
  }
613
561
  }
614
-
615
562
  const location = path.join(this.objectsDir, id, name);
616
563
  if (fs.existsSync(location)) {
617
564
  const dirFiles = fs.readdirSync(location);
@@ -623,10 +570,10 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
623
570
  _files.push(dirFiles[i]);
624
571
  }
625
572
  }
626
- } else {
573
+ }
574
+ else {
627
575
  throw new Error(utils.ERRORS.ERROR_NOT_FOUND);
628
576
  }
629
-
630
577
  _files.sort();
631
578
  const res = [];
632
579
  for (let j = 0; j < _files.length; j++) {
@@ -636,50 +583,38 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
636
583
  if (fs.existsSync(path.join(location, _files[j]))) {
637
584
  try {
638
585
  const stats = fs.statSync(path.join(location, _files[j]));
639
- const acl =
640
- this.fileOptions[id][name + _files[j]] && this.fileOptions[id][name + _files[j]].acl
641
- ? JSON.parse(JSON.stringify(this.fileOptions[id][name + _files[j]].acl)) // copy settings
642
- : {
643
- read: true,
644
- write: true,
645
- owner:
646
- (this.defaultNewAcl && this.defaultNewAcl.owner) ||
647
- utils.CONSTS.SYSTEM_ADMIN_USER,
648
- ownerGroup:
649
- (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
650
- utils.CONSTS.SYSTEM_ADMIN_GROUP,
651
- permissions:
652
- (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
653
- utils.CONSTS.ACCESS_USER_RW |
654
- utils.CONSTS.ACCESS_GROUP_READ |
655
- utils.CONSTS.ACCESS_EVERY_READ
656
- };
657
-
586
+ const acl = this.fileOptions[id][name + _files[j]] && this.fileOptions[id][name + _files[j]].acl
587
+ ? deepClone(this.fileOptions[id][name + _files[j]].acl) // copy settings
588
+ : {
589
+ read: true,
590
+ write: true,
591
+ owner: (this.defaultNewAcl && this.defaultNewAcl.owner) ||
592
+ utils.CONSTS.SYSTEM_ADMIN_USER,
593
+ ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
594
+ utils.CONSTS.SYSTEM_ADMIN_GROUP,
595
+ permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
596
+ utils.CONSTS.ACCESS_USER_RW |
597
+ utils.CONSTS.ACCESS_GROUP_READ |
598
+ utils.CONSTS.ACCESS_EVERY_READ
599
+ };
658
600
  // if filter for user
659
601
  if (options.filter && acl) {
660
602
  // If user may not write
661
603
  if (!options.acl.file.write) {
662
604
  // write
663
- acl.permissions &= ~(
664
- utils.CONSTS.ACCESS_USER_WRITE |
605
+ acl.permissions &= ~(utils.CONSTS.ACCESS_USER_WRITE |
665
606
  utils.CONSTS.ACCESS_GROUP_WRITE |
666
- utils.CONSTS.ACCESS_EVERY_WRITE
667
- );
607
+ utils.CONSTS.ACCESS_EVERY_WRITE);
668
608
  }
669
609
  // If user may not read
670
610
  if (!options.acl.file.read) {
671
611
  // read
672
- acl.permissions &= ~(
673
- utils.CONSTS.ACCESS_USER_READ |
612
+ acl.permissions &= ~(utils.CONSTS.ACCESS_USER_READ |
674
613
  utils.CONSTS.ACCESS_GROUP_READ |
675
- utils.CONSTS.ACCESS_EVERY_READ
676
- );
614
+ utils.CONSTS.ACCESS_EVERY_READ);
677
615
  }
678
-
679
- if (
680
- options.user !== utils.CONSTS.SYSTEM_ADMIN_USER &&
681
- options.groups.includes(utils.CONSTS.SYSTEM_ADMIN_GROUP)
682
- ) {
616
+ if (options.user !== utils.CONSTS.SYSTEM_ADMIN_USER &&
617
+ options.groups.includes(utils.CONSTS.SYSTEM_ADMIN_GROUP)) {
683
618
  if (acl.owner !== options.user) {
684
619
  // Check if the user is in the group
685
620
  if (options.groups.includes(acl.ownerGroup)) {
@@ -689,7 +624,8 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
689
624
  }
690
625
  acl.read = !!(acl.permissions & utils.CONSTS.ACCESS_GROUP_READ);
691
626
  acl.write = !!(acl.permissions & utils.CONSTS.ACCESS_GROUP_WRITE);
692
- } else {
627
+ }
628
+ else {
693
629
  // everybody
694
630
  if (!(acl.permissions & utils.CONSTS.ACCESS_EVERY_RW)) {
695
631
  continue;
@@ -697,7 +633,8 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
697
633
  acl.read = !!(acl.permissions & utils.CONSTS.ACCESS_EVERY_READ);
698
634
  acl.write = !!(acl.permissions & utils.CONSTS.ACCESS_EVERY_WRITE);
699
635
  }
700
- } else {
636
+ }
637
+ else {
701
638
  // Check user rights
702
639
  if (!(acl.permissions & utils.CONSTS.ACCESS_USER_RW)) {
703
640
  continue;
@@ -705,12 +642,12 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
705
642
  acl.read = !!(acl.permissions & utils.CONSTS.ACCESS_USER_READ);
706
643
  acl.write = !!(acl.permissions & utils.CONSTS.ACCESS_USER_WRITE);
707
644
  }
708
- } else {
645
+ }
646
+ else {
709
647
  acl.read = true;
710
648
  acl.write = true;
711
649
  }
712
650
  }
713
-
714
651
  res.push({
715
652
  file: _files[j],
716
653
  stats: stats,
@@ -723,22 +660,14 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
723
660
  ? this.fileOptions[id][name + _files[j]].createdAt
724
661
  : undefined
725
662
  });
726
- } catch (e) {
727
- this.log.error(
728
- `${this.namespace} Cannot read permissions of ${path.join(
729
- this.objectsDir,
730
- id,
731
- name,
732
- _files[j]
733
- )}: ${e.message}`
734
- );
663
+ }
664
+ catch (e) {
665
+ this.log.error(`${this.namespace} Cannot read permissions of ${path.join(this.objectsDir, id, name, _files[j])}: ${e.message}`);
735
666
  }
736
667
  }
737
668
  }
738
-
739
669
  return res;
740
670
  }
741
-
742
671
  // needed by server
743
672
  _rename(id, oldName, newName) {
744
673
  const _path = utils.sanitizePath(id, oldName);
@@ -747,15 +676,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
747
676
  if (newName[0] === '/') {
748
677
  newName = newName.substring(1);
749
678
  }
750
-
751
679
  this._loadFileSettings(id);
752
-
753
680
  if (fs.existsSync(path.join(this.objectsDir, id, oldName))) {
754
681
  fs.renameSync(path.join(this.objectsDir, id, oldName), path.join(this.objectsDir, id, newName));
755
- } else {
682
+ }
683
+ else {
756
684
  throw new Error(utils.ERRORS.ERROR_NOT_FOUND);
757
685
  }
758
-
759
686
  Object.keys(this.fileOptions[id]).forEach(name => {
760
687
  const type = this.fileOptions[id][name];
761
688
  if (name.startsWith(oldName)) {
@@ -772,39 +699,50 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
772
699
  });
773
700
  this._saveFileSettings(id, true);
774
701
  }
775
-
776
702
  // internal functionality
777
703
  _clone(obj) {
778
704
  if (obj === null || obj === undefined || !tools.isObject(obj)) {
779
705
  return obj;
780
706
  }
781
-
782
707
  const temp = obj.constructor(); // changed
783
-
784
708
  for (const key of Object.keys(obj)) {
785
709
  temp[key] = this._clone(obj[key]);
786
710
  }
787
711
  return temp;
788
712
  }
789
-
713
+ _subscribeMeta(client, pattern) {
714
+ this.handleSubscribe(client, 'meta', pattern);
715
+ }
790
716
  // needed by server
791
717
  _subscribeConfigForClient(client, pattern) {
792
718
  this.handleSubscribe(client, 'objects', pattern);
793
719
  }
794
-
795
- _subscribeMeta(client, pattern) {
796
- this.handleSubscribe(client, 'meta', pattern);
797
- }
798
720
  // needed by server
799
721
  _unsubscribeConfigForClient(client, pattern) {
800
722
  this.handleUnsubscribe(client, 'objects', pattern); // ignore options => unsubscribe may everyone
801
723
  }
802
-
724
+ // needed by server
725
+ _subscribeFileForClient(client, id, pattern) {
726
+ if (Array.isArray(pattern)) {
727
+ pattern.forEach(pattern => this.handleSubscribe(client, 'files', `${id}$%$${pattern}`));
728
+ }
729
+ else {
730
+ this.handleSubscribe(client, 'files', `${id}$%$${pattern}`);
731
+ }
732
+ }
733
+ // needed by server
734
+ _unsubscribeFileForClient(client, id, pattern) {
735
+ if (Array.isArray(pattern)) {
736
+ pattern.forEach(pattern => this.handleUnsubscribe(client, 'files', `${id}$%$${pattern}`));
737
+ }
738
+ else {
739
+ this.handleUnsubscribe(client, 'files', `${id}$%$${pattern}`);
740
+ }
741
+ }
803
742
  // needed by server
804
743
  _getObject(id) {
805
744
  return this.dataset[id];
806
745
  }
807
-
808
746
  // needed by server
809
747
  _getKeys(pattern) {
810
748
  const r = new RegExp(tools.pattern2RegEx(pattern));
@@ -812,16 +750,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
812
750
  result.sort();
813
751
  return result;
814
752
  }
815
-
816
753
  // needed by server
817
754
  _getObjects(keys) {
818
755
  if (!keys) {
819
756
  throw new Error('no keys');
820
757
  }
821
-
822
758
  return keys.map(id => this.dataset[id]);
823
759
  }
824
-
825
760
  _ensureMetaDict() {
826
761
  let meta = this.dataset['**META**'];
827
762
  if (!meta) {
@@ -830,7 +765,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
830
765
  }
831
766
  return meta;
832
767
  }
833
-
834
768
  /**
835
769
  * Get value of given meta id
836
770
  *
@@ -841,7 +775,6 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
841
775
  const meta = this._ensureMetaDict();
842
776
  return meta[id];
843
777
  }
844
-
845
778
  /**
846
779
  * Sets given value to id in metaNamespace
847
780
  *
@@ -853,70 +786,54 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
853
786
  meta[id] = value;
854
787
  // Make sure the object gets re-written, especially when using an external DB
855
788
  this.dataset['**META**'] = meta;
856
-
857
789
  setImmediate(() => {
858
790
  // publish event in states
859
791
  this.log.silly(`${this.namespace} memory publish meta ${id} ${value}`);
860
792
  this.publishAll('meta', id, value);
861
793
  });
862
-
863
794
  if (!this.stateTimer) {
864
795
  this.stateTimer = setTimeout(() => this.saveState(), this.writeFileInterval);
865
796
  }
866
797
  }
867
-
868
798
  // needed by server
869
799
  _setObjectDirect(id, obj) {
870
800
  this.dataset[id] = obj;
871
-
872
801
  // object updated -> if type changed to meta -> cache
873
802
  if (obj.type === 'meta' && this.existingMetaObjects[id] === false) {
874
803
  this.existingMetaObjects[id] = true;
875
804
  }
876
-
877
805
  setImmediate(() => this.publishAll('objects', id, obj));
878
-
879
806
  this.stateTimer = this.stateTimer || setTimeout(() => this.saveState(), this.writeFileInterval);
880
807
  }
881
-
882
808
  // needed by server
883
809
  _delObject(id) {
884
810
  const obj = this.dataset[id];
885
811
  if (!obj) {
886
812
  throw new Error(utils.ERRORS.ERROR_NOT_FOUND);
887
813
  }
888
-
889
814
  if (obj.common && obj.common.dontDelete) {
890
815
  throw new Error('Object is marked as non deletable');
891
816
  }
892
-
893
817
  delete this.dataset[id];
894
-
895
818
  // object has been deleted -> remove from cached meta if there
896
819
  if (this.existingMetaObjects[id]) {
897
820
  this.existingMetaObjects[id] = false;
898
821
  }
899
-
900
822
  setImmediate(() => this.publishAll('objects', id, null));
901
-
902
823
  if (!this.stateTimer) {
903
824
  this.stateTimer = setTimeout(() => this.saveState(), this.writeFileInterval);
904
825
  }
905
826
  }
906
-
907
827
  // internal functionality
908
828
  _applyView(func, params) {
909
829
  const result = {
910
830
  rows: []
911
831
  };
912
-
913
832
  // eslint-disable-next-line no-unused-vars
914
833
  function _emit_(id, obj) {
915
834
  result.rows.push({ id: id, value: obj });
916
835
  }
917
-
918
836
  const f = eval('(' + func.map.replace(/emit/g, '_emit_') + ')');
919
-
920
837
  for (const id of Object.keys(this.dataset)) {
921
838
  if (params) {
922
839
  if (params.startkey && id < params.startkey) {
@@ -930,7 +847,8 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
930
847
  if (obj) {
931
848
  try {
932
849
  f(obj);
933
- } catch (e) {
850
+ }
851
+ catch (e) {
934
852
  this.log.warn(`${this.namespace} Cannot execute map: ${e.message}`);
935
853
  }
936
854
  }
@@ -945,14 +863,13 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
945
863
  }
946
864
  if (max !== null) {
947
865
  result.rows = [{ id: '_stats', value: { max: max } }];
948
- } else {
866
+ }
867
+ else {
949
868
  result.rows = [];
950
869
  }
951
870
  }
952
-
953
871
  return result;
954
872
  }
955
-
956
873
  // needed by server
957
874
  _getObjectView(design, search, params) {
958
875
  const designObj = this.dataset[`_design/${design}`];
@@ -966,11 +883,9 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
966
883
  }
967
884
  return this._applyView(designObj.views[search], params);
968
885
  }
969
-
970
886
  // Destructor of the class. Called by shutting down.
971
887
  async destroy() {
972
888
  await super.destroy();
973
-
974
889
  this._saveFileSettings(true);
975
890
  if (this.stateTimer) {
976
891
  clearTimeout(this.stateTimer);
@@ -982,5 +897,5 @@ class ObjectsInMemoryFileDB extends InMemoryFileDB {
982
897
  }
983
898
  }
984
899
  }
985
-
986
900
  module.exports = ObjectsInMemoryFileDB;
901
+ //# sourceMappingURL=objectsInMemFileDB.js.map