create relation with holder- and contact-data, and search for contact emailAddress + relation mark #136
@ -40,12 +40,12 @@ public class HsOfficeContactController implements HsOfficeContactsApi {
|
|||||||
final String currentSubject,
|
final String currentSubject,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final String caption,
|
final String caption,
|
||||||
final String emailAddress) {
|
final String emailAddressRegEx) {
|
||||||
context.define(currentSubject, assumedRoles);
|
context.define(currentSubject, assumedRoles);
|
||||||
|
|
||||||
validate("caption, emailAddress").atMaxOne(caption, emailAddress);
|
validate("caption, emailAddress").atMaxOne(caption, emailAddressRegEx);
|
||||||
final var entities = emailAddress != null
|
final var entities = emailAddressRegEx != null
|
||||||
? contactRepo.findContactByEmailAddress(emailAddress)
|
? contactRepo.findContactByEmailAddressRegEx(emailAddressRegEx)
|
||||||
: contactRepo.findContactByOptionalCaptionLike(caption);
|
: contactRepo.findContactByOptionalCaptionLike(caption);
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import io.micrometer.core.annotation.Timed;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
|
import jakarta.validation.ValidationException;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -23,14 +24,22 @@ public interface HsOfficeContactRbacRepository extends Repository<HsOfficeContac
|
|||||||
List<HsOfficeContactRbacEntity> findContactByOptionalCaptionLike(String caption);
|
List<HsOfficeContactRbacEntity> findContactByOptionalCaptionLike(String caption);
|
||||||
|
|
||||||
@Query(value = """
|
@Query(value = """
|
||||||
SELECT c.* FROM hs_office.contact_rv c
|
select c.* from hs_office.contact_rv c
|
||||||
WHERE jsonb_path_exists(c.emailaddresses, cast(:emailAddressExpression as jsonpath))
|
where jsonb_path_exists(c.emailaddresses, cast(:emailAddressExpression as jsonpath))
|
||||||
""", nativeQuery = true)
|
""", nativeQuery = true)
|
||||||
@Timed("app.office.contacts.repo.findContactByEmailAddressImpl.rbac")
|
@Timed("app.office.contacts.repo.findContactByEmailAddressImpl.rbac")
|
||||||
List<HsOfficeContactRbacEntity> findContactByEmailAddressImpl(final String emailAddressExpression);
|
List<HsOfficeContactRbacEntity> findContactByEmailAddressImpl(final String emailAddressExpression);
|
||||||
|
|
||||||
default List<HsOfficeContactRbacEntity> findContactByEmailAddress(@NotNull final String emailAddress) {
|
default List<HsOfficeContactRbacEntity> findContactByEmailAddressRegEx(@NotNull final String emailAddress) {
|
||||||
return findContactByEmailAddressImpl("$.** ? (@ like_regex \"" + emailAddress.replace("%", ".*") + "\")");
|
return findContactByEmailAddressImpl("$.** ? (@ like_regex \"" + emailRegEx(emailAddress) + "\")");
|
||||||
|
}
|
||||||
|
|
||||||
|
static String emailRegEx(@NotNull String emailAddress) {
|
||||||
|
if (emailAddress.contains("'") || emailAddress.endsWith("\\") ) {
|
||||||
|
throw new ValidationException(
|
||||||
|
"emailAddress contains invalid characters: " + emailAddress);
|
||||||
|
}
|
||||||
|
return emailAddress.replace("%", ".*"); // the JSON-matcher in PostgreSQL needs a wildcard
|
||||||
}
|
}
|
||||||
|
|
||||||
@Timed("app.office.contacts.repo.save.rbac")
|
@Timed("app.office.contacts.repo.save.rbac")
|
||||||
|
@ -13,12 +13,13 @@ get:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Beginning of caption to filter the results.
|
description: Beginning of caption to filter the results.
|
||||||
- name: emailAddress
|
- name: emailAddressRegEx
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Beginning of email-address to filter the results, use '%' as wildcard.
|
description:
|
||||||
|
Regular-expression for an email-address to filter the results.
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
|
@ -193,7 +193,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
context("superuser-alex@hostsharing.net", null);
|
context("superuser-alex@hostsharing.net", null);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = contactRepo.findContactByEmailAddress("%@secondcontact.example.com");
|
final var result = contactRepo.findContactByEmailAddressRegEx("@secondcontact.example.com");
|
||||||
|
|
||||||
// then
|
// then
|
||||||
exactlyTheseContactsAreReturned(result, "second contact");
|
exactlyTheseContactsAreReturned(result, "second contact");
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user