@iobroker/db-objects-redis 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.
- package/build/index.d.ts +5 -0
- package/build/index.js +35 -0
- package/build/lib/objects/constants.d.ts +32 -0
- package/build/lib/objects/constants.d.ts.map +1 -0
- package/build/lib/objects/constants.js +35 -0
- package/build/lib/objects/constants.js.map +1 -0
- package/{lib → build/lib}/objects/lua-v3/custom.lua +0 -0
- package/{lib → build/lib}/objects/lua-v3/filter.lua +0 -0
- package/{lib → build/lib}/objects/lua-v3/programs.lua +0 -0
- package/{lib → build/lib}/objects/lua-v3/script.lua +0 -0
- package/{lib → build/lib}/objects/lua-v3/variables.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/custom.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/filter.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/programs.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/redlock_acquire.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/redlock_extend.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/redlock_release.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/script.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4/variables.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/custom.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/filter.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/programs.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/redlock_acquire.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/redlock_extend.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/redlock_release.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/script.lua +0 -0
- package/{lib → build/lib}/objects/lua-v4-no-sets/variables.lua +0 -0
- package/build/lib/objects/objectsInRedisClient.d.ts +340 -0
- package/build/lib/objects/objectsInRedisClient.d.ts.map +1 -0
- package/{lib → build/lib}/objects/objectsInRedisClient.js +1730 -2130
- package/build/lib/objects/objectsInRedisClient.js.map +1 -0
- package/build/lib/objects/objectsUtils.d.ts +57 -0
- package/build/lib/objects/objectsUtils.d.ts.map +1 -0
- package/build/lib/objects/objectsUtils.js +637 -0
- package/build/lib/objects/objectsUtils.js.map +1 -0
- package/package.json +13 -8
- package/index.js +0 -8
- package/lib/objects/objectsUtils.js +0 -777
|
@@ -1,777 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Common functions between client and server
|
|
3
|
-
*
|
|
4
|
-
* Copyright 2013-2022 bluefox <dogafox@gmail.com>
|
|
5
|
-
*
|
|
6
|
-
* MIT License
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
'use strict';
|
|
11
|
-
const stream = require('stream');
|
|
12
|
-
const Writable = stream.Writable;
|
|
13
|
-
const memStore = {};
|
|
14
|
-
const util = require('util');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const deepClone = require('deep-clone');
|
|
17
|
-
const tools = require('@iobroker/db-base').tools;
|
|
18
|
-
|
|
19
|
-
const userStartsWith = 'system.user.';
|
|
20
|
-
const groupStartsWith = 'system.group.';
|
|
21
|
-
const regCheckId = /[*?[\]]|\$%\$/;
|
|
22
|
-
|
|
23
|
-
const SYSTEM_ADMIN_USER = 'system.user.admin';
|
|
24
|
-
const SYSTEM_ADMIN_GROUP = 'system.group.administrator';
|
|
25
|
-
|
|
26
|
-
const ERROR_PERMISSION = 'permissionError';
|
|
27
|
-
const ERROR_NOT_FOUND = 'Not exists';
|
|
28
|
-
const ERROR_DB_CLOSED = 'DB closed';
|
|
29
|
-
|
|
30
|
-
const ACCESS_EVERY_EXEC = 0x1;
|
|
31
|
-
const ACCESS_EVERY_WRITE = 0x2;
|
|
32
|
-
const ACCESS_EVERY_READ = 0x4;
|
|
33
|
-
const ACCESS_EVERY_RW = ACCESS_EVERY_WRITE | ACCESS_EVERY_READ;
|
|
34
|
-
const ACCESS_EVERY_ALL = ACCESS_EVERY_WRITE | ACCESS_EVERY_READ | ACCESS_EVERY_EXEC;
|
|
35
|
-
|
|
36
|
-
const ACCESS_GROUP_EXEC = 0x10;
|
|
37
|
-
const ACCESS_GROUP_WRITE = 0x20;
|
|
38
|
-
const ACCESS_GROUP_READ = 0x40;
|
|
39
|
-
const ACCESS_GROUP_RW = ACCESS_GROUP_WRITE | ACCESS_GROUP_READ;
|
|
40
|
-
const ACCESS_GROUP_ALL = ACCESS_GROUP_WRITE | ACCESS_GROUP_READ | ACCESS_GROUP_EXEC;
|
|
41
|
-
|
|
42
|
-
const ACCESS_USER_EXEC = 0x100;
|
|
43
|
-
const ACCESS_USER_WRITE = 0x200;
|
|
44
|
-
const ACCESS_USER_READ = 0x400;
|
|
45
|
-
const ACCESS_USER_RW = ACCESS_USER_WRITE | ACCESS_USER_READ;
|
|
46
|
-
const ACCESS_USER_ALL = ACCESS_USER_WRITE | ACCESS_USER_READ | ACCESS_USER_EXEC;
|
|
47
|
-
|
|
48
|
-
const ACCESS_WRITE = 0x2;
|
|
49
|
-
const ACCESS_READ = 0x4;
|
|
50
|
-
const ACCESS_LIST = 'list';
|
|
51
|
-
const ACCESS_DELETE = 'delete';
|
|
52
|
-
const ACCESS_CREATE = 'create';
|
|
53
|
-
|
|
54
|
-
const mimeTypes = {
|
|
55
|
-
'.css': { type: 'text/css', binary: false },
|
|
56
|
-
'.bmp': { type: 'image/bmp', binary: true },
|
|
57
|
-
'.png': { type: 'image/png', binary: true },
|
|
58
|
-
'.jpg': { type: 'image/jpeg', binary: true },
|
|
59
|
-
'.jpeg': { type: 'image/jpeg', binary: true },
|
|
60
|
-
'.gif': { type: 'image/gif', binary: true },
|
|
61
|
-
'.ico': { type: 'image/x-icon', binary: true },
|
|
62
|
-
'.webp': { type: 'image/webp', binary: true },
|
|
63
|
-
'.wbmp': { type: 'image/vnd.wap.wbmp', binary: true },
|
|
64
|
-
'.tif': { type: 'image/tiff', binary: true },
|
|
65
|
-
'.js': { type: 'application/javascript', binary: false },
|
|
66
|
-
'.html': { type: 'text/html', binary: false },
|
|
67
|
-
'.htm': { type: 'text/html', binary: false },
|
|
68
|
-
'.json': { type: 'application/json', binary: false },
|
|
69
|
-
'.md': { type: 'text/markdown', binary: false },
|
|
70
|
-
'.xml': { type: 'text/xml', binary: false },
|
|
71
|
-
'.svg': { type: 'image/svg+xml', binary: false },
|
|
72
|
-
'.eot': { type: 'application/vnd.ms-fontobject', binary: true },
|
|
73
|
-
'.ttf': { type: 'application/font-sfnt', binary: true },
|
|
74
|
-
'.cur': { type: 'application/x-win-bitmap', binary: true },
|
|
75
|
-
'.woff': { type: 'application/font-woff', binary: true },
|
|
76
|
-
'.wav': { type: 'audio/wav', binary: true },
|
|
77
|
-
'.mp3': { type: 'audio/mpeg3', binary: true },
|
|
78
|
-
'.avi': { type: 'video/avi', binary: true },
|
|
79
|
-
'.qt': { type: 'video/quicktime', binary: true },
|
|
80
|
-
'.ppt': { type: 'application/vnd.ms-powerpoint', binary: true },
|
|
81
|
-
'.pptx': { type: 'application/vnd.ms-powerpoint', binary: true },
|
|
82
|
-
'.doc': { type: 'application/msword', binary: true },
|
|
83
|
-
'.docx': { type: 'application/msword', binary: true },
|
|
84
|
-
'.xls': { type: 'application/vnd.ms-excel', binary: true },
|
|
85
|
-
'.xlsx': { type: 'application/vnd.ms-excel', binary: true },
|
|
86
|
-
'.mp4': { type: 'video/mp4', binary: true },
|
|
87
|
-
'.mkv': { type: 'video/mkv', binary: true },
|
|
88
|
-
'.zip': { type: 'application/zip', binary: true },
|
|
89
|
-
'.ogg': { type: 'audio/ogg', binary: true },
|
|
90
|
-
'.manifest': { type: 'text/cache-manifest', binary: false },
|
|
91
|
-
'.pdf': { type: 'application/pdf', binary: true },
|
|
92
|
-
'.gz': { type: 'application/gzip', binary: true },
|
|
93
|
-
'.gzip': { type: 'application/gzip', binary: true }
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
let users = {};
|
|
97
|
-
let groups = {};
|
|
98
|
-
|
|
99
|
-
function getMimeType(ext) {
|
|
100
|
-
if (!ext) {
|
|
101
|
-
return { mimeType: 'text/html', isBinary: false };
|
|
102
|
-
}
|
|
103
|
-
if (ext instanceof Array) {
|
|
104
|
-
ext = ext[0];
|
|
105
|
-
}
|
|
106
|
-
ext = ext.toLowerCase();
|
|
107
|
-
let mimeType = 'text/javascript';
|
|
108
|
-
let isBinary = false;
|
|
109
|
-
|
|
110
|
-
if (mimeTypes[ext]) {
|
|
111
|
-
mimeType = mimeTypes[ext].type;
|
|
112
|
-
isBinary = mimeTypes[ext].binary;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return { mimeType, isBinary };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @class
|
|
120
|
-
* Writable memory stream
|
|
121
|
-
*/
|
|
122
|
-
function WMStrm(key, options) {
|
|
123
|
-
// allow use without new operator
|
|
124
|
-
if (!(this instanceof WMStrm)) {
|
|
125
|
-
return new WMStrm(key, options);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
Writable.call(this, options); // init super
|
|
129
|
-
this.key = key; // save key
|
|
130
|
-
memStore[key] = Buffer.alloc(0); // empty
|
|
131
|
-
}
|
|
132
|
-
util.inherits(WMStrm, Writable);
|
|
133
|
-
|
|
134
|
-
WMStrm.prototype._write = function (chunk, enc, cb) {
|
|
135
|
-
if (chunk) {
|
|
136
|
-
// our memory store stores things in buffers
|
|
137
|
-
const buffer = Buffer.isBuffer(chunk)
|
|
138
|
-
? chunk // already is Buffer use it
|
|
139
|
-
: Buffer.from(chunk, enc); // string, convert
|
|
140
|
-
|
|
141
|
-
// concatenate to the buffer already there
|
|
142
|
-
if (!memStore[this.key]) {
|
|
143
|
-
memStore[this.key] = Buffer.alloc(0);
|
|
144
|
-
console.log(`memstore for ${this.key} is null`);
|
|
145
|
-
}
|
|
146
|
-
memStore[this.key] = Buffer.concat([memStore[this.key], buffer]);
|
|
147
|
-
}
|
|
148
|
-
if (!cb) {
|
|
149
|
-
throw new Error('Callback is empty');
|
|
150
|
-
}
|
|
151
|
-
cb();
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
function insert(objects, id, attName, _ignore, options, _obj, callback) {
|
|
155
|
-
if (typeof options === 'string') {
|
|
156
|
-
options = { mimeType: options };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// return pipe for write into redis
|
|
160
|
-
const strm = new WMStrm(`${id}/${attName}`);
|
|
161
|
-
// @ts-ignore
|
|
162
|
-
strm.on('finish', () => {
|
|
163
|
-
let error = null;
|
|
164
|
-
if (!memStore[id + '/' + attName]) {
|
|
165
|
-
error = `File ${id} / ${attName} is empty`;
|
|
166
|
-
}
|
|
167
|
-
objects.writeFile(id, attName, memStore[id + '/' + attName] || '', options, () => {
|
|
168
|
-
if (memStore[id + '/' + attName] !== undefined) {
|
|
169
|
-
delete memStore[id + '/' + attName];
|
|
170
|
-
}
|
|
171
|
-
return tools.maybeCallbackWithError(callback, error, null);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
return strm;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
function checkFile(fileOptions, options, flag, defaultNewAcl) {
|
|
178
|
-
if (typeof fileOptions.acl !== 'object') {
|
|
179
|
-
fileOptions = {};
|
|
180
|
-
fileOptions.mimeType = deepClone(fileOptions);
|
|
181
|
-
fileOptions.acl = {
|
|
182
|
-
owner: (defaultNewAcl && defaultNewAcl.owner) || SYSTEM_ADMIN_USER,
|
|
183
|
-
ownerGroup: (defaultNewAcl && defaultNewAcl.ownerGroup) || SYSTEM_ADMIN_GROUP,
|
|
184
|
-
permissions: (defaultNewAcl && defaultNewAcl.file) || ACCESS_USER_RW | ACCESS_GROUP_READ | ACCESS_EVERY_READ // '0644'
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Set default owner group
|
|
189
|
-
fileOptions.acl.ownerGroup =
|
|
190
|
-
fileOptions.acl.ownerGroup || (defaultNewAcl && defaultNewAcl.ownerGroup) || SYSTEM_ADMIN_GROUP;
|
|
191
|
-
fileOptions.acl.owner = fileOptions.acl.owner || (defaultNewAcl && defaultNewAcl.owner) || SYSTEM_ADMIN_USER;
|
|
192
|
-
fileOptions.acl.permissions =
|
|
193
|
-
fileOptions.acl.permissions ||
|
|
194
|
-
(defaultNewAcl && defaultNewAcl.file) ||
|
|
195
|
-
ACCESS_USER_RW | ACCESS_GROUP_READ | ACCESS_EVERY_READ; // '0644'
|
|
196
|
-
|
|
197
|
-
if (options.user !== SYSTEM_ADMIN_USER && options.groups.indexOf(SYSTEM_ADMIN_GROUP) === -1 && fileOptions.acl) {
|
|
198
|
-
if (fileOptions.acl.owner !== options.user) {
|
|
199
|
-
// Check if the user is in the group
|
|
200
|
-
if (options.groups.indexOf(fileOptions.acl.ownerGroup) !== -1) {
|
|
201
|
-
// Check group rights
|
|
202
|
-
if (!(fileOptions.acl.permissions & (flag << 4))) {
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
} else {
|
|
206
|
-
// everybody
|
|
207
|
-
if (!(fileOptions.acl.permissions & flag)) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
// Check user rights
|
|
213
|
-
if (!(fileOptions.acl.permissions & (flag << 8))) {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function checkFileRights(objects, id, name, options, flag, callback) {
|
|
222
|
-
options = options || {};
|
|
223
|
-
if (!options.user) {
|
|
224
|
-
// Before files converted, lets think: if no options it is admin
|
|
225
|
-
options = {
|
|
226
|
-
user: 'system.user.admin',
|
|
227
|
-
params: options,
|
|
228
|
-
group: 'system.group.administrator'
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/*if (options.checked) {
|
|
233
|
-
return callback(null, options);
|
|
234
|
-
}*/
|
|
235
|
-
|
|
236
|
-
if (!options.acl) {
|
|
237
|
-
objects.getUserGroup(options.user, (_user, groups, acl) => {
|
|
238
|
-
options.acl = acl || {};
|
|
239
|
-
options.groups = groups;
|
|
240
|
-
options.group = groups ? groups[0] : null;
|
|
241
|
-
checkFileRights(objects, id, name, options, flag, callback);
|
|
242
|
-
});
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
// If user may write
|
|
246
|
-
if (flag === 2 && !options.acl.file.write) {
|
|
247
|
-
// write
|
|
248
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
249
|
-
}
|
|
250
|
-
// If user may read
|
|
251
|
-
if (flag === 4 && !options.acl.file.read) {
|
|
252
|
-
// read
|
|
253
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
options.checked = true;
|
|
257
|
-
objects.checkFile(id, name, options, flag, (err, options, opt) => {
|
|
258
|
-
if (err) {
|
|
259
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
260
|
-
} else {
|
|
261
|
-
return tools.maybeCallbackWithError(callback, null, options, opt);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
/*if (typeof fileOptions[id][name].acl != 'object') {
|
|
266
|
-
fileOptions[id][name] = {
|
|
267
|
-
mimeType: fileOptions[id][name],
|
|
268
|
-
acl: {
|
|
269
|
-
owner: 'system.user.admin',
|
|
270
|
-
permissions: 0x644,
|
|
271
|
-
ownerGroup: 'system.group.administrator'
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
// Set default onwer group
|
|
276
|
-
fileOptions[id][name].acl.ownerGroup = fileOptions[id][name].acl.ownerGroup || 'system.group.administrator';
|
|
277
|
-
|
|
278
|
-
if (options.user != 'system.user.admin' &&
|
|
279
|
-
options.groups.indexOf('system.group.administrator') == -1 &&
|
|
280
|
-
fileOptions[id][name].acl) {
|
|
281
|
-
if (fileOptions[id][name].acl.owner != options.user) {
|
|
282
|
-
// Check if the user is in the group
|
|
283
|
-
if (options.groups.indexOf(fileOptions[id][name].acl.ownerGroup) != -1) {
|
|
284
|
-
// Check group rights
|
|
285
|
-
if (!(fileOptions[id][name].acl.permissions & (flag << 4))) {
|
|
286
|
-
return callback(ERROR_PERMISSION, options);
|
|
287
|
-
}
|
|
288
|
-
} else {
|
|
289
|
-
// everybody
|
|
290
|
-
if (!(fileOptions[id][name].acl.permissions & flag)) {
|
|
291
|
-
return callback(ERROR_PERMISSION, options);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
// Check user rights
|
|
296
|
-
if (!(fileOptions[id][name].acl.permissions & (flag << 8))) {
|
|
297
|
-
return callback(ERROR_PERMISSION, options);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return callback(null, options);*/
|
|
302
|
-
}
|
|
303
|
-
// For users and groups
|
|
304
|
-
function getDefaultAdminRights(acl, _isState) {
|
|
305
|
-
acl = acl || {};
|
|
306
|
-
acl.file = {
|
|
307
|
-
list: true,
|
|
308
|
-
read: true,
|
|
309
|
-
write: true,
|
|
310
|
-
create: true,
|
|
311
|
-
delete: true
|
|
312
|
-
};
|
|
313
|
-
acl.object = {
|
|
314
|
-
create: true,
|
|
315
|
-
list: true,
|
|
316
|
-
read: true,
|
|
317
|
-
write: true,
|
|
318
|
-
delete: true
|
|
319
|
-
};
|
|
320
|
-
acl.users = {
|
|
321
|
-
create: true,
|
|
322
|
-
list: true,
|
|
323
|
-
read: true,
|
|
324
|
-
write: true,
|
|
325
|
-
delete: true
|
|
326
|
-
};
|
|
327
|
-
acl.state = {
|
|
328
|
-
read: true,
|
|
329
|
-
write: true,
|
|
330
|
-
delete: true,
|
|
331
|
-
create: true,
|
|
332
|
-
list: true
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
return acl;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function getUserGroup(objects, user, callback) {
|
|
339
|
-
if (!user || typeof user !== 'string' || !user.startsWith(userStartsWith)) {
|
|
340
|
-
console.log(`invalid user name: ${user}`);
|
|
341
|
-
user = JSON.stringify(user);
|
|
342
|
-
// deep copy
|
|
343
|
-
return tools.maybeCallbackWithError(
|
|
344
|
-
callback,
|
|
345
|
-
`invalid user name: ${user}`,
|
|
346
|
-
user,
|
|
347
|
-
[],
|
|
348
|
-
deepClone(defaultAcl.acl)
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
if (users[user]) {
|
|
352
|
-
return tools.maybeCallbackWithError(callback, null, user, users[user].groups, users[user].acl);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
let error;
|
|
356
|
-
// Read all groups
|
|
357
|
-
objects.getObjectList(
|
|
358
|
-
{ startkey: 'system.group.', endkey: 'system.group.\u9999' },
|
|
359
|
-
{ checked: true },
|
|
360
|
-
(err, arr) => {
|
|
361
|
-
if (err) {
|
|
362
|
-
error = err;
|
|
363
|
-
}
|
|
364
|
-
groups = [];
|
|
365
|
-
if (arr) {
|
|
366
|
-
// Read all groups
|
|
367
|
-
for (let g = 0; g < arr.rows.length; g++) {
|
|
368
|
-
groups[g] = arr.rows[g].value;
|
|
369
|
-
if (groups[g]._id === SYSTEM_ADMIN_GROUP) {
|
|
370
|
-
groups[g].common.acl = getDefaultAdminRights(groups[g].common.acl);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
objects.getObjectList(
|
|
376
|
-
{ startkey: 'system.user.', endkey: 'system.user.\u9999' },
|
|
377
|
-
{ checked: true },
|
|
378
|
-
(err, arr) => {
|
|
379
|
-
if (err) {
|
|
380
|
-
error = err;
|
|
381
|
-
}
|
|
382
|
-
users = {};
|
|
383
|
-
|
|
384
|
-
if (arr) {
|
|
385
|
-
for (let i = 0; i < arr.rows.length; i++) {
|
|
386
|
-
// cannot use here Object.assign, because required deep copy
|
|
387
|
-
users[arr.rows[i].value._id] = deepClone(defaultAcl);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
users[SYSTEM_ADMIN_USER] = users[SYSTEM_ADMIN_USER] || deepClone(defaultAcl);
|
|
391
|
-
users[SYSTEM_ADMIN_USER].acl = getDefaultAdminRights(users[SYSTEM_ADMIN_USER].acl);
|
|
392
|
-
|
|
393
|
-
for (let g = 0; g < groups.length; g++) {
|
|
394
|
-
if (!groups[g] || !groups[g].common || !groups[g].common.members) {
|
|
395
|
-
continue;
|
|
396
|
-
}
|
|
397
|
-
for (let m = 0; m < groups[g].common.members.length; m++) {
|
|
398
|
-
const u = groups[g].common.members[m];
|
|
399
|
-
if (!users[u]) {
|
|
400
|
-
error =
|
|
401
|
-
error ||
|
|
402
|
-
`Unknown user in group "${groups[g]._id.replace('system.group.', '')}": ${u}`;
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
users[u].groups.push(groups[g]._id);
|
|
406
|
-
|
|
407
|
-
if (groups[g].common.acl && groups[g].common.acl.file) {
|
|
408
|
-
if (!users[u].acl || !users[u].acl.file) {
|
|
409
|
-
users[u].acl = users[u].acl || {};
|
|
410
|
-
users[u].acl.file = users[u].acl.file || {};
|
|
411
|
-
|
|
412
|
-
users[u].acl.file.create = groups[g].common.acl.file.create;
|
|
413
|
-
users[u].acl.file.read = groups[g].common.acl.file.read;
|
|
414
|
-
users[u].acl.file.write = groups[g].common.acl.file.write;
|
|
415
|
-
users[u].acl.file['delete'] = groups[g].common.acl.file['delete'];
|
|
416
|
-
users[u].acl.file.list = groups[g].common.acl.file.list;
|
|
417
|
-
} else {
|
|
418
|
-
users[u].acl.file.create =
|
|
419
|
-
users[u].acl.file.create || groups[g].common.acl.file.create;
|
|
420
|
-
users[u].acl.file.read = users[u].acl.file.read || groups[g].common.acl.file.read;
|
|
421
|
-
users[u].acl.file.write =
|
|
422
|
-
users[u].acl.file.write || groups[g].common.acl.file.write;
|
|
423
|
-
users[u].acl.file['delete'] =
|
|
424
|
-
users[u].acl.file['delete'] || groups[g].common.acl.file['delete'];
|
|
425
|
-
users[u].acl.file.list = users[u].acl.file.list || groups[g].common.acl.file.list;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
if (groups[g].common.acl && groups[g].common.acl.object) {
|
|
430
|
-
if (!users[u].acl || !users[u].acl.object) {
|
|
431
|
-
users[u].acl = users[u].acl || {};
|
|
432
|
-
users[u].acl.object = users[u].acl.object || {};
|
|
433
|
-
|
|
434
|
-
users[u].acl.object.create = groups[g].common.acl.object.create;
|
|
435
|
-
users[u].acl.object.read = groups[g].common.acl.object.read;
|
|
436
|
-
users[u].acl.object.write = groups[g].common.acl.object.write;
|
|
437
|
-
users[u].acl.object['delete'] = groups[g].common.acl.object['delete'];
|
|
438
|
-
users[u].acl.object.list = groups[g].common.acl.object.list;
|
|
439
|
-
} else {
|
|
440
|
-
users[u].acl.object.create =
|
|
441
|
-
users[u].acl.object.create || groups[g].common.acl.object.create;
|
|
442
|
-
users[u].acl.object.read =
|
|
443
|
-
users[u].acl.object.read || groups[g].common.acl.object.read;
|
|
444
|
-
users[u].acl.object.write =
|
|
445
|
-
users[u].acl.object.write || groups[g].common.acl.object.write;
|
|
446
|
-
users[u].acl.object['delete'] =
|
|
447
|
-
users[u].acl.object['delete'] || groups[g].common.acl.object['delete'];
|
|
448
|
-
users[u].acl.object.list =
|
|
449
|
-
users[u].acl.object.list || groups[g].common.acl.object.list;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (groups[g].common.acl && groups[g].common.acl.users) {
|
|
454
|
-
if (!users[u].acl || !users[u].acl.users) {
|
|
455
|
-
users[u].acl = users[u].acl || {};
|
|
456
|
-
users[u].acl.users = users[u].acl.users || {};
|
|
457
|
-
|
|
458
|
-
users[u].acl.users.create = groups[g].common.acl.users.create;
|
|
459
|
-
users[u].acl.users.read = groups[g].common.acl.users.read;
|
|
460
|
-
users[u].acl.users.write = groups[g].common.acl.users.write;
|
|
461
|
-
users[u].acl.users['delete'] = groups[g].common.acl.users['delete'];
|
|
462
|
-
users[u].acl.users.list = groups[g].common.acl.users.list;
|
|
463
|
-
} else {
|
|
464
|
-
users[u].acl.users.create =
|
|
465
|
-
users[u].acl.users.create || groups[g].common.acl.users.create;
|
|
466
|
-
users[u].acl.users.read =
|
|
467
|
-
users[u].acl.users.read || groups[g].common.acl.users.read;
|
|
468
|
-
users[u].acl.users.write =
|
|
469
|
-
users[u].acl.users.write || groups[g].common.acl.users.write;
|
|
470
|
-
users[u].acl.users['delete'] =
|
|
471
|
-
users[u].acl.users['delete'] || groups[g].common.acl.users['delete'];
|
|
472
|
-
users[u].acl.users.list =
|
|
473
|
-
users[u].acl.users.list || groups[g].common.acl.users.list;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
if (groups[g].common.acl && groups[g].common.acl.state) {
|
|
478
|
-
if (!users[u].acl || !users[u].acl.state) {
|
|
479
|
-
users[u].acl = users[u].acl || {};
|
|
480
|
-
users[u].acl.state = users[u].acl.state || {};
|
|
481
|
-
|
|
482
|
-
users[u].acl.state.create = groups[g].common.acl.state.create;
|
|
483
|
-
users[u].acl.state.read = groups[g].common.acl.state.read;
|
|
484
|
-
users[u].acl.state.write = groups[g].common.acl.state.write;
|
|
485
|
-
users[u].acl.state['delete'] = groups[g].common.acl.state['delete'];
|
|
486
|
-
users[u].acl.state.list = groups[g].common.acl.state.list;
|
|
487
|
-
} else {
|
|
488
|
-
users[u].acl.state.create =
|
|
489
|
-
users[u].acl.state.create || groups[g].common.acl.state.create;
|
|
490
|
-
users[u].acl.state.read =
|
|
491
|
-
users[u].acl.state.read || groups[g].common.acl.state.read;
|
|
492
|
-
users[u].acl.state.write =
|
|
493
|
-
users[u].acl.state.write || groups[g].common.acl.state.write;
|
|
494
|
-
users[u].acl.state['delete'] =
|
|
495
|
-
users[u].acl.state['delete'] || groups[g].common.acl.state['delete'];
|
|
496
|
-
users[u].acl.state.list =
|
|
497
|
-
users[u].acl.state.list || groups[g].common.acl.state.list;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
return tools.maybeCallbackWithError(
|
|
504
|
-
callback,
|
|
505
|
-
error,
|
|
506
|
-
user,
|
|
507
|
-
users[user] ? users[user].groups : [],
|
|
508
|
-
users[user] ? users[user].acl : JSON.parse(JSON.stringify(defaultAcl.acl))
|
|
509
|
-
);
|
|
510
|
-
}
|
|
511
|
-
);
|
|
512
|
-
}
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function sanitizePath(id, name) {
|
|
517
|
-
if (!name) {
|
|
518
|
-
name = '';
|
|
519
|
-
}
|
|
520
|
-
if (name[0] === '/') {
|
|
521
|
-
name = name.substring(1);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if (!id) {
|
|
525
|
-
throw new Error('Empty ID');
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
id = id.replace(/[\][*,;'"`<>\\?/]/g, ''); // remove all invalid characters from states plus slashes
|
|
529
|
-
id = id.replace(/\.\./g, ''); // do not allow to write in parent directories
|
|
530
|
-
|
|
531
|
-
if (name.includes('..')) {
|
|
532
|
-
name = path.normalize('/' + name);
|
|
533
|
-
}
|
|
534
|
-
if (name.includes('..')) {
|
|
535
|
-
// Also after normalization we still have .. in it - should not happen if normalize worked correctly
|
|
536
|
-
name = name.replace(/\.\./g, '');
|
|
537
|
-
name = path.normalize('/' + name);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
name = name.replace(/\\/g, '/'); // replace win path backslashes
|
|
541
|
-
|
|
542
|
-
if (name[0] === '/') {
|
|
543
|
-
name = name.substring(1);
|
|
544
|
-
} // do not allow absolute paths
|
|
545
|
-
|
|
546
|
-
return { id: id, name: name };
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function checkObject(obj, options, flag) {
|
|
550
|
-
// read rights of object
|
|
551
|
-
if (!obj || !obj.common || !obj.acl || flag === ACCESS_LIST) {
|
|
552
|
-
return true;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
if (options.user === SYSTEM_ADMIN_USER) {
|
|
556
|
-
return true;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// admins may always see everything
|
|
560
|
-
if (options.group === SYSTEM_ADMIN_GROUP || options.groups.includes(SYSTEM_ADMIN_GROUP)) {
|
|
561
|
-
return true;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
// checkObject always called after checkObjectRights and admin is checked there
|
|
565
|
-
if (obj.acl.owner !== options.user) {
|
|
566
|
-
// Check if the user is in the group
|
|
567
|
-
if (
|
|
568
|
-
(options.group && options.group === obj.acl.ownerGroup) ||
|
|
569
|
-
(options.groups && options.groups.includes(obj.acl.ownerGroup))
|
|
570
|
-
) {
|
|
571
|
-
// Check group rights
|
|
572
|
-
if (!(obj.acl.object & (flag << 4))) {
|
|
573
|
-
return false;
|
|
574
|
-
}
|
|
575
|
-
} else {
|
|
576
|
-
// everybody
|
|
577
|
-
if (!(obj.acl.object & flag)) {
|
|
578
|
-
return false;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
// Check group rights
|
|
583
|
-
if (!(obj.acl.object & (flag << 8))) {
|
|
584
|
-
return false;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
return true; // ALL OK
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function checkObjectRights(objects, id, object, options, flag, callback) {
|
|
591
|
-
options = options || {};
|
|
592
|
-
|
|
593
|
-
if (!options.user) {
|
|
594
|
-
// Before files converted, lets think: if no options it is admin
|
|
595
|
-
options = {
|
|
596
|
-
user: SYSTEM_ADMIN_USER,
|
|
597
|
-
params: options,
|
|
598
|
-
group: SYSTEM_ADMIN_GROUP,
|
|
599
|
-
groups: [SYSTEM_ADMIN_GROUP],
|
|
600
|
-
acl: getDefaultAdminRights()
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
if (!options.acl) {
|
|
605
|
-
return objects.getUserGroup(options.user, (_user, groups, acl) => {
|
|
606
|
-
options.acl = acl || {};
|
|
607
|
-
options.groups = groups;
|
|
608
|
-
options.group = groups ? groups[0] : null;
|
|
609
|
-
checkObjectRights(objects, id, object, options, flag, callback);
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// now options are filled and we can go
|
|
614
|
-
if (
|
|
615
|
-
options.user === SYSTEM_ADMIN_USER ||
|
|
616
|
-
options.group === SYSTEM_ADMIN_GROUP ||
|
|
617
|
-
(options.groups && options.groups.includes(SYSTEM_ADMIN_GROUP))
|
|
618
|
-
) {
|
|
619
|
-
return tools.maybeCallbackWithError(callback, null, options);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// if user or group objects
|
|
623
|
-
if (typeof id === 'string' && (id.startsWith(userStartsWith) || id.startsWith(groupStartsWith))) {
|
|
624
|
-
// If user may write
|
|
625
|
-
if (flag === ACCESS_WRITE && !options.acl.users.write) {
|
|
626
|
-
// write
|
|
627
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// If user may read
|
|
631
|
-
if (flag === ACCESS_READ && !options.acl.users.read) {
|
|
632
|
-
// read
|
|
633
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// If user may delete
|
|
637
|
-
if (flag === ACCESS_DELETE && !options.acl.users.delete) {
|
|
638
|
-
// delete
|
|
639
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// If user may list
|
|
643
|
-
if (flag === ACCESS_LIST && !options.acl.users.list) {
|
|
644
|
-
// list
|
|
645
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// If user may create
|
|
649
|
-
if (flag === ACCESS_CREATE && !options.acl.users.create) {
|
|
650
|
-
// create
|
|
651
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// If user may write
|
|
655
|
-
if (flag === ACCESS_DELETE) {
|
|
656
|
-
// he may delete
|
|
657
|
-
flag = ACCESS_WRITE;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// If user may write
|
|
662
|
-
if (flag === ACCESS_WRITE && !options.acl.object.write) {
|
|
663
|
-
// write
|
|
664
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// If user may read
|
|
668
|
-
if (flag === ACCESS_READ && !options.acl.object.read) {
|
|
669
|
-
// read
|
|
670
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
// If user may delete
|
|
674
|
-
if (flag === ACCESS_DELETE && !options.acl.object.delete) {
|
|
675
|
-
// delete
|
|
676
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// If user may list
|
|
680
|
-
if (flag === ACCESS_LIST && !options.acl.object.list) {
|
|
681
|
-
// list
|
|
682
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
if (flag === ACCESS_DELETE) {
|
|
686
|
-
// write
|
|
687
|
-
flag = ACCESS_WRITE;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (id && !checkObject(object, options, flag)) {
|
|
691
|
-
return tools.maybeCallbackWithError(callback, ERROR_PERMISSION, options);
|
|
692
|
-
} else {
|
|
693
|
-
return tools.maybeCallbackWithError(callback, null, options);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// For objects
|
|
698
|
-
const defaultAcl = {
|
|
699
|
-
groups: [],
|
|
700
|
-
acl: {
|
|
701
|
-
file: {
|
|
702
|
-
list: false,
|
|
703
|
-
read: false,
|
|
704
|
-
write: false,
|
|
705
|
-
create: false,
|
|
706
|
-
delete: false
|
|
707
|
-
},
|
|
708
|
-
object: {
|
|
709
|
-
list: false,
|
|
710
|
-
read: false,
|
|
711
|
-
write: false,
|
|
712
|
-
create: false,
|
|
713
|
-
delete: false
|
|
714
|
-
},
|
|
715
|
-
state: {
|
|
716
|
-
list: false,
|
|
717
|
-
read: false,
|
|
718
|
-
write: false,
|
|
719
|
-
create: false,
|
|
720
|
-
delete: false
|
|
721
|
-
},
|
|
722
|
-
users: {
|
|
723
|
-
list: false,
|
|
724
|
-
read: false,
|
|
725
|
-
write: false,
|
|
726
|
-
create: false,
|
|
727
|
-
delete: false
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
};
|
|
731
|
-
|
|
732
|
-
module.exports = {
|
|
733
|
-
getMimeType,
|
|
734
|
-
insert,
|
|
735
|
-
checkFileRights,
|
|
736
|
-
checkFile,
|
|
737
|
-
getUserGroup,
|
|
738
|
-
sanitizePath,
|
|
739
|
-
checkObject,
|
|
740
|
-
checkObjectRights,
|
|
741
|
-
|
|
742
|
-
regCheckId,
|
|
743
|
-
|
|
744
|
-
ERRORS: {
|
|
745
|
-
ERROR_PERMISSION,
|
|
746
|
-
ERROR_NOT_FOUND,
|
|
747
|
-
ERROR_DB_CLOSED
|
|
748
|
-
},
|
|
749
|
-
CONSTS: {
|
|
750
|
-
SYSTEM_ADMIN_USER,
|
|
751
|
-
SYSTEM_ADMIN_GROUP,
|
|
752
|
-
|
|
753
|
-
ACCESS_EVERY_EXEC,
|
|
754
|
-
ACCESS_EVERY_WRITE,
|
|
755
|
-
ACCESS_EVERY_READ,
|
|
756
|
-
ACCESS_EVERY_RW,
|
|
757
|
-
ACCESS_EVERY_ALL,
|
|
758
|
-
|
|
759
|
-
ACCESS_GROUP_EXEC,
|
|
760
|
-
ACCESS_GROUP_WRITE,
|
|
761
|
-
ACCESS_GROUP_READ,
|
|
762
|
-
ACCESS_GROUP_RW,
|
|
763
|
-
ACCESS_GROUP_ALL,
|
|
764
|
-
|
|
765
|
-
ACCESS_USER_EXEC,
|
|
766
|
-
ACCESS_USER_WRITE,
|
|
767
|
-
ACCESS_USER_READ,
|
|
768
|
-
ACCESS_USER_RW,
|
|
769
|
-
ACCESS_USER_ALL,
|
|
770
|
-
|
|
771
|
-
ACCESS_WRITE,
|
|
772
|
-
ACCESS_READ,
|
|
773
|
-
ACCESS_LIST,
|
|
774
|
-
ACCESS_DELETE,
|
|
775
|
-
ACCESS_CREATE
|
|
776
|
-
}
|
|
777
|
-
};
|