mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-01-14 04:05:31 +00:00
Implement React Query (Tanner) (#1263)
* Implement React Query (Tanner) Also, replace PermissionCache with the framework's hooks. * Update App.tsx See if tools are causing cypress error * Push div above query elements Might solve a cypress problem. * Remove old PermissionCache, and add docs/comments
This commit is contained in:
parent
b5b8031b44
commit
917ee504cb
416
spiffworkflow-frontend/package-lock.json
generated
416
spiffworkflow-frontend/package-lock.json
generated
@ -25,6 +25,8 @@
|
||||
"@rjsf/mui": "5.0.0-beta.20",
|
||||
"@rjsf/utils": "5.0.0-beta.20",
|
||||
"@rjsf/validator-ajv8": "5.0.0-beta.20",
|
||||
"@tanstack/react-query": "^5.28.6",
|
||||
"@tanstack/react-query-devtools": "^5.28.6",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^14.2.1",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
@ -67,6 +69,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/grep": "^3.1.0",
|
||||
"@tanstack/eslint-plugin-query": "^5.28.6",
|
||||
"@types/carbon__colors": "^10.31.3",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"@types/lodash.merge": "^4.6.7",
|
||||
@ -5358,6 +5361,228 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.28.6.tgz",
|
||||
"integrity": "sha512-kIvdN/EvbOrk4bbXOBm/Ik+uhQl5hawikkF5dLLmlvK3aZJzwRaRGpezYDM5Xw/6GCsATy+woh+Wvzj//BRvsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "^6.20.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
|
||||
"integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/visitor-keys": "6.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/@typescript-eslint/types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
|
||||
"integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
|
||||
"integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/visitor-keys": "6.21.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "9.0.3",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/@typescript-eslint/utils": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
|
||||
"integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.21.0",
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/typescript-estree": "6.21.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
|
||||
"integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/minimatch": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/eslint-plugin-query/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.28.6.tgz",
|
||||
"integrity": "sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-devtools": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.28.6.tgz",
|
||||
"integrity": "sha512-DXJGqbrsteWU9XehDf6s3k3QxwQqGUlNXpitsF1xbwkYBcDaAakiC6hjJSMfPBHOrbZCnWfAGCVf4vh2D75/xw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.28.6.tgz",
|
||||
"integrity": "sha512-/DdYuDBSsA21Qbcder1R8Cr/3Nx0ZnA2lgtqKsLMvov8wL4+g0HBz/gWYZPlIsof7iyfQafyhg4wUVUsS3vWZw==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "5.28.6"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query-devtools": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.28.6.tgz",
|
||||
"integrity": "sha512-xSfskHlM2JkP7WpN89UqhJV2RbFxg8YnOMzQz+EEzWSsgxMI5Crce8HO9pcUAcJce8gSmw93RQwuKNdG3FbT6w==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-devtools": "5.28.6"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/react-query": "^5.28.6",
|
||||
"react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/dom": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz",
|
||||
@ -5905,9 +6130,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
@ -6061,9 +6286,9 @@
|
||||
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw=="
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
|
||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="
|
||||
},
|
||||
"node_modules/@types/serve-index": {
|
||||
"version": "1.9.1",
|
||||
@ -13256,9 +13481,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
@ -31052,6 +31277,18 @@
|
||||
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
|
||||
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA=="
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
|
||||
"integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||
@ -37820,6 +38057,142 @@
|
||||
"defer-to-connect": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@tanstack/eslint-plugin-query": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.28.6.tgz",
|
||||
"integrity": "sha512-kIvdN/EvbOrk4bbXOBm/Ik+uhQl5hawikkF5dLLmlvK3aZJzwRaRGpezYDM5Xw/6GCsATy+woh+Wvzj//BRvsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/utils": "^6.20.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
|
||||
"integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/visitor-keys": "6.21.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
|
||||
"integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
|
||||
"integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/visitor-keys": "6.21.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "9.0.3",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/utils": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
|
||||
"integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "6.21.0",
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"@typescript-eslint/typescript-estree": "6.21.0",
|
||||
"semver": "^7.5.4"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/visitor-keys": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
|
||||
"integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/types": "6.21.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@tanstack/query-core": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.28.6.tgz",
|
||||
"integrity": "sha512-hnhotV+DnQtvtR3jPvbQMPNMW4KEK0J4k7c609zJ8muiNknm+yoDyMHmxTWM5ZnlZpsz0zOxYFr+mzRJNHWJsA=="
|
||||
},
|
||||
"@tanstack/query-devtools": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.28.6.tgz",
|
||||
"integrity": "sha512-DXJGqbrsteWU9XehDf6s3k3QxwQqGUlNXpitsF1xbwkYBcDaAakiC6hjJSMfPBHOrbZCnWfAGCVf4vh2D75/xw=="
|
||||
},
|
||||
"@tanstack/react-query": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.28.6.tgz",
|
||||
"integrity": "sha512-/DdYuDBSsA21Qbcder1R8Cr/3Nx0ZnA2lgtqKsLMvov8wL4+g0HBz/gWYZPlIsof7iyfQafyhg4wUVUsS3vWZw==",
|
||||
"requires": {
|
||||
"@tanstack/query-core": "5.28.6"
|
||||
}
|
||||
},
|
||||
"@tanstack/react-query-devtools": {
|
||||
"version": "5.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.28.6.tgz",
|
||||
"integrity": "sha512-xSfskHlM2JkP7WpN89UqhJV2RbFxg8YnOMzQz+EEzWSsgxMI5Crce8HO9pcUAcJce8gSmw93RQwuKNdG3FbT6w==",
|
||||
"requires": {
|
||||
"@tanstack/query-devtools": "5.28.6"
|
||||
}
|
||||
},
|
||||
"@testing-library/dom": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz",
|
||||
@ -38264,9 +38637,9 @@
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
|
||||
},
|
||||
"@types/json5": {
|
||||
"version": "0.0.29",
|
||||
@ -38420,9 +38793,9 @@
|
||||
"integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
"integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw=="
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
|
||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="
|
||||
},
|
||||
"@types/serve-index": {
|
||||
"version": "1.9.1",
|
||||
@ -44116,9 +44489,9 @@
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ=="
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="
|
||||
},
|
||||
"eslint-webpack-plugin": {
|
||||
"version": "3.2.0",
|
||||
@ -57217,6 +57590,13 @@
|
||||
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
|
||||
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA=="
|
||||
},
|
||||
"ts-api-utils": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
|
||||
"integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"ts-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||
|
@ -20,6 +20,8 @@
|
||||
"@rjsf/mui": "5.0.0-beta.20",
|
||||
"@rjsf/utils": "5.0.0-beta.20",
|
||||
"@rjsf/validator-ajv8": "5.0.0-beta.20",
|
||||
"@tanstack/react-query": "^5.28.6",
|
||||
"@tanstack/react-query-devtools": "^5.28.6",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^14.2.1",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
@ -96,6 +98,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/grep": "^3.1.0",
|
||||
"@tanstack/eslint-plugin-query": "^5.28.6",
|
||||
"@types/carbon__colors": "^10.31.3",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"@types/lodash.merge": "^4.6.7",
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { defineAbility } from '@casl/ability';
|
||||
import React from 'react';
|
||||
|
||||
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom';
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { AbilityContext } from './contexts/Can';
|
||||
import APIErrorProvider from './contexts/APIErrorContext';
|
||||
import ContainerForExtensions from './ContainerForExtensions';
|
||||
import PublicRoutes from './routes/PublicRoutes';
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export default function App() {
|
||||
const ability = defineAbility(() => {});
|
||||
const routeComponents = () => {
|
||||
@ -19,14 +22,22 @@ export default function App() {
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Note that QueryClientProvider and ReactQueryDevTools
|
||||
* are React Qery, now branded under the Tanstack packages.
|
||||
* https://tanstack.com/query/latest
|
||||
*/
|
||||
const layout = () => {
|
||||
return (
|
||||
<div className="cds--white">
|
||||
<APIErrorProvider>
|
||||
<AbilityContext.Provider value={ability}>
|
||||
<Outlet />
|
||||
</AbilityContext.Provider>
|
||||
</APIErrorProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<APIErrorProvider>
|
||||
<AbilityContext.Provider value={ability}>
|
||||
<Outlet />
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
</AbilityContext.Provider>
|
||||
</APIErrorProvider>
|
||||
</QueryClientProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,28 +1,11 @@
|
||||
// We may need to update usage of Ability when we update.
|
||||
// They say they are going to rename PureAbility to Ability and remove the old class.
|
||||
import { AbilityBuilder, Ability } from '@casl/ability';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { AbilityContext } from '../contexts/Can';
|
||||
import { PermissionCheckResponseBody, PermissionsToCheck } from '../interfaces';
|
||||
import HttpService from '../services/HttpService';
|
||||
import {
|
||||
findPermissionsInCache,
|
||||
updatePermissionsCache,
|
||||
} from '../services/PermissionCacheService';
|
||||
|
||||
export const checkPermissions = (
|
||||
permissionsToCheck: PermissionsToCheck,
|
||||
successCallback: Function
|
||||
) => {
|
||||
if (Object.keys(permissionsToCheck).length !== 0) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/permissions-check`,
|
||||
httpMethod: 'POST',
|
||||
successCallback,
|
||||
postBody: { requests_to_check: permissionsToCheck },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const usePermissionFetcher = (
|
||||
permissionsToCheck: PermissionsToCheck
|
||||
@ -30,46 +13,53 @@ export const usePermissionFetcher = (
|
||||
const ability = useContext(AbilityContext);
|
||||
const [permissionsLoaded, setPermissionsLoaded] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const processPermissionResult = (result: PermissionCheckResponseBody) => {
|
||||
const oldRules = ability.rules;
|
||||
const { can, cannot, rules } = new AbilityBuilder(Ability);
|
||||
Object.keys(result.results).forEach((url: string) => {
|
||||
const permissionVerbResults = result.results[url];
|
||||
Object.keys(permissionVerbResults).forEach((permissionVerb: string) => {
|
||||
const hasPermission = permissionVerbResults[permissionVerb];
|
||||
if (hasPermission) {
|
||||
can(permissionVerb, url);
|
||||
} else {
|
||||
cannot(permissionVerb, url);
|
||||
}
|
||||
});
|
||||
});
|
||||
oldRules.forEach((oldRule: any) => {
|
||||
if (oldRule.inverted) {
|
||||
cannot(oldRule.action, oldRule.subject);
|
||||
const processPermissionResult = (result: PermissionCheckResponseBody) => {
|
||||
const oldRules = ability.rules;
|
||||
const { can, cannot, rules } = new AbilityBuilder(Ability);
|
||||
Object.keys(result.results).forEach((url: string) => {
|
||||
const permissionVerbResults = result.results[url];
|
||||
Object.keys(permissionVerbResults).forEach((permissionVerb: string) => {
|
||||
const hasPermission = permissionVerbResults[permissionVerb];
|
||||
if (hasPermission) {
|
||||
can(permissionVerb, url);
|
||||
} else {
|
||||
can(oldRule.action, oldRule.subject);
|
||||
cannot(permissionVerb, url);
|
||||
}
|
||||
});
|
||||
ability.update(rules);
|
||||
});
|
||||
oldRules.forEach((oldRule: any) => {
|
||||
if (oldRule.inverted) {
|
||||
cannot(oldRule.action, oldRule.subject);
|
||||
} else {
|
||||
can(oldRule.action, oldRule.subject);
|
||||
}
|
||||
});
|
||||
ability.update(rules);
|
||||
|
||||
// Update the cache with the new permissions
|
||||
updatePermissionsCache(result);
|
||||
setPermissionsLoaded(true);
|
||||
};
|
||||
setPermissionsLoaded(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Are the incoming permission requests all in the cache?
|
||||
* If not, make the backend call, update the cache, and process the results.
|
||||
* Otherwise, use the cached results.
|
||||
*/
|
||||
const foundResults = findPermissionsInCache(permissionsToCheck);
|
||||
if (foundResults) {
|
||||
processPermissionResult(foundResults);
|
||||
} else {
|
||||
checkPermissions(permissionsToCheck, processPermissionResult);
|
||||
const checkPermissions = async () => {
|
||||
if (Object.keys(permissionsToCheck).length !== 0) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/permissions-check`,
|
||||
httpMethod: 'POST',
|
||||
successCallback: processPermissionResult,
|
||||
postBody: { requests_to_check: permissionsToCheck },
|
||||
});
|
||||
}
|
||||
|
||||
/** Query functions used by TanStack Query (React Query)
|
||||
* must always return data, but we don't need to use it
|
||||
*/
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/** TanStack (React Query) trigger to do it's SWR state/cache thing */
|
||||
useQuery({
|
||||
queryKey: ['permissions-check', permissionsToCheck || {}],
|
||||
queryFn: () => checkPermissions(),
|
||||
});
|
||||
|
||||
return { ability, permissionsLoaded };
|
||||
|
@ -1,56 +0,0 @@
|
||||
import {
|
||||
updatePermissionsCache,
|
||||
inspectPermissionsCache,
|
||||
clearPermissionsCache,
|
||||
} from './PermissionCacheService';
|
||||
|
||||
describe('updatePermissionsCache', () => {
|
||||
it('should update the permission cache with the provided permissions', () => {
|
||||
const permissionsResponse = {
|
||||
results: {
|
||||
'/path1': { GET: true },
|
||||
'/path2': { POST: true },
|
||||
},
|
||||
};
|
||||
updatePermissionsCache(permissionsResponse);
|
||||
// Note the cache stores the perms in an array
|
||||
expect(inspectPermissionsCache().get('/path1')).toEqual([{ GET: true }]);
|
||||
expect(inspectPermissionsCache().get('/path2')).toEqual([{ POST: true }]);
|
||||
});
|
||||
it('should update the permissions cache with the new permissions', () => {
|
||||
// Add more permissions to a given path
|
||||
const permissionsResponse = {
|
||||
results: {
|
||||
'/path1': { POST: true },
|
||||
'/path2': { GET: true },
|
||||
},
|
||||
};
|
||||
updatePermissionsCache(permissionsResponse);
|
||||
// Each path should now have the new permissions added to the existing ones
|
||||
expect(inspectPermissionsCache().get('/path1')).toEqual([
|
||||
{ GET: true },
|
||||
{ POST: true },
|
||||
]);
|
||||
expect(inspectPermissionsCache().get('/path2')).toEqual([
|
||||
{ POST: true },
|
||||
{ GET: true },
|
||||
]);
|
||||
});
|
||||
it('cache should be unchanged if results are empty', () => {
|
||||
const permissionsResponse = { results: {} };
|
||||
updatePermissionsCache(permissionsResponse);
|
||||
expect(inspectPermissionsCache().get('/path1')).toEqual([
|
||||
{ GET: true },
|
||||
{ POST: true },
|
||||
]);
|
||||
expect(inspectPermissionsCache().get('/path2')).toEqual([
|
||||
{ POST: true },
|
||||
{ GET: true },
|
||||
]);
|
||||
expect(inspectPermissionsCache().size).toEqual(2);
|
||||
});
|
||||
it('should clear the permissions cache when told to', () => {
|
||||
clearPermissionsCache();
|
||||
expect(inspectPermissionsCache().size).toEqual(0);
|
||||
});
|
||||
});
|
@ -1,91 +0,0 @@
|
||||
/**
|
||||
* There can be a lot of redundant requests for permissions (probably deps/contexts firing etc.)
|
||||
* This service provides a cache to check for already-processed perms.
|
||||
*/
|
||||
import {
|
||||
PermissionCheckResponseBody,
|
||||
PermissionVerbResults,
|
||||
PermissionsToCheck,
|
||||
} from '../interfaces';
|
||||
|
||||
/** Map makes sense: no prototype to hack, high perf, easily wiped. */
|
||||
const permissionsCache = new Map<string, Array<PermissionVerbResults>>();
|
||||
|
||||
const updatePermissionsCache = (
|
||||
permissionsResponse: PermissionCheckResponseBody
|
||||
) => {
|
||||
if (Object.entries(permissionsResponse.results).length > 0) {
|
||||
Object.entries(permissionsResponse.results).forEach(
|
||||
([path, permissions]) => {
|
||||
if (permissionsCache.has(path)) {
|
||||
const cachedPermissions = permissionsCache.get(path);
|
||||
// Make sure we don't add duplicate PermissionVerb objects
|
||||
if (
|
||||
cachedPermissions &&
|
||||
!cachedPermissions.some(
|
||||
(p) => JSON.stringify(p) === JSON.stringify(permissions)
|
||||
)
|
||||
) {
|
||||
cachedPermissions.push(permissions);
|
||||
}
|
||||
} else {
|
||||
permissionsCache.set(path, [permissions]);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Look for the permissions in the cache. If satisfied, we don't need to make a backend call.
|
||||
* Then, create a response object and return it so we can complete any callbacks.
|
||||
*/
|
||||
const findPermissionsInCache = (
|
||||
permissionsToCheck: PermissionsToCheck
|
||||
): PermissionCheckResponseBody | null => {
|
||||
const results: Record<string, PermissionVerbResults> = {};
|
||||
if (permissionsToCheck) {
|
||||
Object.entries(permissionsToCheck).forEach(([path, verbs]) => {
|
||||
const cachedPermissions = permissionsCache.get(path);
|
||||
if (cachedPermissions) {
|
||||
const found = cachedPermissions.find((p) => {
|
||||
// Note that the project config doesn't seem to support "hasOwn"
|
||||
return Object.prototype.hasOwnProperty.call(p, verbs[0]);
|
||||
});
|
||||
|
||||
if (found) {
|
||||
results[path] = found;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Results must have content, and must be the same number of permissions as we're checking
|
||||
* TODO: This implementation can lead to redundant permissions requests if
|
||||
* the same individual permission is requested by different permission sets
|
||||
* (any perm in a set not found will trigger a backend call for the whole set).
|
||||
* This is erring on the side of caution for now, but a more robust individual
|
||||
* checker might be useful.
|
||||
*/
|
||||
return Object.keys(results).length > 0 &&
|
||||
Object.keys(results).length === Object.keys(permissionsToCheck).length
|
||||
? { results: results as any }
|
||||
: null;
|
||||
};
|
||||
|
||||
// Don't allow retrieval or manipulation of the cache directly
|
||||
const inspectPermissionsCache = () => {
|
||||
return new Map(permissionsCache);
|
||||
};
|
||||
|
||||
const clearPermissionsCache = () => {
|
||||
permissionsCache.clear();
|
||||
};
|
||||
|
||||
export {
|
||||
updatePermissionsCache,
|
||||
findPermissionsInCache,
|
||||
clearPermissionsCache,
|
||||
inspectPermissionsCache,
|
||||
};
|
@ -3,7 +3,6 @@ import cookie from 'cookie';
|
||||
import { BACKEND_BASE_URL } from '../config';
|
||||
import { AuthenticationOption } from '../interfaces';
|
||||
import { parseTaskShowUrl } from '../helpers';
|
||||
import { clearPermissionsCache } from './PermissionCacheService';
|
||||
|
||||
// NOTE: this currently stores the jwt token in local storage
|
||||
// which is considered insecure. Server set cookies seem to be considered
|
||||
@ -102,10 +101,6 @@ const doLogout = () => {
|
||||
logoutRedirectUrl += '&backend_only=true';
|
||||
}
|
||||
|
||||
// Wipe all cached permissions so if user logs back in
|
||||
// (either as themselves or a different user), they get the correct permissions
|
||||
clearPermissionsCache();
|
||||
|
||||
window.location.href = logoutRedirectUrl;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user