diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java index 4de33a2b0c4..fca009b24e4 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/glossary/GlossaryResourceTest.java @@ -341,7 +341,9 @@ public class GlossaryResourceTest extends EntityResourceTest history.push( getGlossaryPathWithAction( - selectedData.fullyQualifiedName ?? '', + encodeURIComponent(selectedData.fullyQualifiedName ?? ''), EntityAction.IMPORT ) ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Tag/Tags/tags.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Tag/Tags/tags.tsx index e73481abde1..a6c909f35b0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Tag/Tags/tags.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Tag/Tags/tags.tsx @@ -92,7 +92,9 @@ const Tags: FunctionComponent = ({ onClick={() => { if (tag.source && startWith !== TAG_START_WITH.PLUS) { tag.source === TagSource.Glossary - ? history.push(`${ROUTES.GLOSSARY}/${tag.tagFQN}`) + ? history.push( + `${ROUTES.GLOSSARY}/${encodeURIComponent(tag.tagFQN)}` + ) : history.push(`${ROUTES.TAGS}/${tag.tagFQN.split('.')[0]}`); } }}> diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/regex.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/regex.constants.ts index eaf0436fffc..306f7cada8e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/regex.constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/regex.constants.ts @@ -24,7 +24,7 @@ export const FQN_REGEX = new RegExp( * strings that contain a combination of letters, alphanumeric characters, hyphens, * spaces, periods, single quotes, ampersands, and parentheses, with support for Unicode characters. */ -export const ENTITY_NAME_REGEX = /^[\p{L}\w\- .'&()]+$/u; +export const ENTITY_NAME_REGEX = /^[\p{L}\w\- .'&()%]+$/u; export const delimiterRegex = /[\\[\]\\()\\;\\,\\|\\{}\\``\\/\\<>\\^]/g; export const nameWithSpace = /\s/g; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryLeftPanel/GlossaryLeftPanel.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryLeftPanel/GlossaryLeftPanel.component.tsx index 4c681c5227e..5441e43eb17 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryLeftPanel/GlossaryLeftPanel.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryLeftPanel/GlossaryLeftPanel.component.tsx @@ -34,6 +34,7 @@ const GlossaryLeftPanel = ({ glossaries }: GlossaryLeftPanelProps) => { const { t } = useTranslation(); const { permissions } = usePermissionProvider(); const { glossaryName } = useParams<{ glossaryName: string }>(); + const glossaryFqn = glossaryName ? decodeURIComponent(glossaryName) : null; const history = useHistory(); const createGlossaryPermission = useMemo( @@ -42,12 +43,12 @@ const GlossaryLeftPanel = ({ glossaries }: GlossaryLeftPanelProps) => { [permissions] ); const selectedKey = useMemo(() => { - if (glossaryName) { - return Fqn.split(glossaryName)[0]; + if (glossaryFqn) { + return Fqn.split(glossaryFqn)[0]; } return glossaries[0].name; - }, [glossaryName]); + }, [glossaryFqn]); const menuItems: ItemType[] = useMemo(() => { return glossaries.reduce((acc, glossary) => { diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx index a351969ad6a..af13fdb31ab 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/Glossary/GlossaryPage/GlossaryPage.component.tsx @@ -48,7 +48,8 @@ import GlossaryLeftPanel from '../GlossaryLeftPanel/GlossaryLeftPanel.component' const GlossaryPage = () => { const { t } = useTranslation(); const { permissions } = usePermissionProvider(); - const { glossaryName: glossaryFqn } = useParams<{ glossaryName: string }>(); + const { glossaryName } = useParams<{ glossaryName: string }>(); + const glossaryFqn = decodeURIComponent(glossaryName); const history = useHistory(); const [glossaries, setGlossaries] = useState([]); const [isLoading, setIsLoading] = useState(true); diff --git a/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts b/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts index 8cd2c4cead7..d16167cbffe 100644 --- a/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/rest/glossaryAPI.ts @@ -135,7 +135,7 @@ export const getGlossaryTermByFQN = async ( arrQueryFields: string | string[] = '' ) => { const url = getURLWithQueryFields( - `/glossaryTerms/name/${glossaryTermFQN}`, + `/glossaryTerms/name/${encodeURIComponent(glossaryTermFQN)}`, arrQueryFields ); @@ -193,7 +193,9 @@ export const importGlossaryInCSVFormat = async ( headers: { 'Content-type': 'text/plain' }, }; const response = await APIClient.put>( - `/glossaries/name/${glossaryName}/import?dryRun=${dryRun}`, + `/glossaries/name/${encodeURIComponent( + glossaryName + )}/import?dryRun=${dryRun}`, data, configOptions ); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts index 142c489eb3f..a57c47b7952 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/RouterUtils.ts @@ -139,7 +139,7 @@ export const getGlossaryPath = (fqn?: string) => { let path = ROUTES.GLOSSARY; if (fqn) { path = ROUTES.GLOSSARY_DETAILS; - path = path.replace(PLACEHOLDER_GLOSSARY_NAME, fqn); + path = path.replace(PLACEHOLDER_GLOSSARY_NAME, encodeURIComponent(fqn)); } return path; @@ -456,7 +456,7 @@ export const getGlossaryTermsVersionsPath = ( ? ROUTES.GLOSSARY_TERMS_VERSION_TAB : ROUTES.GLOSSARY_TERMS_VERSION; path = path - .replace(PLACEHOLDER_GLOSSARY_NAME, glossaryTermsFQN) + .replace(PLACEHOLDER_GLOSSARY_NAME, encodeURIComponent(glossaryTermsFQN)) .replace(PLACEHOLDER_ROUTE_VERSION, version); if (tab) { diff --git a/openmetadata-ui/src/main/resources/ui/yarn.lock b/openmetadata-ui/src/main/resources/ui/yarn.lock index 17dcb33d125..114cd7167ac 100644 --- a/openmetadata-ui/src/main/resources/ui/yarn.lock +++ b/openmetadata-ui/src/main/resources/ui/yarn.lock @@ -2078,6 +2078,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.12.13": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" @@ -8075,17 +8082,16 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== +history@4.5.1, history@^4.9.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.5.1.tgz#44935a51021e3b8e67ebac267a35675732aba569" + integrity sha512-gfHeJeYeMzFtos61gdA1AloO0hGXPF2Yum+2FRdJvlylYQOz51OnT1zuwg9UYst1BRrONhcAh3Nmsg9iblgl6g== dependencies: - "@babel/runtime" "^7.1.2" + invariant "^2.2.1" loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" + resolve-pathname "^2.0.0" + value-equal "^0.2.0" + warning "^3.0.0" hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" @@ -8456,7 +8462,7 @@ interpret@^2.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -invariant@^2.2.4: +invariant@^2.2.1, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -10112,7 +10118,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-create-react-context@^0.4.0, mini-create-react-context@^0.4.1: +mini-create-react-context@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== @@ -12253,28 +12259,27 @@ react-resize-detector@^8.0.4: lodash "^4.17.21" react-router-dom@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" - integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: - "@babel/runtime" "^7.1.2" + "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.2.0" + react-router "5.3.4" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" - integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== +react-router@5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== dependencies: - "@babel/runtime" "^7.1.2" + "@babel/runtime" "^7.12.13" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" path-to-regexp "^1.7.0" prop-types "^15.6.2" react-is "^16.6.0" @@ -12709,10 +12714,10 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== +resolve-pathname@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" + integrity sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg== resolve-url@^0.2.1: version "0.2.1" @@ -14516,10 +14521,10 @@ validate.io-number@^1.0.3: resolved "https://registry.yarnpkg.com/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8" integrity sha1-9j/+2iSL8opnqNSODjtGGhZluvg= -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== +value-equal@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d" + integrity sha512-yRL36Xb2K/HmFT5Fe3M86S7mu4+a12/3l7uytUh6eNPPjP77ldPBvsAvmnWff39sXn55naRMZN8LZWRO8PWaeQ== vary@~1.1.2: version "1.1.2" @@ -14591,6 +14596,13 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + integrity sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ== + dependencies: + loose-envify "^1.0.0" + watchpack@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"