diff --git a/src/main/java/net/hostsharing/hsadminng/config/WebSecurityConfig.java b/src/main/java/net/hostsharing/hsadminng/config/WebSecurityConfig.java index 3585dd8c..6da383ab 100644 --- a/src/main/java/net/hostsharing/hsadminng/config/WebSecurityConfig.java +++ b/src/main/java/net/hostsharing/hsadminng/config/WebSecurityConfig.java @@ -17,10 +17,11 @@ public class WebSecurityConfig { return http .authorizeHttpRequests(authorize -> authorize .requestMatchers("/api/**").permitAll() // TODO.impl: implement authentication + .requestMatchers("/swagger-ui/**").permitAll() + .requestMatchers("/v3/api-docs/**").permitAll() .requestMatchers("/actuator/**").permitAll() .anyRequest().authenticated() ) .build(); } - } 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 fe08bd4f..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 @@ -17,6 +17,7 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; +import static net.hostsharing.hsadminng.errors.Validate.validate; import static net.hostsharing.hsadminng.mapper.KeyValueMap.from; @RestController @@ -38,10 +39,14 @@ public class HsOfficeContactController implements HsOfficeContactsApi { public ResponseEntity> getListOfContacts( final String currentSubject, final String assumedRoles, - final String caption) { + final String caption, + final String emailAddress) { context.define(currentSubject, assumedRoles); - final var entities = contactRepo.findContactByOptionalCaptionLike(caption); + 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); return ResponseEntity.ok(resources); 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 f3a88bc0..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 @@ -21,6 +21,16 @@ public interface HsOfficeContactRbacRepository extends Repository findContactByOptionalCaptionLike(String caption); + @Query(value = """ + select c.* from hs_office.contact_rv c + where exists ( + SELECT 1 FROM jsonb_each_text(c.emailAddresses) AS kv(key, value) + WHERE kv.value LIKE :emailAddressRegEx + ) + """, nativeQuery = true) + @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/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java index 3c39c616..02012820 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java @@ -35,10 +35,10 @@ public class HsOfficePersonController implements HsOfficePersonsApi { public ResponseEntity> getListOfPersons( final String currentSubject, final String assumedRoles, - final String caption) { + final String name) { context.define(currentSubject, assumedRoles); - final var entities = personRepo.findPersonByOptionalNameLike(caption); + final var entities = personRepo.findPersonByOptionalNameLike(name); final var resources = mapper.mapList(entities, HsOfficePersonResource.class); return ResponseEntity.ok(resources); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java index 97e7dac0..cf712640 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationController.java @@ -54,6 +54,7 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi { final String assumedRoles, final UUID personUuid, final HsOfficeRelationTypeResource relationType, + final String mark, final String personData, final String contactData) { context.define(currentSubject, assumedRoles); @@ -62,7 +63,7 @@ public class HsOfficeRelationController implements HsOfficeRelationsApi { rbacRelationRepo.findRelationRelatedToPersonUuidRelationTypePersonAndContactData( personUuid, relationType == null ? null : HsOfficeRelationType.valueOf(relationType.name()), - personData, contactData); + mark, personData, contactData); final var resources = mapper.mapList(entities, HsOfficeRelationResource.class, RELATION_ENTITY_TO_RESOURCE_POSTMAPPER); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRbacRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRbacRepository.java index 0443bc00..82e245ae 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRbacRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRbacRepository.java @@ -26,24 +26,29 @@ public interface HsOfficeRelationRbacRepository extends Repository findRelationRelatedToPersonUuidRelationTypePersonAndContactData( + default List findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData( final UUID personUuid, final HsOfficeRelationType relationType, + final String mark, final String personData, final String contactData) { - return findRelationRelatedToPersonUuidRelationTypePersonAndContactDataImpl( - personUuid, toStringOrNull(relationType), toSqlLikeOperand(personData), toSqlLikeOperand(contactData)); + return findRelationRelatedToPersonUuidRelationByTypeMarkPersonAndContactDataImpl( + personUuid, toStringOrNull(relationType), + toSqlLikeOperand(mark), toSqlLikeOperand(personData), toSqlLikeOperand(contactData)); } + // TODO: use ELIKE instead of lower(...) LIKE ...? Or use jsonb_path with RegEx like emailAddressRegEx in ContactRepo? @Query(value = """ SELECT rel FROM HsOfficeRelationRbacEntity AS rel WHERE (:relationType IS NULL OR CAST(rel.type AS String) = :relationType) AND ( :personUuid IS NULL OR rel.anchor.uuid = :personUuid OR rel.holder.uuid = :personUuid ) + AND ( :mark IS NULL OR lower(rel.mark) LIKE :mark ) AND ( :personData IS NULL OR lower(rel.anchor.tradeName) LIKE :personData OR lower(rel.holder.tradeName) LIKE :personData OR lower(rel.anchor.familyName) LIKE :personData OR lower(rel.holder.familyName) LIKE :personData @@ -54,10 +59,11 @@ public interface HsOfficeRelationRbacRepository extends Repository findRelationRelatedToPersonUuidRelationTypePersonAndContactDataImpl( + @Timed("app.office.relations.repo.findRelationRelatedToPersonUuidRelationByTypeMarkPersonAndContactDataImpl.rbac") + List findRelationRelatedToPersonUuidRelationByTypeMarkPersonAndContactDataImpl( final UUID personUuid, final String relationType, + final String mark, final String personData, final String contactData); 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 f7412ddf..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 @@ -7,12 +7,19 @@ get: parameters: - $ref: 'auth.yaml#/components/parameters/currentSubject' - $ref: 'auth.yaml#/components/parameters/assumedRoles' - - name: name + - name: caption in: query required: false schema: type: string - description: Prefix of caption to filter the results. + description: Beginning of caption to filter the results. + - name: emailAddress + in: query + required: false + schema: + type: string + description: + 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-coopassets-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml index a666229d..e84e733c 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml @@ -27,8 +27,6 @@ components: nullable: false membership.memberNumber: type: string - minLength: 9 - maxLength: 9 pattern: 'M-[0-9]{7}' transactionType: $ref: '#/components/schemas/HsOfficeCoopAssetsTransactionType' @@ -69,8 +67,6 @@ components: nullable: false membership.memberNumber: type: string - minLength: 9 - maxLength: 9 pattern: 'M-[0-9]{7}' transactionType: $ref: '#/components/schemas/HsOfficeCoopAssetsTransactionType' @@ -130,8 +126,6 @@ components: format: uuid adoptingMembership.memberNumber: type: string - minLength: 9 - maxLength: 9 pattern: 'M-[0-9]{7}' required: - membership.uuid diff --git a/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml index bca2f0a2..c868a459 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-debitor-schemas.yaml @@ -13,8 +13,6 @@ components: $ref: 'hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation' debitorNumber: type: string - minLength: 9 - maxLength: 9 pattern: 'D-[0-9]{7}' debitorNumberSuffix: type: string diff --git a/src/main/resources/api-definition/hs-office/hs-office-debitors-with-debitorNumber.yaml b/src/main/resources/api-definition/hs-office/hs-office-debitors-with-debitorNumber.yaml index 565f2523..9e34b758 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-debitors-with-debitorNumber.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-debitors-with-debitorNumber.yaml @@ -12,8 +12,8 @@ get: schema: type: number format: integer -# minimum: 1000000 -# maximum: 9999999 + minimum: 1000000 + maximum: 9999999 description: debitor-number of the debitor to fetch. responses: "200": diff --git a/src/main/resources/api-definition/hs-office/hs-office-debitors.yaml b/src/main/resources/api-definition/hs-office/hs-office-debitors.yaml index 05533d03..20ceb02c 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-debitors.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-debitors.yaml @@ -25,8 +25,6 @@ get: required: false schema: type: string - minLength: 7 - maxLength: 7 pattern: 'P-[0-9]{5}' description: Partner number of the requested debitor. responses: diff --git a/src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml index cc723a41..f7263700 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml @@ -27,14 +27,10 @@ components: $ref: 'hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor' memberNumber: type: string - minLength: 9 - maxLength: 9 pattern: 'M-[0-9]{7}' memberNumberSuffix: type: string - minLength: 2 - maxLength: 2 - pattern: '[0-9]+' + pattern: '[0-9]{2}' validFrom: type: string format: date @@ -69,9 +65,7 @@ components: nullable: false memberNumberSuffix: type: string - minLength: 2 - maxLength: 2 - pattern: '[0-9]+' + pattern: '[0-9]{2}' nullable: false validFrom: type: string diff --git a/src/main/resources/api-definition/hs-office/hs-office-memberships.yaml b/src/main/resources/api-definition/hs-office/hs-office-memberships.yaml index f0da7c61..1be0fd23 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-memberships.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-memberships.yaml @@ -20,8 +20,6 @@ get: required: false schema: type: string - minLength: 7 - maxLength: 7 pattern: 'P-[0-9]{5}' description: partnerNumber of the partner the memberships belong to responses: diff --git a/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml index 2fd3d39b..727c5b61 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml @@ -11,8 +11,6 @@ components: format: uuid partnerNumber: type: string - minLength: 7 - maxLength: 7 pattern: 'P-[0-9]{5}' partnerRel: $ref: 'hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelation' @@ -87,8 +85,6 @@ components: properties: partnerNumber: type: string - minLength: 7 - maxLength: 7 pattern: 'P-[0-9]{5}' partnerRel: $ref: '#/components/schemas/HsOfficePartnerRelInsert' 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 70218c00..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,13 @@ 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 + schema: + type: string + description: - name: personData in: query required: false diff --git a/src/test/java/net/hostsharing/hsadminng/config/WebSecurityConfigIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/config/WebSecurityConfigIntegrationTest.java index 8b2bf3a0..a69ca9f4 100644 --- a/src/test/java/net/hostsharing/hsadminng/config/WebSecurityConfigIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/config/WebSecurityConfigIntegrationTest.java @@ -42,6 +42,20 @@ class WebSecurityConfigIntegrationTest { assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); } + @Test + public void shouldSupportSwaggerUi() { + final var result = this.restTemplate.getForEntity( + "http://localhost:" + this.managementPort + "/swagger-ui/index.html", String.class); + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + public void shouldSupportApiDocs() { + final var result = this.restTemplate.getForEntity( + "http://localhost:" + this.managementPort + "/v3/api-docs/swagger-config", String.class); + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); // permitted but not configured + } + @Test public void shouldSupportHealthEndpoint() { final var result = this.restTemplate.getForEntity( 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 b05b6da7..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 @@ -127,7 +127,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC } @Nested - class FindAllContacts { + class FindContacts { @Test public void globalAdmin_withoutAssumedRole_canViewAllContacts() { @@ -184,6 +184,22 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC } } + @Nested + class FindByEmailAddress { + + @Test + public void globalAdmin_withoutAssumedRole_canFindContactsByEmailAddress() { + // given + context("superuser-alex@hostsharing.net", null); + + // when + final var result = contactRepo.findContactByEmailAddress("%@secondcontact.example.com"); + + // then + exactlyTheseContactsAreReturned(result, "second contact"); + } + } + @Nested class DeleteByUuid { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java index 0d937904..39af92bc 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java @@ -306,10 +306,10 @@ public class HsOfficeMembershipControllerRestTest { public enum InvalidMemberSuffixVariants { MISSING("", "[memberNumberSuffix must not be null but is \"null\"]"), - TOO_SMALL("\"memberNumberSuffix\": \"9\",", "memberNumberSuffix size must be between 2 and 2 but is \"9\""), - TOO_LARGE("\"memberNumberSuffix\": \"100\",", "memberNumberSuffix size must be between 2 and 2 but is \"100\""), - NOT_NUMERIC("\"memberNumberSuffix\": \"AA\",", "memberNumberSuffix must match \"[0-9]+\" but is \"AA\""), - EMPTY("\"memberNumberSuffix\": \"\",", "memberNumberSuffix size must be between 2 and 2 but is \"\""); + TOO_SMALL("\"memberNumberSuffix\": \"9\",", "memberNumberSuffix must match \"[0-9]{2}\" but is \"9\""), + TOO_LARGE("\"memberNumberSuffix\": \"100\",", "memberNumberSuffix must match \"[0-9]{2}\" but is \"100\""), + NOT_NUMERIC("\"memberNumberSuffix\": \"AA\",", "memberNumberSuffix must match \"[0-9]{2}\" but is \"AA\""), + EMPTY("\"memberNumberSuffix\": \"\",", "memberNumberSuffix must match \"[0-9]{2}\" but is \"\""); private final String memberNumberSuffixEntry; private final String expectedErrorMessage; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index b2f50977..e55959c7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -193,7 +193,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea .findFirst().orElseThrow(); // when: - final var result = relationRbacRepo.findRelationRelatedToPersonUuidRelationTypePersonAndContactData(person.getUuid(), null, null, null); + final var result = relationRbacRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(person.getUuid(), null, null, null, null); // then: exactlyTheseRelationsAreReturned( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java index 15045cf7..124d3731 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java @@ -32,7 +32,8 @@ import net.hostsharing.hsadminng.hs.office.scenarios.partner.DeletePartner; import net.hostsharing.hsadminng.hs.office.scenarios.partner.ReplaceDeceasedPartnerWithCommunityOfHeirs; import net.hostsharing.hsadminng.hs.office.scenarios.person.ShouldUpdatePersonData; import net.hostsharing.hsadminng.hs.office.scenarios.subscription.RemoveOperationsContactFromPartner; -import net.hostsharing.hsadminng.hs.office.scenarios.subscription.SubscribeToMailinglist; +import net.hostsharing.hsadminng.hs.office.scenarios.subscription.SubscribeExistingPersonAndContactToMailinglist; +import net.hostsharing.hsadminng.hs.office.scenarios.subscription.SubscribeNewPersonAndContactToMailinglist; import net.hostsharing.hsadminng.hs.office.scenarios.subscription.UnsubscribeFromMailinglist; import net.hostsharing.hsadminng.hs.scenarios.Produces; import net.hostsharing.hsadminng.hs.scenarios.Requires; @@ -570,7 +571,7 @@ class HsOfficeScenarioTests extends ScenarioTest { @Requires("Person: Test AG") @Produces("Subscription: Michael Miller to operations-announce") void shouldSubscribeNewPersonAndContactToMailinglist() { - new SubscribeToMailinglist(scenarioTest) + new SubscribeNewPersonAndContactToMailinglist(scenarioTest) // TODO.spec: do we need the personType? or is an operational contact always a natural person? what about distribution lists? .given("partnerPersonTradeName", "Test AG") .given("subscriberFamilyName", "Miller") @@ -584,7 +585,22 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(5001) @Requires("Subscription: Michael Miller to operations-announce") - void shouldUnsubscribeNewPersonAndContactToMailinglist() { + @Produces("Subscription: Michael Miller to operations-discussion") + void shouldSubscribeExistingPersonAndContactToMailinglist() { + new SubscribeExistingPersonAndContactToMailinglist(scenarioTest) + .given("partnerPersonTradeName", "Test AG") + .given("subscriberFamilyName", "Miller") + .given("subscriberGivenName", "Michael") + .given("subscriberEMailAddress", "michael.miller@example.org") + .given("mailingList", "operations-discussion") + .doRun() + .keep(); + } + + @Test + @Order(5002) + @Requires("Subscription: Michael Miller to operations-announce") + void shouldUnsubscribePersonAndContactFromMailinglist() { new UnsubscribeFromMailinglist(scenarioTest) .given("mailingList", "operations-announce") .given("subscriberEMailAddress", "michael.miller@example.org") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeExistingPersonAndContactToMailinglist.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeExistingPersonAndContactToMailinglist.java new file mode 100644 index 00000000..f018c454 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeExistingPersonAndContactToMailinglist.java @@ -0,0 +1,54 @@ +package net.hostsharing.hsadminng.hs.office.scenarios.subscription; + +import io.restassured.http.ContentType; +import net.hostsharing.hsadminng.hs.scenarios.ScenarioTest; +import net.hostsharing.hsadminng.hs.scenarios.UseCase; +import org.springframework.http.HttpStatus; + +import static io.restassured.http.ContentType.JSON; +import static org.springframework.http.HttpStatus.CREATED; +import static org.springframework.http.HttpStatus.OK; + +public class SubscribeExistingPersonAndContactToMailinglist extends UseCase { + + public SubscribeExistingPersonAndContactToMailinglist(final ScenarioTest testSuite) { + super(testSuite); + } + + @Override + protected HttpResponse run() { + + obtain("Person: %{partnerPersonTradeName}", () -> + httpGet("/api/hs/office/persons?name=" + uriEncoded("%{partnerPersonTradeName}")) + .expecting(OK).expecting(JSON), + response -> response.expectArrayElements(1).getFromBody("[0].uuid"), + "In production, data this query could result in multiple outputs. In that case, you have to find out which is the right one." + ); + + obtain( + "Person: %{subscriberGivenName} %{subscriberFamilyName}", () -> + httpGet("/api/hs/office/persons?name=%{subscriberFamilyName}") + .expecting(HttpStatus.OK).expecting(ContentType.JSON), + response -> response.expectArrayElements(1).getFromBody("[0].uuid"), + "In real scenarios there are most likely multiple results and you have to choose the right one." + ); + + obtain("Contact: %{subscriberEMailAddress}", () -> + httpGet("/api/hs/office/contacts?emailAddress=%{subscriberEMailAddress}") + .expecting(HttpStatus.OK).expecting(ContentType.JSON), + response -> response.expectArrayElements(1).getFromBody("[0].uuid"), + "In real scenarios there are most likely multiple results and you have to choose the right one." + ); + + return httpPost("/api/hs/office/relations", usingJsonBody(""" + { + "type": "SUBSCRIBER", + "mark": ${mailingList}, + "anchor.uuid": ${Person: %{partnerPersonTradeName}}, + "holder.uuid": ${Person: %{subscriberGivenName} %{subscriberFamilyName}}, + "contact.uuid": ${Contact: %{subscriberEMailAddress}} + } + """)) + .expecting(CREATED).expecting(JSON); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeNewPersonAndContactToMailinglist.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeNewPersonAndContactToMailinglist.java new file mode 100644 index 00000000..5638e440 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeNewPersonAndContactToMailinglist.java @@ -0,0 +1,46 @@ +package net.hostsharing.hsadminng.hs.office.scenarios.subscription; + +import net.hostsharing.hsadminng.hs.scenarios.UseCase; +import net.hostsharing.hsadminng.hs.scenarios.ScenarioTest; + +import static io.restassured.http.ContentType.JSON; +import static org.springframework.http.HttpStatus.CREATED; +import static org.springframework.http.HttpStatus.OK; + +public class SubscribeNewPersonAndContactToMailinglist extends UseCase { + + public SubscribeNewPersonAndContactToMailinglist(final ScenarioTest testSuite) { + super(testSuite); + } + + @Override + protected HttpResponse run() { + + obtain("Person: %{partnerPersonTradeName}", () -> + httpGet("/api/hs/office/persons?name=" + uriEncoded("%{partnerPersonTradeName}")) + .expecting(OK).expecting(JSON), + response -> response.expectArrayElements(1).getFromBody("[0].uuid"), + "In production, data this query could result in multiple outputs. In that case, you have to find out which is the right one." + ); + + return httpPost("/api/hs/office/relations", usingJsonBody(""" + { + "type": "SUBSCRIBER", + "mark": ${mailingList}, + "anchor.uuid": ${Person: %{partnerPersonTradeName}}, + "holder": { + "personType": "NATURAL_PERSON", + "familyName": ${subscriberFamilyName}, + "givenName": ${subscriberGivenName} + }, + "contact": { + "caption": "%{subscriberGivenName} %{subscriberFamilyName}", + "emailAddresses": { + "main": ${subscriberEMailAddress} + } + } + } + """)) + .expecting(CREATED).expecting(JSON); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeToMailinglist.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeToMailinglist.java deleted file mode 100644 index c524fb18..00000000 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/subscription/SubscribeToMailinglist.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.hostsharing.hsadminng.hs.office.scenarios.subscription; - -import io.restassured.http.ContentType; -import net.hostsharing.hsadminng.hs.scenarios.UseCase; -import net.hostsharing.hsadminng.hs.scenarios.ScenarioTest; -import org.springframework.http.HttpStatus; - -import static io.restassured.http.ContentType.JSON; -import static org.springframework.http.HttpStatus.CREATED; -import static org.springframework.http.HttpStatus.OK; - -public class SubscribeToMailinglist extends UseCase { - - public SubscribeToMailinglist(final ScenarioTest testSuite) { - super(testSuite); - } - - @Override - protected HttpResponse run() { - - obtain("Person: %{partnerPersonTradeName}", () -> - httpGet("/api/hs/office/persons?name=" + uriEncoded("%{partnerPersonTradeName}")) - .expecting(OK).expecting(JSON), - response -> response.expectArrayElements(1).getFromBody("[0].uuid"), - "In production, data this query could result in multiple outputs. In that case, you have to find out which is the right one." - ); - - obtain("Person: %{subscriberGivenName} %{subscriberFamilyName}", () -> - httpPost("/api/hs/office/persons", usingJsonBody(""" - { - "personType": "NATURAL_PERSON", - "familyName": ${subscriberFamilyName}, - "givenName": ${subscriberGivenName} - } - """)) - .expecting(HttpStatus.CREATED).expecting(ContentType.JSON) - ); - - obtain("Contact: %{subscriberGivenName} %{subscriberFamilyName}", () -> - httpPost("/api/hs/office/contacts", usingJsonBody(""" - { - "caption": "%{subscriberGivenName} %{subscriberFamilyName}", - "emailAddresses": { - "main": ${subscriberEMailAddress} - } - } - """)) - .expecting(CREATED).expecting(JSON) - ); - - return httpPost("/api/hs/office/relations", usingJsonBody(""" - { - "type": "SUBSCRIBER", - "mark": ${mailingList}, - "anchor.uuid": ${Person: %{partnerPersonTradeName}}, - "holder.uuid": ${Person: %{subscriberGivenName} %{subscriberFamilyName}}, - "contact.uuid": ${Contact: %{subscriberGivenName} %{subscriberFamilyName}} - } - """)) - .expecting(CREATED).expecting(JSON); - } -}