diff --git a/portals/admin/package-lock.json b/portals/admin/package-lock.json new file mode 100644 index 00000000000..10281dff4b9 --- /dev/null +++ b/portals/admin/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "admin", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/portals/admin/src/main/webapp/package-lock.json b/portals/admin/src/main/webapp/package-lock.json index a2e6d97c918..cc0916d574b 100644 --- a/portals/admin/src/main/webapp/package-lock.json +++ b/portals/admin/src/main/webapp/package-lock.json @@ -13,6 +13,7 @@ "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", "@hapi/joi": "^15.1.1", + "@material-ui/icons": "^4.11.3", "@monaco-editor/react": "^4.6.0", "@mui/icons-material": "^5.15.4", "@mui/lab": "^5.0.0-alpha.160", @@ -30,6 +31,8 @@ "lodash.clonedeep": "^4.5.0", "lodash.isempty": "^4.4.0", "lodash.sortby": "^4.7.0", + "material-ui-chip-input": "^1.1.0", + "material-ui-color": "^1.2.0", "moment": "^2.29.4", "mui-chips-input": "^2.1.3", "mui-datatables": "^4.3.0", @@ -3470,6 +3473,206 @@ "node": ">=10" } }, + "node_modules/@material-ui/core": { + "version": "4.12.4", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", + "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.5", + "@material-ui/system": "^4.12.2", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/core/node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT", + "peer": true + }, + "node_modules/@material-ui/core/node_modules/@material-ui/styles": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", + "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/core/node_modules/@material-ui/system": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", + "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/core/node_modules/@material-ui/utils": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", + "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@material-ui/core/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@material-ui/core/node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==", + "license": "MIT", + "peer": true + }, + "node_modules/@material-ui/core/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT", + "peer": true + }, + "node_modules/@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.4.4" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0", + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@monaco-editor/loader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", @@ -7849,6 +8052,17 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -10745,6 +10959,13 @@ "integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==", "license": "ISC" }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -11168,6 +11389,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==", + "license": "MIT", + "peer": true + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -13405,6 +13633,104 @@ "node": ">=12.0.0" } }, + "node_modules/jss": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", + "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/jss" + } + }, + "node_modules/jss-plugin-camel-case": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", + "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-default-unit": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", + "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-global": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", + "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-nested": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", + "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-props-sort": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", + "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0" + } + }, + "node_modules/jss-plugin-rule-value-function": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", + "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "jss": "10.10.0", + "tiny-warning": "^1.0.2" + } + }, + "node_modules/jss-plugin-vendor-prefixer": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", + "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -13758,6 +14084,66 @@ "tmpl": "1.0.5" } }, + "node_modules/material-ui-chip-input": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/material-ui-chip-input/-/material-ui-chip-input-1.1.0.tgz", + "integrity": "sha512-95JsxYtzBFUyvzLC0Ae8qo1h8heu9wcSgnGjF/Sy9QQ9pL/ufLVUyjS8uFULW4kEyeNZbZurux3KZKC3FLnoqg==", + "license": "MIT", + "dependencies": { + "classnames": "^2.2.5", + "prop-types": "^15.6.1" + }, + "peerDependencies": { + "@material-ui/core": "^1.0.0 || ^3.1.0", + "react": "^16.3.0", + "react-dom": "^16.3.0" + } + }, + "node_modules/material-ui-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/material-ui-color/-/material-ui-color-1.2.0.tgz", + "integrity": "sha512-bD2Rww+hakJxD2/19uxc280Vh292DnRStLke2LDFavVtGd5fzOz09zIrHO3ZHlMkJFsvwx6IwiB4/932ftv0sQ==", + "license": "MIT", + "peerDependencies": { + "@material-ui/core": "^4.9.5", + "material-ui-popup-state": "^1.5.3", + "prop-types": "^15.7.2", + "react": "^16.0.0 || ^17.0.0", + "react-dom": "^16.0.0 || ^17.0.0" + } + }, + "node_modules/material-ui-popup-state": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/material-ui-popup-state/-/material-ui-popup-state-1.9.3.tgz", + "integrity": "sha512-+Ete5Tzw5rXlYfmqptOS8kBUH8vnK5OJsd6IQ7SHtLjU0PsvsmM73M/k8ot0xkX4RmPGuNRsFbK3mlCe/ClQuw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@material-ui/types": "^6.0.1", + "classnames": "^2.2.6", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0 || ^5.0.0-beta", + "react": "^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/material-ui-popup-state/node_modules/@material-ui/types": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-6.0.2.tgz", + "integrity": "sha512-/XUca4wUb9pWimLLdM1PE8KS8rTbDEGohSGkGtk3WST7lm23m+8RYv9uOmrvOg/VSsl4bMiOv4t2/LCb+RLbTg==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -15185,6 +15571,13 @@ "node": ">=4" } }, + "node_modules/popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==", + "license": "MIT", + "peer": true + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", diff --git a/portals/admin/src/main/webapp/package.json b/portals/admin/src/main/webapp/package.json index 66aa97d7c84..7b225c35fce 100644 --- a/portals/admin/src/main/webapp/package.json +++ b/portals/admin/src/main/webapp/package.json @@ -32,6 +32,7 @@ "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", "@hapi/joi": "^15.1.1", + "@material-ui/icons": "^4.11.3", "@monaco-editor/react": "^4.6.0", "@mui/icons-material": "^5.15.4", "@mui/lab": "^5.0.0-alpha.160", @@ -49,6 +50,8 @@ "lodash.clonedeep": "^4.5.0", "lodash.isempty": "^4.4.0", "lodash.sortby": "^4.7.0", + "material-ui-chip-input": "^1.1.0", + "material-ui-color": "^1.2.0", "moment": "^2.29.4", "mui-chips-input": "^2.1.3", "mui-datatables": "^4.3.0", diff --git a/portals/admin/src/main/webapp/site/public/locales/en.json b/portals/admin/src/main/webapp/site/public/locales/en.json index 02c3505abec..8bd7b9c39e1 100644 --- a/portals/admin/src/main/webapp/site/public/locales/en.json +++ b/portals/admin/src/main/webapp/site/public/locales/en.json @@ -206,6 +206,7 @@ "Api.Provider": "Provider", "Api.Version": "Version", "Apis.Details.Scopes.CreateScope.roles.help": "Enter a valid role and press `Enter`.", + "Apis.Details.Scopes.Roles.Invalid": "Invalid Role(s) Found", "Apis.Details.Scopes.permission.status.allow": "Allow", "Apis.Details.Scopes.permission.status.deny": "Deny", "Apis.Details.Scopes.permission.status.none": "None", @@ -334,6 +335,8 @@ "Dashboard.tasksWorkflow.noTasks.card.description": "Manage workflow tasks, increase productivity and enhance competitiveness by enabling developers to easily deploy business processes and models.", "Dashboard.tasksWorkflow.noTasks.card.title": "All the pending tasks completed", "Form.Dialog.Base.cancel.btn": "Cancel", + "Gateway.AddEditGWEnvironment.permission.allowed": "Use of this Gateway Environment is \"Allowed\" for above roles.", + "Gateway.AddEditGWEnvironment.permission.denied": "Use of this Gateway Environment is \"Denied\" for above roles.", "GatewayEnvironments.AddEditGWEnvironment.form.description.help": "Description of the Gateway Environment", "GatewayEnvironments.AddEditGWEnvironment.form.description.label": "Description", "GatewayEnvironments.AddEditGWEnvironment.form.displayName": "Display Name", @@ -350,6 +353,9 @@ "GatewayEnvironments.AddEditGWEnvironment.form.info.edit.successful": "Gateway Environment edited successfully", "GatewayEnvironments.AddEditGWEnvironment.form.name": "Name", "GatewayEnvironments.AddEditGWEnvironment.form.name.help": "Name of the Gateway Environment", + "GatewayEnvironments.AddEditGWEnvironment.form.permission.type": "Gateway Environment Permission", + "GatewayEnvironments.AddEditGWEnvironment.form.permissions": "Permissions", + "GatewayEnvironments.AddEditGWEnvironment.form.permissions.add.description": "Permissions for the Gateway Environment", "GatewayEnvironments.AddEditGWEnvironment.form.save.button.label": "Save", "GatewayEnvironments.AddEditGWEnvironment.form.type.helper.text": "Supported Key Type of the Gateway Environment", "GatewayEnvironments.AddEditGWEnvironment.form.type.hybrid.option": "Hybrid", diff --git a/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx b/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx index 7b7213ec568..bfa8346bdf9 100644 --- a/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx +++ b/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/AddEditGWEnvironment.jsx @@ -19,8 +19,10 @@ import React, { useEffect, useReducer, useState } from 'react'; import { styled } from '@mui/material/styles'; import API from 'AppData/api'; +import base64url from 'base64url'; import PropTypes from 'prop-types'; import { useAppContext } from 'AppComponents/Shared/AppContext'; +import Box from '@mui/material/Box'; import TextField from '@mui/material/TextField'; import { FormattedMessage, useIntl } from 'react-intl'; import Select from '@mui/material//Select'; @@ -35,6 +37,10 @@ import Typography from '@mui/material/Typography'; import FormControlLabel from '@mui/material/FormControlLabel'; import FormHelperText from '@mui/material/FormHelperText'; import FormLabel from '@mui/material/FormLabel'; +import { MuiChipsInput } from 'mui-chips-input'; +import Error from '@material-ui/icons/Error'; +import InputAdornment from '@material-ui/core/InputAdornment'; +import { red } from '@material-ui/core/colors/'; import AddEditVhost from 'AppComponents/GatewayEnvironments/AddEditVhost'; const styles = { @@ -77,6 +83,15 @@ const StyledLabel = styled('span')({ ...styles.label, ...styles.newLabel }); const StyledSpan = styled('span')(({ theme }) => ({ color: theme.palette.error.dark })); +const useStyles = styled(() => ({ + chipInputBox: { + marginRight: '30px', + marginLeft: '10px', + marginTop: '10px', + marginBottom: '10px', + }, +})); + /** * Reducer * @param {JSON} state State @@ -91,10 +106,16 @@ function reducer(state, { field, value }) { case 'gatewayType': case 'description': case 'type': + case 'roles': case 'vhosts': return { ...state, [field]: value }; case 'editDetails': return value; + case 'permissionType': + return { + ...state, + permissions: { ...state.permissions, [field]: value }, + }; default: return state; } @@ -106,6 +127,7 @@ function reducer(state, { field, value }) { * @returns {JSX}. */ function AddEditGWEnvironment(props) { + const classes = useStyles(); const intl = useIntl(); const { updateList, dataRow, icon, triggerButtonText, title, @@ -115,6 +137,9 @@ function AddEditGWEnvironment(props) { host: '', httpContext: '', httpsPort: 8243, httpPort: 8280, wssPort: 8099, wsPort: 9099, isNew: true, }; const { settings } = useAppContext(); + const [validRoles, setValidRoles] = useState([]); + const [invalidRoles, setInvalidRoles] = useState([]); + const [roleValidity, setRoleValidity] = useState(true); const { gatewayTypes } = settings; const [initialState, setInitialState] = useState({ displayName: '', @@ -122,15 +147,61 @@ function AddEditGWEnvironment(props) { gatewayType: gatewayTypes && gatewayTypes.length > 1 ? 'Regular' : gatewayTypes[0], type: 'hybrid', vhosts: [defaultVhost], + permissions: { + roles: [], + permissionType: 'PUBLIC', + }, }); const [editMode, setIsEditMode] = useState(false); const [state, dispatch] = useReducer(reducer, initialState); const { - name, displayName, description, vhosts, type, gatewayType, + name, displayName, description, vhosts, type, gatewayType, permissions, } = state; + let permissionType = ''; + if (permissions) { + permissionType = state.permissions.permissionType; + } + const handleRoleDeletion = (role) => { + if (invalidRoles.includes(role)) { + const invalidRolesArray = invalidRoles.filter((existingRole) => existingRole !== role); + setInvalidRoles(invalidRolesArray); + if (invalidRolesArray.length === 0) { + setRoleValidity(true); + } + } else { + setValidRoles(validRoles.filter((existingRole) => existingRole !== role)); + } + }; + + const restApi = new API(); + const handleRoleAddition = (role) => { + const promise = restApi.validateSystemRole(base64url.encode(role)); + promise + .then(() => { + setValidRoles(validRoles.concat(role)); + if (invalidRoles.length === 0) { + setRoleValidity(true); + } else { + setRoleValidity(false); + } + }) + .catch((error) => { + if (error.status === 404) { + setInvalidRoles(invalidRoles.concat(role)); + setRoleValidity(false); + } else { + Alert.error('Error when validating role: ' + role); + console.error('Error when validating role ' + error); + } + }); + }; const onChange = (e) => { + if (e.target.name === 'GatewayPermissionRestrict') { + permissionType = e.target.value; + dispatch({ field: 'permissionType', value: permissionType }); + } dispatch({ field: e.target.name, value: e.target.value }); }; @@ -147,6 +218,10 @@ function AddEditGWEnvironment(props) { gatewayType: '', type: 'hybrid', vhosts: [defaultVhost], + permissions: { + roles: [], + permissionType: 'PUBLIC', + }, }); }, []); @@ -322,18 +397,18 @@ function AddEditGWEnvironment(props) { }); }); } - - const restApi = new API(); + permissions.permissionType = state.permissions.permissionType; + permissions.roles = validRoles; let promiseAPICall; if (dataRow) { // assign the update promise to the promiseAPICall promiseAPICall = restApi.updateGatewayEnvironment( - dataRow.id, name.trim(), displayName, type, description, gatewayType, vhostDto, + dataRow.id, name.trim(), displayName, type, description, gatewayType, vhostDto, permissions, ); } else { // assign the create promise to the promiseAPICall promiseAPICall = restApi.addGatewayEnvironment(name.trim(), displayName, type, description, - gatewayType, vhostDto); + gatewayType, vhostDto, permissions); } return promiseAPICall.then(() => { @@ -372,6 +447,7 @@ function AddEditGWEnvironment(props) { type: originalType, vhosts: originalVhosts, gatewayType: originalGatewayType, + permissions: originalPermissions, } = dataRow; setIsEditMode(true); dispatch({ @@ -383,6 +459,7 @@ function AddEditGWEnvironment(props) { gatewayType: originalGatewayType, description: originalDescription, vhosts: originalVhosts, + permissions: originalPermissions, }, }); } @@ -614,6 +691,148 @@ function AddEditGWEnvironment(props) { /> + {/* Permissions */} + + + + + + + + + + { + (permissionType === 'ALLOW' || permissionType === 'DENY') + && ( + + + + + ), + }} + onAddChip={handleRoleAddition} + renderChip={(ChipComponent, key, ChipProps) => ( + handleRoleDeletion(ChipProps.label)} + data-testid={ChipProps.label} + style={{ + backgroundColor: + invalidRoles.includes(ChipProps.label) + ? red[300] : null, + margin: '8px 8px 8px 0', + float: 'left', + }} + /> + )} + error={!roleValidity} + helperText={ + !roleValidity ? ( + + ) : [ + (permissionType === 'ALLOW' + ? ( + + ) + : ( + + ) + ), + ' ', + , + ] + } + /> + + ) + } + + { + return ( +
+ +
+ ); + }, + }, + }, ]; } else { columProps = [ @@ -174,6 +195,26 @@ export default function ListGWEnviornments() { }, }, }, + { + name: 'permissions', + label: intl.formatMessage({ + id: 'AdminPages.Gateways.table.header.permission', + defaultMessage: 'Permission', + }), + options: { + sort: false, + customBodyRender: (permissions) => { + return ( +
+ +
+ ); + }, + }, + }, ]; } const addButtonProps = { diff --git a/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/Permission.jsx b/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/Permission.jsx new file mode 100644 index 00000000000..ad29f151f3b --- /dev/null +++ b/portals/admin/src/main/webapp/source/src/app/components/GatewayEnvironments/Permission.jsx @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Popper from '@mui/material/Popper'; + +/** + * Renders a Permission list + * @class Environments + * @extends {React.Component} + */ +export default function SimplePopper(props) { + const { + type, + roles, + } = props; + const [anchorEl, setAnchorEl] = React.useState(null); + + let msg = roles.toString(); + if (type === 'PUBLIC') { + msg = 'No Visibility Restrictions!'; + } + + const handleClick = (event) => { + setAnchorEl(anchorEl ? null : event.currentTarget); + }; + + const open = Boolean(anchorEl); + const id = open ? 'simple-popper' : undefined; + + return ( +
+ + + + {msg} + + +
+ ); +} diff --git a/portals/admin/src/main/webapp/source/src/app/data/api.js b/portals/admin/src/main/webapp/source/src/app/data/api.js index e7c2d04c0bf..2720021eafc 100644 --- a/portals/admin/src/main/webapp/source/src/app/data/api.js +++ b/portals/admin/src/main/webapp/source/src/app/data/api.js @@ -494,9 +494,9 @@ class API extends Resource { /** * Add a Gateway Environment */ - addGatewayEnvironment(name, displayName, type, description, gatewayType, vhosts, provider="wso2", callback = null) { + addGatewayEnvironment(name, displayName, type, description, gatewayType, vhosts, permissions, provider="wso2", callback = null) { return this.client.then((client) => { - const data = { name, displayName, type, description, gatewayType, vhosts, provider }; + const data = { name, displayName, type, description, gatewayType, vhosts, permissions, provider }; const payload = { 'Content-Type': 'application/json', }; @@ -511,9 +511,9 @@ class API extends Resource { /** * Update a Gateway Environment */ - updateGatewayEnvironment(id, name, displayName, type, description, gatewayType, vhosts, callback = null) { + updateGatewayEnvironment(id, name, displayName, type, description, gatewayType, vhosts, permissions, callback = null) { return this.client.then((client) => { - const data = { name, displayName, type, description, gatewayType, vhosts }; + const data = { name, displayName, type, description, gatewayType, vhosts, permissions }; return client.apis['Environments'].put_environments__environmentId_( { environmentId: id }, { requestBody: data }, diff --git a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Permission.jsx b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Permission.jsx index 6d9f68a8637..ad29f151f3b 100644 --- a/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Permission.jsx +++ b/portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/Environments/Permission.jsx @@ -35,7 +35,7 @@ export default function SimplePopper(props) { let msg = roles.toString(); if (type === 'PUBLIC') { - msg = 'No Visibility Restrictions!' + msg = 'No Visibility Restrictions!'; } const handleClick = (event) => { @@ -51,10 +51,19 @@ export default function SimplePopper(props) { {type} - + {msg} ); -} \ No newline at end of file +}