diff --git a/CHANGELOG.md b/CHANGELOG.md index ffcd1f82f..2559caee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,7 +77,10 @@ - **Notifications** - rename translation key from 'appsubscription' to 'appSubscription' [#1054](https://github.com/eclipse-tractusx/portal-frontend/pull/1054) - **User Management** + - fixed displaying of user management navigation button based on role validation [#1073](https://github.com/eclipse-tractusx/portal-frontend/pull/1073) + - Fixed special characters in user management email filters [#1128](https://github.com/eclipse-tractusx/portal-frontend/issues/1128) + - **App Management** - fixed 400 Bad Request error due to search filter [#1057](https://github.com/eclipse-tractusx/portal-frontend/pull/1058) - added load more button app overview [#1009](https://github.com/eclipse-tractusx/portal-frontend/pull/1009) diff --git a/DEPENDENCIES b/DEPENDENCIES index c3d4f373d..ee294e91b 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -609,16 +609,16 @@ npm/npmjs/@emotion/babel-plugin/11.11.0, MIT, approved, #8386 npm/npmjs/@emotion/cache/11.11.0, MIT, approved, #8401 npm/npmjs/@emotion/hash/0.9.1, MIT, approved, #8394 npm/npmjs/@emotion/hash/0.9.2, MIT, approved, #8394 -npm/npmjs/@emotion/is-prop-valid/1.3.0, MIT, approved, clearlydefined +npm/npmjs/@emotion/is-prop-valid/1.3.0, MIT AND (BSD-2-Clause AND MIT), approved, #16339 npm/npmjs/@emotion/memoize/0.8.1, MIT, approved, #8408 npm/npmjs/@emotion/memoize/0.9.0, MIT, approved, clearlydefined npm/npmjs/@emotion/react/11.11.4, MIT AND (BSD-3-Clause AND MIT), approved, #8931 -npm/npmjs/@emotion/serialize/1.3.0, MIT, approved, clearlydefined +npm/npmjs/@emotion/serialize/1.3.0, MIT AND (BSD-2-Clause AND MIT), approved, #16340 npm/npmjs/@emotion/sheet/1.2.2, MIT, approved, #8389 npm/npmjs/@emotion/styled/11.11.5, MIT, approved, clearlydefined npm/npmjs/@emotion/unitless/0.9.0, MIT, approved, clearlydefined npm/npmjs/@emotion/use-insertion-effect-with-fallbacks/1.0.1, MIT, approved, #8419 -npm/npmjs/@emotion/utils/1.4.0, MIT, approved, clearlydefined +npm/npmjs/@emotion/utils/1.4.0, MIT AND (BSD-2-Clause AND MIT), approved, #16344 npm/npmjs/@emotion/weak-memoize/0.3.1, MIT, approved, #8402 npm/npmjs/@esbuild/aix-ppc64/0.20.2, MIT, approved, clearlydefined npm/npmjs/@esbuild/android-arm/0.20.2, Apache-2.0 AND MIT AND BSD-3-Clause AND (BSD-2-Clause AND BSD-3-Clause), approved, #15302 @@ -759,8 +759,8 @@ npm/npmjs/@types/lodash/4.17.7, MIT, approved, clearlydefined npm/npmjs/@types/node/20.11.30, MIT, approved, #13826 npm/npmjs/@types/papaparse/5.3.14, MIT, approved, #10964 npm/npmjs/@types/parse-json/4.0.2, MIT, approved, clearlydefined -npm/npmjs/@types/prop-types/15.7.11, MIT, approved, clearlydefined -npm/npmjs/@types/prop-types/15.7.12, MIT, approved, clearlydefined +npm/npmjs/@types/prop-types/15.7.11, MIT, approved, #16176 +npm/npmjs/@types/prop-types/15.7.12, MIT, approved, #16176 npm/npmjs/@types/qs/6.9.15, MIT, approved, #14071 npm/npmjs/@types/react-dom/18.2.22, MIT, approved, #8256 npm/npmjs/@types/react-redux/7.1.33, MIT, approved, #10970 diff --git a/src/components/shared/frame/UserList/index.tsx b/src/components/shared/frame/UserList/index.tsx index 695e51e9e..c56248041 100644 --- a/src/components/shared/frame/UserList/index.tsx +++ b/src/components/shared/frame/UserList/index.tsx @@ -33,6 +33,7 @@ import type { TenantUser } from 'features/admin/userApiSlice' import './style.scss' import { setSearchInput } from 'features/appManagement/actions' import { appManagementSelector } from 'features/appManagement/slice' +import { isSearchUserEmail } from 'types/Patterns' interface FetchHookArgsType { appId?: string @@ -87,7 +88,7 @@ export const UserList = ({ const searchInputData = useSelector(appManagementSelector) const validateSearchText = (expr: string) => { - const validateExpr = /^[ A-Za-z0-9._!@-]*$/.test(expr) + const validateExpr = isSearchUserEmail(expr) if (validateExpr) dispatch(setSearchInput({ open: true, text: expr })) return validateExpr } diff --git a/src/features/admin/appuserApiSlice.ts b/src/features/admin/appuserApiSlice.ts index 8d19d5731..fba3c076c 100644 --- a/src/features/admin/appuserApiSlice.ts +++ b/src/features/admin/appuserApiSlice.ts @@ -88,7 +88,7 @@ export const apiSlice = createApi({ fetchAppUsersSearch: builder.query, PaginFetchArgs>( { query: (fetchArgs) => { - const emailExpr = `&email=${fetchArgs.args!.expr}` + const emailExpr = `&email=${encodeURIComponent(fetchArgs.args!.expr)}` return { url: `/api/administration/user/owncompany/apps/${ fetchArgs.args!.appId diff --git a/src/features/admin/userApiSlice.ts b/src/features/admin/userApiSlice.ts index 41982d8b4..ac8860bae 100644 --- a/src/features/admin/userApiSlice.ts +++ b/src/features/admin/userApiSlice.ts @@ -151,7 +151,7 @@ export const apiSlice = createApi({ query: (fetchArgs) => `/api/administration/user/owncompany/users?status=ACTIVE&size=${PAGE_SIZE}&page=${ fetchArgs.page - }&email=${fetchArgs.args!.expr}`, + }&email=${encodeURIComponent(fetchArgs.args!.expr)}`, }), fetchUsersRoles: builder.query, string>({ query: (companyUserId) => diff --git a/src/types/Patterns.test.ts b/src/types/Patterns.test.ts index 601842341..3040fdf3b 100644 --- a/src/types/Patterns.test.ts +++ b/src/types/Patterns.test.ts @@ -29,6 +29,7 @@ import { isCountryCode, isClientID, isPersonName, + isSearchUserEmail, } from './Patterns' const TESTDATA = { @@ -214,6 +215,23 @@ const TESTDATA = { valid: ['sa-12', 'JSSS', 'Julia12'], invalid: ['&^%#@', '!', 'hash &*^#$'], }, + EMAIL_SEARCH: { + valid: [ + 'john.doe@example.com', + 'jane_doe123@example.com', + 'user+tag@example.com', + 'email@sub.domain.com', + 'first.last@another-domain.org', + 'name-with-dash@example-company.com', + 'name.surname@domain.travel', + 'name123@domain.ac', + 'firstname+lastname@example.com', + 'very.common@example.com', + 'disposable.style.email.with+symbol@example.com', + 'admin@admin-portal.co.uk', + ], + invalid: ['()*&^%$#/\\?><,`~'], + }, } describe('Input Pattern Tests', () => { @@ -304,4 +322,13 @@ describe('Input Pattern Tests', () => { expect(isClientID(expr)).toBe(false) }) }) + + it('Validate email search for users', () => { + TESTDATA.EMAIL_SEARCH.valid.forEach((expr) => { + expect(isSearchUserEmail(expr)).toBe(true) + }) + TESTDATA.EMAIL_SEARCH.invalid.forEach((expr) => { + expect(isSearchUserEmail(expr)).toBe(false) + }) + }) }) diff --git a/src/types/Patterns.ts b/src/types/Patterns.ts index 168946180..8bf6a0ff8 100644 --- a/src/types/Patterns.ts +++ b/src/types/Patterns.ts @@ -61,7 +61,7 @@ export const Patterns = { URL: prefixUrlPattern, MAIL: /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@/, }, - SEARCH: /^[a-zA-ZÀ-ÿ0-9 !?@&_\-.]{3,80}$/, + SEARCH: /^[a-zA-ZÀ-ÿ0-9 !?@&_+\-.]{3,80}$/, partner: { COMMERCIAL_REG_NUMBER: /^[a-zA-Z\d-\s]{9}$/, VAT_ID: /^[a-zA-Z\d-\s]{8,15}$/, @@ -120,6 +120,7 @@ export const Patterns = { POSTAL_CODE: /^(?!.*\s$)(?=[a-zA-Z\d-]{0,10}[-\s]?[a-zA-Z\d-]{0,10}$)[a-zA-Z\d\s-]{2,10}$/, }, + EMAIL_SEARCH: /^[ A-Za-z0-9._!@+-]*$/, } export const isEmpty = (expr: string) => !expr || expr.trim() === '' @@ -208,5 +209,7 @@ export const isCompanyVies = (expr: string) => Patterns.companyData.VIES.test(expr) export const isPostalCode = (expr: string) => Patterns.companyData.POSTAL_CODE.test(expr) +export const isSearchUserEmail = (expr: string) => + Patterns.EMAIL_SEARCH.test(expr) export default Patterns