From c1c6f8b92da514adf14a5949d1f9640bc4f463f1 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 13 Dec 2024 12:34:13 +0100 Subject: [PATCH] /contacts?emailAddressRegEx -> emailAddress with optional '%' as wildcard --- .../contact/HsOfficeContactController.java | 8 ++--- .../HsOfficeContactRbacRepository.java | 24 ++++----------- .../hs-office/hs-office-contacts.yaml | 4 +-- .../hs-office/hs-office-relations.yaml | 2 +- ...eContactRbacRepositoryIntegrationTest.java | 2 +- ...HsOfficeContactRbacRepositoryUnitTest.java | 29 ------------------- 6 files changed, 14 insertions(+), 55 deletions(-) delete mode 100644 src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java index 548282d3..572a0ce8 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java @@ -40,12 +40,12 @@ public class HsOfficeContactController implements HsOfficeContactsApi { final String currentSubject, final String assumedRoles, final String caption, - final String emailAddressRegEx) { + final String emailAddress) { context.define(currentSubject, assumedRoles); - validate("caption, emailAddress").atMaxOne(caption, emailAddressRegEx); - final var entities = emailAddressRegEx != null - ? contactRepo.findContactByEmailAddressRegEx(emailAddressRegEx) + validate("caption, emailAddress").atMaxOne(caption, emailAddress); + final var entities = emailAddress != null + ? contactRepo.findContactByEmailAddress(emailAddress) : contactRepo.findContactByOptionalCaptionLike(caption); final var resources = mapper.mapList(entities, HsOfficeContactResource.class); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepository.java index 1e82a7ac..4576ef58 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepository.java @@ -4,8 +4,6 @@ import io.micrometer.core.annotation.Timed; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; -import jakarta.validation.ValidationException; -import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -25,23 +23,13 @@ public interface HsOfficeContactRbacRepository extends Repository findContactByEmailAddressImpl(final String emailAddressExpression); - - default List findContactByEmailAddressRegEx(@NotNull final String emailAddress) { - return findContactByEmailAddressImpl("$.** ? (@ like_regex \"" + emailRegEx(emailAddress) + "\")"); - } - - static String emailRegEx(@NotNull String emailAddress) { - // TODO.impl: find more secure solution, maybe we substitute a placeholder with the whole expression? - if (emailAddress.contains("'") || emailAddress.contains("\"") || emailAddress.endsWith("\\") ) { - throw new ValidationException( - "emailAddressRegEx contains invalid characters: " + emailAddress); - } - return emailAddress.replace("%", ".*"); // the JSON-matcher in PostgreSQL needs a wildcard - } + @Timed("app.office.contacts.repo.findContactByEmailAddress.rbac") + List findContactByEmailAddress(final String emailAddressRegEx); @Timed("app.office.contacts.repo.save.rbac") HsOfficeContactRbacEntity save(final HsOfficeContactRbacEntity entity); diff --git a/src/main/resources/api-definition/hs-office/hs-office-contacts.yaml b/src/main/resources/api-definition/hs-office/hs-office-contacts.yaml index 022756d8..d6ca9db5 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-contacts.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-contacts.yaml @@ -13,13 +13,13 @@ get: schema: type: string description: Beginning of caption to filter the results. - - name: emailAddressRegEx + - name: emailAddress in: query required: false schema: type: string description: - Regular-expression for an email-address to filter the results. + Email-address to filter the results, use '%' as wildcard. responses: "200": description: OK diff --git a/src/main/resources/api-definition/hs-office/hs-office-relations.yaml b/src/main/resources/api-definition/hs-office/hs-office-relations.yaml index 35619f07..93d5fdc5 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-relations.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-relations.yaml @@ -21,7 +21,7 @@ get: required: false schema: $ref: 'hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationType' - description: Prefix of name properties from holder or contact to filter the results. + description: Beginning of name properties from holder or contact to filter the results. - name: mark in: query required: false diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java index 6a7f45e3..5b59f3b6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java @@ -193,7 +193,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC context("superuser-alex@hostsharing.net", null); // when - final var result = contactRepo.findContactByEmailAddressRegEx("@secondcontact.example.com"); + final var result = contactRepo.findContactByEmailAddress("%@secondcontact.example.com"); // then exactlyTheseContactsAreReturned(result, "second contact"); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryUnitTest.java deleted file mode 100644 index d6c6574f..00000000 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryUnitTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.hostsharing.hsadminng.hs.office.contact; - -import org.junit.jupiter.api.Test; - -import jakarta.validation.ValidationException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; - -class HsOfficeContactRbacRepositoryUnitTest { - - @Test - void rejectsSingleQuoteInEmailAddressRegEx() { - final var throwable = catchThrowable( () -> - HsOfficeContactRbacRepository.emailRegEx("target@'example.org") - ); - - assertThat(throwable).isInstanceOf(ValidationException.class); - } - - @Test - void rejectsTrailingBackslashInEmailAddressRegEx() { - final var throwable = catchThrowable( () -> - HsOfficeContactRbacRepository.emailRegEx("target@example.org\\") - ); - - assertThat(throwable).isInstanceOf(ValidationException.class); - } -}