@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
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common functions between client and server
|
|
3
|
+
*
|
|
4
|
+
* Copyright 2013-2022 bluefox <dogafox@gmail.com>
|
|
5
|
+
*
|
|
6
|
+
* MIT License
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
'use strict';
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
27
|
+
if (mod && mod.__esModule) return mod;
|
|
28
|
+
var result = {};
|
|
29
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
30
|
+
__setModuleDefault(result, mod);
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
34
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.checkObjectRights = exports.checkObject = exports.sanitizePath = exports.getUserGroup = exports.checkFileRights = exports.checkFile = exports.insert = exports.WMStrm = exports.getMimeType = exports.REG_CHECK_ID = exports.ERRORS = exports.CONSTS = void 0;
|
|
38
|
+
const stream_1 = require("stream");
|
|
39
|
+
const path_1 = __importDefault(require("path"));
|
|
40
|
+
const deep_clone_1 = __importDefault(require("deep-clone"));
|
|
41
|
+
const db_base_1 = require("@iobroker/db-base");
|
|
42
|
+
const CONSTS = __importStar(require("./constants"));
|
|
43
|
+
exports.CONSTS = __importStar(require("./constants"));
|
|
44
|
+
exports.ERRORS = CONSTS.ERRORS;
|
|
45
|
+
exports.REG_CHECK_ID = CONSTS.REG_CHECK_ID;
|
|
46
|
+
const USER_STARTS_WITH = CONSTS.USER_STARTS_WITH;
|
|
47
|
+
const GROUP_STARTS_WITH = CONSTS.GROUP_STARTS_WITH;
|
|
48
|
+
const memStore = {};
|
|
49
|
+
const mimeTypes = {
|
|
50
|
+
'.css': { type: 'text/css', binary: false },
|
|
51
|
+
'.bmp': { type: 'image/bmp', binary: true },
|
|
52
|
+
'.png': { type: 'image/png', binary: true },
|
|
53
|
+
'.jpg': { type: 'image/jpeg', binary: true },
|
|
54
|
+
'.jpeg': { type: 'image/jpeg', binary: true },
|
|
55
|
+
'.gif': { type: 'image/gif', binary: true },
|
|
56
|
+
'.ico': { type: 'image/x-icon', binary: true },
|
|
57
|
+
'.webp': { type: 'image/webp', binary: true },
|
|
58
|
+
'.wbmp': { type: 'image/vnd.wap.wbmp', binary: true },
|
|
59
|
+
'.tif': { type: 'image/tiff', binary: true },
|
|
60
|
+
'.js': { type: 'application/javascript', binary: false },
|
|
61
|
+
'.html': { type: 'text/html', binary: false },
|
|
62
|
+
'.htm': { type: 'text/html', binary: false },
|
|
63
|
+
'.json': { type: 'application/json', binary: false },
|
|
64
|
+
'.md': { type: 'text/markdown', binary: false },
|
|
65
|
+
'.xml': { type: 'text/xml', binary: false },
|
|
66
|
+
'.svg': { type: 'image/svg+xml', binary: false },
|
|
67
|
+
'.eot': { type: 'application/vnd.ms-fontobject', binary: true },
|
|
68
|
+
'.ttf': { type: 'application/font-sfnt', binary: true },
|
|
69
|
+
'.cur': { type: 'application/x-win-bitmap', binary: true },
|
|
70
|
+
'.woff': { type: 'application/font-woff', binary: true },
|
|
71
|
+
'.wav': { type: 'audio/wav', binary: true },
|
|
72
|
+
'.mp3': { type: 'audio/mpeg3', binary: true },
|
|
73
|
+
'.avi': { type: 'video/avi', binary: true },
|
|
74
|
+
'.qt': { type: 'video/quicktime', binary: true },
|
|
75
|
+
'.ppt': { type: 'application/vnd.ms-powerpoint', binary: true },
|
|
76
|
+
'.pptx': { type: 'application/vnd.ms-powerpoint', binary: true },
|
|
77
|
+
'.doc': { type: 'application/msword', binary: true },
|
|
78
|
+
'.docx': { type: 'application/msword', binary: true },
|
|
79
|
+
'.xls': { type: 'application/vnd.ms-excel', binary: true },
|
|
80
|
+
'.xlsx': { type: 'application/vnd.ms-excel', binary: true },
|
|
81
|
+
'.mp4': { type: 'video/mp4', binary: true },
|
|
82
|
+
'.mkv': { type: 'video/mkv', binary: true },
|
|
83
|
+
'.zip': { type: 'application/zip', binary: true },
|
|
84
|
+
'.ogg': { type: 'audio/ogg', binary: true },
|
|
85
|
+
'.manifest': { type: 'text/cache-manifest', binary: false },
|
|
86
|
+
'.pdf': { type: 'application/pdf', binary: true },
|
|
87
|
+
'.gz': { type: 'application/gzip', binary: true },
|
|
88
|
+
'.gzip': { type: 'application/gzip', binary: true }
|
|
89
|
+
};
|
|
90
|
+
function isKnownMimeType(ext) {
|
|
91
|
+
return ext in mimeTypes;
|
|
92
|
+
}
|
|
93
|
+
// For objects
|
|
94
|
+
const defaultAcl = {
|
|
95
|
+
groups: [],
|
|
96
|
+
acl: {
|
|
97
|
+
file: {
|
|
98
|
+
list: false,
|
|
99
|
+
read: false,
|
|
100
|
+
write: false,
|
|
101
|
+
create: false,
|
|
102
|
+
delete: false
|
|
103
|
+
},
|
|
104
|
+
object: {
|
|
105
|
+
list: false,
|
|
106
|
+
read: false,
|
|
107
|
+
write: false,
|
|
108
|
+
create: false,
|
|
109
|
+
delete: false
|
|
110
|
+
},
|
|
111
|
+
state: {
|
|
112
|
+
list: false,
|
|
113
|
+
read: false,
|
|
114
|
+
write: false,
|
|
115
|
+
create: false,
|
|
116
|
+
delete: false
|
|
117
|
+
},
|
|
118
|
+
users: {
|
|
119
|
+
list: false,
|
|
120
|
+
read: false,
|
|
121
|
+
write: false,
|
|
122
|
+
create: false,
|
|
123
|
+
delete: false
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
// FIXME: This should have better types. Probably Record<string, {acl: ioBroker.ObjectPermissions, [x: string | number | symbol]: any}>
|
|
128
|
+
let users = {};
|
|
129
|
+
let groups = [];
|
|
130
|
+
function getMimeType(ext) {
|
|
131
|
+
if (!ext) {
|
|
132
|
+
return { mimeType: 'text/html', isBinary: false };
|
|
133
|
+
}
|
|
134
|
+
if (ext instanceof Array) {
|
|
135
|
+
ext = ext[0];
|
|
136
|
+
}
|
|
137
|
+
ext = ext.toLowerCase();
|
|
138
|
+
let mimeType = 'text/javascript';
|
|
139
|
+
let isBinary = false;
|
|
140
|
+
if (isKnownMimeType(ext)) {
|
|
141
|
+
mimeType = mimeTypes[ext].type;
|
|
142
|
+
isBinary = mimeTypes[ext].binary;
|
|
143
|
+
}
|
|
144
|
+
return { mimeType, isBinary };
|
|
145
|
+
}
|
|
146
|
+
exports.getMimeType = getMimeType;
|
|
147
|
+
/**
|
|
148
|
+
* Writable memory stream
|
|
149
|
+
*/
|
|
150
|
+
class WMStrm extends stream_1.Writable {
|
|
151
|
+
constructor(key, options) {
|
|
152
|
+
super(options); // init super
|
|
153
|
+
this.key = key; // save key
|
|
154
|
+
memStore[key] = Buffer.alloc(0); // empty
|
|
155
|
+
}
|
|
156
|
+
_write(chunk, enc, cb) {
|
|
157
|
+
if (chunk) {
|
|
158
|
+
// our memory store stores things in buffers
|
|
159
|
+
const buffer = Buffer.isBuffer(chunk)
|
|
160
|
+
? chunk // already is Buffer use it
|
|
161
|
+
: Buffer.from(chunk, enc); // string, convert
|
|
162
|
+
// concatenate to the buffer already there
|
|
163
|
+
if (!memStore[this.key]) {
|
|
164
|
+
memStore[this.key] = Buffer.alloc(0);
|
|
165
|
+
console.log(`memstore for ${this.key} is null`);
|
|
166
|
+
}
|
|
167
|
+
memStore[this.key] = Buffer.concat([memStore[this.key], buffer]);
|
|
168
|
+
}
|
|
169
|
+
if (!cb) {
|
|
170
|
+
throw new Error('Callback is empty');
|
|
171
|
+
}
|
|
172
|
+
cb();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
exports.WMStrm = WMStrm;
|
|
176
|
+
function insert(objects, id, attName, _ignore, options, _obj, callback) {
|
|
177
|
+
if (typeof options === 'string') {
|
|
178
|
+
options = { mimeType: options };
|
|
179
|
+
}
|
|
180
|
+
// return pipe for write into redis
|
|
181
|
+
const strm = new WMStrm(`${id}/${attName}`, {});
|
|
182
|
+
strm.on('finish', () => {
|
|
183
|
+
let error = null;
|
|
184
|
+
if (!memStore[id + '/' + attName]) {
|
|
185
|
+
error = `File ${id} / ${attName} is empty`;
|
|
186
|
+
}
|
|
187
|
+
objects.writeFile(id, attName, memStore[id + '/' + attName] || '', options, () => {
|
|
188
|
+
if (memStore[id + '/' + attName] !== undefined) {
|
|
189
|
+
delete memStore[id + '/' + attName];
|
|
190
|
+
}
|
|
191
|
+
return db_base_1.tools.maybeCallbackWithError(callback, error, null);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
return strm;
|
|
195
|
+
}
|
|
196
|
+
exports.insert = insert;
|
|
197
|
+
function checkFile(fileOptions, options, flag, defaultNewAcl) {
|
|
198
|
+
if (typeof fileOptions.acl !== 'object') {
|
|
199
|
+
fileOptions = {};
|
|
200
|
+
fileOptions.mimeType = (0, deep_clone_1.default)(fileOptions);
|
|
201
|
+
fileOptions.acl = {
|
|
202
|
+
owner: (defaultNewAcl && defaultNewAcl.owner) || CONSTS.SYSTEM_ADMIN_USER,
|
|
203
|
+
ownerGroup: (defaultNewAcl && defaultNewAcl.ownerGroup) || CONSTS.SYSTEM_ADMIN_GROUP,
|
|
204
|
+
permissions: (defaultNewAcl && defaultNewAcl.file) ||
|
|
205
|
+
CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ // '0644'
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// Set default owner group
|
|
209
|
+
fileOptions.acl.ownerGroup =
|
|
210
|
+
fileOptions.acl.ownerGroup || (defaultNewAcl && defaultNewAcl.ownerGroup) || CONSTS.SYSTEM_ADMIN_GROUP;
|
|
211
|
+
fileOptions.acl.owner = fileOptions.acl.owner || (defaultNewAcl && defaultNewAcl.owner) || CONSTS.SYSTEM_ADMIN_USER;
|
|
212
|
+
fileOptions.acl.permissions =
|
|
213
|
+
fileOptions.acl.permissions ||
|
|
214
|
+
(defaultNewAcl && defaultNewAcl.file) ||
|
|
215
|
+
CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ; // '0644'
|
|
216
|
+
if (options.user !== CONSTS.SYSTEM_ADMIN_USER &&
|
|
217
|
+
options.groups.indexOf(CONSTS.SYSTEM_ADMIN_GROUP) === -1 &&
|
|
218
|
+
fileOptions.acl) {
|
|
219
|
+
if (fileOptions.acl.owner !== options.user) {
|
|
220
|
+
// Check if the user is in the group
|
|
221
|
+
if (options.groups.indexOf(fileOptions.acl.ownerGroup) !== -1) {
|
|
222
|
+
// Check group rights
|
|
223
|
+
if (!(fileOptions.acl.permissions & (flag << 4))) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// everybody
|
|
229
|
+
if (!(fileOptions.acl.permissions & flag)) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
// Check user rights
|
|
236
|
+
if (!(fileOptions.acl.permissions & (flag << 8))) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
exports.checkFile = checkFile;
|
|
244
|
+
function checkFileRights(objects, id, name, options, flag, callback) {
|
|
245
|
+
const _options = options || {};
|
|
246
|
+
if (!_options.user) {
|
|
247
|
+
// Before files converted, lets think: if no options it is admin
|
|
248
|
+
_options.user = 'system.user.admin';
|
|
249
|
+
_options.params = _options;
|
|
250
|
+
_options.group = 'system.group.administrator';
|
|
251
|
+
}
|
|
252
|
+
if (!_options.acl) {
|
|
253
|
+
objects.getUserGroup(_options.user, (_user, groups, acl) => {
|
|
254
|
+
_options.acl = acl || {};
|
|
255
|
+
_options.groups = groups;
|
|
256
|
+
_options.group = groups ? groups[0] : null;
|
|
257
|
+
checkFileRights(objects, id, name, _options, flag, callback);
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
// If user may write
|
|
262
|
+
if (flag === CONSTS.ACCESS_WRITE && !_options.acl.file.write) {
|
|
263
|
+
// write
|
|
264
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, _options);
|
|
265
|
+
}
|
|
266
|
+
// If user may read
|
|
267
|
+
if (flag === CONSTS.ACCESS_READ && !_options.acl.file.read) {
|
|
268
|
+
// read
|
|
269
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, _options);
|
|
270
|
+
}
|
|
271
|
+
_options.checked = true;
|
|
272
|
+
objects.checkFile(id, name, _options, flag, (err, options, opt) => {
|
|
273
|
+
if (err) {
|
|
274
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
return db_base_1.tools.maybeCallbackWithError(callback, null, options, opt);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
exports.checkFileRights = checkFileRights;
|
|
282
|
+
// For users and groups
|
|
283
|
+
function getDefaultAdminRights(acl, _isState) {
|
|
284
|
+
return {
|
|
285
|
+
...acl,
|
|
286
|
+
file: {
|
|
287
|
+
list: true,
|
|
288
|
+
read: true,
|
|
289
|
+
write: true,
|
|
290
|
+
create: true,
|
|
291
|
+
delete: true
|
|
292
|
+
},
|
|
293
|
+
object: {
|
|
294
|
+
create: true,
|
|
295
|
+
list: true,
|
|
296
|
+
read: true,
|
|
297
|
+
write: true,
|
|
298
|
+
delete: true
|
|
299
|
+
},
|
|
300
|
+
users: {
|
|
301
|
+
create: true,
|
|
302
|
+
list: true,
|
|
303
|
+
read: true,
|
|
304
|
+
write: true,
|
|
305
|
+
delete: true
|
|
306
|
+
},
|
|
307
|
+
state: {
|
|
308
|
+
read: true,
|
|
309
|
+
write: true,
|
|
310
|
+
delete: true,
|
|
311
|
+
create: true,
|
|
312
|
+
list: true
|
|
313
|
+
},
|
|
314
|
+
other: {
|
|
315
|
+
execute: false,
|
|
316
|
+
http: false,
|
|
317
|
+
sendto: false
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function getUserGroup(objects, user, callback) {
|
|
322
|
+
if (!user || typeof user !== 'string' || !user.startsWith(USER_STARTS_WITH)) {
|
|
323
|
+
console.log(`invalid user name: ${user}`);
|
|
324
|
+
user = JSON.stringify(user);
|
|
325
|
+
// deep copy
|
|
326
|
+
return db_base_1.tools.maybeCallbackWithError(callback, `invalid user name: ${user}`, user, [], (0, deep_clone_1.default)(defaultAcl.acl));
|
|
327
|
+
}
|
|
328
|
+
if (users[user]) {
|
|
329
|
+
return db_base_1.tools.maybeCallbackWithError(callback, null, user, users[user].groups, users[user].acl);
|
|
330
|
+
}
|
|
331
|
+
let error;
|
|
332
|
+
// Read all groups
|
|
333
|
+
objects.getObjectList({ startkey: 'system.group.', endkey: 'system.group.\u9999' }, { checked: true }, (err, arr) => {
|
|
334
|
+
if (err) {
|
|
335
|
+
error = err;
|
|
336
|
+
}
|
|
337
|
+
groups = [];
|
|
338
|
+
if (arr) {
|
|
339
|
+
// Read all groups
|
|
340
|
+
for (const g in arr.rows) {
|
|
341
|
+
const val = arr.rows[g].value;
|
|
342
|
+
if (!val) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
groups[g] = val;
|
|
346
|
+
if (groups[g]._id === CONSTS.SYSTEM_ADMIN_GROUP) {
|
|
347
|
+
groups[g].common.acl = getDefaultAdminRights(groups[g].common.acl);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
objects.getObjectList({ startkey: 'system.user.', endkey: 'system.user.\u9999' }, { checked: true }, (err, arr) => {
|
|
352
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
353
|
+
if (err) {
|
|
354
|
+
error = err;
|
|
355
|
+
}
|
|
356
|
+
users = {};
|
|
357
|
+
if (arr) {
|
|
358
|
+
for (const row of arr.rows) {
|
|
359
|
+
// cannot use here Object.assign, because required deep copy
|
|
360
|
+
users[row.value._id] = (0, deep_clone_1.default)(defaultAcl);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
users[CONSTS.SYSTEM_ADMIN_USER] = users[CONSTS.SYSTEM_ADMIN_USER] || (0, deep_clone_1.default)(defaultAcl);
|
|
364
|
+
users[CONSTS.SYSTEM_ADMIN_USER].acl = getDefaultAdminRights(users[CONSTS.SYSTEM_ADMIN_USER].acl);
|
|
365
|
+
for (let g = 0; g < groups.length; g++) {
|
|
366
|
+
if (!groups[g] || !groups[g].common || !groups[g].common.members) {
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
for (let m = 0; m < groups[g].common.members.length; m++) {
|
|
370
|
+
const u = groups[g].common.members[m];
|
|
371
|
+
if (!users[u]) {
|
|
372
|
+
error =
|
|
373
|
+
error ||
|
|
374
|
+
`Unknown user in group "${groups[g]._id.replace('system.group.', '')}": ${u}`;
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
users[u].groups.push(groups[g]._id);
|
|
378
|
+
if (groups[g].common.acl && groups[g].common.acl.file) {
|
|
379
|
+
if (!users[u].acl || !users[u].acl.file) {
|
|
380
|
+
users[u].acl = users[u].acl || {};
|
|
381
|
+
users[u].acl.file = users[u].acl.file || {};
|
|
382
|
+
users[u].acl.file.create = groups[g].common.acl.file.create;
|
|
383
|
+
users[u].acl.file.read = groups[g].common.acl.file.read;
|
|
384
|
+
users[u].acl.file.write = groups[g].common.acl.file.write;
|
|
385
|
+
users[u].acl.file.delete = groups[g].common.acl.file.delete;
|
|
386
|
+
users[u].acl.file.list = groups[g].common.acl.file.list;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
users[u].acl.file.create =
|
|
390
|
+
users[u].acl.file.create || groups[g].common.acl.file.create;
|
|
391
|
+
users[u].acl.file.read = users[u].acl.file.read || groups[g].common.acl.file.read;
|
|
392
|
+
users[u].acl.file.write =
|
|
393
|
+
users[u].acl.file.write || groups[g].common.acl.file.write;
|
|
394
|
+
users[u].acl.file.delete =
|
|
395
|
+
users[u].acl.file.delete || groups[g].common.acl.file.delete;
|
|
396
|
+
users[u].acl.file.list = users[u].acl.file.list || groups[g].common.acl.file.list;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (groups[g].common.acl && groups[g].common.acl.object) {
|
|
400
|
+
if (!users[u].acl || !users[u].acl.object) {
|
|
401
|
+
users[u].acl = users[u].acl || {};
|
|
402
|
+
users[u].acl.object = users[u].acl.object || {};
|
|
403
|
+
users[u].acl.object.create = groups[g].common.acl.object.create;
|
|
404
|
+
users[u].acl.object.read = groups[g].common.acl.object.read;
|
|
405
|
+
users[u].acl.object.write = groups[g].common.acl.object.write;
|
|
406
|
+
users[u].acl.object.delete = groups[g].common.acl.object.delete;
|
|
407
|
+
users[u].acl.object.list = groups[g].common.acl.object.list;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
users[u].acl.object.create =
|
|
411
|
+
users[u].acl.object.create || groups[g].common.acl.object.create;
|
|
412
|
+
users[u].acl.object.read =
|
|
413
|
+
users[u].acl.object.read || groups[g].common.acl.object.read;
|
|
414
|
+
users[u].acl.object.write =
|
|
415
|
+
users[u].acl.object.write || groups[g].common.acl.object.write;
|
|
416
|
+
users[u].acl.object.delete =
|
|
417
|
+
users[u].acl.object.delete || groups[g].common.acl.object.delete;
|
|
418
|
+
users[u].acl.object.list =
|
|
419
|
+
users[u].acl.object.list || groups[g].common.acl.object.list;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (groups[g].common.acl && groups[g].common.acl.users) {
|
|
423
|
+
if (!users[u].acl || !users[u].acl.users) {
|
|
424
|
+
users[u].acl = users[u].acl || {};
|
|
425
|
+
users[u].acl.users = users[u].acl.users || {};
|
|
426
|
+
users[u].acl.users.create = groups[g].common.acl.users.create;
|
|
427
|
+
users[u].acl.users.read = groups[g].common.acl.users.read;
|
|
428
|
+
users[u].acl.users.write = groups[g].common.acl.users.write;
|
|
429
|
+
users[u].acl.users.delete = groups[g].common.acl.users.delete;
|
|
430
|
+
users[u].acl.users.list = groups[g].common.acl.users.list;
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
users[u].acl.users.create =
|
|
434
|
+
users[u].acl.users.create || groups[g].common.acl.users.create;
|
|
435
|
+
users[u].acl.users.read =
|
|
436
|
+
users[u].acl.users.read || groups[g].common.acl.users.read;
|
|
437
|
+
users[u].acl.users.write =
|
|
438
|
+
users[u].acl.users.write || groups[g].common.acl.users.write;
|
|
439
|
+
users[u].acl.users.delete =
|
|
440
|
+
users[u].acl.users.delete || groups[g].common.acl.users.delete;
|
|
441
|
+
users[u].acl.users.list =
|
|
442
|
+
users[u].acl.users.list || groups[g].common.acl.users.list;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (groups[g].common.acl && groups[g].common.acl.state) {
|
|
446
|
+
if (!users[u].acl || !users[u].acl.state) {
|
|
447
|
+
users[u].acl = users[u].acl || {};
|
|
448
|
+
users[u].acl.state = users[u].acl.state || {};
|
|
449
|
+
users[u].acl.state.create = (_a = groups[g].common.acl.state) === null || _a === void 0 ? void 0 : _a.create;
|
|
450
|
+
users[u].acl.state.read = (_b = groups[g].common.acl.state) === null || _b === void 0 ? void 0 : _b.read;
|
|
451
|
+
users[u].acl.state.write = (_c = groups[g].common.acl.state) === null || _c === void 0 ? void 0 : _c.write;
|
|
452
|
+
users[u].acl.state.delete = (_d = groups[g].common.acl.state) === null || _d === void 0 ? void 0 : _d.delete;
|
|
453
|
+
users[u].acl.state.list = (_e = groups[g].common.acl.state) === null || _e === void 0 ? void 0 : _e.list;
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
users[u].acl.state.create =
|
|
457
|
+
users[u].acl.state.create || ((_f = groups[g].common.acl.state) === null || _f === void 0 ? void 0 : _f.create);
|
|
458
|
+
users[u].acl.state.read =
|
|
459
|
+
users[u].acl.state.read || ((_g = groups[g].common.acl.state) === null || _g === void 0 ? void 0 : _g.read);
|
|
460
|
+
users[u].acl.state.write =
|
|
461
|
+
users[u].acl.state.write || ((_h = groups[g].common.acl.state) === null || _h === void 0 ? void 0 : _h.write);
|
|
462
|
+
users[u].acl.state.delete =
|
|
463
|
+
users[u].acl.state.delete || ((_j = groups[g].common.acl.state) === null || _j === void 0 ? void 0 : _j.delete);
|
|
464
|
+
users[u].acl.state.list =
|
|
465
|
+
users[u].acl.state.list || ((_k = groups[g].common.acl.state) === null || _k === void 0 ? void 0 : _k.list);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return db_base_1.tools.maybeCallbackWithError(callback, error, user, users[user] ? users[user].groups : [], users[user] ? users[user].acl : (0, deep_clone_1.default)(defaultAcl.acl));
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
exports.getUserGroup = getUserGroup;
|
|
475
|
+
function sanitizePath(id, name) {
|
|
476
|
+
if (!name) {
|
|
477
|
+
name = '';
|
|
478
|
+
}
|
|
479
|
+
if (name[0] === '/') {
|
|
480
|
+
name = name.substring(1);
|
|
481
|
+
}
|
|
482
|
+
if (!id) {
|
|
483
|
+
throw new Error('Empty ID');
|
|
484
|
+
}
|
|
485
|
+
id = id.replace(/[\][*,;'"`<>\\?/]/g, ''); // remove all invalid characters from states plus slashes
|
|
486
|
+
id = id.replace(/\.\./g, ''); // do not allow to write in parent directories
|
|
487
|
+
if (name.includes('..')) {
|
|
488
|
+
name = path_1.default.normalize('/' + name);
|
|
489
|
+
}
|
|
490
|
+
if (name.includes('..')) {
|
|
491
|
+
// Also after normalization we still have .. in it - should not happen if normalize worked correctly
|
|
492
|
+
name = name.replace(/\.\./g, '');
|
|
493
|
+
name = path_1.default.normalize('/' + name);
|
|
494
|
+
}
|
|
495
|
+
name = name.replace(/\\/g, '/'); // replace win path backslashes
|
|
496
|
+
if (name[0] === '/') {
|
|
497
|
+
name = name.substring(1);
|
|
498
|
+
} // do not allow absolute paths
|
|
499
|
+
return { id: id, name: name };
|
|
500
|
+
}
|
|
501
|
+
exports.sanitizePath = sanitizePath;
|
|
502
|
+
function checkObject(obj, options, flag) {
|
|
503
|
+
// read rights of object
|
|
504
|
+
if (!obj || !('common' in obj) || !obj.acl || flag === CONSTS.ACCESS_LIST) {
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
507
|
+
if (options.user === CONSTS.SYSTEM_ADMIN_USER) {
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
// admins may always see everything
|
|
511
|
+
if (options.group === CONSTS.SYSTEM_ADMIN_GROUP || options.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP)) {
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
// FIXME: what if flag is ACCESS_DELETE or ACCESS_CREATE? currently it will end in false
|
|
515
|
+
if (flag === CONSTS.ACCESS_DELETE || flag === CONSTS.ACCESS_CREATE) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
// checkObject always called after checkObjectRights and admin is checked there
|
|
519
|
+
if (obj.acl.owner !== options.user) {
|
|
520
|
+
// Check if the user is in the group
|
|
521
|
+
if ((options.group && options.group === obj.acl.ownerGroup) ||
|
|
522
|
+
(options.groups && options.groups.includes(obj.acl.ownerGroup))) {
|
|
523
|
+
// Check group rights
|
|
524
|
+
if (!(obj.acl.object & (flag << 4))) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
// everybody
|
|
530
|
+
if (!(obj.acl.object & flag)) {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
// Check group rights
|
|
537
|
+
if (!(obj.acl.object & (flag << 8))) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return true; // ALL OK
|
|
542
|
+
}
|
|
543
|
+
exports.checkObject = checkObject;
|
|
544
|
+
function checkObjectRights(objects, id, object, options, flag, callback) {
|
|
545
|
+
options = options || {};
|
|
546
|
+
if (!options.user) {
|
|
547
|
+
// Before files converted, lets think: if no options it is admin
|
|
548
|
+
options = {
|
|
549
|
+
user: CONSTS.SYSTEM_ADMIN_USER,
|
|
550
|
+
params: options,
|
|
551
|
+
group: CONSTS.SYSTEM_ADMIN_GROUP,
|
|
552
|
+
groups: [CONSTS.SYSTEM_ADMIN_GROUP],
|
|
553
|
+
acl: getDefaultAdminRights()
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
if (!options.acl) {
|
|
557
|
+
return objects.getUserGroup(options.user, (_user, groups, acl) => {
|
|
558
|
+
// TODO: ts needs it because we are doing async call before
|
|
559
|
+
options = options || {};
|
|
560
|
+
options.acl = acl || {};
|
|
561
|
+
options.groups = groups;
|
|
562
|
+
options.group = groups ? groups[0] : null;
|
|
563
|
+
checkObjectRights(objects, id, object, options, flag, callback);
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
// now options are filled and we can go
|
|
567
|
+
if (options.user === CONSTS.SYSTEM_ADMIN_USER ||
|
|
568
|
+
options.group === CONSTS.SYSTEM_ADMIN_GROUP ||
|
|
569
|
+
(options.groups && options.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP))) {
|
|
570
|
+
return db_base_1.tools.maybeCallbackWithError(callback, null, options);
|
|
571
|
+
}
|
|
572
|
+
// if user or group objects
|
|
573
|
+
if (typeof id === 'string' && (id.startsWith(USER_STARTS_WITH) || id.startsWith(GROUP_STARTS_WITH))) {
|
|
574
|
+
// If user may write
|
|
575
|
+
if (flag === CONSTS.ACCESS_WRITE && !options.acl.users.write) {
|
|
576
|
+
// write
|
|
577
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
578
|
+
}
|
|
579
|
+
// If user may read
|
|
580
|
+
if (flag === CONSTS.ACCESS_READ && !options.acl.users.read) {
|
|
581
|
+
// read
|
|
582
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
583
|
+
}
|
|
584
|
+
// If user may delete
|
|
585
|
+
if (flag === CONSTS.ACCESS_DELETE && !options.acl.users.delete) {
|
|
586
|
+
// delete
|
|
587
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
588
|
+
}
|
|
589
|
+
// If user may list
|
|
590
|
+
if (flag === CONSTS.ACCESS_LIST && !options.acl.users.list) {
|
|
591
|
+
// list
|
|
592
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
593
|
+
}
|
|
594
|
+
// If user may create
|
|
595
|
+
if (flag === CONSTS.ACCESS_CREATE && !options.acl.users.create) {
|
|
596
|
+
// create
|
|
597
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
598
|
+
}
|
|
599
|
+
// If user may write
|
|
600
|
+
if (flag === CONSTS.ACCESS_DELETE) {
|
|
601
|
+
// he may delete
|
|
602
|
+
flag = CONSTS.ACCESS_WRITE;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// If user may write
|
|
606
|
+
if (flag === CONSTS.ACCESS_WRITE && !options.acl.object.write) {
|
|
607
|
+
// write
|
|
608
|
+
db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
609
|
+
}
|
|
610
|
+
// If user may read
|
|
611
|
+
if (flag === CONSTS.ACCESS_READ && !options.acl.object.read) {
|
|
612
|
+
// read
|
|
613
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
614
|
+
}
|
|
615
|
+
// If user may delete
|
|
616
|
+
if (flag === CONSTS.ACCESS_DELETE && !options.acl.object.delete) {
|
|
617
|
+
// delete
|
|
618
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
619
|
+
}
|
|
620
|
+
// If user may list
|
|
621
|
+
if (flag === CONSTS.ACCESS_LIST && !options.acl.object.list) {
|
|
622
|
+
// list
|
|
623
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
624
|
+
}
|
|
625
|
+
if (flag === CONSTS.ACCESS_DELETE) {
|
|
626
|
+
// write
|
|
627
|
+
flag = CONSTS.ACCESS_WRITE;
|
|
628
|
+
}
|
|
629
|
+
if (id && !checkObject(object, options, flag)) {
|
|
630
|
+
return db_base_1.tools.maybeCallbackWithError(callback, exports.ERRORS.ERROR_PERMISSION, options);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
return db_base_1.tools.maybeCallbackWithError(callback, null, options);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
exports.checkObjectRights = checkObjectRights;
|
|
637
|
+
//# sourceMappingURL=objectsUtils.js.map
|