ACL 2/2
This commit is contained in:
parent
4bb566b1b7
commit
891de54560
379
packages/acl/package-lock.json
generated
379
packages/acl/package-lock.json
generated
@ -1,24 +1,17 @@
|
||||
{
|
||||
"name": "@polymech/acl",
|
||||
"version": "0.1.5",
|
||||
"version": "0.2.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@polymech/acl",
|
||||
"version": "0.1.5",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@polymech/cache": "file:../cache",
|
||||
"@polymech/commons": "file:../commons",
|
||||
"@polymech/core": "file:../core",
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@polymech/log": "file:../log",
|
||||
"p-map": "7.0.3",
|
||||
"p-throttle": "7.0.0",
|
||||
"ts-retry": "6.0.0",
|
||||
"yargs": "17.7.2",
|
||||
"zod": "3.24.3"
|
||||
"ignore": "^7.0.5",
|
||||
"mime": "^4.1.0",
|
||||
"pino": "^9.6.0"
|
||||
},
|
||||
"bin": {
|
||||
"pm-acl": "dist-in/main.js"
|
||||
@ -31,12 +24,13 @@
|
||||
"@vitest/coverage-v8": "^2.1.8",
|
||||
"@vitest/ui": "2.1.9",
|
||||
"typescript": "^5.7.2",
|
||||
"zod-to-json-schema": "3.24.1"
|
||||
"vitest": "^2.1.8"
|
||||
}
|
||||
},
|
||||
"../cache": {
|
||||
"name": "@polymech/cache",
|
||||
"version": "0.4.8",
|
||||
"extraneous": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@polymech/commons": "file:../commons",
|
||||
@ -57,6 +51,7 @@
|
||||
"../commons": {
|
||||
"name": "@polymech/commons",
|
||||
"version": "0.2.6",
|
||||
"extraneous": true,
|
||||
"license": "BSD",
|
||||
"dependencies": {
|
||||
"@polymech/core": "file:../core",
|
||||
@ -90,6 +85,7 @@
|
||||
"../core": {
|
||||
"name": "@polymech/core",
|
||||
"version": "0.2.6",
|
||||
"extraneous": true,
|
||||
"license": "BSD",
|
||||
"dependencies": {
|
||||
"tslog": "^3.3.3",
|
||||
@ -105,6 +101,7 @@
|
||||
"../fs": {
|
||||
"name": "@polymech/fs",
|
||||
"version": "0.13.41",
|
||||
"extraneous": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@polymech/core": "file:../core",
|
||||
@ -135,6 +132,7 @@
|
||||
"../log": {
|
||||
"name": "@polymech/log",
|
||||
"version": "0.2.6",
|
||||
"extraneous": true,
|
||||
"license": "BSD",
|
||||
"dependencies": {
|
||||
"@polymech/core": "file:../core",
|
||||
@ -686,6 +684,16 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@ -961,6 +969,12 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@pinojs/redact": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
|
||||
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@ -979,26 +993,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@polymech/cache": {
|
||||
"resolved": "../cache",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@polymech/commons": {
|
||||
"resolved": "../commons",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@polymech/core": {
|
||||
"resolved": "../core",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@polymech/fs": {
|
||||
"resolved": "../fs",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@polymech/log": {
|
||||
"resolved": "../log",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@repo/typescript-config": {
|
||||
"resolved": "../typescript-config",
|
||||
"link": true
|
||||
@ -1421,6 +1415,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
|
||||
@ -1805,6 +1809,7 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -1814,6 +1819,7 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
@ -1852,6 +1858,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/atomic-sleep": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
||||
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@ -1946,24 +1961,11 @@
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
@ -1976,6 +1978,7 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
@ -2072,6 +2075,7 @@
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
@ -2120,15 +2124,6 @@
|
||||
"@esbuild/win32-x64": "0.21.5"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
@ -2241,6 +2236,16 @@
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@ -2510,15 +2515,6 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
@ -2615,6 +2611,16 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/globby/node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
@ -2640,10 +2646,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
||||
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
@ -2709,6 +2714,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -2981,6 +2987,21 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-4.1.0.tgz",
|
||||
"integrity": "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||
@ -3050,6 +3071,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/on-exit-leak-free": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@ -3110,30 +3140,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-map": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz",
|
||||
"integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-throttle": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-throttle/-/p-throttle-7.0.0.tgz",
|
||||
"integrity": "sha512-aio0v+S0QVkH1O+9x4dHtD4dgCExACcL+3EtNaGqC01GBudS9ijMuUsmN8OVScyV4OOp0jqdLShZFuSlbL/AsA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
@ -3248,6 +3254,43 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pino": {
|
||||
"version": "9.14.0",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz",
|
||||
"integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pinojs/redact": "^0.4.0",
|
||||
"atomic-sleep": "^1.0.0",
|
||||
"on-exit-leak-free": "^2.1.0",
|
||||
"pino-abstract-transport": "^2.0.0",
|
||||
"pino-std-serializers": "^7.0.0",
|
||||
"process-warning": "^5.0.0",
|
||||
"quick-format-unescaped": "^4.0.3",
|
||||
"real-require": "^0.2.0",
|
||||
"safe-stable-stringify": "^2.3.1",
|
||||
"sonic-boom": "^4.0.1",
|
||||
"thread-stream": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"pino": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-abstract-transport": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
|
||||
"integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"split2": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-std-serializers": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz",
|
||||
"integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.6",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||
@ -3287,6 +3330,22 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-warning": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
|
||||
"integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
@ -3318,13 +3377,19 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"node_modules/quick-format-unescaped": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/real-require": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
||||
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
"node": ">= 12.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-from": {
|
||||
@ -3434,6 +3499,15 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-stable-stringify": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
|
||||
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.7.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||
@ -3515,6 +3589,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/sonic-boom": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz",
|
||||
"integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"atomic-sleep": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
@ -3525,6 +3608,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/split2": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
||||
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/stackback": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
|
||||
@ -3543,6 +3635,7 @@
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
@ -3573,6 +3666,7 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
@ -3681,6 +3775,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/thread-stream": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
|
||||
"integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"real-require": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tinybench": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||
@ -3810,12 +3913,6 @@
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-retry": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-retry/-/ts-retry-6.0.0.tgz",
|
||||
"integrity": "sha512-WsVRE/P+VNYbiQC3E6TeIXBRCQj7vzjN4MlXd84AC88K7WwuWShN7A3Q/QSV/yd1hjO8qn2Cevdqny2HMwKUaA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
@ -3880,6 +3977,7 @@
|
||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
@ -4067,23 +4165,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi-cjs": {
|
||||
"name": "wrap-ansi",
|
||||
"version": "7.0.0",
|
||||
@ -4110,42 +4191,6 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
@ -4158,26 +4203,6 @@
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.24.3",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz",
|
||||
"integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
},
|
||||
"node_modules/zod-to-json-schema": {
|
||||
"version": "3.24.1",
|
||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz",
|
||||
"integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.24.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polymech/acl",
|
||||
"version": "0.1.5",
|
||||
"version": "0.2.0",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@ -20,23 +20,15 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "tsc -p . --watch",
|
||||
"test:core": "vitest run src/acl.test.ts",
|
||||
"lint": "eslint src --ext .ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polymech/cache": "file:../cache",
|
||||
"@polymech/commons": "file:../commons",
|
||||
"@polymech/core": "file:../core",
|
||||
"@polymech/fs": "file:../fs",
|
||||
"@polymech/log": "file:../log",
|
||||
"p-map": "7.0.3",
|
||||
"p-throttle": "7.0.0",
|
||||
"ts-retry": "6.0.0",
|
||||
"yargs": "17.7.2",
|
||||
"zod": "3.24.3"
|
||||
"ignore": "^7.0.5",
|
||||
"mime": "^4.1.0",
|
||||
"pino": "^9.6.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"devDependencies": {
|
||||
"@repo/typescript-config": "file:../typescript-config",
|
||||
"@types/node": "22.10.2",
|
||||
@ -45,6 +37,6 @@
|
||||
"@vitest/coverage-v8": "^2.1.8",
|
||||
"@vitest/ui": "2.1.9",
|
||||
"typescript": "^5.7.2",
|
||||
"zod-to-json-schema": "3.24.1"
|
||||
"vitest": "^2.1.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,745 +0,0 @@
|
||||
/*
|
||||
ACL System inspired on Zend_ACL.
|
||||
All functions accept strings, objects or arrays unless specified otherwise.
|
||||
|
||||
'*' is used to express 'all'
|
||||
|
||||
Database structure in Redis (using default prefix 'acl')
|
||||
|
||||
Users:
|
||||
|
||||
acl_roles_{userid} = set(roles)
|
||||
|
||||
Roles:
|
||||
|
||||
acl_roles = {roleNames} // Used to remove all the permissions associated to ONE resource.
|
||||
|
||||
acl_parents_{roleName} = set(parents)
|
||||
acl_resources_{roleName} = set(resourceNames)
|
||||
|
||||
Permissions:
|
||||
acl_allows_{resourceName}_{roleName} = set(permissions)
|
||||
Note: user ids, role names and resource names are all case sensitive.
|
||||
|
||||
Roadmap:
|
||||
- Add support for locking resources. If a user has roles that gives him permissions to lock
|
||||
a resource, then he can get exclusive write operation on the locked resource.
|
||||
This lock should expire if the resource has not been accessed in some time.
|
||||
*/
|
||||
import * as _ from 'lodash';
|
||||
import * as bluebird from 'bluebird';
|
||||
import { contract } from './contract';
|
||||
import { ILogger, IAcl, IBucketsOption, IBackend, Action } from './interfaces';
|
||||
import { Value, Values, strings, Callback, AnyCallback, AllowedCallback } from './interfaces';
|
||||
contract.debug = true;
|
||||
|
||||
function makeArray(arr: any | Object): Array<any> {
|
||||
return Array.isArray(arr) ? arr : [arr];
|
||||
}
|
||||
|
||||
function allowsBucket(role: string): string {
|
||||
return 'allows_' + role;
|
||||
}
|
||||
|
||||
function keyFromAllowsBucket(str: string): string {
|
||||
return str.replace(/^allows_/, '');
|
||||
}
|
||||
|
||||
export class ACL implements IAcl {
|
||||
logger: any;
|
||||
backend: any;
|
||||
options: any;
|
||||
constructor(backend: IBackend<Action[]>, logger: ILogger | any, options?: any) {
|
||||
const buckets: IBucketsOption = {
|
||||
meta: 'meta',
|
||||
parents: 'parents',
|
||||
permissions: 'permissions',
|
||||
resources: 'resources',
|
||||
roles: 'roles',
|
||||
users: 'users'
|
||||
};
|
||||
|
||||
options = _.extend({
|
||||
buckets: buckets
|
||||
}, options);
|
||||
|
||||
this.logger = logger;
|
||||
this.backend = backend;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public allow(roles: Values, resources: strings, permissions: strings, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string|array', 'string|array', 'string|array', 'function')
|
||||
.params('string|array', 'string|array', 'string|array')
|
||||
.params('array', 'function')
|
||||
.params('array')
|
||||
.end();
|
||||
|
||||
if ((arguments.length === 1) || ((arguments.length === 2) && _.isObject(roles) && _.isFunction(resources))) {
|
||||
return this._allowEx(roles).nodeify(resources);
|
||||
} else {
|
||||
let _this = this;
|
||||
roles = makeArray(roles);
|
||||
resources = makeArray(resources);
|
||||
let backend = _this.backend;
|
||||
let transaction = _this.backend.begin();
|
||||
backend.add(transaction, _this.options.buckets.meta, 'roles', roles);
|
||||
resources.forEach(function (resource) {
|
||||
_.each(roles, (role) => {
|
||||
backend.add(transaction, allowsBucket(resource), role, permissions);
|
||||
});
|
||||
});
|
||||
roles.forEach(function (role) {
|
||||
_this.backend.add(transaction, _this.options.buckets.resources, role, resources);
|
||||
});
|
||||
return backend.endAsync(transaction).nodeify(cb);
|
||||
}
|
||||
}
|
||||
/* addUserRoles( userId, roles, function(err) )
|
||||
* Adds roles to a given user id.
|
||||
@param {String|Number} User id.
|
||||
@param {String|Array} Role(s) to add to the user id.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved when finished
|
||||
*/
|
||||
public addUserRoles(userId: Value, roles: strings, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string|number', 'string|array', 'function')
|
||||
.params('string|number', 'string|array')
|
||||
.end();
|
||||
|
||||
let transaction = this.backend.begin();
|
||||
this.backend.add(transaction, this.options.buckets.meta, 'users', userId);
|
||||
this.backend.add(transaction, this.options.buckets.users, userId, roles);
|
||||
|
||||
if (Array.isArray(roles)) {
|
||||
let _this = this;
|
||||
|
||||
roles.forEach(function (role) {
|
||||
_this.backend.add(transaction, _this.options.buckets.roles, role, userId);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.backend.add(transaction, this.options.buckets.roles, roles, userId);
|
||||
}
|
||||
|
||||
return this.backend.endAsync(transaction).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
removeUserRoles( userId, roles, function(err) )
|
||||
Remove roles from a given user.
|
||||
@param {String|Number} User id.
|
||||
@param {String|Array} Role(s) to remove to the user id.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved when finished
|
||||
*/
|
||||
public removeUserRoles(userId: Value, roles: strings, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string|number', 'string|array', 'function')
|
||||
.params('string|number', 'string|array')
|
||||
.end();
|
||||
|
||||
let transaction = this.backend.begin();
|
||||
this.backend.remove(transaction, this.options.buckets.users, userId, roles);
|
||||
|
||||
if (Array.isArray(roles)) {
|
||||
let _this = this;
|
||||
|
||||
roles.forEach(function (role) {
|
||||
_this.backend.remove(transaction, _this.options.buckets.roles, role, userId);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.backend.remove(transaction, this.options.buckets.roles, roles, userId);
|
||||
}
|
||||
|
||||
return this.backend.endAsync(transaction).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
userRoles( userId, function(err, roles) )
|
||||
Return all the roles from a given user.
|
||||
|
||||
@param {String|Number} User id.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved with an array of user roles
|
||||
*/
|
||||
public userRoles(userId: Value, cb?: (err: Error, roles: string[]) => any): bluebird<string[]> {
|
||||
return this.backend.getAsync(this.options.buckets.users, userId).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
roleUsers( roleName, function(err, users) )
|
||||
Return all users who has a given role.
|
||||
@param {String|Number} rolename.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved with an array of users
|
||||
*/
|
||||
public roleUsers(role: Value, cb?: (err: Error, users: Values) => any): Promise<any> {
|
||||
return this.backend.getAsync(this.options.buckets.roles, role).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
hasRole( userId, rolename, function(err, is_in_role) )
|
||||
Return boolean whether user is in the role
|
||||
@param {String|Number} User id.
|
||||
@param {String|Number} rolename.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved with boolean of whether user is in role
|
||||
*/
|
||||
public hasRole(userId: Value, role: string, cb?: (err: Error, isInRole: boolean) => any): bluebird<boolean> {
|
||||
return this.userRoles(userId).then(function (roles) {
|
||||
return roles.indexOf(role) !== -1;
|
||||
}).nodeify(cb);
|
||||
}
|
||||
|
||||
/*
|
||||
addRoleParents( role, parents, function(err) )
|
||||
Adds a parent or parent list to role.
|
||||
@param {String} Child role.
|
||||
@param {String|Array} Parent role(s) to be added.
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved when finished
|
||||
*/
|
||||
public addRoleParents(role: string, parents: Values, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string|number', 'string|array', 'function')
|
||||
.params('string|number', 'string|array')
|
||||
.end();
|
||||
|
||||
let transaction = this.backend.begin();
|
||||
this.backend.add(transaction, this.options.buckets.meta, 'roles', role);
|
||||
this.backend.add(transaction, this.options.buckets.parents, role, parents);
|
||||
return this.backend.endAsync(transaction).nodeify(cb);
|
||||
};
|
||||
|
||||
/*
|
||||
removeRoleParents( role, parents, function(err) )
|
||||
|
||||
Removes a parent or parent list from role.
|
||||
|
||||
If `parents` is not specified, removes all parents.
|
||||
|
||||
@param {String} Child role.
|
||||
@param {String|Array} Parent role(s) to be removed [optional].
|
||||
@param {Function} Callback called when finished [optional].
|
||||
@return {Promise} Promise resolved when finished.
|
||||
*/
|
||||
public removeRoleParents(role: any, parents: Function, cb: Function) {
|
||||
contract(arguments)
|
||||
.params('string', 'string|array', 'function')
|
||||
.params('string', 'string|array')
|
||||
.params('string', 'function')
|
||||
.params('string')
|
||||
.end();
|
||||
|
||||
if (!cb && _.isFunction(parents)) {
|
||||
cb = parents;
|
||||
parents = null;
|
||||
}
|
||||
|
||||
let transaction = this.backend.begin();
|
||||
if (parents) {
|
||||
this.backend.remove(transaction, this.options.buckets.parents, role, parents);
|
||||
} else {
|
||||
this.backend.del(transaction, this.options.buckets.parents, role);
|
||||
}
|
||||
return this.backend.endAsync(transaction).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
removeRole( role, function(err) )
|
||||
|
||||
Removes a role from the system.
|
||||
|
||||
@param {String} Role to be removed
|
||||
@param {Function} Callback called when finished.
|
||||
*/
|
||||
public removeRole(role: string, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string', 'function')
|
||||
.params('string').end();
|
||||
|
||||
let _this = this;
|
||||
// Note that this is not fully transactional.
|
||||
return this.backend.getAsync(this.options.buckets.resources, role).then((resources) => {
|
||||
let transaction = _this.backend.begin();
|
||||
resources.forEach((resource) => {
|
||||
let bucket = allowsBucket(resource);
|
||||
_this.backend.del(transaction, bucket, role);
|
||||
});
|
||||
_this.backend.del(transaction, _this.options.buckets.resources, role);
|
||||
_this.backend.del(transaction, _this.options.buckets.parents, role);
|
||||
_this.backend.del(transaction, _this.options.buckets.roles, role);
|
||||
_this.backend.remove(transaction, _this.options.buckets.meta, 'roles', role);
|
||||
|
||||
// `users` collection keeps the removed role
|
||||
// because we don't know what users have `role` assigned.
|
||||
return _this.backend.endAsync(transaction);
|
||||
}).nodeify(cb);
|
||||
};
|
||||
/*
|
||||
removeResource( resource, function(err) )
|
||||
Removes a resource from the system
|
||||
@param {String} Resource to be removed
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved when finished
|
||||
*/
|
||||
public removeResource(resource: string, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string', 'function')
|
||||
.params('string')
|
||||
.end();
|
||||
|
||||
let _this = this;
|
||||
return this.backend.getAsync(this.options.buckets.meta, 'roles').then(function (roles: Array<String>) {
|
||||
let transaction = _this.backend.begin();
|
||||
_this.backend.del(transaction, allowsBucket(resource), roles);
|
||||
roles.forEach((role) => {
|
||||
_this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
|
||||
});
|
||||
return _this.backend.endAsync(transaction);
|
||||
}).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
allow( roles, resources, permissions, function(err) )
|
||||
Adds the given permissions to the given roles over the given resources.
|
||||
|
||||
@param {String|Array} role(s) to add permissions to.
|
||||
@param {String|Array} resource(s) to add permisisons to.
|
||||
@param {String|Array} permission(s) to add to the roles over the resources.
|
||||
@param {Function} Callback called when finished.
|
||||
|
||||
allow( permissionsArray, function(err) )
|
||||
|
||||
@param {Array} Array with objects expressing what permissions to give.
|
||||
|
||||
[{roles:{String|Array}, allows:[{resources:{String|Array}, permissions:{String|Array}]]
|
||||
|
||||
@param {Function} Callback called when finished.
|
||||
@return {Promise} Promise resolved when finished
|
||||
*/
|
||||
public removeAllow(role: string, resources: strings, permissions: strings, cb?: Callback): Promise<void> {
|
||||
contract(arguments)
|
||||
.params('string', 'string|array', 'string|array', 'function')
|
||||
.params('string', 'string|array', 'string|array')
|
||||
.params('string', 'string|array', 'function')
|
||||
.params('string', 'string|array')
|
||||
.end();
|
||||
|
||||
resources = makeArray(resources);
|
||||
if (cb || (permissions && !_.isFunction(permissions))) {
|
||||
permissions = makeArray(permissions);
|
||||
} else {
|
||||
cb = (permissions as any);
|
||||
permissions = null;
|
||||
}
|
||||
|
||||
return this.removePermissions(role, resources, permissions, cb);
|
||||
};
|
||||
/*
|
||||
removePermissions( role, resources, permissions)
|
||||
Remove permissions from the given roles owned by the given role.
|
||||
Note: we loose atomicity when removing empty role_resources.
|
||||
@param {String}
|
||||
@param {String|Array}
|
||||
@param {String|Array}
|
||||
*/
|
||||
public removePermissions(role: string, resources: strings, permissions: strings, cb?: Function): Promise<void> {
|
||||
let _this = this;
|
||||
let transaction = _this.backend.begin();
|
||||
_.each(resources, resource => {
|
||||
let bucket = allowsBucket(resource);
|
||||
if (permissions) {
|
||||
_this.backend.remove(transaction, bucket, role, permissions);
|
||||
} else {
|
||||
_this.backend.del(transaction, bucket, role);
|
||||
_this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove resource from role if no rights for that role exists.
|
||||
// Not fully atomic...
|
||||
return _this.backend.endAsync(transaction).then(function () {
|
||||
let transaction = _this.backend.begin();
|
||||
return bluebird.all(_.map(resources, resource => {
|
||||
let bucket = allowsBucket(resource);
|
||||
return _this.backend.getAsync(bucket, role).then(function (permissions) {
|
||||
if (permissions.length === 0) {
|
||||
_this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
|
||||
}
|
||||
});
|
||||
})).then(function () {
|
||||
return _this.backend.endAsync(transaction);
|
||||
});
|
||||
}).nodeify(cb);
|
||||
};
|
||||
/*
|
||||
allowedPermissions( userId, resources, function(err, obj) )
|
||||
Returns all the allowable permissions a given user have to
|
||||
access the given resources.
|
||||
It returns an array of objects where every object maps a
|
||||
resource name to a list of permissions for that resource.
|
||||
|
||||
@param {String|Number} User id.
|
||||
@param {String|Array} resource(s) to ask permissions for.
|
||||
@param {Function} Callback called when finished.
|
||||
*/
|
||||
public allowedPermissions(userId: Value, resources: strings, cb?: AnyCallback): bluebird<any> {
|
||||
if (!userId) {
|
||||
return cb(null, {});
|
||||
}
|
||||
|
||||
contract(arguments)
|
||||
.params('string|number', 'string|array', 'function')
|
||||
.params('string|number', 'string|array')
|
||||
.end();
|
||||
|
||||
if (this.backend.unionsAsync) {
|
||||
return this.optimizedAllowedPermissions(userId, resources, cb);
|
||||
}
|
||||
|
||||
let _this = this;
|
||||
resources = makeArray(resources);
|
||||
return this.userRoles(userId).then(roles => {
|
||||
let result = {};
|
||||
|
||||
return bluebird.all(_.map(resources, resource => {
|
||||
return _this._resourcePermissions(roles, resource).then(function (permissions) {
|
||||
result[resource] = permissions;
|
||||
});
|
||||
})).then(function () {
|
||||
return result;
|
||||
});
|
||||
|
||||
}).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
optimizedAllowedPermissions( userId, resources, function(err, obj) )
|
||||
|
||||
Returns all the allowable permissions a given user have to
|
||||
access the given resources.
|
||||
|
||||
It returns a map of resource name to a list of permissions for that resource.
|
||||
|
||||
This is the same as allowedPermissions, it just takes advantage of the unions
|
||||
function if available to reduce the number of backend queries.
|
||||
|
||||
@param {String|Number} User id.
|
||||
@param {String|Array} resource(s) to ask permissions for.
|
||||
@param {Function} Callback called when finished.
|
||||
*/
|
||||
public optimizedAllowedPermissions(userId, resources, cb) {
|
||||
if (!userId) {
|
||||
return cb(null, {});
|
||||
}
|
||||
|
||||
contract(arguments)
|
||||
.params('string|number', 'string|array', 'function|undefined')
|
||||
.params('string|number', 'string|array')
|
||||
.end();
|
||||
|
||||
resources = makeArray(resources);
|
||||
let self = this;
|
||||
|
||||
return this._allUserRoles(userId).then(function (roles) {
|
||||
let buckets = resources.map(allowsBucket);
|
||||
if (roles.length === 0) {
|
||||
let emptyResult = {};
|
||||
buckets.forEach(function (bucket) {
|
||||
emptyResult[bucket] = [];
|
||||
});
|
||||
return bluebird.resolve(emptyResult);
|
||||
}
|
||||
|
||||
return self.backend.unionsAsync(buckets, roles);
|
||||
}).then(function (response) {
|
||||
let result = {};
|
||||
Object.keys(response).forEach(function (bucket) {
|
||||
result[keyFromAllowsBucket(bucket)] = response[bucket];
|
||||
});
|
||||
|
||||
return result;
|
||||
}).nodeify(cb);
|
||||
}
|
||||
/*
|
||||
isAllowed( userId, resource, permissions, function(err, allowed) )
|
||||
|
||||
Checks if the given user is allowed to access the resource for the given
|
||||
permissions (note: it must fulfill all the permissions).
|
||||
|
||||
@param {String|Number} User id.
|
||||
@param {String|Array} resource(s) to ask permissions for.
|
||||
@param {String|Array} asked permissions.
|
||||
@param {Function} Callback called wish the result.
|
||||
*/
|
||||
public isAllowed(userId: Value, resource: strings, permissions: strings, cb?: AllowedCallback): Promise<boolean> {
|
||||
contract(arguments)
|
||||
.params('string|number', 'string', 'string|array', 'function')
|
||||
.params('string|number', 'string', 'string|array')
|
||||
.end();
|
||||
|
||||
let _this = this;
|
||||
return this.backend.getAsync(this.options.buckets.users, userId).then(function (roles) {
|
||||
if (roles.length) {
|
||||
return _this.areAnyRolesAllowed(roles, resource, permissions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}).nodeify(cb);
|
||||
}
|
||||
|
||||
/*
|
||||
areAnyRolesAllowed( roles, resource, permissions, function(err, allowed) )
|
||||
|
||||
Returns true if any of the given roles have the right permissions.
|
||||
|
||||
@param {String|Array} Role(s) to check the permissions for.
|
||||
@param {String} resource(s) to ask permissions for.
|
||||
@param {String|Array} asked permissions.
|
||||
@param {Function} Callback called with the result.
|
||||
*/
|
||||
public areAnyRolesAllowed(roles: strings, resource: strings, permissions: strings, cb?: AllowedCallback): Promise<boolean> {
|
||||
contract(arguments)
|
||||
.params('string|array', 'string', 'string|array', 'function')
|
||||
.params('string|array', 'string', 'string|array')
|
||||
.end();
|
||||
|
||||
roles = makeArray(roles);
|
||||
permissions = makeArray(permissions);
|
||||
|
||||
if (roles.length === 0) {
|
||||
return (bluebird as any).resolve(false).nodeify(cb);
|
||||
} else {
|
||||
return this._checkPermissions(roles, resource, permissions).nodeify(cb);
|
||||
}
|
||||
}
|
||||
/*
|
||||
whatResources(role, function(err, {resourceName: [permissions]})
|
||||
|
||||
Returns what resources a given role or roles have permissions over.
|
||||
|
||||
whatResources(role, permissions, function(err, resources) )
|
||||
|
||||
Returns what resources a role has the given permissions over.
|
||||
|
||||
@param {String|Array} Roles
|
||||
@param {String[Array} Permissions
|
||||
@param {Function} Callback called wish the result.
|
||||
*/
|
||||
public whatResources(roles: strings, permissions: strings, cb?: AnyCallback): Promise<any> {
|
||||
contract(arguments)
|
||||
.params('string|array')
|
||||
.params('string|array', 'string|array')
|
||||
.params('string|array', 'function')
|
||||
.params('string|array', 'string|array', 'function')
|
||||
.end();
|
||||
|
||||
roles = makeArray(roles);
|
||||
if (_.isFunction(permissions)) {
|
||||
cb = (<any>permissions);
|
||||
permissions = undefined;
|
||||
} else if (permissions) {
|
||||
permissions = makeArray(permissions);
|
||||
}
|
||||
|
||||
return this.permittedResources(roles, permissions, cb);
|
||||
}
|
||||
|
||||
public permittedResources(roles: strings, permissions: strings, cb?: Function): Promise<void> {
|
||||
let _this = this;
|
||||
let result: any = _.isUndefined(permissions) ? {} : [];
|
||||
return this._rolesResources(roles).then(function (resources) {
|
||||
return bluebird.all(resources.map(function (resource) {
|
||||
return _this._resourcePermissions(roles, resource).then(function (p) {
|
||||
if (permissions) {
|
||||
let commonPermissions = _.intersection(permissions, p);
|
||||
if (commonPermissions.length > 0) {
|
||||
result.push(resource);
|
||||
}
|
||||
} else {
|
||||
result[resource] = p;
|
||||
}
|
||||
});
|
||||
})).then(function () {
|
||||
return result;
|
||||
});
|
||||
}).nodeify(cb);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Private methods
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Same as allow but accepts a more compact input.
|
||||
//
|
||||
private _allowEx(objs): any {
|
||||
let _this = this;
|
||||
objs = makeArray(objs);
|
||||
|
||||
let demuxed = [];
|
||||
objs.forEach(function (obj) {
|
||||
let roles = obj.roles;
|
||||
obj.allows.forEach(function (allow) {
|
||||
demuxed.push({
|
||||
roles: roles,
|
||||
resources: allow.resources,
|
||||
permissions: allow.permissions
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return bluebird.reduce(demuxed, function (values, obj) {
|
||||
const roles: Values = obj.roles;
|
||||
const resources: strings = obj.resources;
|
||||
const permissions: strings = obj.permissions;
|
||||
return _this.allow(roles, resources, permissions, null);
|
||||
}, null);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the parents of the given roles
|
||||
//
|
||||
private _rolesParents(roles) {
|
||||
return this.backend.unionAsync(this.options.buckets.parents, roles);
|
||||
}
|
||||
//
|
||||
// Return all roles in the hierarchy including the given roles.
|
||||
//
|
||||
/*
|
||||
Acl.prototype._allRoles = function(roleNames, cb){
|
||||
var _this = this, roles;
|
||||
|
||||
_this._rolesParents(roleNames, function(err, parents){
|
||||
roles = _.union(roleNames, parents);
|
||||
async.whilst(
|
||||
function (){
|
||||
return parents.length >0;
|
||||
},
|
||||
function (cb) {
|
||||
_this._rolesParents(parents, function(err, result){
|
||||
if(!err){
|
||||
roles = _.union(roles, parents);
|
||||
parents = result;
|
||||
}
|
||||
cb(err);
|
||||
});
|
||||
},
|
||||
function(err){
|
||||
cb(err, roles);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
*/
|
||||
//
|
||||
// Return all roles in the hierarchy including the given roles.
|
||||
//
|
||||
private _allRoles(roleNames) {
|
||||
let _this = this;
|
||||
|
||||
return this._rolesParents(roleNames).then(function (parents) {
|
||||
if (parents.length > 0) {
|
||||
return _this._allRoles(parents).then(function (parentRoles) {
|
||||
return _.union(roleNames, parentRoles);
|
||||
});
|
||||
} else {
|
||||
return roleNames;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Return all roles in the hierarchy of the given user.
|
||||
//
|
||||
private _allUserRoles(userId) {
|
||||
let _this = this;
|
||||
|
||||
return this.userRoles(userId).then(function (roles) {
|
||||
if (roles && roles.length > 0) {
|
||||
return _this._allRoles(roles);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Returns an array with resources for the given roles.
|
||||
//
|
||||
private _rolesResources(roles) {
|
||||
let _this = this;
|
||||
roles = makeArray(roles);
|
||||
|
||||
return this._allRoles(roles).then(function (allRoles) {
|
||||
let result = [];
|
||||
|
||||
// check if bluebird.map simplifies this code
|
||||
return bluebird.all(allRoles.map(function (role) {
|
||||
return _this.backend.getAsync(_this.options.buckets.resources, role).then(function (resources) {
|
||||
result = result.concat(resources);
|
||||
});
|
||||
})).then(function () {
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the permissions for the given resource and set of roles
|
||||
//
|
||||
private _resourcePermissions(roles, resource): any {
|
||||
let _this = this;
|
||||
|
||||
if (roles.length === 0) {
|
||||
return bluebird.resolve([]);
|
||||
} else {
|
||||
return this.backend.unionAsync(allowsBucket(resource), roles).then(function (resourcePermissions) {
|
||||
return _this._rolesParents(roles).then(function (parents) {
|
||||
if (parents && parents.length) {
|
||||
return _this._resourcePermissions(parents, resource).then(function (morePermissions) {
|
||||
return _.union(resourcePermissions, morePermissions);
|
||||
});
|
||||
} else {
|
||||
return resourcePermissions;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: This function will not handle circular dependencies and result in a crash.
|
||||
//
|
||||
private _checkPermissions(roles, resource, permissions): any {
|
||||
let _this = this;
|
||||
return this.backend.unionAsync(allowsBucket(resource), roles).then(function (resourcePermissions) {
|
||||
if (resourcePermissions.indexOf('*') !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
permissions = permissions.filter(function (p) {
|
||||
return resourcePermissions.indexOf(p) === -1;
|
||||
});
|
||||
|
||||
if (permissions.length === 0) {
|
||||
return true;
|
||||
} else {
|
||||
return _this.backend.unionAsync(_this.options.buckets.parents, roles).then(function (parents) {
|
||||
if (parents && parents.length) {
|
||||
return _this._checkPermissions(parents, resource, permissions);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Backend Interface.
|
||||
|
||||
Implement this API for providing a backend for the acl module.
|
||||
*/
|
||||
|
||||
import { contract } from './contract';
|
||||
import { IBucketsOption, Action, Value, Values, IBackend } from './interfaces';
|
||||
|
||||
export let Backend = {
|
||||
/*
|
||||
Begins a transaction.
|
||||
*/
|
||||
begin: function () {
|
||||
// returns a transaction object
|
||||
},
|
||||
|
||||
/*
|
||||
Ends a transaction (and executes it)
|
||||
*/
|
||||
end: function (transaction, cb) {
|
||||
contract(arguments).params('object', 'function').end();
|
||||
// Execute transaction
|
||||
},
|
||||
|
||||
/*
|
||||
Cleans the whole storage.
|
||||
*/
|
||||
clean: function (cb) {
|
||||
contract(arguments).params('function').end();
|
||||
},
|
||||
|
||||
/*
|
||||
Gets the contents at the bucket's key.
|
||||
*/
|
||||
get: function (bucket, key, cb) {
|
||||
contract(arguments)
|
||||
.params('string', 'string|number', 'function')
|
||||
.end();
|
||||
},
|
||||
|
||||
/*
|
||||
Gets the union of contents of the specified keys in each of the specified buckets and returns
|
||||
a mapping of bucket to union.
|
||||
*/
|
||||
unions: function (bucket, keys, cb) {
|
||||
contract(arguments)
|
||||
.params('array', 'array', 'function')
|
||||
.end();
|
||||
},
|
||||
|
||||
/*
|
||||
Returns the union of the values in the given keys.
|
||||
*/
|
||||
union: function (bucket, keys, cb) {
|
||||
contract(arguments)
|
||||
.params('string', 'array', 'function')
|
||||
.end();
|
||||
},
|
||||
|
||||
/*
|
||||
Adds values to a given key inside a bucket.
|
||||
*/
|
||||
add: function (transaction, bucket, key, values) {
|
||||
contract(arguments)
|
||||
.params('object', 'string', 'string|number', 'string|array|number')
|
||||
.end();
|
||||
},
|
||||
|
||||
/*
|
||||
Delete the given key(s) at the bucket
|
||||
*/
|
||||
del: function (transaction, bucket, keys) {
|
||||
contract(arguments)
|
||||
.params('object', 'string', 'string|array')
|
||||
.end();
|
||||
},
|
||||
|
||||
/*
|
||||
Removes values from a given key inside a bucket.
|
||||
*/
|
||||
remove: function (transaction, bucket, key, values) {
|
||||
contract(arguments)
|
||||
.params('object', 'string', 'string|number', 'string|array|number')
|
||||
.end();
|
||||
}
|
||||
};
|
||||
@ -1,51 +0,0 @@
|
||||
import { IObjectLiteral } from '../../interfaces/index';
|
||||
import { IStoreIO } from '../../interfaces/Store';
|
||||
import { Memory } from './Memory';
|
||||
import * as fs from 'fs';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import * as _path from 'path';
|
||||
const writeFileAtomic = require('write-file-atomic');
|
||||
const permissionError = 'You don\'t have access to this file.';
|
||||
const defaultPathMode: number = parseInt('0700', 8);
|
||||
const writeFileOptions: IObjectLiteral = { mode: parseInt('0600', 8) };
|
||||
export class File extends Memory implements IStoreIO {
|
||||
configPath: string;
|
||||
read(path?: string): any {
|
||||
path = path || this.configPath;
|
||||
try {
|
||||
this._buckets = JSON.parse(fs.readFileSync(path, 'utf8'));
|
||||
} catch (err) {
|
||||
// create dir if it doesn't exist
|
||||
if (err.code === 'ENOENT') {
|
||||
mkdirp.sync(_path.dirname(path), defaultPathMode);
|
||||
return {};
|
||||
}
|
||||
// improve the message of permission errors
|
||||
if (err.code === 'EACCES') {
|
||||
err.message = err.message + '\n' + permissionError + '\n';
|
||||
}
|
||||
// empty the file if it encounters invalid JSON
|
||||
if (err.name === 'SyntaxError') {
|
||||
writeFileAtomic.sync(path, '', writeFileOptions);
|
||||
return {};
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
write(path?: string): any {
|
||||
path = path || this.configPath;
|
||||
const data = this.data();
|
||||
try {
|
||||
// make sure the folder exists as it
|
||||
// could have been deleted in the meantime
|
||||
mkdirp.sync(_path.dirname(path), defaultPathMode);
|
||||
writeFileAtomic.sync(path, JSON.stringify(data, null, 4), writeFileOptions);
|
||||
} catch (err) {
|
||||
// improve the message of permission errors
|
||||
if (err.code === 'EACCES') {
|
||||
err.message = err.message + '\n' + permissionError + '\n';
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,178 +0,0 @@
|
||||
/*
|
||||
Memory Backend.
|
||||
In-memory implementation of the storage.
|
||||
*/
|
||||
import * as _ from 'lodash';
|
||||
import { contract } from '../contract';
|
||||
import { Action, IBackend, Value, Values } from '../interfaces';
|
||||
import { IObjectLiteral, List } from '../../interfaces/index';
|
||||
import * as bluebird from 'bluebird';
|
||||
function makeArray(arr) {
|
||||
return Array.isArray(arr) ? arr : [arr];
|
||||
}
|
||||
export class Memory implements IBackend<Action[]> {
|
||||
endAsync = bluebird.promisify(this.end);
|
||||
getAsync = bluebird.promisify(this.get);
|
||||
cleanAsync = bluebird.promisify(this.clean);
|
||||
unionAsync = bluebird.promisify(this.union);
|
||||
unionsAsync = bluebird.promisify(this.unions);
|
||||
_buckets: IObjectLiteral;
|
||||
data() {
|
||||
return this._buckets as Action[];
|
||||
}
|
||||
constructor() {
|
||||
this._buckets = {};
|
||||
}
|
||||
/*
|
||||
Begins a transaction.
|
||||
*/
|
||||
begin() {
|
||||
// returns a transaction object(just an array of functions will do here.)
|
||||
return [];
|
||||
};
|
||||
|
||||
/*
|
||||
Ends a transaction (and executes it)
|
||||
*/
|
||||
end(transaction: Action[], cb: Action) {
|
||||
contract(arguments).params('array', 'function').end();
|
||||
// Execute transaction
|
||||
for (let i = 0, len = transaction.length; i < len; i++) {
|
||||
transaction[i]();
|
||||
}
|
||||
cb();
|
||||
}
|
||||
/*
|
||||
Cleans the whole storage.
|
||||
*/
|
||||
clean(cb: Action) {
|
||||
contract(arguments).params('function').end();
|
||||
this._buckets = {};
|
||||
cb();
|
||||
}
|
||||
/*
|
||||
Gets the contents at the bucket's key.
|
||||
*/
|
||||
get(bucket: string, key: Value, cb: Action) {
|
||||
contract(arguments)
|
||||
.params('string', 'string|number', 'function')
|
||||
.end();
|
||||
|
||||
if (this._buckets[bucket]) {
|
||||
(cb as Function)(null, this._buckets[bucket][key] || []);
|
||||
} else {
|
||||
(cb as Function)(null, []);
|
||||
}
|
||||
}
|
||||
/*
|
||||
Gets the union of the keys in each of the specified buckets
|
||||
*/
|
||||
unions(buckets, keys, cb) {
|
||||
contract(arguments)
|
||||
.params('array', 'array', 'function')
|
||||
.end();
|
||||
|
||||
const self = this;
|
||||
let results = {};
|
||||
|
||||
buckets.forEach(function (bucket) {
|
||||
if (self._buckets[bucket]) {
|
||||
results[bucket] = _.uniq(_.flatten(_.values(_.pick(self._buckets[bucket], keys))));
|
||||
} else {
|
||||
results[bucket] = [];
|
||||
}
|
||||
});
|
||||
cb(null, results);
|
||||
}
|
||||
/*
|
||||
Returns the union of the values in the given keys.
|
||||
*/
|
||||
union(bucket: string, keys: Values[], cb: Action): void {
|
||||
contract(arguments)
|
||||
.params('string', 'array', 'function')
|
||||
.end();
|
||||
|
||||
let match;
|
||||
let re;
|
||||
if (!this._buckets[bucket]) {
|
||||
Object.keys(this._buckets).some(function (b) {
|
||||
re = new RegExp("^" + b + "$");
|
||||
match = re.test(bucket);
|
||||
if (match) { bucket = b; }
|
||||
return match;
|
||||
});
|
||||
}
|
||||
|
||||
if (this._buckets[bucket]) {
|
||||
const keyArrays = [];
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
if (this._buckets[bucket][keys[i] as Value]) {
|
||||
keyArrays.push.apply(keyArrays, this._buckets[bucket][keys[i] as Value]);
|
||||
}
|
||||
}
|
||||
(cb as Function)(undefined, _.union(keyArrays));
|
||||
} else {
|
||||
(cb as Function)(undefined, []);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Adds values to a given key inside a bucket.
|
||||
*/
|
||||
add(transaction: Action[], bucket: string, key: Value, values: Values) {
|
||||
contract(arguments)
|
||||
.params('array', 'string', 'string|number', 'string|array|number')
|
||||
.end();
|
||||
|
||||
const self = this;
|
||||
values = makeArray(values);
|
||||
|
||||
transaction.push(function () {
|
||||
if (!self._buckets[bucket]) {
|
||||
self._buckets[bucket] = {};
|
||||
}
|
||||
if (!self._buckets[bucket][key]) {
|
||||
self._buckets[bucket][key] = values;
|
||||
} else {
|
||||
self._buckets[bucket][key] = _.union(values as List<Value>, self._buckets[bucket][key]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Delete the given key(s) at the bucket
|
||||
*/
|
||||
del(transaction: Action[], bucket: string, keys: Values) {
|
||||
contract(arguments)
|
||||
.params('array', 'string', 'string|array')
|
||||
.end();
|
||||
|
||||
const self = this;
|
||||
keys = makeArray(keys);
|
||||
transaction.push(function () {
|
||||
if (self._buckets[bucket]) {
|
||||
for (let i = 0, len = (keys as List<Value>).length; i < len; i++) {
|
||||
delete self._buckets[bucket][keys[i]];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Removes values from a given key inside a bucket.
|
||||
*/
|
||||
remove(transaction: Action[], bucket: string, key: Value, values: Values) {
|
||||
contract(arguments)
|
||||
.params('array', 'string', 'string|number', 'string|array|number')
|
||||
.end();
|
||||
|
||||
const self = this;
|
||||
values = makeArray(values);
|
||||
transaction.push(function () {
|
||||
let old;
|
||||
if (self._buckets[bucket] && (old = self._buckets[bucket][key])) {
|
||||
self._buckets[bucket][key] = _.difference(old, values as List<Value>);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -81,8 +81,7 @@ export interface IAcl {
|
||||
isAllowed(userId: Value, resource: string, permissions: Values): Promise<boolean>;
|
||||
areAnyRolesAllowed(roles: Values, resource: string, permissions: Values): Promise<boolean>;
|
||||
|
||||
whatResources(roles: Values): Promise<Record<string, string[]>>;
|
||||
whatResources(roles: Values, permissions: Values): Promise<string[]>;
|
||||
whatResources(roles: Values, permissions?: Values): Promise<Record<string, string[]> | string[]>;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@ -4,11 +4,10 @@
|
||||
"outDir": "./dist-in",
|
||||
"rootDir": "src",
|
||||
"baseUrl": ".",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"composite": false,
|
||||
"importHelpers": false,
|
||||
"inlineSourceMap": true,
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
@ -16,14 +15,11 @@
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"dist-in"
|
||||
],
|
||||
"files": [
|
||||
"src/index.ts"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user