From 03b38277243c9b4b4f5bcb17d747a131e51528d2 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 31 Oct 2022 19:26:02 -0400 Subject: [PATCH 1/5] Show ACL on every resource if you're an admin. Just had this idea this afternoon: wouldn't it be nice if we can quickly see the ACL list of every resource in an API by a click of the button. This middleware does that. If you're an admin, a new button gets rendered everywhere. Click it, and you'll see all the relevant privileges as fetched from a12n-server. --- package-lock.json | 210 ++++++++++++++++++++++-------------------- src/a12n.ts | 18 +++- src/app.ts | 2 + src/middleware/acl.ts | 51 ++++++++++ 4 files changed, 181 insertions(+), 100 deletions(-) create mode 100644 src/middleware/acl.ts diff --git a/package-lock.json b/package-lock.json index a9074cf..bef9794 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,9 +90,9 @@ } }, "node_modules/@curveball/browser": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@curveball/browser/-/browser-0.19.7.tgz", - "integrity": "sha512-H/qd8L60SQW//0svb8Lsfb5UH9FC8lflqxaFW6LdCuizXyN5IKZ9wuJypA7oNWZmyX4cJlPvyJ4HeIn+4XCBzg==", + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@curveball/browser/-/browser-0.19.8.tgz", + "integrity": "sha512-sfRZunIAG3NcpSPBtEliIDAkBoh7ELKjcj3xgvLZfQng7hHIZQx2LR91JhZZUh7qHImCNTr4nbMjy8xVHZtPJA==", "dependencies": { "@curveball/static": "^0.3.0", "csv-parse": "^5.1.0", @@ -475,9 +475,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.7.tgz", - "integrity": "sha512-LhFTglglr63mNXUSRYD8A+ZAIu5sFqNJ4Y2fPuY7UlrySJH87rRRlhtVmMHplmfk5WkoJGmDjE9oiTfyX94CpQ==" + "version": "18.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.8.tgz", + "integrity": "sha512-uGwPWlE0Hj972KkHtCDVwZ8O39GmyjfMane1Z3GUBGGnkZ2USDq7SxLpVIiIHpweY9DS0QTDH0Nw7RNBsAAZ5A==" }, "node_modules/@types/semver": { "version": "7.3.13", @@ -494,16 +494,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.41.0.tgz", - "integrity": "sha512-DXUS22Y57/LAFSg3x7Vi6RNAuLpTXwxB9S2nIA7msBb/Zt8p7XqMwdpdc1IU7CkOQUPgAqR5fWvxuKCbneKGmA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz", + "integrity": "sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/type-utils": "5.41.0", - "@typescript-eslint/utils": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/type-utils": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" @@ -526,14 +527,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.41.0.tgz", - "integrity": "sha512-HQVfix4+RL5YRWZboMD1pUfFN8MpRH4laziWkkAzyO1fvNOY/uinZcvo3QiFJVS/siNHupV8E5+xSwQZrl6PZA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.0.tgz", + "integrity": "sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/typescript-estree": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "debug": "^4.3.4" }, "engines": { @@ -553,13 +554,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.41.0.tgz", - "integrity": "sha512-xOxPJCnuktUkY2xoEZBKXO5DBCugFzjrVndKdUnyQr3+9aDWZReKq9MhaoVnbL+maVwWJu/N0SEtrtEUNb62QQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz", + "integrity": "sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/visitor-keys": "5.41.0" + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -570,13 +571,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.41.0.tgz", - "integrity": "sha512-L30HNvIG6A1Q0R58e4hu4h+fZqaO909UcnnPbwKiN6Rc3BUEx6ez2wgN7aC0cBfcAjZfwkzE+E2PQQ9nEuoqfA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz", + "integrity": "sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.41.0", - "@typescript-eslint/utils": "5.41.0", + "@typescript-eslint/typescript-estree": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -597,9 +598,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.41.0.tgz", - "integrity": "sha512-5BejraMXMC+2UjefDvrH0Fo/eLwZRV6859SXRg+FgbhA0R0l6lDqDGAQYhKbXhPN2ofk2kY5sgGyLNL907UXpA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.0.tgz", + "integrity": "sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -610,13 +611,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.41.0.tgz", - "integrity": "sha512-SlzFYRwFSvswzDSQ/zPkIWcHv8O5y42YUskko9c4ki+fV6HATsTODUPbRbcGDFYP86gaJL5xohUEytvyNNcXWg==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz", + "integrity": "sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/visitor-keys": "5.41.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -637,16 +638,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.41.0.tgz", - "integrity": "sha512-QlvfwaN9jaMga9EBazQ+5DDx/4sAdqDkcs05AsQHMaopluVCUyu1bTRUVKzXbgjDlrRAQrYVoi/sXJ9fmG+KLQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.0.tgz", + "integrity": "sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/typescript-estree": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -663,12 +664,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.41.0.tgz", - "integrity": "sha512-vilqeHj267v8uzzakbm13HkPMl7cbYpKVjgFWZPIOHIJHZtinvypUhJ5xBXfWYg4eFKqztbMMpOgFpT9Gfx4fw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz", + "integrity": "sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.41.0", + "@typescript-eslint/types": "5.42.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1901,9 +1902,9 @@ } }, "node_modules/luxon": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.0.4.tgz", - "integrity": "sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.1.0.tgz", + "integrity": "sha512-7w6hmKC0/aoWnEsmPCu5Br54BmbmUp5GfcqBxQngRcXJ+q5fdfjEzn7dxmJh2YdDhgW8PccYtlWKSv4tQkrTQg==", "engines": { "node": ">=12" } @@ -2058,6 +2059,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2953,9 +2960,9 @@ "requires": {} }, "@curveball/browser": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@curveball/browser/-/browser-0.19.7.tgz", - "integrity": "sha512-H/qd8L60SQW//0svb8Lsfb5UH9FC8lflqxaFW6LdCuizXyN5IKZ9wuJypA7oNWZmyX4cJlPvyJ4HeIn+4XCBzg==", + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@curveball/browser/-/browser-0.19.8.tgz", + "integrity": "sha512-sfRZunIAG3NcpSPBtEliIDAkBoh7ELKjcj3xgvLZfQng7hHIZQx2LR91JhZZUh7qHImCNTr4nbMjy8xVHZtPJA==", "requires": { "@curveball/static": "^0.3.0", "csv-parse": "^5.1.0", @@ -3245,9 +3252,9 @@ "dev": true }, "@types/node": { - "version": "18.11.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.7.tgz", - "integrity": "sha512-LhFTglglr63mNXUSRYD8A+ZAIu5sFqNJ4Y2fPuY7UlrySJH87rRRlhtVmMHplmfk5WkoJGmDjE9oiTfyX94CpQ==" + "version": "18.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.8.tgz", + "integrity": "sha512-uGwPWlE0Hj972KkHtCDVwZ8O39GmyjfMane1Z3GUBGGnkZ2USDq7SxLpVIiIHpweY9DS0QTDH0Nw7RNBsAAZ5A==" }, "@types/semver": { "version": "7.3.13", @@ -3264,69 +3271,70 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.41.0.tgz", - "integrity": "sha512-DXUS22Y57/LAFSg3x7Vi6RNAuLpTXwxB9S2nIA7msBb/Zt8p7XqMwdpdc1IU7CkOQUPgAqR5fWvxuKCbneKGmA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz", + "integrity": "sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/type-utils": "5.41.0", - "@typescript-eslint/utils": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/type-utils": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.41.0.tgz", - "integrity": "sha512-HQVfix4+RL5YRWZboMD1pUfFN8MpRH4laziWkkAzyO1fvNOY/uinZcvo3QiFJVS/siNHupV8E5+xSwQZrl6PZA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.0.tgz", + "integrity": "sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/typescript-estree": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.41.0.tgz", - "integrity": "sha512-xOxPJCnuktUkY2xoEZBKXO5DBCugFzjrVndKdUnyQr3+9aDWZReKq9MhaoVnbL+maVwWJu/N0SEtrtEUNb62QQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz", + "integrity": "sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==", "dev": true, "requires": { - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/visitor-keys": "5.41.0" + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0" } }, "@typescript-eslint/type-utils": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.41.0.tgz", - "integrity": "sha512-L30HNvIG6A1Q0R58e4hu4h+fZqaO909UcnnPbwKiN6Rc3BUEx6ez2wgN7aC0cBfcAjZfwkzE+E2PQQ9nEuoqfA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz", + "integrity": "sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.41.0", - "@typescript-eslint/utils": "5.41.0", + "@typescript-eslint/typescript-estree": "5.42.0", + "@typescript-eslint/utils": "5.42.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.41.0.tgz", - "integrity": "sha512-5BejraMXMC+2UjefDvrH0Fo/eLwZRV6859SXRg+FgbhA0R0l6lDqDGAQYhKbXhPN2ofk2kY5sgGyLNL907UXpA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.0.tgz", + "integrity": "sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.41.0.tgz", - "integrity": "sha512-SlzFYRwFSvswzDSQ/zPkIWcHv8O5y42YUskko9c4ki+fV6HATsTODUPbRbcGDFYP86gaJL5xohUEytvyNNcXWg==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz", + "integrity": "sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/visitor-keys": "5.41.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/visitor-keys": "5.42.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3335,28 +3343,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.41.0.tgz", - "integrity": "sha512-QlvfwaN9jaMga9EBazQ+5DDx/4sAdqDkcs05AsQHMaopluVCUyu1bTRUVKzXbgjDlrRAQrYVoi/sXJ9fmG+KLQ==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.0.tgz", + "integrity": "sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.41.0", - "@typescript-eslint/types": "5.41.0", - "@typescript-eslint/typescript-estree": "5.41.0", + "@typescript-eslint/scope-manager": "5.42.0", + "@typescript-eslint/types": "5.42.0", + "@typescript-eslint/typescript-estree": "5.42.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.41.0.tgz", - "integrity": "sha512-vilqeHj267v8uzzakbm13HkPMl7cbYpKVjgFWZPIOHIJHZtinvypUhJ5xBXfWYg4eFKqztbMMpOgFpT9Gfx4fw==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz", + "integrity": "sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.41.0", + "@typescript-eslint/types": "5.42.0", "eslint-visitor-keys": "^3.3.0" } }, @@ -4272,9 +4280,9 @@ } }, "luxon": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.0.4.tgz", - "integrity": "sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.1.0.tgz", + "integrity": "sha512-7w6hmKC0/aoWnEsmPCu5Br54BmbmUp5GfcqBxQngRcXJ+q5fdfjEzn7dxmJh2YdDhgW8PccYtlWKSv4tQkrTQg==" }, "make-error": { "version": "1.3.6", @@ -4401,6 +4409,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", diff --git a/src/a12n.ts b/src/a12n.ts index 5ac8fbc..0060211 100644 --- a/src/a12n.ts +++ b/src/a12n.ts @@ -1,8 +1,6 @@ import ketting from './ketting'; import { LinkNotFound } from 'ketting'; - - export async function addUserPrivilege(principal: string|URL, privilege: string, resource: string|URL): Promise { let userPrivilegesRes; @@ -25,3 +23,19 @@ export async function addUserPrivilege(principal: string|URL, privilege: string, resource: resource.toString() }); } + +type PrivilegeEntry = { + resource: string; + principal: string; + privilege: string; +} + +export async function getPrivilegesForResource(resource: string|URL): Promise { + + const privilegeSearchRes = await ketting + .follow('privilege-collection') + .follow('search-resource-privileges', { resource: resource.toString() }); + + return (await privilegeSearchRes.get()).data; + +} diff --git a/src/app.ts b/src/app.ts index 38cf6f6..419377d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -16,6 +16,7 @@ import oauth2Client from './oauth2'; import * as path from 'path'; import routes from './routes'; +import acl from './middleware/acl'; const app = new Application(); @@ -68,6 +69,7 @@ app.use(oauth2({ client: oauth2Client, })); +app.use(acl()); app.use(...routes); diff --git a/src/middleware/acl.ts b/src/middleware/acl.ts new file mode 100644 index 0000000..89d8a09 --- /dev/null +++ b/src/middleware/acl.ts @@ -0,0 +1,51 @@ +import { Middleware, Context } from '@curveball/kernel'; +import { getPrivilegesForResource } from '../a12n'; + +export default function aclMw(): Middleware { + + return async (ctx, next) => { + + if ('acl' in ctx.query) return aclDocument(ctx); + + await next(); + aclLink(ctx); + + }; + +} + +/** + * Adds a 'acl' link to the response. + */ +function aclLink(ctx: Context) { + + if (ctx.privileges.has('admin')) { + ctx.response.links.add({ + rel: 'acl', + href: ctx.path + '?acl', + title: 'ACL', + }); + } + +} + +/** + * Renders the 'ACL document' + */ +async function aclDocument(ctx: Context) { + + const aclEntries = await getPrivilegesForResource( + new URL(ctx.path, ctx.request.origin) + ); + + ctx.response.body = { + _links: { + self: { + href: ctx.path + '?acl', + title: 'ACL rules for ' + ctx.path + } + }, + rules: aclEntries, + }; + +} From 740a052543c2e85ce523b21d129a17ead710271e Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 31 Oct 2022 19:29:13 -0400 Subject: [PATCH 2/5] Require admin to see ACL page --- src/middleware/acl.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/middleware/acl.ts b/src/middleware/acl.ts index 89d8a09..fb78695 100644 --- a/src/middleware/acl.ts +++ b/src/middleware/acl.ts @@ -34,6 +34,8 @@ function aclLink(ctx: Context) { */ async function aclDocument(ctx: Context) { + ctx.privileges.require('admin'); + const aclEntries = await getPrivilegesForResource( new URL(ctx.path, ctx.request.origin) ); From f9d5d2a05c0e00e8ec943fe593251a5f3c587546 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 31 Oct 2022 19:30:45 -0400 Subject: [PATCH 3/5] Show the related resource --- src/middleware/acl.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/middleware/acl.ts b/src/middleware/acl.ts index fb78695..f3ed0fa 100644 --- a/src/middleware/acl.ts +++ b/src/middleware/acl.ts @@ -45,6 +45,9 @@ async function aclDocument(ctx: Context) { self: { href: ctx.path + '?acl', title: 'ACL rules for ' + ctx.path + }, + about: { + href: ctx.path } }, rules: aclEntries, From 1d2cdd1fe429f358aa1c25b166fd5c0d2f458a37 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 31 Oct 2022 19:35:04 -0400 Subject: [PATCH 4/5] Fix relative-to-a12nserver URIs --- src/a12n.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/a12n.ts b/src/a12n.ts index 0060211..fbe17cf 100644 --- a/src/a12n.ts +++ b/src/a12n.ts @@ -36,6 +36,16 @@ export async function getPrivilegesForResource(resource: string|URL): Promise { + + return { + resource: entry.resource, + privilege: entry.privilege, + principal: new URL(entry.principal, ketting.go().uri).toString(), + }; + + }); } From aee1e49e60410934acf9f817ae5c8d1de98594f3 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Mon, 31 Oct 2022 19:39:46 -0400 Subject: [PATCH 5/5] Use the same format a12n-server emits --- src/middleware/acl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middleware/acl.ts b/src/middleware/acl.ts index f3ed0fa..1730c49 100644 --- a/src/middleware/acl.ts +++ b/src/middleware/acl.ts @@ -50,7 +50,7 @@ async function aclDocument(ctx: Context) { href: ctx.path } }, - rules: aclEntries, + privileges: aclEntries, }; }