diff --git a/CHANGELOG.md b/CHANGELOG.md index a8a1df89e..04007ae0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -124,7 +124,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/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 5449c77bd..521bb9e05 100644 --- a/src/types/Patterns.ts +++ b/src/types/Patterns.ts @@ -58,7 +58,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}$/, @@ -117,6 +117,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() === '' @@ -205,5 +206,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