diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java index 95f1845c..a31d785f 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java @@ -98,8 +98,18 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { @Override @Transactional - public ResponseEntity deletePartnerByUuid(final String currentUser, final String assumedRoles, final UUID userUuid) { - return null; + public ResponseEntity deletePartnerByUuid( + final String currentUser, + final String assumedRoles, + final UUID partnerUuid) { + context.define(currentUser, assumedRoles); + + final var result = partnerRepo.deleteByUuid(partnerUuid); + if (result == 0) { + return ResponseEntity.notFound().build(); + } + + return ResponseEntity.noContent().build(); } @Override diff --git a/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml b/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml index 757f97f7..63562bb2 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml @@ -12,6 +12,7 @@ get: schema: type: string format: uuid + description: UUID of the partner to fetch. responses: "200": description: OK @@ -55,21 +56,21 @@ patch: "403": $ref: './error-responses.yaml#/components/responses/Forbidden' - delete: tags: - hs-office-partners + description: 'Delete a single business partner by its uuid, if permitted for the current subject.' operationId: deletePartnerByUuid parameters: - $ref: './auth.yaml#/components/parameters/currentUser' - $ref: './auth.yaml#/components/parameters/assumedRoles' - - name: userUuid + - name: partnerUUID in: path required: true schema: type: string format: uuid - description: UUID of the user to delete. + description: UUID of the partner to delete. responses: "204": description: No Content diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java index a3765394..892d7b0b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java @@ -24,6 +24,7 @@ import java.util.UUID; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assumptions.assumeThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; @@ -267,11 +268,89 @@ class HsOfficePartnerControllerAcceptanceTest { } } + @Nested + @Accepts({ "Partner:D(Delete)" }) + class DeletePartner { + + @Test + void globalAdmin_withoutAssumedRole_canDeleteArbitraryPartner() { + context.define("superuser-alex@hostsharing.net"); + final var givenPartner = givenSomeTemporaryPartnerBessler(); + + RestAssured // @formatter:off + .given() + .header("current-user", "superuser-alex@hostsharing.net") + .port(port) + .when() + .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .then().log().body().assertThat() + .statusCode(204); // @formatter:on + + // then the given partner is gone + assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isEmpty(); + } + + @Test + @Accepts({ "Partner:X(Access Control)" }) + void contactAdminUser_canNotDeleteRelatedPartner() { + context.define("superuser-alex@hostsharing.net"); + final var givenPartner = givenSomeTemporaryPartnerBessler(); + assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact"); + + RestAssured // @formatter:off + .given() + .header("current-user", "customer-admin@forthcontact.example.com") + .port(port) + .when() + .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .then().log().body().assertThat() + .statusCode(403); // @formatter:on + + // then the given partner is still there + assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isNotEmpty(); + } + + @Test + @Accepts({ "Partner:X(Access Control)" }) + void normalUser_canNotDeleteUnrelatedPartner() { + context.define("superuser-alex@hostsharing.net"); + final var givenPartner = givenSomeTemporaryPartnerBessler(); + assumeThat(givenPartner.getContact().getLabel()).isEqualTo("forth contact"); + + RestAssured // @formatter:off + .given() + .header("current-user", "selfregistered-user-drew@hostsharing.org") + .port(port) + .when() + .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .then().log().body().assertThat() + .statusCode(404); // @formatter:on + + // then the given partner is still there + assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isNotEmpty(); + } + } + private UUID toCleanup(final UUID tempPartnerUuid) { tempPartnerUuids.add(tempPartnerUuid); return tempPartnerUuid; } + private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler() { + return jpaAttempt.transacted(() -> { + context.define("superuser-alex@hostsharing.net"); + final var givenPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); + final var givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0); + final var newPartner = HsOfficePartnerEntity.builder() + .uuid(UUID.randomUUID()) + .person(givenPerson) + .contact(givenContact) + .build(); + + return partnerRepo.save(newPartner); + }).assertSuccessful().returnedValue(); + } + @AfterEach void cleanup() { tempPartnerUuids.forEach(uuid -> { @@ -279,7 +358,7 @@ class HsOfficePartnerControllerAcceptanceTest { context.define("superuser-alex@hostsharing.net", null); System.out.println("DELETING temporary partner: " + uuid); final var count = partnerRepo.deleteByUuid(uuid); - assertThat(count).isGreaterThan(0); + System.out.println("DELETED temporary partner: " + uuid + (count > 0 ? " successful" : " failed")); }); }); }