@iobroker/db-objects-redis 7.2.3 → 8.0.0-alpha.1-20260921-e5941ca8a

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.
Files changed (57) hide show
  1. package/build/cjs/index.d.ts +1 -1
  2. package/build/cjs/index.js +5 -3
  3. package/build/cjs/index.js.map +2 -2
  4. package/build/cjs/lib/objects/constants.js.map +2 -2
  5. package/build/cjs/lib/objects/interview.js +2 -0
  6. package/build/cjs/lib/objects/interview.js.map +1 -1
  7. package/build/cjs/lib/objects/lua-v3/custom.lua +23 -1
  8. package/build/cjs/lib/objects/lua-v3/filter.lua +23 -1
  9. package/build/cjs/lib/objects/lua-v3/programs.lua +23 -1
  10. package/build/cjs/lib/objects/lua-v3/script.lua +23 -1
  11. package/build/cjs/lib/objects/lua-v3/variables.lua +23 -1
  12. package/build/cjs/lib/objects/lua-v4/custom.lua +23 -1
  13. package/build/cjs/lib/objects/lua-v4/filter.lua +23 -1
  14. package/build/cjs/lib/objects/lua-v4/programs.lua +23 -1
  15. package/build/cjs/lib/objects/lua-v4/script.lua +23 -1
  16. package/build/cjs/lib/objects/lua-v4/variables.lua +23 -1
  17. package/build/cjs/lib/objects/lua-v4-no-sets/custom.lua +23 -1
  18. package/build/cjs/lib/objects/lua-v4-no-sets/filter.lua +23 -1
  19. package/build/cjs/lib/objects/lua-v4-no-sets/programs.lua +23 -1
  20. package/build/cjs/lib/objects/lua-v4-no-sets/script.lua +23 -1
  21. package/build/cjs/lib/objects/lua-v4-no-sets/variables.lua +23 -1
  22. package/build/cjs/lib/objects/objectsInRedisClient.d.ts +961 -125
  23. package/build/cjs/lib/objects/objectsInRedisClient.js +1092 -776
  24. package/build/cjs/lib/objects/objectsInRedisClient.js.map +3 -3
  25. package/build/cjs/lib/objects/objectsUtils.d.ts +139 -17
  26. package/build/cjs/lib/objects/objectsUtils.js +212 -192
  27. package/build/cjs/lib/objects/objectsUtils.js.map +3 -3
  28. package/build/esm/index.d.ts +1 -1
  29. package/build/esm/index.d.ts.map +1 -1
  30. package/build/esm/index.js.map +1 -1
  31. package/build/esm/lib/objects/constants.d.ts.map +1 -1
  32. package/build/esm/lib/objects/constants.js.map +1 -1
  33. package/build/esm/lib/objects/lua-v3/custom.lua +23 -1
  34. package/build/esm/lib/objects/lua-v3/filter.lua +23 -1
  35. package/build/esm/lib/objects/lua-v3/programs.lua +23 -1
  36. package/build/esm/lib/objects/lua-v3/script.lua +23 -1
  37. package/build/esm/lib/objects/lua-v3/variables.lua +23 -1
  38. package/build/esm/lib/objects/lua-v4/custom.lua +23 -1
  39. package/build/esm/lib/objects/lua-v4/filter.lua +23 -1
  40. package/build/esm/lib/objects/lua-v4/programs.lua +23 -1
  41. package/build/esm/lib/objects/lua-v4/script.lua +23 -1
  42. package/build/esm/lib/objects/lua-v4/variables.lua +23 -1
  43. package/build/esm/lib/objects/lua-v4-no-sets/custom.lua +23 -1
  44. package/build/esm/lib/objects/lua-v4-no-sets/filter.lua +23 -1
  45. package/build/esm/lib/objects/lua-v4-no-sets/programs.lua +23 -1
  46. package/build/esm/lib/objects/lua-v4-no-sets/script.lua +23 -1
  47. package/build/esm/lib/objects/lua-v4-no-sets/variables.lua +23 -1
  48. package/build/esm/lib/objects/objectsInRedisClient.d.ts +961 -125
  49. package/build/esm/lib/objects/objectsInRedisClient.d.ts.map +1 -1
  50. package/build/esm/lib/objects/objectsInRedisClient.js +880 -571
  51. package/build/esm/lib/objects/objectsInRedisClient.js.map +1 -1
  52. package/build/esm/lib/objects/objectsUtils.d.ts +139 -17
  53. package/build/esm/lib/objects/objectsUtils.d.ts.map +1 -1
  54. package/build/esm/lib/objects/objectsUtils.js +273 -221
  55. package/build/esm/lib/objects/objectsUtils.js.map +1 -1
  56. package/build/tsconfig.build.tsbuildinfo +1 -1
  57. package/package.json +9 -9
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/objects/objectsUtils.ts"],
4
- "sourcesContent": ["/**\n * Common functions between client and server\n *\n * Copyright 2013-2024 bluefox <dogafox@gmail.com>\n *\n * MIT License\n *\n */\n\nimport path from 'node:path';\nimport deepClone from 'deep-clone';\nimport { tools } from '@iobroker/db-base';\nimport * as CONSTS from '@/lib/objects/constants.js';\nimport mime from 'mime-types';\n\nexport * as CONSTS from '@/lib/objects/constants.js';\nexport const ERRORS = CONSTS.ERRORS;\nexport const REG_CHECK_ID = CONSTS.REG_CHECK_ID;\n\nconst USER_STARTS_WITH = CONSTS.USER_STARTS_WITH;\nconst GROUP_STARTS_WITH = CONSTS.GROUP_STARTS_WITH;\n\nexport interface FileMimeInformation {\n /** the mime type, of the file */\n mimeType: string;\n /** if content is binary or textual */\n isBinary: boolean;\n}\n\nexport interface ACLObject {\n owner: string;\n ownerGroup: string;\n object: number;\n state: number;\n file: number;\n}\n\nexport interface FileObject {\n virtualFile?: boolean;\n stats: any;\n modifiedAt: number;\n createdAt: number;\n acl: ioBroker.EvaluatedFileACL;\n}\n\nexport type CheckFileRightsCallback = (err: Error | null | undefined, options: Record<string, any>, opt?: any) => void;\n\nconst textTypes = ['.js', '.json', '.svg'];\n\n/**\n * Checks if the mime type, of an extension is a known one and if it corresponds to binary content\n *\n * @param ext the file extension e.g. `.txt`\n */\nfunction getKnownMimeType(ext: string): FileMimeInformation | null {\n try {\n const mimeType = mime.lookup(ext);\n if (mimeType) {\n return { mimeType, isBinary: !mimeType.startsWith('text/') && !textTypes.includes(ext) };\n }\n } catch {\n // ignore\n }\n\n return null;\n}\n\n// For objects\nconst defaultAcl = {\n groups: [],\n acl: {\n file: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n object: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n state: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n users: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n },\n} as const;\n\n// FIXME: This should have better types. Probably Record<string, {acl: ioBroker.ObjectPermissions, [x: string | number | symbol]: any}>\nlet users: Record<ioBroker.ObjectIDs.User, any> = {};\nlet groups: ioBroker.GroupObject[] = [];\n\n/**\n * Determines the mime type, of an extension and if it is binary content\n *\n * @param ext file extension e.g. `.txt`\n * @param isTextData if content is of type string\n */\nexport function getMimeType(ext: string, isTextData: boolean): FileMimeInformation {\n if (!ext) {\n return { mimeType: isTextData ? 'text/plain' : 'application/octet-stream', isBinary: !isTextData };\n }\n\n ext = ext.toLowerCase();\n const mimeInfo = getKnownMimeType(ext);\n if (mimeInfo) {\n return mimeInfo;\n }\n return { mimeType: isTextData ? 'text/plain' : 'application/octet-stream', isBinary: !isTextData };\n}\n\nexport function checkFile(\n fileOptions: Record<string, any>,\n options: Record<string, any>,\n flag: any,\n defaultNewAcl?: ACLObject | null,\n): boolean {\n if (typeof fileOptions.acl !== 'object') {\n fileOptions = {};\n fileOptions.mimeType = deepClone(fileOptions);\n fileOptions.acl = {\n owner: (defaultNewAcl && defaultNewAcl.owner) || CONSTS.SYSTEM_ADMIN_USER,\n ownerGroup: (defaultNewAcl && defaultNewAcl.ownerGroup) || CONSTS.SYSTEM_ADMIN_GROUP,\n permissions:\n (defaultNewAcl && defaultNewAcl.file) ||\n CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ, // '0644'\n };\n }\n\n // Set default owner group\n fileOptions.acl.ownerGroup =\n fileOptions.acl.ownerGroup || (defaultNewAcl && defaultNewAcl.ownerGroup) || CONSTS.SYSTEM_ADMIN_GROUP;\n fileOptions.acl.owner = fileOptions.acl.owner || (defaultNewAcl && defaultNewAcl.owner) || CONSTS.SYSTEM_ADMIN_USER;\n fileOptions.acl.permissions =\n fileOptions.acl.permissions ||\n (defaultNewAcl && defaultNewAcl.file) ||\n CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ; // '0644'\n\n if (\n options.user !== CONSTS.SYSTEM_ADMIN_USER &&\n options.groups.indexOf(CONSTS.SYSTEM_ADMIN_GROUP) === -1 &&\n fileOptions.acl\n ) {\n if (fileOptions.acl.owner !== options.user) {\n // Check if the user is in the group\n if (options.groups.indexOf(fileOptions.acl.ownerGroup) !== -1) {\n // Check group rights\n if (!(fileOptions.acl.permissions & (flag << 4))) {\n return false;\n }\n } else {\n // everybody\n if (!(fileOptions.acl.permissions & flag)) {\n return false;\n }\n }\n } else {\n // Check user rights\n if (!(fileOptions.acl.permissions & (flag << 8))) {\n return false;\n }\n }\n }\n return true;\n}\n\nexport function checkFileRights(\n objects: any,\n id: string,\n name: string | null,\n options: Record<string, any> | null | undefined,\n flag: CONSTS.GenericAccessFlags,\n callback?: CheckFileRightsCallback,\n): any {\n const _options = options || {};\n if (!_options.user) {\n // Before files converted, lets think: if no options it is admin\n _options.user = 'system.user.admin';\n _options.params = _options;\n _options.group = 'system.group.administrator';\n }\n\n if (!_options.acl) {\n objects.getUserGroup(_options.user, (_user: any, groups: any, acl: Record<string, any>) => {\n _options.acl = acl || {};\n _options.groups = groups;\n _options.group = groups ? groups[0] : null;\n checkFileRights(objects, id, name, _options, flag, callback);\n });\n return;\n }\n // If user may write\n if (flag === CONSTS.ACCESS_WRITE && !_options.acl.file.write) {\n // write\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, _options);\n }\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !_options.acl.file.read) {\n // read\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, _options);\n }\n\n _options.checked = true;\n objects.checkFile(id, name, _options, flag, (err: Error, options: Record<string, any>, opt: any) => {\n if (err) {\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n return tools.maybeCallbackWithError(callback, null, options, opt);\n });\n}\n\n// For users and groups\nfunction getDefaultAdminRights(\n acl?: ioBroker.ObjectPermissions,\n _isState?: boolean,\n): Omit<ioBroker.PermissionSet, 'user' | 'groups'> {\n return {\n ...acl,\n file: {\n list: true,\n read: true,\n write: true,\n create: true,\n delete: true,\n },\n object: {\n create: true,\n list: true,\n read: true,\n write: true,\n delete: true,\n },\n users: {\n create: true,\n list: true,\n read: true,\n write: true,\n delete: true,\n },\n state: {\n read: true,\n write: true,\n delete: true,\n create: true,\n list: true,\n },\n other: {\n execute: false,\n http: false,\n sendto: false,\n },\n };\n}\n\nexport type GetUserGroupPromiseReturn = [user: string, groups: string[], acl: ioBroker.ObjectPermissions];\n\ntype GetUserGroupCallback = (\n err: Error | null | undefined,\n user: string,\n groups: string[],\n acl: ioBroker.ObjectPermissions,\n) => void;\n\nexport function getUserGroup(\n objects: any,\n user: ioBroker.ObjectIDs.User,\n callback?: GetUserGroupCallback,\n): Promise<GetUserGroupPromiseReturn> | void {\n if (!user || typeof user !== 'string' || !user.startsWith(USER_STARTS_WITH)) {\n console.log(`invalid user name: ${user}`);\n\n return tools.maybeCallbackWithError(\n callback,\n `invalid user name: ${user}`,\n deepClone(user),\n [],\n deepClone(defaultAcl.acl),\n );\n }\n if (users[user]) {\n return tools.maybeCallbackWithError(callback, null, user, users[user].groups, users[user].acl);\n }\n\n let error: Error;\n // Read all groups\n objects.getObjectList(\n { startkey: 'system.group.', endkey: 'system.group.\\u9999' },\n { checked: true },\n (\n err: Error,\n arr: {\n rows: Array<ioBroker.GetObjectViewItem<ioBroker.GroupObject>>;\n },\n ) => {\n if (err) {\n error = err;\n }\n groups = [];\n if (arr) {\n // Read all groups\n for (const g in arr.rows) {\n const val = arr.rows[g].value;\n if (!val) {\n continue;\n }\n\n groups[g] = val;\n if (groups[g]._id === CONSTS.SYSTEM_ADMIN_GROUP) {\n groups[g].common.acl = getDefaultAdminRights(groups[g].common.acl);\n }\n }\n }\n\n objects.getObjectList(\n { startkey: 'system.user.', endkey: 'system.user.\\u9999' },\n { checked: true },\n (\n err?: Error | null,\n arr?: {\n rows: ioBroker.GetObjectListItem<ioBroker.UserObject>[];\n },\n ) => {\n if (err) {\n error = err;\n }\n users = {};\n\n if (arr) {\n for (const row of arr.rows) {\n // cannot use here Object.assign, because required deep copy\n users[row.value._id] = deepClone(defaultAcl);\n }\n }\n users[CONSTS.SYSTEM_ADMIN_USER] = users[CONSTS.SYSTEM_ADMIN_USER] || deepClone(defaultAcl);\n users[CONSTS.SYSTEM_ADMIN_USER].acl = getDefaultAdminRights(users[CONSTS.SYSTEM_ADMIN_USER].acl);\n\n for (let g = 0; g < groups.length; g++) {\n if (!groups[g] || !groups[g].common || !groups[g].common.members) {\n continue;\n }\n for (let m = 0; m < groups[g].common.members.length; m++) {\n const u = groups[g].common.members[m];\n if (!users[u]) {\n error =\n error ||\n `Unknown user in group \"${groups[g]._id.replace('system.group.', '')}\": ${u}`;\n continue;\n }\n users[u].groups.push(groups[g]._id);\n\n if (groups[g].common.acl && groups[g].common.acl.file) {\n if (!users[u].acl || !users[u].acl.file) {\n users[u].acl = users[u].acl || {};\n users[u].acl.file = users[u].acl.file || {};\n\n users[u].acl.file.create = groups[g].common.acl.file.create;\n users[u].acl.file.read = groups[g].common.acl.file.read;\n users[u].acl.file.write = groups[g].common.acl.file.write;\n users[u].acl.file.delete = groups[g].common.acl.file.delete;\n users[u].acl.file.list = groups[g].common.acl.file.list;\n } else {\n users[u].acl.file.create =\n users[u].acl.file.create || groups[g].common.acl.file.create;\n users[u].acl.file.read = users[u].acl.file.read || groups[g].common.acl.file.read;\n users[u].acl.file.write =\n users[u].acl.file.write || groups[g].common.acl.file.write;\n users[u].acl.file.delete =\n users[u].acl.file.delete || groups[g].common.acl.file.delete;\n users[u].acl.file.list = users[u].acl.file.list || groups[g].common.acl.file.list;\n }\n }\n\n if (groups[g].common.acl && groups[g].common.acl.object) {\n if (!users[u].acl || !users[u].acl.object) {\n users[u].acl = users[u].acl || {};\n users[u].acl.object = users[u].acl.object || {};\n\n users[u].acl.object.create = groups[g].common.acl.object.create;\n users[u].acl.object.read = groups[g].common.acl.object.read;\n users[u].acl.object.write = groups[g].common.acl.object.write;\n users[u].acl.object.delete = groups[g].common.acl.object.delete;\n users[u].acl.object.list = groups[g].common.acl.object.list;\n } else {\n users[u].acl.object.create =\n users[u].acl.object.create || groups[g].common.acl.object.create;\n users[u].acl.object.read =\n users[u].acl.object.read || groups[g].common.acl.object.read;\n users[u].acl.object.write =\n users[u].acl.object.write || groups[g].common.acl.object.write;\n users[u].acl.object.delete =\n users[u].acl.object.delete || groups[g].common.acl.object.delete;\n users[u].acl.object.list =\n users[u].acl.object.list || groups[g].common.acl.object.list;\n }\n }\n\n if (groups[g].common.acl && groups[g].common.acl.users) {\n if (!users[u].acl || !users[u].acl.users) {\n users[u].acl = users[u].acl || {};\n users[u].acl.users = users[u].acl.users || {};\n\n users[u].acl.users.create = groups[g].common.acl.users.create;\n users[u].acl.users.read = groups[g].common.acl.users.read;\n users[u].acl.users.write = groups[g].common.acl.users.write;\n users[u].acl.users.delete = groups[g].common.acl.users.delete;\n users[u].acl.users.list = groups[g].common.acl.users.list;\n } else {\n users[u].acl.users.create =\n users[u].acl.users.create || groups[g].common.acl.users.create;\n users[u].acl.users.read =\n users[u].acl.users.read || groups[g].common.acl.users.read;\n users[u].acl.users.write =\n users[u].acl.users.write || groups[g].common.acl.users.write;\n users[u].acl.users.delete =\n users[u].acl.users.delete || groups[g].common.acl.users.delete;\n users[u].acl.users.list =\n users[u].acl.users.list || groups[g].common.acl.users.list;\n }\n }\n\n if (groups[g].common.acl && groups[g].common.acl.state) {\n if (!users[u].acl || !users[u].acl.state) {\n users[u].acl = users[u].acl || {};\n users[u].acl.state = users[u].acl.state || {};\n\n users[u].acl.state.create = groups[g].common.acl.state?.create;\n users[u].acl.state.read = groups[g].common.acl.state?.read;\n users[u].acl.state.write = groups[g].common.acl.state?.write;\n users[u].acl.state.delete = groups[g].common.acl.state?.delete;\n users[u].acl.state.list = groups[g].common.acl.state?.list;\n } else {\n users[u].acl.state.create =\n users[u].acl.state.create || groups[g].common.acl.state?.create;\n users[u].acl.state.read =\n users[u].acl.state.read || groups[g].common.acl.state?.read;\n users[u].acl.state.write =\n users[u].acl.state.write || groups[g].common.acl.state?.write;\n users[u].acl.state.delete =\n users[u].acl.state.delete || groups[g].common.acl.state?.delete;\n users[u].acl.state.list =\n users[u].acl.state.list || groups[g].common.acl.state?.list;\n }\n }\n }\n }\n\n return tools.maybeCallbackWithError(\n callback,\n error,\n user,\n users[user] ? users[user].groups : [],\n users[user] ? users[user].acl : deepClone(defaultAcl.acl),\n );\n },\n );\n },\n );\n}\n\nexport function sanitizePath(\n id: string,\n name: string,\n): {\n id: string;\n name: string;\n} {\n if (!name) {\n name = '';\n }\n if (name[0] === '/') {\n name = name.substring(1);\n }\n\n if (!id) {\n throw new Error('Empty ID');\n }\n\n id = id.replace(/[\\][*,;'\"`<>\\\\?/]/g, ''); // remove all invalid characters from states plus slashes\n id = id.replace(/\\.\\./g, ''); // do not allow to write in parent directories\n\n if (name.includes('..')) {\n name = path.normalize(`/${name}`);\n }\n if (name.includes('..')) {\n // Also after normalization we still have .. in it - should not happen if normalize worked correctly\n name = name.replace(/\\.\\./g, '');\n name = path.normalize(`/${name}`);\n }\n\n name = name.replace(/\\\\/g, '/'); // replace win path backslashes\n\n if (name[0] === '/') {\n name = name.substring(1);\n } // do not allow absolute paths\n\n return { id: id, name: name };\n}\n\nexport function checkObject(\n obj: ioBroker.AnyObject | FileObject | null,\n options: Record<string, any>,\n flag: CONSTS.GenericAccessFlags,\n): boolean {\n // read rights of object\n if (!obj || !('common' in obj) || !obj.acl || flag === CONSTS.ACCESS_LIST) {\n return true;\n }\n\n if (options.user === CONSTS.SYSTEM_ADMIN_USER) {\n return true;\n }\n\n // admins may always see everything\n if (options.group === CONSTS.SYSTEM_ADMIN_GROUP || options.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP)) {\n return true;\n }\n\n // FIXME: what if flag is ACCESS_DELETE or ACCESS_CREATE? currently it will end in false\n if (flag === CONSTS.ACCESS_DELETE || flag === CONSTS.ACCESS_CREATE) {\n return false;\n }\n\n // checkObject always called after checkObjectRights and admin is checked there\n if (obj.acl.owner !== options.user) {\n // Check if the user is in the group\n if (\n (options.group && options.group === obj.acl.ownerGroup) ||\n (options.groups && options.groups.includes(obj.acl.ownerGroup))\n ) {\n // Check group rights\n if (!(obj.acl.object & (flag << 4))) {\n return false;\n }\n } else {\n // everybody\n if (!(obj.acl.object & flag)) {\n return false;\n }\n }\n } else {\n // Check group rights\n if (!(obj.acl.object & (flag << 8))) {\n return false;\n }\n }\n return true; // ALL OK\n}\n\nexport function checkObjectRights(\n objects: any,\n id: string | null,\n object: ioBroker.Object | null,\n options: Record<string, any> | null | undefined,\n flag: CONSTS.GenericAccessFlags,\n callback: (err: Error | null | undefined, options: Record<string, any>) => void,\n): void | Promise<Record<string, any>> {\n options = options || {};\n\n if (!options.user) {\n // Before files converted, lets think: if no options it is admin\n options = {\n user: CONSTS.SYSTEM_ADMIN_USER,\n params: options,\n group: CONSTS.SYSTEM_ADMIN_GROUP,\n groups: [CONSTS.SYSTEM_ADMIN_GROUP],\n acl: getDefaultAdminRights(),\n };\n }\n\n if (!options.acl) {\n return objects.getUserGroup(options.user, (_user: string, groups: any, acl: Record<string, any>) => {\n // TODO: ts needs it because we are doing async call before\n options = options || {};\n options.acl = acl || {};\n options.groups = groups;\n options.group = groups ? groups[0] : null;\n checkObjectRights(objects, id, object, options, flag, callback);\n });\n }\n\n // now options are filled and we can go\n if (\n options.user === CONSTS.SYSTEM_ADMIN_USER ||\n options.group === CONSTS.SYSTEM_ADMIN_GROUP ||\n (options.groups && options.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP))\n ) {\n return tools.maybeCallbackWithError(callback, null, options);\n }\n\n // if user or group objects\n if (typeof id === 'string' && (id.startsWith(USER_STARTS_WITH) || id.startsWith(GROUP_STARTS_WITH))) {\n // If user may write\n if (flag === CONSTS.ACCESS_WRITE && !options.acl.users.write) {\n // write\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !options.acl.users.read) {\n // read\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may delete\n if (flag === CONSTS.ACCESS_DELETE && !options.acl.users.delete) {\n // delete\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may list\n if (flag === CONSTS.ACCESS_LIST && !options.acl.users.list) {\n // list\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may create\n if (flag === CONSTS.ACCESS_CREATE && !options.acl.users.create) {\n // create\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may write\n if (flag === CONSTS.ACCESS_DELETE) {\n // he may delete\n flag = CONSTS.ACCESS_WRITE;\n }\n }\n\n // If user may write\n if (flag === CONSTS.ACCESS_WRITE && !options.acl.object.write) {\n // write\n tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !options.acl.object.read) {\n // read\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may delete\n if (flag === CONSTS.ACCESS_DELETE && !options.acl.object.delete) {\n // delete\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n // If user may list\n if (flag === CONSTS.ACCESS_LIST && !options.acl.object.list) {\n // list\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n\n if (flag === CONSTS.ACCESS_DELETE) {\n // write\n flag = CONSTS.ACCESS_WRITE;\n }\n\n if (id && !checkObject(object, options, flag)) {\n return tools.maybeCallbackWithError(callback, ERRORS.ERROR_PERMISSION, options);\n }\n return tools.maybeCallbackWithError(callback, null, options);\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;gBAAAA;EAAA;;;;;;;;;;;AASA,uBAAiB;AACjB,wBAAsB;AACtB,qBAAsB;AACtB,aAAwB;AACxB,wBAAiB;AAEjB,IAAAC,UAAwB;AACjB,MAAM,SAAS,OAAO;AACtB,MAAM,eAAe,OAAO;AAEnC,MAAM,mBAAmB,OAAO;AAChC,MAAM,oBAAoB,OAAO;AA2BjC,MAAM,YAAY,CAAC,OAAO,SAAS,MAAM;AAOzC,SAAS,iBAAiB,KAAW;AACjC,MAAI;AACA,UAAM,WAAW,kBAAAC,QAAK,OAAO,GAAG;AAChC,QAAI,UAAU;AACV,aAAO,EAAE,UAAU,UAAU,CAAC,SAAS,WAAW,OAAO,KAAK,CAAC,UAAU,SAAS,GAAG,EAAC;IAC1F;EACJ,QAAQ;EAER;AAEA,SAAO;AACX;AAGA,MAAM,aAAa;EACf,QAAQ,CAAA;EACR,KAAK;IACD,MAAM;MACF,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;;IAEZ,QAAQ;MACJ,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;;IAEZ,OAAO;MACH,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;;IAEZ,OAAO;MACH,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;;;;AAMpB,IAAI,QAA8C,CAAA;AAClD,IAAI,SAAiC,CAAA;AAQ/B,SAAU,YAAY,KAAa,YAAmB;AACxD,MAAI,CAAC,KAAK;AACN,WAAO,EAAE,UAAU,aAAa,eAAe,4BAA4B,UAAU,CAAC,WAAU;EACpG;AAEA,QAAM,IAAI,YAAW;AACrB,QAAM,WAAW,iBAAiB,GAAG;AACrC,MAAI,UAAU;AACV,WAAO;EACX;AACA,SAAO,EAAE,UAAU,aAAa,eAAe,4BAA4B,UAAU,CAAC,WAAU;AACpG;AAEM,SAAU,UACZ,aACA,SACA,MACA,eAAgC;AAEhC,MAAI,OAAO,YAAY,QAAQ,UAAU;AACrC,kBAAc,CAAA;AACd,gBAAY,eAAW,kBAAAC,SAAU,WAAW;AAC5C,gBAAY,MAAM;MACd,OAAQ,iBAAiB,cAAc,SAAU,OAAO;MACxD,YAAa,iBAAiB,cAAc,cAAe,OAAO;MAClE,aACK,iBAAiB,cAAc,QAChC,OAAO,iBAAiB,OAAO,oBAAoB,OAAO;;;EAEtE;AAGA,cAAY,IAAI,aACZ,YAAY,IAAI,cAAe,iBAAiB,cAAc,cAAe,OAAO;AACxF,cAAY,IAAI,QAAQ,YAAY,IAAI,SAAU,iBAAiB,cAAc,SAAU,OAAO;AAClG,cAAY,IAAI,cACZ,YAAY,IAAI,eACf,iBAAiB,cAAc,QAChC,OAAO,iBAAiB,OAAO,oBAAoB,OAAO;AAE9D,MACI,QAAQ,SAAS,OAAO,qBACxB,QAAQ,OAAO,QAAQ,OAAO,kBAAkB,MAAM,MACtD,YAAY,KACd;AACE,QAAI,YAAY,IAAI,UAAU,QAAQ,MAAM;AAExC,UAAI,QAAQ,OAAO,QAAQ,YAAY,IAAI,UAAU,MAAM,IAAI;AAE3D,YAAI,EAAE,YAAY,IAAI,cAAe,QAAQ,IAAK;AAC9C,iBAAO;QACX;MACJ,OAAO;AAEH,YAAI,EAAE,YAAY,IAAI,cAAc,OAAO;AACvC,iBAAO;QACX;MACJ;IACJ,OAAO;AAEH,UAAI,EAAE,YAAY,IAAI,cAAe,QAAQ,IAAK;AAC9C,eAAO;MACX;IACJ;EACJ;AACA,SAAO;AACX;AAEM,SAAU,gBACZ,SACA,IACA,MACA,SACA,MACA,UAAkC;AAElC,QAAM,WAAW,WAAW,CAAA;AAC5B,MAAI,CAAC,SAAS,MAAM;AAEhB,aAAS,OAAO;AAChB,aAAS,SAAS;AAClB,aAAS,QAAQ;EACrB;AAEA,MAAI,CAAC,SAAS,KAAK;AACf,YAAQ,aAAa,SAAS,MAAM,CAAC,OAAYC,SAAa,QAA4B;AACtF,eAAS,MAAM,OAAO,CAAA;AACtB,eAAS,SAASA;AAClB,eAAS,QAAQA,UAASA,QAAO,CAAC,IAAI;AACtC,sBAAgB,SAAS,IAAI,MAAM,UAAU,MAAM,QAAQ;IAC/D,CAAC;AACD;EACJ;AAEA,MAAI,SAAS,OAAO,gBAAgB,CAAC,SAAS,IAAI,KAAK,OAAO;AAE1D,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,QAAQ;EACnF;AAEA,MAAI,SAAS,OAAO,eAAe,CAAC,SAAS,IAAI,KAAK,MAAM;AAExD,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,QAAQ;EACnF;AAEA,WAAS,UAAU;AACnB,UAAQ,UAAU,IAAI,MAAM,UAAU,MAAM,CAAC,KAAYC,UAA8B,QAAY;AAC/F,QAAI,KAAK;AACL,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkBA,QAAO;IAClF;AACA,WAAO,qBAAM,uBAAuB,UAAU,MAAMA,UAAS,GAAG;EACpE,CAAC;AACL;AAGA,SAAS,sBACL,KACA,UAAkB;AAElB,SAAO;IACH,GAAG;IACH,MAAM;MACF,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;;IAEZ,QAAQ;MACJ,QAAQ;MACR,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;;IAEZ,OAAO;MACH,QAAQ;MACR,MAAM;MACN,MAAM;MACN,OAAO;MACP,QAAQ;;IAEZ,OAAO;MACH,MAAM;MACN,OAAO;MACP,QAAQ;MACR,QAAQ;MACR,MAAM;;IAEV,OAAO;MACH,SAAS;MACT,MAAM;MACN,QAAQ;;;AAGpB;AAWM,SAAU,aACZ,SACA,MACA,UAA+B;AAE/B,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,WAAW,gBAAgB,GAAG;AACzE,YAAQ,IAAI,sBAAsB,IAAI,EAAE;AAExC,WAAO,qBAAM,uBACT,UACA,sBAAsB,IAAI,QAC1B,kBAAAF,SAAU,IAAI,GACd,CAAA,OACA,kBAAAA,SAAU,WAAW,GAAG,CAAC;EAEjC;AACA,MAAI,MAAM,IAAI,GAAG;AACb,WAAO,qBAAM,uBAAuB,UAAU,MAAM,MAAM,MAAM,IAAI,EAAE,QAAQ,MAAM,IAAI,EAAE,GAAG;EACjG;AAEA,MAAI;AAEJ,UAAQ,cACJ,EAAE,UAAU,iBAAiB,QAAQ,sBAAqB,GAC1D,EAAE,SAAS,KAAI,GACf,CACI,KACA,QAGA;AACA,QAAI,KAAK;AACL,cAAQ;IACZ;AACA,aAAS,CAAA;AACT,QAAI,KAAK;AAEL,iBAAW,KAAK,IAAI,MAAM;AACtB,cAAM,MAAM,IAAI,KAAK,CAAC,EAAE;AACxB,YAAI,CAAC,KAAK;AACN;QACJ;AAEA,eAAO,CAAC,IAAI;AACZ,YAAI,OAAO,CAAC,EAAE,QAAQ,OAAO,oBAAoB;AAC7C,iBAAO,CAAC,EAAE,OAAO,MAAM,sBAAsB,OAAO,CAAC,EAAE,OAAO,GAAG;QACrE;MACJ;IACJ;AAEA,YAAQ,cACJ,EAAE,UAAU,gBAAgB,QAAQ,qBAAoB,GACxD,EAAE,SAAS,KAAI,GACf,CACIG,MACAC,SAGA;AACA,UAAID,MAAK;AACL,gBAAQA;MACZ;AACA,cAAQ,CAAA;AAER,UAAIC,MAAK;AACL,mBAAW,OAAOA,KAAI,MAAM;AAExB,gBAAM,IAAI,MAAM,GAAG,QAAI,kBAAAJ,SAAU,UAAU;QAC/C;MACJ;AACA,YAAM,OAAO,iBAAiB,IAAI,MAAM,OAAO,iBAAiB,SAAK,kBAAAA,SAAU,UAAU;AACzF,YAAM,OAAO,iBAAiB,EAAE,MAAM,sBAAsB,MAAM,OAAO,iBAAiB,EAAE,GAAG;AAE/F,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACpC,YAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,SAAS;AAC9D;QACJ;AACA,iBAAS,IAAI,GAAG,IAAI,OAAO,CAAC,EAAE,OAAO,QAAQ,QAAQ,KAAK;AACtD,gBAAM,IAAI,OAAO,CAAC,EAAE,OAAO,QAAQ,CAAC;AACpC,cAAI,CAAC,MAAM,CAAC,GAAG;AACX,oBACI,SACA,0BAA0B,OAAO,CAAC,EAAE,IAAI,QAAQ,iBAAiB,EAAE,CAAC,MAAM,CAAC;AAC/E;UACJ;AACA,gBAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,EAAE,GAAG;AAElC,cAAI,OAAO,CAAC,EAAE,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AACnD,gBAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM;AACrC,oBAAM,CAAC,EAAE,MAAM,MAAM,CAAC,EAAE,OAAO,CAAA;AAC/B,oBAAM,CAAC,EAAE,IAAI,OAAO,MAAM,CAAC,EAAE,IAAI,QAAQ,CAAA;AAEzC,oBAAM,CAAC,EAAE,IAAI,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AACrD,oBAAM,CAAC,EAAE,IAAI,KAAK,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AACnD,oBAAM,CAAC,EAAE,IAAI,KAAK,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AACpD,oBAAM,CAAC,EAAE,IAAI,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AACrD,oBAAM,CAAC,EAAE,IAAI,KAAK,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;YACvD,OAAO;AACH,oBAAM,CAAC,EAAE,IAAI,KAAK,SACd,MAAM,CAAC,EAAE,IAAI,KAAK,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AAC1D,oBAAM,CAAC,EAAE,IAAI,KAAK,OAAO,MAAM,CAAC,EAAE,IAAI,KAAK,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AAC7E,oBAAM,CAAC,EAAE,IAAI,KAAK,QACd,MAAM,CAAC,EAAE,IAAI,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AACzD,oBAAM,CAAC,EAAE,IAAI,KAAK,SACd,MAAM,CAAC,EAAE,IAAI,KAAK,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;AAC1D,oBAAM,CAAC,EAAE,IAAI,KAAK,OAAO,MAAM,CAAC,EAAE,IAAI,KAAK,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,KAAK;YACjF;UACJ;AAEA,cAAI,OAAO,CAAC,EAAE,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,QAAQ;AACrD,gBAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,QAAQ;AACvC,oBAAM,CAAC,EAAE,MAAM,MAAM,CAAC,EAAE,OAAO,CAAA;AAC/B,oBAAM,CAAC,EAAE,IAAI,SAAS,MAAM,CAAC,EAAE,IAAI,UAAU,CAAA;AAE7C,oBAAM,CAAC,EAAE,IAAI,OAAO,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACzD,oBAAM,CAAC,EAAE,IAAI,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACvD,oBAAM,CAAC,EAAE,IAAI,OAAO,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACxD,oBAAM,CAAC,EAAE,IAAI,OAAO,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACzD,oBAAM,CAAC,EAAE,IAAI,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;YAC3D,OAAO;AACH,oBAAM,CAAC,EAAE,IAAI,OAAO,SAChB,MAAM,CAAC,EAAE,IAAI,OAAO,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC9D,oBAAM,CAAC,EAAE,IAAI,OAAO,OAChB,MAAM,CAAC,EAAE,IAAI,OAAO,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC5D,oBAAM,CAAC,EAAE,IAAI,OAAO,QAChB,MAAM,CAAC,EAAE,IAAI,OAAO,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC7D,oBAAM,CAAC,EAAE,IAAI,OAAO,SAChB,MAAM,CAAC,EAAE,IAAI,OAAO,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC9D,oBAAM,CAAC,EAAE,IAAI,OAAO,OAChB,MAAM,CAAC,EAAE,IAAI,OAAO,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;YAChE;UACJ;AAEA,cAAI,OAAO,CAAC,EAAE,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACpD,gBAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO;AACtC,oBAAM,CAAC,EAAE,MAAM,MAAM,CAAC,EAAE,OAAO,CAAA;AAC/B,oBAAM,CAAC,EAAE,IAAI,QAAQ,MAAM,CAAC,EAAE,IAAI,SAAS,CAAA;AAE3C,oBAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AACvD,oBAAM,CAAC,EAAE,IAAI,MAAM,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AACrD,oBAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AACtD,oBAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AACvD,oBAAM,CAAC,EAAE,IAAI,MAAM,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;YACzD,OAAO;AACH,oBAAM,CAAC,EAAE,IAAI,MAAM,SACf,MAAM,CAAC,EAAE,IAAI,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AAC5D,oBAAM,CAAC,EAAE,IAAI,MAAM,OACf,MAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AAC1D,oBAAM,CAAC,EAAE,IAAI,MAAM,QACf,MAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AAC3D,oBAAM,CAAC,EAAE,IAAI,MAAM,SACf,MAAM,CAAC,EAAE,IAAI,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;AAC5D,oBAAM,CAAC,EAAE,IAAI,MAAM,OACf,MAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,MAAM;YAC9D;UACJ;AAEA,cAAI,OAAO,CAAC,EAAE,OAAO,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACpD,gBAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO;AACtC,oBAAM,CAAC,EAAE,MAAM,MAAM,CAAC,EAAE,OAAO,CAAA;AAC/B,oBAAM,CAAC,EAAE,IAAI,QAAQ,MAAM,CAAC,EAAE,IAAI,SAAS,CAAA;AAE3C,oBAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACxD,oBAAM,CAAC,EAAE,IAAI,MAAM,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACtD,oBAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACvD,oBAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AACxD,oBAAM,CAAC,EAAE,IAAI,MAAM,OAAO,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;YAC1D,OAAO;AACH,oBAAM,CAAC,EAAE,IAAI,MAAM,SACf,MAAM,CAAC,EAAE,IAAI,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC7D,oBAAM,CAAC,EAAE,IAAI,MAAM,OACf,MAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC3D,oBAAM,CAAC,EAAE,IAAI,MAAM,QACf,MAAM,CAAC,EAAE,IAAI,MAAM,SAAS,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC5D,oBAAM,CAAC,EAAE,IAAI,MAAM,SACf,MAAM,CAAC,EAAE,IAAI,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;AAC7D,oBAAM,CAAC,EAAE,IAAI,MAAM,OACf,MAAM,CAAC,EAAE,IAAI,MAAM,QAAQ,OAAO,CAAC,EAAE,OAAO,IAAI,OAAO;YAC/D;UACJ;QACJ;MACJ;AAEA,aAAO,qBAAM,uBACT,UACA,OACA,MACA,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,SAAS,CAAA,GACnC,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE,UAAM,kBAAAA,SAAU,WAAW,GAAG,CAAC;IAEjE,CAAC;EAET,CAAC;AAET;AAEM,SAAU,aACZ,IACA,MAAY;AAKZ,MAAI,CAAC,MAAM;AACP,WAAO;EACX;AACA,MAAI,KAAK,CAAC,MAAM,KAAK;AACjB,WAAO,KAAK,UAAU,CAAC;EAC3B;AAEA,MAAI,CAAC,IAAI;AACL,UAAM,IAAI,MAAM,UAAU;EAC9B;AAEA,OAAK,GAAG,QAAQ,sBAAsB,EAAE;AACxC,OAAK,GAAG,QAAQ,SAAS,EAAE;AAE3B,MAAI,KAAK,SAAS,IAAI,GAAG;AACrB,WAAO,iBAAAK,QAAK,UAAU,IAAI,IAAI,EAAE;EACpC;AACA,MAAI,KAAK,SAAS,IAAI,GAAG;AAErB,WAAO,KAAK,QAAQ,SAAS,EAAE;AAC/B,WAAO,iBAAAA,QAAK,UAAU,IAAI,IAAI,EAAE;EACpC;AAEA,SAAO,KAAK,QAAQ,OAAO,GAAG;AAE9B,MAAI,KAAK,CAAC,MAAM,KAAK;AACjB,WAAO,KAAK,UAAU,CAAC;EAC3B;AAEA,SAAO,EAAE,IAAQ,KAAU;AAC/B;AAEM,SAAU,YACZ,KACA,SACA,MAA+B;AAG/B,MAAI,CAAC,OAAO,EAAE,YAAY,QAAQ,CAAC,IAAI,OAAO,SAAS,OAAO,aAAa;AACvE,WAAO;EACX;AAEA,MAAI,QAAQ,SAAS,OAAO,mBAAmB;AAC3C,WAAO;EACX;AAGA,MAAI,QAAQ,UAAU,OAAO,sBAAsB,QAAQ,OAAO,SAAS,OAAO,kBAAkB,GAAG;AACnG,WAAO;EACX;AAGA,MAAI,SAAS,OAAO,iBAAiB,SAAS,OAAO,eAAe;AAChE,WAAO;EACX;AAGA,MAAI,IAAI,IAAI,UAAU,QAAQ,MAAM;AAEhC,QACK,QAAQ,SAAS,QAAQ,UAAU,IAAI,IAAI,cAC3C,QAAQ,UAAU,QAAQ,OAAO,SAAS,IAAI,IAAI,UAAU,GAC/D;AAEE,UAAI,EAAE,IAAI,IAAI,SAAU,QAAQ,IAAK;AACjC,eAAO;MACX;IACJ,OAAO;AAEH,UAAI,EAAE,IAAI,IAAI,SAAS,OAAO;AAC1B,eAAO;MACX;IACJ;EACJ,OAAO;AAEH,QAAI,EAAE,IAAI,IAAI,SAAU,QAAQ,IAAK;AACjC,aAAO;IACX;EACJ;AACA,SAAO;AACX;AAEM,SAAU,kBACZ,SACA,IACA,QACA,SACA,MACA,UAA+E;AAE/E,YAAU,WAAW,CAAA;AAErB,MAAI,CAAC,QAAQ,MAAM;AAEf,cAAU;MACN,MAAM,OAAO;MACb,QAAQ;MACR,OAAO,OAAO;MACd,QAAQ,CAAC,OAAO,kBAAkB;MAClC,KAAK,sBAAqB;;EAElC;AAEA,MAAI,CAAC,QAAQ,KAAK;AACd,WAAO,QAAQ,aAAa,QAAQ,MAAM,CAAC,OAAeJ,SAAa,QAA4B;AAE/F,gBAAU,WAAW,CAAA;AACrB,cAAQ,MAAM,OAAO,CAAA;AACrB,cAAQ,SAASA;AACjB,cAAQ,QAAQA,UAASA,QAAO,CAAC,IAAI;AACrC,wBAAkB,SAAS,IAAI,QAAQ,SAAS,MAAM,QAAQ;IAClE,CAAC;EACL;AAGA,MACI,QAAQ,SAAS,OAAO,qBACxB,QAAQ,UAAU,OAAO,sBACxB,QAAQ,UAAU,QAAQ,OAAO,SAAS,OAAO,kBAAkB,GACtE;AACE,WAAO,qBAAM,uBAAuB,UAAU,MAAM,OAAO;EAC/D;AAGA,MAAI,OAAO,OAAO,aAAa,GAAG,WAAW,gBAAgB,KAAK,GAAG,WAAW,iBAAiB,IAAI;AAEjG,QAAI,SAAS,OAAO,gBAAgB,CAAC,QAAQ,IAAI,MAAM,OAAO;AAE1D,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;IAClF;AAGA,QAAI,SAAS,OAAO,eAAe,CAAC,QAAQ,IAAI,MAAM,MAAM;AAExD,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;IAClF;AAGA,QAAI,SAAS,OAAO,iBAAiB,CAAC,QAAQ,IAAI,MAAM,QAAQ;AAE5D,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;IAClF;AAGA,QAAI,SAAS,OAAO,eAAe,CAAC,QAAQ,IAAI,MAAM,MAAM;AAExD,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;IAClF;AAGA,QAAI,SAAS,OAAO,iBAAiB,CAAC,QAAQ,IAAI,MAAM,QAAQ;AAE5D,aAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;IAClF;AAGA,QAAI,SAAS,OAAO,eAAe;AAE/B,aAAO,OAAO;IAClB;EACJ;AAGA,MAAI,SAAS,OAAO,gBAAgB,CAAC,QAAQ,IAAI,OAAO,OAAO;AAE3D,yBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;EAC3E;AAGA,MAAI,SAAS,OAAO,eAAe,CAAC,QAAQ,IAAI,OAAO,MAAM;AAEzD,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;EAClF;AAGA,MAAI,SAAS,OAAO,iBAAiB,CAAC,QAAQ,IAAI,OAAO,QAAQ;AAE7D,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;EAClF;AAGA,MAAI,SAAS,OAAO,eAAe,CAAC,QAAQ,IAAI,OAAO,MAAM;AAEzD,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;EAClF;AAEA,MAAI,SAAS,OAAO,eAAe;AAE/B,WAAO,OAAO;EAClB;AAEA,MAAI,MAAM,CAAC,YAAY,QAAQ,SAAS,IAAI,GAAG;AAC3C,WAAO,qBAAM,uBAAuB,UAAU,OAAO,kBAAkB,OAAO;EAClF;AACA,SAAO,qBAAM,uBAAuB,UAAU,MAAM,OAAO;AAC/D;",
6
- "names": ["CONSTS", "CONSTS", "mime", "deepClone", "groups", "options", "err", "arr", "path"]
4
+ "sourcesContent": ["/**\n * Common functions between client and server\n *\n * Copyright 2013-2026 bluefox <dogafox@gmail.com>\n *\n * MIT License\n *\n */\n\nimport path from 'node:path';\nimport deepClone from 'deep-clone';\nimport mime from 'mime-types';\n\nimport { tools } from '@iobroker/db-base';\nimport * as CONSTS from '@/lib/objects/constants.js';\nimport type { Client as ObjectClient } from '@iobroker/db-objects-redis';\nimport { SYSTEM_ADMIN_GROUP, SYSTEM_ADMIN_USER } from '@/lib/objects/constants.js';\n\nexport * as CONSTS from '@/lib/objects/constants.js';\nexport const ERRORS = CONSTS.ERRORS;\nexport const REG_CHECK_ID = CONSTS.REG_CHECK_ID;\n\nconst USER_STARTS_WITH = CONSTS.USER_STARTS_WITH;\nconst GROUP_STARTS_WITH = CONSTS.GROUP_STARTS_WITH;\n\n/** Resolved permission context of the user performing a request */\nexport interface UserContext {\n /** The user on whose behalf the request is performed */\n user: ioBroker.ObjectIDs.User;\n /** The primary group of the user */\n group: ioBroker.ObjectIDs.Group;\n /** All groups the user is a member of */\n groups: ioBroker.ObjectIDs.Group[];\n /** The effective permissions resolved from the user and its groups */\n acl: ioBroker.ObjectPermissions;\n /** Whether the permissions have already been resolved/checked */\n checked?: boolean;\n}\n\n/** Information about a file's mime type */\nexport interface FileMimeInformation {\n /** the mime type, of the file */\n mimeType: string;\n /** if the content is binary or textual */\n isBinary: boolean;\n}\n\n/** The access control list of an object, state or file */\nexport interface ACLObject {\n /** The user that owns the object */\n owner: ioBroker.ObjectIDs.User;\n /** The group that owns the object */\n ownerGroup: ioBroker.ObjectIDs.Group;\n /** Permission bitmask for object access */\n object: number;\n /** Permission bitmask for state access */\n state: number;\n /** Permission bitmask for file access */\n file: number;\n}\n\n/** Metadata of a stored file */\nexport interface FileObject {\n /** Whether this is a virtual file (a directory placeholder) */\n virtualFile?: boolean;\n /** File system stats of the file */\n stats?: {\n size?: number;\n };\n /** Timestamp (ms) when the file was last modified */\n modifiedAt?: number;\n /** Timestamp (ms) when the file was created */\n createdAt?: number;\n /** Evaluated access control list of the file */\n acl?: ioBroker.EvaluatedFileACL;\n /** Whether the entry is a directory */\n isDir?: boolean;\n /** Whether the file does not exist (yet) */\n notExists?: boolean;\n /** The mime type of the file */\n mimeType?: string;\n /** Whether the file content is binary */\n binary?: boolean;\n}\n\nconst textTypes = ['.js', '.json', '.svg'];\n\n/**\n * Checks if the mime type, of an extension is a known one and if it corresponds to binary content\n *\n * @param ext the file extension e.g. `.txt`\n */\nfunction getKnownMimeType(ext: string): FileMimeInformation | null {\n try {\n const mimeType = mime.lookup(ext);\n if (mimeType) {\n return { mimeType, isBinary: !mimeType.startsWith('text/') && !textTypes.includes(ext) };\n }\n } catch {\n // ignore\n }\n\n return null;\n}\n\n// For objects\nconst defaultAcl: {\n groups: ioBroker.ObjectIDs.Group[];\n acl: ioBroker.ObjectPermissions;\n} = {\n groups: [],\n acl: {\n file: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n object: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n state: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n users: {\n list: false,\n read: false,\n write: false,\n create: false,\n delete: false,\n },\n },\n};\n\n// FIXME: This should have better types. Probably Record<string, {acl: ioBroker.ObjectPermissions, [x: string | number | symbol]: any}>\nlet users: Record<\n ioBroker.ObjectIDs.User,\n {\n groups: ioBroker.ObjectIDs.Group[];\n acl: ioBroker.ObjectPermissions;\n }\n> = {};\nlet groups: ioBroker.GroupObject[] = [];\n\n/**\n * Determines the mime type, of an extension and if it is binary content\n *\n * @param ext file extension e.g. `.txt`\n * @param isTextData if content is of type string\n */\nexport function getMimeType(ext: string, isTextData?: boolean): FileMimeInformation {\n if (!ext) {\n return { mimeType: isTextData ? 'text/plain' : 'application/octet-stream', isBinary: !isTextData };\n }\n\n ext = ext.toLowerCase();\n const mimeInfo = getKnownMimeType(ext);\n if (mimeInfo) {\n return mimeInfo;\n }\n return { mimeType: isTextData ? 'text/plain' : 'application/octet-stream', isBinary: !isTextData };\n}\n\n/**\n * Check if the given options have the required rights on a file according to its ACL\n *\n * @param fileOptions The stored file options including its ACL\n * @param fileOptions.mimeType The mime type of the file\n * @param fileOptions.notExists Whether the file does not exist yet\n * @param fileOptions.acl The access control list stored for the file\n * @param userContext The current request options including the user and group\n * @param flag The access flag(s) to check for\n * @param defaultNewAcl The default ACL to use if the file has none yet\n */\nexport function checkFile(\n fileOptions: {\n mimeType?: string;\n notExists?: boolean;\n acl?: ioBroker.FileACL;\n },\n userContext: UserContext,\n flag: number,\n defaultNewAcl?: ACLObject | null,\n): boolean {\n // convert string to structure\n fileOptions ||= {};\n fileOptions.acl ||= {\n owner: defaultNewAcl?.owner || CONSTS.SYSTEM_ADMIN_USER,\n ownerGroup: defaultNewAcl?.ownerGroup || CONSTS.SYSTEM_ADMIN_GROUP,\n permissions: defaultNewAcl?.file || CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ, // '0644'\n };\n\n // Set default owner group\n fileOptions.acl.owner ||= defaultNewAcl?.owner || CONSTS.SYSTEM_ADMIN_USER;\n fileOptions.acl.ownerGroup ||= defaultNewAcl?.ownerGroup || CONSTS.SYSTEM_ADMIN_GROUP;\n fileOptions.acl.permissions ||=\n defaultNewAcl?.file || CONSTS.ACCESS_USER_RW | CONSTS.ACCESS_GROUP_READ | CONSTS.ACCESS_EVERY_READ; // '0644'\n\n if (\n userContext.user !== CONSTS.SYSTEM_ADMIN_USER &&\n !userContext.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP) &&\n fileOptions.acl\n ) {\n if (fileOptions.acl.owner !== userContext.user) {\n // Check if the user is in the group\n if (userContext.groups.includes(fileOptions.acl.ownerGroup)) {\n // Check group rights\n if (!(fileOptions.acl.permissions & (flag << 4))) {\n return false;\n }\n } else {\n // everybody\n if (!(fileOptions.acl.permissions & flag)) {\n return false;\n }\n }\n } else {\n // Check user rights\n if (!(fileOptions.acl.permissions & (flag << 8))) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Check whether the given user is allowed to access a file and call back with the effective options\n *\n * @param objects The objects database client\n * @param id The id of the object owning the file\n * @param name The file name, or null for the whole namespace\n * @param options The current request options including the user\n * @param flag The access flag(s) to check for\n */\nexport async function checkFileRightsAsync(\n objects: ObjectClient,\n id: string,\n name: string | null,\n options:\n | {\n user?: ioBroker.ObjectIDs.User;\n }\n | null\n | undefined,\n flag: CONSTS.GenericAccessFlags,\n): Promise<{\n fileOptions: FileObject;\n userContext: UserContext;\n}> {\n let userContext: UserContext;\n if (!options?.user) {\n // Before files converted, lets think: if no options it is admin\n userContext = {\n user: SYSTEM_ADMIN_USER,\n group: SYSTEM_ADMIN_GROUP,\n groups: [SYSTEM_ADMIN_GROUP],\n acl: getDefaultAdminRights(),\n };\n } else {\n const [, groups, acl] = await getUserGroupAsync(objects, options.user);\n userContext = {\n user: options.user,\n group: groups?.[0] || null,\n groups,\n acl,\n };\n }\n\n if (flag === CONSTS.ACCESS_WRITE && !userContext.acl.file.write) {\n // If user may write\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !userContext.acl.file.read) {\n // read\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n userContext.checked = true;\n const fileOptions = await objects.checkFileAsync(id, name, userContext, flag);\n if (!fileOptions) {\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n return { fileOptions, userContext };\n}\n\n// For users and groups\nfunction getDefaultAdminRights(\n acl?: ioBroker.ObjectPermissions,\n _isState?: boolean,\n): Omit<ioBroker.PermissionSet, 'user' | 'groups'> {\n return {\n ...acl,\n file: {\n list: true,\n read: true,\n write: true,\n create: true,\n delete: true,\n },\n object: {\n create: true,\n list: true,\n read: true,\n write: true,\n delete: true,\n },\n users: {\n create: true,\n list: true,\n read: true,\n write: true,\n delete: true,\n },\n state: {\n read: true,\n write: true,\n delete: true,\n create: true,\n list: true,\n },\n other: {\n execute: false,\n http: false,\n sendto: false,\n },\n };\n}\n\nexport type GetUserGroupPromiseReturn = [\n user: ioBroker.ObjectIDs.User,\n groups: ioBroker.ObjectIDs.Group[],\n acl: ioBroker.ObjectPermissions,\n];\n\ntype GetUserGroupCallback = (\n err: Error | null | undefined,\n user: ioBroker.ObjectIDs.User,\n groups: ioBroker.ObjectIDs.Group[],\n acl: ioBroker.ObjectPermissions,\n) => void;\n\n/**\n * Determine the groups and effective ACL of the given user\n *\n * @param objects The objects database client\n * @param user The id of the user to look up\n * @param callback Called with the user, its groups and the effective ACL\n */\nexport function getUserGroup(\n objects: ObjectClient,\n user: ioBroker.ObjectIDs.User,\n callback: GetUserGroupCallback,\n): void {\n try {\n getUserGroupAsync(objects, user)\n .then(result => tools.maybeCallbackWithError(callback, null, result[0], result[1], result[2]))\n .catch(err => tools.maybeCallbackWithError(callback, err, deepClone(user), [], deepClone(defaultAcl.acl)));\n } catch (err) {\n return tools.maybeCallbackWithError(callback, err, deepClone(user), [], deepClone(defaultAcl.acl));\n }\n}\n\n/**\n * Determine the groups and effective ACL of the given user\n *\n * @param objects The objects database client\n * @param user The id of the user to look up\n */\nexport async function getUserGroupAsync(\n objects: ObjectClient,\n user: ioBroker.ObjectIDs.User,\n): Promise<GetUserGroupPromiseReturn> {\n if (!user || typeof user !== 'string' || !user.startsWith(USER_STARTS_WITH)) {\n console.log(`invalid user name: ${user}`);\n\n throw new Error(`invalid user name: ${user}`);\n }\n\n if (users[user]) {\n return [user, users[user].groups, users[user].acl];\n }\n\n let error: Error | string | undefined;\n groups = [];\n // Read all groups\n const groupList = await objects.getObjectListAsync(\n { startkey: 'system.group.', endkey: 'system.group.\\u9999' },\n { checked: true },\n );\n if (groupList) {\n // Read all groups\n for (let g = 0; g < groupList.rows.length; g++) {\n const val = groupList.rows[g].value;\n if (!val) {\n continue;\n }\n\n groups[g] = val as ioBroker.GroupObject;\n if (groups[g]._id === CONSTS.SYSTEM_ADMIN_GROUP) {\n groups[g].common.acl = getDefaultAdminRights(groups[g].common.acl);\n }\n }\n }\n\n users = {};\n const userList = await objects.getObjectListAsync(\n { startkey: 'system.user.', endkey: 'system.user.\\u9999' },\n { checked: true },\n );\n if (userList) {\n for (const row of userList.rows) {\n // cannot use here Object.assign, because required deep copy\n users[(row.value as ioBroker.UserObject)._id] = deepClone<{\n groups: ioBroker.ObjectIDs.Group[];\n acl: ioBroker.ObjectPermissions;\n }>(defaultAcl);\n }\n }\n\n users[CONSTS.SYSTEM_ADMIN_USER] ||= deepClone(defaultAcl);\n users[CONSTS.SYSTEM_ADMIN_USER].acl = getDefaultAdminRights(users[CONSTS.SYSTEM_ADMIN_USER].acl);\n\n for (let g = 0; g < groups.length; g++) {\n if (!groups[g]?.common?.members) {\n continue;\n }\n for (let m = 0; m < groups[g].common.members.length; m++) {\n const u = groups[g].common.members[m];\n if (!users[u]) {\n error ||= `Unknown user in group \"${groups[g]._id.replace('system.group.', '')}\": ${u}`;\n continue;\n }\n users[u].groups.push(groups[g]._id);\n\n if (groups[g].common.acl?.file) {\n if (!users[u].acl?.file) {\n users[u].acl ||= {} as ioBroker.ObjectPermissions;\n users[u].acl.file ||= {} as ioBroker.ObjectPermissions['file'];\n\n users[u].acl.file.create = groups[g].common.acl.file.create;\n users[u].acl.file.read = groups[g].common.acl.file.read;\n users[u].acl.file.write = groups[g].common.acl.file.write;\n users[u].acl.file.delete = groups[g].common.acl.file.delete;\n users[u].acl.file.list = groups[g].common.acl.file.list;\n } else {\n users[u].acl.file.create ||= groups[g].common.acl.file.create;\n users[u].acl.file.read ||= groups[g].common.acl.file.read;\n users[u].acl.file.write ||= groups[g].common.acl.file.write;\n users[u].acl.file.delete ||= groups[g].common.acl.file.delete;\n users[u].acl.file.list ||= groups[g].common.acl.file.list;\n }\n }\n\n if (groups[g].common.acl?.object) {\n if (!users[u].acl?.object) {\n users[u].acl ||= {} as ioBroker.ObjectPermissions;\n users[u].acl.object ||= {} as ioBroker.ObjectPermissions['object'];\n\n users[u].acl.object.create = groups[g].common.acl.object.create;\n users[u].acl.object.read = groups[g].common.acl.object.read;\n users[u].acl.object.write = groups[g].common.acl.object.write;\n users[u].acl.object.delete = groups[g].common.acl.object.delete;\n users[u].acl.object.list = groups[g].common.acl.object.list;\n } else {\n users[u].acl.object.create ||= groups[g].common.acl.object.create;\n users[u].acl.object.read ||= groups[g].common.acl.object.read;\n users[u].acl.object.write ||= groups[g].common.acl.object.write;\n users[u].acl.object.delete ||= groups[g].common.acl.object.delete;\n users[u].acl.object.list ||= groups[g].common.acl.object.list;\n }\n }\n\n if (groups[g].common.acl?.users) {\n if (!users[u].acl?.users) {\n users[u].acl ||= {} as ioBroker.ObjectPermissions;\n users[u].acl.users ||= {} as ioBroker.ObjectPermissions['users'];\n\n users[u].acl.users.create = groups[g].common.acl.users.create;\n users[u].acl.users.read = groups[g].common.acl.users.read;\n users[u].acl.users.write = groups[g].common.acl.users.write;\n users[u].acl.users.delete = groups[g].common.acl.users.delete;\n users[u].acl.users.list = groups[g].common.acl.users.list;\n } else {\n users[u].acl.users.create ||= groups[g].common.acl.users.create;\n users[u].acl.users.read ||= groups[g].common.acl.users.read;\n users[u].acl.users.write ||= groups[g].common.acl.users.write;\n users[u].acl.users.delete ||= groups[g].common.acl.users.delete;\n users[u].acl.users.list ||= groups[g].common.acl.users.list;\n }\n }\n\n if (groups[g].common.acl?.state) {\n if (!users[u].acl?.state) {\n users[u].acl ||= {} as ioBroker.ObjectPermissions;\n users[u].acl.state ||= {} as ioBroker.ObjectPermissions['state'];\n\n users[u].acl.state!.create = groups[g].common.acl.state!.create;\n users[u].acl.state!.read = groups[g].common.acl.state!.read;\n users[u].acl.state!.write = groups[g].common.acl.state!.write;\n users[u].acl.state!.delete = groups[g].common.acl.state!.delete;\n users[u].acl.state!.list = groups[g].common.acl.state!.list;\n } else {\n users[u].acl.state.create ||= groups[g].common.acl.state!.create;\n users[u].acl.state.read ||= groups[g].common.acl.state!.read;\n users[u].acl.state.write ||= groups[g].common.acl.state!.write;\n users[u].acl.state.delete ||= groups[g].common.acl.state!.delete;\n users[u].acl.state.list ||= groups[g].common.acl.state!.list;\n }\n }\n }\n }\n return [user, users[user]?.groups || [], users[user]?.acl || deepClone(defaultAcl.acl)];\n}\n\n/**\n * Sanitize an object id and file name so they cannot escape the intended directory\n *\n * @param id The object id owning the file\n * @param name The file name to sanitize\n */\nexport function sanitizePath(\n id: string,\n name: string,\n): {\n /** The sanitized object id */\n id: string;\n /** The sanitized file name */\n name: string;\n} {\n if (!name) {\n name = '';\n }\n if (name[0] === '/') {\n name = name.substring(1);\n }\n\n if (!id) {\n throw new Error('Empty ID');\n }\n\n id = id.replace(/[\\][*,;'\"`<>\\\\?/]/g, ''); // remove all invalid characters from states plus slashes\n id = id.replace(/\\.\\./g, ''); // do not allow to write in parent directories\n\n if (name.includes('..')) {\n name = path.normalize(`/${name}`);\n }\n if (name.includes('..')) {\n // Also after normalization we still have .. in it - should not happen if normalize worked correctly\n name = name.replace(/\\.\\./g, '');\n name = path.normalize(`/${name}`);\n }\n\n name = name.replace(/\\\\/g, '/'); // replace win path backslashes\n\n if (name[0] === '/') {\n name = name.substring(1);\n } // do not allow absolute paths\n\n return { id: id, name: name };\n}\n\n/**\n * Check if the given options have the required rights on an object according to its ACL\n *\n * @param obj The object (or file object) to check, or null\n * @param options The current request options including the user and group\n * @param flag The access flag(s) to check for\n */\nexport function checkObject(\n obj: ioBroker.AnyObject | FileObject | null,\n options: UserContext,\n flag: CONSTS.GenericAccessFlags,\n): boolean {\n // read rights of object\n if (!obj || !('common' in obj) || !obj.acl || flag === CONSTS.ACCESS_LIST) {\n return true;\n }\n\n if (options.user === CONSTS.SYSTEM_ADMIN_USER) {\n return true;\n }\n\n // admins may always see everything\n if (options.group === CONSTS.SYSTEM_ADMIN_GROUP || options.groups.includes(CONSTS.SYSTEM_ADMIN_GROUP)) {\n return true;\n }\n\n // FIXME: what if flag is ACCESS_DELETE or ACCESS_CREATE? currently it will end in false\n if (flag === CONSTS.ACCESS_DELETE || flag === CONSTS.ACCESS_CREATE) {\n return false;\n }\n\n // checkObject always called after checkObjectRights and admin is checked there\n if (obj.acl.owner !== options.user) {\n // Check if the user is in the group\n if (\n (options.group && options.group === obj.acl.ownerGroup) ||\n (options.groups && options.groups.includes(obj.acl.ownerGroup))\n ) {\n // Check group rights\n if (!(obj.acl.object & (flag << 4))) {\n return false;\n }\n } else {\n // everybody\n if (!(obj.acl.object & flag)) {\n return false;\n }\n }\n } else {\n // Check group rights\n if (!(obj.acl.object & (flag << 8))) {\n return false;\n }\n }\n return true; // ALL OK\n}\n\n/**\n * Check whether the given user is allowed to access an object and call back with the effective options\n *\n * @param objects The objects database client\n * @param id The id of the object, or null\n * @param object The object to check, or null\n * @param options The current request options including the user\n * @param flag The access flag(s) to check for\n * @param callback Called with the effective options once the rights have been checked\n */\nexport function checkObjectRights(\n objects: ObjectClient,\n id: string | null,\n object: ioBroker.Object | null,\n options: { user?: ioBroker.ObjectIDs.User } | null | undefined,\n flag: CONSTS.GenericAccessFlags,\n callback: (err: Error | null | undefined, userContext?: UserContext) => void,\n): void {\n try {\n checkObjectRightsAsync(objects, id, object, options, flag)\n .then(userContext => tools.maybeCallbackWithError(callback, null, userContext))\n .catch(error => tools.maybeCallbackWithError(callback, error));\n } catch (error) {\n tools.maybeCallbackWithError(callback, error);\n }\n}\n\n/**\n * Check whether the given user is allowed to access an object and call back with the effective options\n *\n * @param objects The objects database client\n * @param id The id of the object, or null\n * @param object The object to check, or null\n * @param options The current request options including the user\n * @param flag The access flag(s) to check for\n */\nexport async function checkObjectRightsAsync(\n objects: ObjectClient,\n id: string | null,\n object: ioBroker.Object | null,\n options: { user?: ioBroker.ObjectIDs.User } | null | undefined,\n flag: CONSTS.GenericAccessFlags,\n): Promise<UserContext> {\n let userContext: UserContext;\n options ||= {};\n\n if (!options?.user) {\n // Before files converted, lets think: if no options it is admin\n userContext = {\n user: CONSTS.SYSTEM_ADMIN_USER,\n group: CONSTS.SYSTEM_ADMIN_GROUP,\n groups: [CONSTS.SYSTEM_ADMIN_GROUP],\n acl: getDefaultAdminRights(),\n };\n } else {\n const [, groups, acl] = await getUserGroupAsync(objects, options.user);\n userContext = {\n user: options.user,\n groups,\n acl: acl || {},\n group: groups?.[0] || null,\n };\n }\n\n // now options are filled and we can go\n if (\n userContext.user === CONSTS.SYSTEM_ADMIN_USER ||\n userContext.group === CONSTS.SYSTEM_ADMIN_GROUP ||\n userContext.groups?.includes(CONSTS.SYSTEM_ADMIN_GROUP)\n ) {\n return userContext;\n }\n\n // if user or group objects\n if (typeof id === 'string' && (id.startsWith(USER_STARTS_WITH) || id.startsWith(GROUP_STARTS_WITH))) {\n // If user may write\n if (flag === CONSTS.ACCESS_WRITE && !userContext.acl.users.write) {\n // write\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !userContext.acl.users.read) {\n // read\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may delete\n if (flag === CONSTS.ACCESS_DELETE && !userContext.acl.users.delete) {\n // delete\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may list\n if (flag === CONSTS.ACCESS_LIST && !userContext.acl.users.list) {\n // list\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may create\n if (flag === CONSTS.ACCESS_CREATE && !userContext.acl.users.create) {\n // create\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may write\n if (flag === CONSTS.ACCESS_DELETE) {\n // he may delete\n flag = CONSTS.ACCESS_WRITE;\n }\n }\n\n // If user may write\n if (flag === CONSTS.ACCESS_WRITE && !userContext.acl.object.write) {\n // write\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may read\n if (flag === CONSTS.ACCESS_READ && !userContext.acl.object.read) {\n // read\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may delete\n if (flag === CONSTS.ACCESS_DELETE && !userContext.acl.object.delete) {\n // delete\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n // If user may list\n if (flag === CONSTS.ACCESS_LIST && !userContext.acl.object.list) {\n // list\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n\n if (flag === CONSTS.ACCESS_DELETE) {\n // write\n flag = CONSTS.ACCESS_WRITE;\n }\n\n if (id && !checkObject(object, userContext, flag)) {\n throw new Error(ERRORS.ERROR_PERMISSION);\n }\n return userContext;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["CONSTS", "CONSTS", "mime", "groups", "deepClone", "path"]
7
7
  }
@@ -5,7 +5,7 @@
5
5
  */
6
6
  export declare function getDefaultPort(host: string): number;
7
7
  export declare const Server: null;
8
- export { ObjectsInRedisClient as Client } from './lib/objects/objectsInRedisClient.js';
8
+ export { ObjectsInRedisClient as Client, type ObjectsSettings } from './lib/objects/objectsInRedisClient.js';
9
9
  export { interview } from './lib/objects/interview.js';
10
10
  export * as objectsUtils from './lib/objects/objectsUtils.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AACD,eAAO,MAAM,MAAM,MAAO,CAAC;AAC3B,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AACD,eAAO,MAAM,MAAM,MAAO,CAAC;AAC3B,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AACD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;AAC3B,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAE,MAAM,uCAAuC,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AACD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC;AAC3B,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAwB,MAAM,uCAAuC,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/objects/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,MAAM;IACd,gBAAgB,oBAAoB;IACpC,eAAe,eAAe;IAC9B,eAAe,cAAc;CAChC;AAED,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,kBAAkB,+BAA+B,CAAC;AAE/D,eAAO,MAAM,iBAAiB,IAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,IAAM,CAAC;AACtC,eAAO,MAAM,iBAAiB,IAAM,CAAC;AACrC,eAAO,MAAM,eAAe,QAAyC,CAAC;AACtE,eAAO,MAAM,gBAAgB,QAA6D,CAAC;AAE3F,eAAO,MAAM,iBAAiB,KAAO,CAAC;AACtC,eAAO,MAAM,kBAAkB,KAAO,CAAC;AACvC,eAAO,MAAM,iBAAiB,KAAO,CAAC;AACtC,eAAO,MAAM,eAAe,QAAyC,CAAC;AACtE,eAAO,MAAM,gBAAgB,QAA6D,CAAC;AAE3F,eAAO,MAAM,gBAAgB,MAAQ,CAAC;AACtC,eAAO,MAAM,iBAAiB,MAAQ,CAAC;AACvC,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AACtC,eAAO,MAAM,cAAc,QAAuC,CAAC;AACnE,eAAO,MAAM,eAAe,QAA0D,CAAC;AAEvF,eAAO,MAAM,YAAY,IAAM,CAAC;AAChC,eAAO,MAAM,WAAW,IAAM,CAAC;AAC/B,eAAO,MAAM,WAAW,SAAS,CAAC;AAClC,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GACxB,OAAO,YAAY,GACnB,OAAO,WAAW,GAClB,OAAO,WAAW,GAClB,OAAO,aAAa,GACpB,OAAO,aAAa,CAAC;AAE3B,eAAO,MAAM,YAAY,QAAkB,CAAC;AAE5C,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/lib/objects/constants.ts"],"names":[],"mappings":"AAAA,oBAAY,MAAM;IACd,gBAAgB,oBAAoB;IACpC,eAAe,eAAe;IAC9B,eAAe,cAAc;CAChC;AAED,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,kBAAkB,+BAA+B,CAAC;AAE/D,eAAO,MAAM,iBAAiB,IAAM,CAAC;AACrC,eAAO,MAAM,kBAAkB,IAAM,CAAC;AACtC,eAAO,MAAM,iBAAiB,IAAM,CAAC;AACrC,eAAO,MAAM,eAAe,QAAyC,CAAC;AACtE,eAAO,MAAM,gBAAgB,QAA6D,CAAC;AAE3F,eAAO,MAAM,iBAAiB,KAAO,CAAC;AACtC,eAAO,MAAM,kBAAkB,KAAO,CAAC;AACvC,eAAO,MAAM,iBAAiB,KAAO,CAAC;AACtC,eAAO,MAAM,eAAe,QAAyC,CAAC;AACtE,eAAO,MAAM,gBAAgB,QAA6D,CAAC;AAE3F,eAAO,MAAM,gBAAgB,MAAQ,CAAC;AACtC,eAAO,MAAM,iBAAiB,MAAQ,CAAC;AACvC,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AACtC,eAAO,MAAM,cAAc,QAAuC,CAAC;AACnE,eAAO,MAAM,eAAe,QAA0D,CAAC;AAEvF,eAAO,MAAM,YAAY,IAAM,CAAC;AAChC,eAAO,MAAM,WAAW,IAAM,CAAC;AAC/B,eAAO,MAAM,WAAW,SAAS,CAAC;AAClC,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC,eAAO,MAAM,aAAa,WAAW,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAC1B,OAAO,YAAY,GAAG,OAAO,WAAW,GAAG,OAAO,WAAW,GAAG,OAAO,aAAa,GAAG,OAAO,aAAa,CAAC;AAEhH,eAAO,MAAM,YAAY,QAAkB,CAAC;AAE5C,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/lib/objects/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,MAIX;AAJD,WAAY,MAAM;IACd,8CAAoC,CAAA;IACpC,wCAA8B,CAAA;IAC9B,uCAA6B,CAAA;AACjC,CAAC,EAJW,MAAM,KAAN,MAAM,QAIjB;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AAE/D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3F,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAEvF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAStC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/lib/objects/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,MAIX;AAJD,WAAY,MAAM;IACd,8CAAoC,CAAA;IACpC,wCAA8B,CAAA;IAC9B,uCAA6B,CAAA;AACjC,CAAC,EAJW,MAAM,KAAN,MAAM,QAIjB;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AAE/D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,GAAG,iBAAiB,CAAC;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE3F,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AACnE,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAEvF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAKtC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAE5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC"}
@@ -8,13 +8,35 @@ cursor = result[1]
8
8
  local keys = result[2]
9
9
  local argStart = KEYS[1] .. KEYS[2]
10
10
  local argEnd = KEYS[1] .. KEYS[3]
11
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
12
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
13
+ local sLen = #argStart
14
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
15
+ local function byteLess(a, b, from)
16
+ local la, lb = #a, #b
17
+ local i = from or 1
18
+ while i <= la and i <= lb do
19
+ local ca, cb = a:byte(i), b:byte(i)
20
+ if ca ~= cb then
21
+ return ca < cb
22
+ end
23
+ i = i + 1
24
+ end
25
+ return la < lb
26
+ end
27
+ local function inRange(key)
28
+ if endHasPrefix then
29
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
30
+ end
31
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
32
+ end
11
33
  local checkStr = string.format("%q:{", "custom")
12
34
  -- function(doc) {
13
35
  -- if (doc.type==="state" && (doc.common.custom || doc.common.history))
14
36
  -- emit(doc._id, doc.common.custom || doc.common.history)
15
37
  -- }
16
38
  for _, key in ipairs(keys) do
17
- if (key >= argStart and key < argEnd) then
39
+ if (inRange(key)) then
18
40
  local obj = redis.call("get", key)
19
41
  if (obj:find(checkStr) ~= nil) then
20
42
  local success, decoded = pcall(cjson.decode, obj)
@@ -7,12 +7,34 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  local type = KEYS[4]
11
33
  local checkStr = string.format("%q:%q", "type", type)
12
34
  local skipCheck = not (type == "channel" or type == "device" or type == "folder")
13
35
  -- function(doc) { if (doc.type === "chart") emit(doc._id, doc); }
14
36
  for _, key in ipairs(keys) do
15
- if (key >= argStart and key < argEnd) then
37
+ if (inRange(key)) then
16
38
  local obj = redis.call("get", key)
17
39
  if (skipCheck or obj:find(checkStr) ~= nil) then
18
40
  local success, decoded = pcall(cjson.decode, obj)
@@ -7,6 +7,28 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  local checkStr = string.format("%q:%q", "TypeName", "PROGRAM")
11
33
  -- function(doc) {
12
34
  -- if (doc._id.match(/^hm-rega\\.[0-9]+\\.[0-9,A-Z,a-z]+/) && (doc.native.TypeName === "PROGRAM")) {
@@ -14,7 +36,7 @@ local checkStr = string.format("%q:%q", "TypeName", "PROGRAM")
14
36
  -- }
15
37
  -- }
16
38
  for _, key in ipairs(keys) do
17
- if (key >= argStart and key < argEnd and key:sub(7, 13) == "hm-rega") then
39
+ if (inRange(key) and key:sub(7, 13) == "hm-rega") then
18
40
  local obj = redis.call("get", key)
19
41
  if (obj:find(checkStr) ~= nil) then
20
42
  local success, decoded = pcall(cjson.decode, obj)
@@ -7,11 +7,33 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  local checkStr = string.format("%q:%q", "type", "script")
11
33
  -- function(doc) {
12
34
  -- if (doc.type === "script" && doc.common.engineType.match(/^[jJ]ava[sS]cript|^[cC]offee[sS]cript|^[tT]ype[sS]cript|^Blockly/)) emit(doc.common.name, doc); }
13
35
  for _, key in ipairs(keys) do
14
- if (key >= argStart and key < argEnd) then
36
+ if (inRange(key)) then
15
37
  local obj = redis.call("get", key)
16
38
  if (obj:find(checkStr) ~= nil) then
17
39
  local success, decoded = pcall(cjson.decode, obj)
@@ -8,6 +8,28 @@ cursor = result[1]
8
8
  local keys = result[2]
9
9
  local argStart = KEYS[1] .. KEYS[2]
10
10
  local argEnd = KEYS[1] .. KEYS[3]
11
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
12
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
13
+ local sLen = #argStart
14
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
15
+ local function byteLess(a, b, from)
16
+ local la, lb = #a, #b
17
+ local i = from or 1
18
+ while i <= la and i <= lb do
19
+ local ca, cb = a:byte(i), b:byte(i)
20
+ if ca ~= cb then
21
+ return ca < cb
22
+ end
23
+ i = i + 1
24
+ end
25
+ return la < lb
26
+ end
27
+ local function inRange(key)
28
+ if endHasPrefix then
29
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
30
+ end
31
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
32
+ end
11
33
  local checkStr = string.format("%q:", "TypeName");
12
34
  -- function(doc) {
13
35
  -- if (doc._id.match(/^hm-rega\\.[0-9]+\\.[0-9,A-Z,a-z]+/) && (doc.native.TypeName === "ALARMDP" || doc.native.TypeName === "VARDP")) {
@@ -15,7 +37,7 @@ local checkStr = string.format("%q:", "TypeName");
15
37
  -- }
16
38
  -- }
17
39
  for _, key in ipairs(keys) do
18
- if (key >= argStart and key < argEnd and key:sub(7, 13) == "hm-rega") then
40
+ if (inRange(key) and key:sub(7, 13) == "hm-rega") then
19
41
  local obj = redis.call("get", key)
20
42
  if (obj:find(checkStr) ~= nil) then
21
43
  local success, decoded = pcall(cjson.decode, obj)
@@ -8,12 +8,34 @@ cursor = result[1]
8
8
  local keys = result[2]
9
9
  local argStart = KEYS[1] .. KEYS[2]
10
10
  local argEnd = KEYS[1] .. KEYS[3]
11
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
12
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
13
+ local sLen = #argStart
14
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
15
+ local function byteLess(a, b, from)
16
+ local la, lb = #a, #b
17
+ local i = from or 1
18
+ while i <= la and i <= lb do
19
+ local ca, cb = a:byte(i), b:byte(i)
20
+ if ca ~= cb then
21
+ return ca < cb
22
+ end
23
+ i = i + 1
24
+ end
25
+ return la < lb
26
+ end
27
+ local function inRange(key)
28
+ if endHasPrefix then
29
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
30
+ end
31
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
32
+ end
11
33
  -- function(doc) {
12
34
  -- if (doc.type==="state" && (doc.common.custom || doc.common.history))
13
35
  -- emit(doc._id, doc.common.custom || doc.common.history)
14
36
  -- }
15
37
  for _, key in ipairs(keys) do
16
- if (key >= argStart and key < argEnd) then
38
+ if (inRange(key)) then
17
39
  rep[#rep + 1] = redis.call("get", key)
18
40
  end
19
41
  end
@@ -7,9 +7,31 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  -- function(doc) { if (doc.type === "chart") emit(doc._id, doc); }
11
33
  for _, key in ipairs(keys) do
12
- if (key >= argStart and key < argEnd) then
34
+ if (inRange(key)) then
13
35
  rep[#rep + 1] = redis.call("get", key)
14
36
  end
15
37
  end
@@ -7,6 +7,28 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  local checkStr = string.format("%q:%q", "TypeName", "PROGRAM")
11
33
  -- function(doc) {
12
34
  -- if (doc._id.match(/^hm-rega\\.[0-9]+\\.[0-9,A-Z,a-z]+/) && (doc.native.TypeName === "PROGRAM")) {
@@ -14,7 +36,7 @@ local checkStr = string.format("%q:%q", "TypeName", "PROGRAM")
14
36
  -- }
15
37
  -- }
16
38
  for _, key in ipairs(keys) do
17
- if (key >= argStart and key < argEnd) then
39
+ if (inRange(key)) then
18
40
  local obj = redis.call("get", key)
19
41
  if (obj:find(checkStr) ~= nil) then
20
42
  local success, decoded = pcall(cjson.decode, obj)
@@ -7,10 +7,32 @@ cursor = result[1]
7
7
  local keys = result[2]
8
8
  local argStart = KEYS[1] .. KEYS[2]
9
9
  local argEnd = KEYS[1] .. KEYS[3]
10
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
11
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
12
+ local sLen = #argStart
13
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
14
+ local function byteLess(a, b, from)
15
+ local la, lb = #a, #b
16
+ local i = from or 1
17
+ while i <= la and i <= lb do
18
+ local ca, cb = a:byte(i), b:byte(i)
19
+ if ca ~= cb then
20
+ return ca < cb
21
+ end
22
+ i = i + 1
23
+ end
24
+ return la < lb
25
+ end
26
+ local function inRange(key)
27
+ if endHasPrefix then
28
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
29
+ end
30
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
31
+ end
10
32
  -- function(doc) {
11
33
  -- if (doc.type === "script" && doc.common.engineType.match(/^[jJ]ava[sS]cript|^[cC]offee[sS]cript|^[tT]ype[sS]cript|^Blockly/)) emit(doc.common.name, doc); }
12
34
  for _, key in ipairs(keys) do
13
- if (key >= argStart and key < argEnd) then
35
+ if (inRange(key)) then
14
36
  rep[#rep + 1] = redis.call("get", key)
15
37
  end
16
38
  end
@@ -8,6 +8,28 @@ cursor = result[1]
8
8
  local keys = result[2]
9
9
  local argStart = KEYS[1] .. KEYS[2]
10
10
  local argEnd = KEYS[1] .. KEYS[3]
11
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
12
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
13
+ local sLen = #argStart
14
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
15
+ local function byteLess(a, b, from)
16
+ local la, lb = #a, #b
17
+ local i = from or 1
18
+ while i <= la and i <= lb do
19
+ local ca, cb = a:byte(i), b:byte(i)
20
+ if ca ~= cb then
21
+ return ca < cb
22
+ end
23
+ i = i + 1
24
+ end
25
+ return la < lb
26
+ end
27
+ local function inRange(key)
28
+ if endHasPrefix then
29
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
30
+ end
31
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
32
+ end
11
33
  local checkStr = string.format("%q:", "TypeName");
12
34
  -- function(doc) {
13
35
  -- if (doc._id.match(/^hm-rega\\.[0-9]+\\.[0-9,A-Z,a-z]+/) && (doc.native.TypeName === "ALARMDP" || doc.native.TypeName === "VARDP")) {
@@ -15,7 +37,7 @@ local checkStr = string.format("%q:", "TypeName");
15
37
  -- }
16
38
  -- }
17
39
  for _, key in ipairs(keys) do
18
- if (key >= argStart and key < argEnd) then
40
+ if (inRange(key)) then
19
41
  local obj = redis.call("get", key)
20
42
  if (obj:find(checkStr) ~= nil) then
21
43
  local success, decoded = pcall(cjson.decode, obj)
@@ -8,13 +8,35 @@ cursor = result[1]
8
8
  local keys = result[2]
9
9
  local argStart = KEYS[1] .. KEYS[2]
10
10
  local argEnd = KEYS[1] .. KEYS[3]
11
+ -- Compare bytes: Lua's < uses strcoll(), so it depends on the locale the Redis
12
+ -- server was started with, and argEnd ends in the U+9999 sentinel.
13
+ local sLen = #argStart
14
+ local endHasPrefix = argEnd:sub(1, sLen) == argStart
15
+ local function byteLess(a, b, from)
16
+ local la, lb = #a, #b
17
+ local i = from or 1
18
+ while i <= la and i <= lb do
19
+ local ca, cb = a:byte(i), b:byte(i)
20
+ if ca ~= cb then
21
+ return ca < cb
22
+ end
23
+ i = i + 1
24
+ end
25
+ return la < lb
26
+ end
27
+ local function inRange(key)
28
+ if endHasPrefix then
29
+ return key:sub(1, sLen) == argStart and byteLess(key, argEnd, sLen + 1)
30
+ end
31
+ return not byteLess(key, argStart) and byteLess(key, argEnd)
32
+ end
11
33
  local checkStr = string.format("%q:{", "custom")
12
34
  -- function(doc) {
13
35
  -- if (doc.type==="state" && (doc.common.custom || doc.common.history))
14
36
  -- emit(doc._id, doc.common.custom || doc.common.history)
15
37
  -- }
16
38
  for _, key in ipairs(keys) do
17
- if (key >= argStart and key < argEnd) then
39
+ if (inRange(key)) then
18
40
  local obj = redis.call("get", key)
19
41
  if (obj:find(checkStr) ~= nil) then
20
42
  local success, decoded = pcall(cjson.decode, obj)