From c77039b2168d80f0d2a132519cc6f8f6ebd457ee Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Tue, 2 May 2023 11:08:24 +0200 Subject: [PATCH] Fixed some tests and removed the visibility setting as it is not needed anymore --- .../dbrepo-realm.json | 60 ++-- .../tuwien/endpoints/IdentifierEndpoint.java | 11 +- .../tuwien/endpoints/PersistenceEndpoint.java | 16 +- .../endpoint/IdentifierEndpointUnitTest.java | 97 +----- .../endpoint/PersistenceEndpointUnitTest.java | 294 ++++++++++++++---- .../service/IdentifierServiceUnitTest.java | 27 +- .../src/test/resources/json/metadata0.json | 1 - .../src/test/resources/json/metadata1.json | 1 - .../service/impl/IdentifierServiceImpl.java | 8 +- .../tuwien/api/identifier/IdentifierDto.java | 4 - .../api/identifier/VisibilityTypeDto.java | 29 -- .../entities/identifier/Identifier.java | 5 - .../entities/identifier/VisibilityType.java | 12 - dbrepo-metadata-db/setup-schema.sql | 1 - .../main/java/at/tuwien/test/BaseTest.java | 23 +- 15 files changed, 298 insertions(+), 291 deletions(-) delete mode 100644 dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/VisibilityTypeDto.java delete mode 100644 dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/VisibilityType.java diff --git a/dbrepo-authentication-service/dbrepo-realm.json b/dbrepo-authentication-service/dbrepo-realm.json index a1171d6bf0..64c5e7a690 100644 --- a/dbrepo-authentication-service/dbrepo-realm.json +++ b/dbrepo-authentication-service/dbrepo-realm.json @@ -249,6 +249,14 @@ "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", "attributes" : { } + }, { + "id" : "36e87bdb-ed4c-47a4-a22a-871bc9728061", + "name" : "update-foreign-identifier", + "description" : "${update-foreign-identifier}", + "composite" : false, + "clientRole" : false, + "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", + "attributes" : { } }, { "id" : "e14ab76b-1c24-484d-ae2d-478b8457edea", "name" : "list-licenses", @@ -349,7 +357,7 @@ "description" : "${escalated-identifier-handling}", "composite" : true, "composites" : { - "realm" : [ "delete-identifier", "create-foreign-identifier", "modify-identifier-metadata" ] + "realm" : [ "update-foreign-identifier", "delete-identifier", "create-foreign-identifier", "modify-identifier-metadata" ] }, "clientRole" : false, "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0", @@ -908,7 +916,7 @@ "otpPolicyLookAheadWindow" : 1, "otpPolicyPeriod" : 30, "otpPolicyCodeReusable" : false, - "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName", "totpAppFreeOTPName" ], "webAuthnPolicyRpEntityName" : "keycloak", "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], "webAuthnPolicyRpId" : "", @@ -1898,7 +1906,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper" ] } }, { "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979", @@ -1907,7 +1915,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper" ] } } ], "org.keycloak.keys.KeyProvider" : [ { @@ -1959,7 +1967,7 @@ "internationalizationEnabled" : false, "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "76e548b4-1eab-41b5-9980-34d95e193a54", + "id" : "249e062c-149c-41d8-8edc-fff83c7fc496", "alias" : "Account verification options", "description" : "Method with which to verity the existing account", "providerId" : "basic-flow", @@ -1981,7 +1989,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "d77e95ec-b316-4edd-ab32-b2e28e6654fb", + "id" : "ff69ba5a-e5a4-4afd-b328-0e7e4775f6b3", "alias" : "Authentication Options", "description" : "Authentication options.", "providerId" : "basic-flow", @@ -2010,7 +2018,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "70249f64-bac3-4792-9bd3-87ed99c3e21c", + "id" : "6e865e2b-608e-48fb-b743-98df28be1a86", "alias" : "Browser - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2032,7 +2040,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "64571c59-51eb-4d5f-9c7d-fa70460d52b1", + "id" : "c92e182c-7dc1-4ed6-b9e5-42a47740db06", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2054,7 +2062,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "397d32d5-5d22-4d18-9c09-f5642ed68d83", + "id" : "635e2eb2-8392-44ca-b3fe-76e7c7e7abb5", "alias" : "First broker login - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -2076,7 +2084,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "eab19975-c52a-449d-99a1-284f850e0853", + "id" : "852b7951-4abc-4497-ada6-33d73e99b0b5", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -2098,7 +2106,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "e829aa33-e7d9-41fd-97c0-cdf178f6e055", + "id" : "ee064caa-6fb5-404e-ae05-6b0c36c7834c", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -2120,7 +2128,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "e39097e1-653c-4bf0-8f1f-1513eb3da432", + "id" : "47769628-1cc9-49ab-bf34-79dc30ce9825", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -2143,7 +2151,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "7acd4e52-1c6d-43a0-bcba-c0cbccd7ef34", + "id" : "687f20f9-c783-4876-a621-3260377fca2b", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -2165,7 +2173,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "4569b4fd-6b88-42f0-9f47-f7d95cb36b0d", + "id" : "fd498e51-65ce-4049-84c7-e77da549d480", "alias" : "browser", "description" : "browser based authentication", "providerId" : "basic-flow", @@ -2201,7 +2209,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "ceb5f811-8b55-47e6-8475-978ce5ae2572", + "id" : "d1809c1f-9ccd-424d-9838-27cffa9db66b", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -2237,7 +2245,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "d53784bc-facd-4261-a283-d76dece59feb", + "id" : "8c240fe9-e58f-48b7-a158-6e0e6a9d67a6", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -2266,7 +2274,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "db59555a-b8b5-4af9-81d5-e235131f81b6", + "id" : "35c71a49-4597-4658-bbbd-fd0d54714a40", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -2281,7 +2289,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "a69ee61f-db83-43e9-adb6-9644841e1702", + "id" : "bf40550f-d32e-44ff-8f58-90029ac0d27f", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -2304,7 +2312,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "974f47f5-fefb-4561-ab5d-08836d9d8ef2", + "id" : "131b7668-84aa-411a-8653-a572de9f1dc2", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -2326,7 +2334,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "68b01c05-9928-4752-82fd-0f5474090a48", + "id" : "7ba29293-f649-4078-84de-74a19510797c", "alias" : "http challenge", "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", "providerId" : "basic-flow", @@ -2348,7 +2356,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "ae8b1165-bad6-4b1c-8c72-a987263ed955", + "id" : "71a1fd3b-1b01-4a8c-b05b-6268b2cc9224", "alias" : "registration", "description" : "registration flow", "providerId" : "basic-flow", @@ -2364,7 +2372,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "11d691cd-d529-4b45-97ca-de065d189c76", + "id" : "5e4a99ff-5621-467f-902a-59efede6ef12", "alias" : "registration form", "description" : "registration form", "providerId" : "form-flow", @@ -2400,7 +2408,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "8e0a9ab1-45bf-401b-b67d-b303e7a6c667", + "id" : "3450e93e-3fd5-4eb3-9ae6-fac13f8129d5", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -2436,7 +2444,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "786a56e6-d5e5-4609-9dc1-712acafb7380", + "id" : "27b5c4c4-76e7-49ea-951a-bfdf357886bc", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -2452,13 +2460,13 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "f82d7f9e-a21b-4a71-8c9c-908491ce2ca5", + "id" : "71966a64-76a7-4e1a-b9c7-5f1fbd45e8d0", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "6706f2cc-33ab-43b1-b1cd-1fd6caafc464", + "id" : "1068a85d-838b-47d8-9ca2-4545a7e464a4", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" diff --git a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index 8058288729..2a05154f3e 100644 --- a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -145,10 +145,13 @@ public class IdentifierEndpoint { throw new IdentifierRequestException("Identifier of type database must not have a qid present"); } final User user = userService.findByUsername(principal.getName()); - final DatabaseAccess access = accessService.find(data.getDbid(), user.getId()); - if (!User.hasRole(principal, "create-foreign-identifier") && access.getType().equals(AccessType.READ)) { - log.error("Failed to create identifier: insufficient access"); - throw new NotAllowedException("Failed to create identifier: insufficient access"); + try { + accessService.find(data.getDbid(), user.getId()); + } catch (AccessDeniedException e) { + if (!User.hasRole(principal, "create-foreign-identifier")) { + log.error("Failed to create identifier: insufficient access"); + throw new NotAllowedException("Failed to create identifier: insufficient access"); + } } final Identifier identifier = identifierService.create(data, principal, authorization); return ResponseEntity.status(HttpStatus.CREATED) diff --git a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java index c25aa430ce..46660e5664 100644 --- a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java +++ b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java @@ -153,7 +153,7 @@ public class PersistenceEndpoint { @PutMapping("/{id}") @Transactional @Timed(value = "identifier.update", description = "Time needed to update an identifier") - @PreAuthorize("hasAuthority('update-identifier') or hasAuthority('create-foreign-identifier')") + @PreAuthorize("hasAuthority('update-identifier') or hasAuthority('update-foreign-identifier')") @Operation(summary = "Update some identifier", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -185,15 +185,17 @@ public class PersistenceEndpoint { public ResponseEntity<IdentifierDto> update(@NotNull @PathVariable("id") Long id, @NotNull @Valid @RequestBody IdentifierDto data, @NotNull Principal principal) - throws IdentifierNotFoundException, IdentifierRequestException, UserNotFoundException, NotAllowedException, - AccessDeniedException { + throws IdentifierNotFoundException, IdentifierRequestException, UserNotFoundException, NotAllowedException { log.debug("endpoint update identifier, id={}, data={}", id, data); final Identifier identifier = identifierService.find(id); final User user = userService.findByUsername(principal.getName()); - final DatabaseAccess access = accessService.find(identifier.getDatabaseId(), user.getId()); - if (!User.hasRole(principal, "create-foreign-identifier") && access.getType().equals(AccessType.READ)) { - log.error("Failed to create identifier: insufficient access"); - throw new NotAllowedException("Failed to create identifier: insufficient access"); + try { + accessService.find(identifier.getDatabaseId(), user.getId()); + } catch (AccessDeniedException e) { + if (!User.hasRole(principal, "update-foreign-identifier")) { + log.error("Failed to update identifier: insufficient access"); + throw new NotAllowedException("Failed to update identifier: insufficient access"); + } } final IdentifierDto dto = identifierMapper.identifierToIdentifierDto(identifierService.update(id, data)); log.debug("update identifier resulted in dto={}", dto); diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointUnitTest.java index 0d1f7ce1cc..6a9964bfe0 100644 --- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointUnitTest.java +++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointUnitTest.java @@ -40,7 +40,6 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @ExtendWith(SpringExtension.class) @@ -156,7 +155,7 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) public void create_hasRoleDatabase_succeeds() throws IdentifierAlreadyExistsException, UserNotFoundException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - IdentifierPublishingNotAllowedException, IdentifierRequestException, at.tuwien.exception.AccessDeniedException { + IdentifierPublishingNotAllowedException, IdentifierRequestException, at.tuwien.exception.AccessDeniedException, NotAllowedException { /* mock */ when(accessRepository.findByHdbidAndHuserid(DATABASE_1_ID, USER_1_ID)) @@ -171,7 +170,7 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { public void create_hasRoleDatabaseNoAccess_fails() { /* test */ - assertThrows(at.tuwien.exception.AccessDeniedException.class, () -> { + assertThrows(NotAllowedException.class, () -> { generic_create(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, IDENTIFIER_1_DTO_REQUEST, IDENTIFIER_1, USER_2_PRINCIPAL, USER_2_USERNAME, USER_2); }); } @@ -190,7 +189,7 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_2_USERNAME, authorities = {"create-identifier"}) public void create_hasRoleReadAccessQuery_succeeds() throws IdentifierAlreadyExistsException, UserNotFoundException, QueryNotFoundException, DatabaseNotFoundException, RemoteUnavailableException, - IdentifierPublishingNotAllowedException, IdentifierRequestException, at.tuwien.exception.AccessDeniedException { + IdentifierPublishingNotAllowedException, IdentifierRequestException, at.tuwien.exception.AccessDeniedException, NotAllowedException { /* mock */ when(accessRepository.findByHdbidAndHuserid(DATABASE_2_ID, USER_2_ID)) @@ -249,62 +248,14 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void create_query_fails() { + public void create_queryForeign_fails() { /* test */ - assertThrows(at.tuwien.exception.AccessDeniedException.class, () -> { + assertThrows(NotAllowedException.class, () -> { generic_create(CONTAINER_2_ID, DATABASE_2_ID, DATABASE_2, IDENTIFIER_2_DTO_REQUEST, IDENTIFIER_2, USER_1_PRINCIPAL, USER_1_USERNAME, USER_1); }); } - @Test - public void update_anonymous_fails() { - - /* test */ - assertThrows(AuthenticationCredentialsNotFoundException.class, this::generic_update); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {}) - public void update_noRole_fails() { - - /* test */ - assertThrows(AccessDeniedException.class, this::generic_update); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"update-identifier"}) - public void update_hasRole_succeeds() throws IdentifierPublishingNotAllowedException, - IdentifierNotFoundException, IdentifierRequestException { - - /* test */ - generic_update(); - } - - @Test - @WithAnonymousUser - public void delete_anonymous_fails() { - - /* test */ - assertThrows(AccessDeniedException.class, this::generic_delete); - } - - @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {}) - public void delete_noRole_fails() { - - /* test */ - assertThrows(AccessDeniedException.class, this::generic_delete); - } - - @Test - @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-identifier"}) - public void delete_hasRole_succeeds() throws NotAllowedException, IdentifierNotFoundException { - - /* test */ - this.generic_delete(); - } - /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -314,7 +265,7 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { throws QueryNotFoundException, RemoteUnavailableException, IdentifierAlreadyExistsException, UserNotFoundException, DatabaseNotFoundException, IdentifierPublishingNotAllowedException, - IdentifierRequestException, at.tuwien.exception.AccessDeniedException { + IdentifierRequestException, at.tuwien.exception.AccessDeniedException, NotAllowedException { /* mock */ when(databaseRepository.findById(databaseId)) @@ -368,40 +319,4 @@ public class IdentifierEndpointUnitTest extends BaseUnitTest { return persistenceEndpoint.find(IDENTIFIER_1_ID, accept); } - protected void generic_update() - throws IdentifierPublishingNotAllowedException, IdentifierNotFoundException, IdentifierRequestException { - - /* mock */ - when(identifierService.update(IDENTIFIER_3_ID, IDENTIFIER_3_DTO)) - .thenReturn(IDENTIFIER_3); - when(identifierRepository.save(IDENTIFIER_3)) - .thenReturn(IDENTIFIER_3); - - /* test */ - final ResponseEntity<IdentifierDto> response = identifierEndpoint.update(IDENTIFIER_3_ID, IDENTIFIER_3_DTO); - assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); - final IdentifierDto body = response.getBody(); - assertNotNull(body); - assertEquals(IDENTIFIER_3_ID, body.getId()); - assertEquals(IDENTIFIER_3_TITLE, body.getTitle()); - assertEquals(IDENTIFIER_3_DESCRIPTION, body.getDescription()); - assertEquals(IDENTIFIER_3_QUERY, body.getQuery()); - assertEquals(IDENTIFIER_3_QUERY_HASH, body.getQueryHash()); - assertEquals(IDENTIFIER_3_RESULT_NUMBER, body.getResultNumber()); - assertEquals(IDENTIFIER_3_RESULT_HASH, body.getResultHash()); - } - - protected void generic_delete() throws IdentifierNotFoundException, NotAllowedException { - - /* mock */ - doNothing() - .when(identifierService) - .delete(IDENTIFIER_1_ID); - - /* test */ - final ResponseEntity<?> response = identifierEndpoint.delete(IDENTIFIER_1_ID); - assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); - assertNull(response.getBody()); - } - } diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java index 0fe8adf13f..d5121f9a49 100644 --- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java +++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java @@ -1,20 +1,20 @@ package at.tuwien.endpoint; import at.tuwien.BaseUnitTest; +import at.tuwien.api.identifier.BibliographyTypeDto; import at.tuwien.api.identifier.CreatorDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.config.IndexInitializer; import at.tuwien.config.ReadyConfig; import at.tuwien.endpoints.PersistenceEndpoint; -import at.tuwien.entities.identifier.Creator; -import at.tuwien.exception.IdentifierNotFoundException; -import at.tuwien.exception.IdentifierRequestException; -import at.tuwien.exception.QueryNotFoundException; -import at.tuwien.exception.RemoteUnavailableException; +import at.tuwien.entities.identifier.Identifier; +import at.tuwien.entities.user.User; +import at.tuwien.exception.*; import at.tuwien.gateway.QueryServiceGateway; import at.tuwien.repository.jpa.IdentifierRepository; -import at.tuwien.repository.jpa.RealmRepository; -import com.fasterxml.jackson.core.JsonProcessingException; +import at.tuwien.service.AccessService; +import at.tuwien.service.IdentifierService; +import at.tuwien.service.UserService; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @@ -30,27 +30,24 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.core.io.InputStreamResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.test.context.support.WithAnonymousUser; +import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.web.client.RestTemplate; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.StringWriter; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Date; -import java.util.List; +import java.security.Principal; import java.util.Optional; import java.util.TimeZone; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @SpringBootTest @@ -63,10 +60,13 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { private IndexInitializer indexInitializer; @MockBean - private IdentifierRepository identifierRepository; + private AccessService accessService; @MockBean - private QueryServiceGateway queryServiceGateway; + private IdentifierService identifierService; + + @MockBean + private UserService userService; @Autowired private ObjectMapper objectMapper; @@ -87,14 +87,15 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_json0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "application/json"; final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata0.json"), StandardCharsets.UTF_8), IdentifierDto.class); /* mock */ - when(identifierRepository.findById(IDENTIFIER_4_ID)) - .thenReturn(Optional.of(IDENTIFIER_4)); + when(identifierService.find(IDENTIFIER_4_ID)) + .thenReturn(IDENTIFIER_4); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_4_ID, accept); @@ -118,14 +119,15 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_json1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "application/json"; final IdentifierDto compare = objectMapper.readValue(FileUtils.readFileToString(new File("src/test/resources/json/metadata1.json"), StandardCharsets.UTF_8), IdentifierDto.class); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -154,17 +156,18 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_csv_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/csv"; - final byte[] stream = FileUtils.readFileToByteArray(new File("src/test/resources/csv/keyboard.csv")); final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv"))); + final InputStreamResource mock = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/csv/keyboard.csv"))); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); - when(queryServiceGateway.export(CONTAINER_1_ID, DATABASE_1_ID, QUERY_1_ID)) - .thenReturn(stream); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + when(identifierService.exportResource(IDENTIFIER_1_ID)) + .thenReturn(mock); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -175,15 +178,15 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test - @Disabled + @Disabled("not testable with xml") public void find_xml0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/xml"; final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata0.xml"))); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -194,15 +197,15 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test - @Disabled + @Disabled("not testable with xml") public void find_xml1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/xml"; final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata1.xml"))); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -214,6 +217,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliography_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography"; @@ -221,8 +225,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -233,6 +239,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyApa0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=apa"; @@ -240,8 +247,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_4_ID)) - .thenReturn(Optional.of(IDENTIFIER_4)); + when(identifierService.exportBibliography(IDENTIFIER_4_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_4_ID)) + .thenReturn(IDENTIFIER_4); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_4_ID, accept); @@ -252,6 +261,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyApa1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=apa"; @@ -259,8 +269,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -271,6 +283,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyApa2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=apa"; @@ -278,8 +291,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_2_ID)) - .thenReturn(Optional.of(IDENTIFIER_2)); + when(identifierService.exportBibliography(IDENTIFIER_2_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_2_ID)) + .thenReturn(IDENTIFIER_2); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_2_ID, accept); @@ -290,6 +305,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyApa3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=apa"; @@ -297,8 +313,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_3_ID)) - .thenReturn(Optional.of(IDENTIFIER_3)); + when(identifierService.exportBibliography(IDENTIFIER_3_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_3_ID)) + .thenReturn(IDENTIFIER_3); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_3_ID, accept); @@ -309,6 +327,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyApa4_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=apa"; @@ -316,8 +335,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1_WITH_DOI)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.APA)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1_WITH_DOI); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -328,6 +349,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyIeee0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=ieee"; @@ -335,8 +357,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_4_ID)) - .thenReturn(Optional.of(IDENTIFIER_4)); + when(identifierService.exportBibliography(IDENTIFIER_4_ID, BibliographyTypeDto.IEEE)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_4_ID)) + .thenReturn(IDENTIFIER_4); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_4_ID, accept); @@ -347,6 +371,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyIeee1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=ieee"; @@ -354,8 +379,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.IEEE)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -366,6 +393,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyIeee2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=ieee"; @@ -373,8 +401,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_2_ID)) - .thenReturn(Optional.of(IDENTIFIER_2)); + when(identifierService.exportBibliography(IDENTIFIER_2_ID, BibliographyTypeDto.IEEE)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_2_ID)) + .thenReturn(IDENTIFIER_2); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_2_ID, accept); @@ -385,6 +415,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyIeee3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=ieee"; @@ -392,8 +423,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1_WITH_DOI)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.IEEE)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1_WITH_DOI); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -404,6 +437,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyBibtex0_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=bibtex"; @@ -411,8 +445,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_4_ID)) - .thenReturn(Optional.of(IDENTIFIER_4)); + when(identifierService.exportBibliography(IDENTIFIER_4_ID, BibliographyTypeDto.BIBTEX)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_4_ID)) + .thenReturn(IDENTIFIER_4); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_4_ID, accept); @@ -423,6 +459,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyBibtex1_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=bibtex"; @@ -430,8 +467,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.BIBTEX)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -442,6 +481,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyBibtex2_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=bibtex"; @@ -449,8 +489,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_2_ID)) - .thenReturn(Optional.of(IDENTIFIER_2)); + when(identifierService.exportBibliography(IDENTIFIER_2_ID, BibliographyTypeDto.BIBTEX)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_2_ID)) + .thenReturn(IDENTIFIER_2); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_2_ID, accept); @@ -461,6 +503,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { } @Test + @WithAnonymousUser public void find_bibliographyBibtex3_succeeds() throws IdentifierNotFoundException, QueryNotFoundException, RemoteUnavailableException, IdentifierRequestException, IOException { final String accept = "text/bibliography; style=bibtex"; @@ -468,8 +511,10 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { StandardCharsets.UTF_8); /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(IDENTIFIER_1_WITH_DOI)); + when(identifierService.exportBibliography(IDENTIFIER_1_ID, BibliographyTypeDto.BIBTEX)) + .thenReturn(compare); + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1_WITH_DOI); /* test */ final ResponseEntity<?> response = persistenceEndpoint.find(IDENTIFIER_1_ID, accept); @@ -479,8 +524,135 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest { assertEquals(compare, body); } + @Test + @WithAnonymousUser + public void update_anonymous_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, null, null, null); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {}) + public void update_noRole_fails() { + + /* test */ + assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_3_USERNAME, authorities = {"update-identifier"}) + public void update_hasRoleNoAccess_succeeds() throws at.tuwien.exception.AccessDeniedException { + + /* mock */ + doThrow(at.tuwien.exception.AccessDeniedException.class) + .when(accessService) + .find(IDENTIFIER_3_DATABASE_ID, USER_3_ID); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_3_USERNAME, authorities = {"update-identifier"}) + public void update_hasRoleHasAccess_succeeds() throws IdentifierNotFoundException, IdentifierRequestException, + UserNotFoundException, at.tuwien.exception.AccessDeniedException, NotAllowedException { + + /* mock */ + when(accessService.find(IDENTIFIER_3_DATABASE_ID, USER_3_ID)) + .thenReturn(DATABASE_3_DATA_STEWARD_READ_ACCESS); + + /* test */ + generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL); + } + + @Test + @WithAnonymousUser + public void delete_anonymous_fails() { + + /* test */ + assertThrows(org.springframework.security.access.AccessDeniedException.class, this::generic_delete); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {}) + public void delete_noRole_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, this::generic_delete); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-identifier"}) + public void delete_hasRole_succeeds() throws NotAllowedException, IdentifierNotFoundException { + + /* test */ + this.generic_delete(); + } + + /* ################################################################################################### */ + /* ## GENERIC TEST CASES ## */ + /* ################################################################################################### */ + protected static String inputStreamToString(InputStream inputStream) throws IOException { return IOUtils.toString(inputStream, StandardCharsets.UTF_8); } + protected void generic_update(Long id, Identifier identifier, IdentifierDto data, String username, User user, + Principal principal) throws IdentifierNotFoundException, IdentifierRequestException, + UserNotFoundException, at.tuwien.exception.AccessDeniedException, NotAllowedException { + + /* mock */ + if (identifier != null) { + when(identifierService.update(id, data)) + .thenReturn(identifier); + when(identifierService.find(id)) + .thenReturn(identifier); + } else { + doThrow(IdentifierNotFoundException.class) + .when(identifierService) + .find(id); + } + if (user != null) { + when(userService.findByUsername(username)) + .thenReturn(user); + } else { + doThrow(UserNotFoundException.class) + .when(userService) + .findByUsername(username); + } + + /* test */ + final ResponseEntity<IdentifierDto> response = persistenceEndpoint.update(id, data, principal); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + final IdentifierDto body = response.getBody(); + assertNotNull(body); + assertEquals(IDENTIFIER_3_ID, body.getId()); + assertEquals(IDENTIFIER_3_TITLE, body.getTitle()); + assertEquals(IDENTIFIER_3_DESCRIPTION, body.getDescription()); + assertEquals(IDENTIFIER_3_QUERY, body.getQuery()); + assertEquals(IDENTIFIER_3_QUERY_HASH, body.getQueryHash()); + assertEquals(IDENTIFIER_3_RESULT_NUMBER, body.getResultNumber()); + assertEquals(IDENTIFIER_3_RESULT_HASH, body.getResultHash()); + } + + protected void generic_delete() throws IdentifierNotFoundException, NotAllowedException { + + /* mock */ + doNothing() + .when(identifierService) + .delete(IDENTIFIER_1_ID); + + /* test */ + final ResponseEntity<?> response = persistenceEndpoint.delete(IDENTIFIER_1_ID); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNull(response.getBody()); + } + } diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java index 4eaff8493e..25cb2990f2 100644 --- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java +++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java @@ -3,14 +3,12 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.identifier.IdentifierDto; -import at.tuwien.api.identifier.VisibilityTypeDto; import at.tuwien.config.IndexInitializer; import at.tuwien.entities.identifier.Identifier; import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.exception.*; import at.tuwien.repository.elastic.IdentifierIdxRepository; import at.tuwien.repository.jpa.IdentifierRepository; -import org.apache.http.auth.BasicUserPrincipal; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -24,7 +22,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.RestTemplate; -import java.security.Principal; import java.util.List; import java.util.Optional; @@ -191,8 +188,10 @@ public class IdentifierServiceUnitTest extends BaseUnitTest { @Test public void update_doiChange_fails() { - - IdentifierDto identifierWithNewDoiDto = IdentifierDto.builder().id(IDENTIFIER_1_ID).visibility(VisibilityTypeDto.EVERYONE).doi("10.000/thisisadifferentdoi").build(); + final IdentifierDto request = IdentifierDto.builder() + .id(IDENTIFIER_1_ID) + .doi("10.000/thisisadifferentdoi") + .build(); /* mock */ when(identifierRepository.findById(IDENTIFIER_1_ID)) @@ -200,23 +199,7 @@ public class IdentifierServiceUnitTest extends BaseUnitTest { /* test */ assertThrows(IdentifierRequestException.class, () -> { - identifierService.update(IDENTIFIER_1_ID, identifierWithNewDoiDto); - }); - } - - @Test - public void update_notVisibleByEveryone_fails() { - Identifier identifier = Identifier.builder().id(IDENTIFIER_1_ID).build(); - IdentifierDto identifierDto = IdentifierDto.builder().id(IDENTIFIER_1_ID).visibility(VisibilityTypeDto.TRUSTED).build(); - IDENTIFIER_1_DTO.setVisibility(VisibilityTypeDto.TRUSTED); - - /* mock */ - when(identifierRepository.findById(IDENTIFIER_1_ID)) - .thenReturn(Optional.of(identifier)); - - /* test */ - assertThrows(IdentifierRequestException.class, () -> { - identifierService.update(IDENTIFIER_1_ID, identifierDto); + identifierService.update(IDENTIFIER_1_ID, request); }); } diff --git a/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata0.json b/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata0.json index ab803627d4..d7bb152193 100644 --- a/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata0.json +++ b/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata0.json @@ -6,7 +6,6 @@ "title": "Sweden weather data", "description": "Selecting all from the weather Sweden table", "doi": null, - "visibility": "everyone", "publisher": "Swedish Government", "publication_day": 14, "publication_month": 7, diff --git a/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata1.json b/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata1.json index be2009147b..347b13ed82 100644 --- a/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata1.json +++ b/dbrepo-identifier-service/rest-service/src/test/resources/json/metadata1.json @@ -13,7 +13,6 @@ "execution": "2018-11-07T10:59:12.000+00:00", "result_hash": "def", "result_number": 2, - "visibility": "everyone", "publisher": "Austrian Government", "creators": [ { diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java index f5a94274b6..9228a1af79 100644 --- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java @@ -256,12 +256,10 @@ public class IdentifierServiceImpl implements IdentifierService { public Identifier update(Long identifierId, IdentifierDto data) throws IdentifierNotFoundException, IdentifierRequestException { /* check */ - Identifier old = find(identifierId); - if(data.getVisibility() != VisibilityTypeDto.EVERYONE) { - throw new IdentifierRequestException("Cannot set visibility to other value than \"EVERYONE\"."); - } + final Identifier old = find(identifierId); if(data.getDoi() != null && !data.getDoi().equals(old.getDoi())) { - throw new IdentifierRequestException("The DOI of an identifier cannot be changed."); + log.error("Failed to update: DOI needs to stay the same"); + throw new IdentifierRequestException("Failed to update: DOI needs to stay the same"); } /* map */ final Identifier entity = identifierMapper.identifierDtoToIdentifier(data); diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java index 1234beec96..69e448003e 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java @@ -80,10 +80,6 @@ public class IdentifierDto { @Schema(example = "1") private Long resultNumber; - @NotNull - @Schema(example = "everyone") - private VisibilityTypeDto visibility; - @Schema(example = "10.1038/nphys1170") private String doi; diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/VisibilityTypeDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/VisibilityTypeDto.java deleted file mode 100644 index 25739d3d4d..0000000000 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/VisibilityTypeDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package at.tuwien.api.identifier; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.ToString; - -@Getter -public enum VisibilityTypeDto { - - @JsonProperty("everyone") - EVERYONE("everyone"), - - @JsonProperty("trusted") - TRUSTED("trusted"), - - @JsonProperty("self") - SELF("self"); - - private String name; - - VisibilityTypeDto(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } -} \ No newline at end of file diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java index 66a68c8ff7..7ed3b864b3 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java @@ -114,11 +114,6 @@ public class Identifier implements Serializable { }) private Database database; - @Column(nullable = false, columnDefinition = "enum('EVERYONE', 'TRUSTED', 'SELF')") - @Enumerated(EnumType.STRING) - @Builder.Default - private VisibilityType visibility = VisibilityType.EVERYONE; - @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinColumns({ @JoinColumn(name = "iid", referencedColumnName = "id", insertable = false, updatable = false) diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/VisibilityType.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/VisibilityType.java deleted file mode 100644 index 029ccb3994..0000000000 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/VisibilityType.java +++ /dev/null @@ -1,12 +0,0 @@ -package at.tuwien.entities.identifier; - -import lombok.Getter; -import lombok.ToString; - -@Getter -@ToString -public enum VisibilityType { - EVERYONE, - TRUSTED, - SELF; -} \ No newline at end of file diff --git a/dbrepo-metadata-db/setup-schema.sql b/dbrepo-metadata-db/setup-schema.sql index b78ca3ab39..31eefbbbd3 100644 --- a/dbrepo-metadata-db/setup-schema.sql +++ b/dbrepo-metadata-db/setup-schema.sql @@ -357,7 +357,6 @@ CREATE TABLE IF NOT EXISTS `fda`.`mdb_identifiers` language VARCHAR(50), license VARCHAR(50), description TEXT, - visibility ENUM ('SELF', 'TRUSTED', 'EVERYONE') NOT NULL, publication_year INTEGER NOT NULL, publication_month INTEGER, publication_day INTEGER, diff --git a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java index 56bdd5503d..7bd9dff9d6 100644 --- a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java @@ -116,7 +116,7 @@ public abstract class BaseTest { "create-identifier", "find-identifier", "list-identifiers"}; public final static String[] ESCALATED_IDENTIFIER_HANDLING = new String[]{"escalated-identifier-handling", - "modify-identifier-metadata", "delete-identifier"}; + "modify-identifier-metadata", "delete-identifier", "update-foreign-identifier", "create-foreign-identifier"}; public final static String[] DEFAULT_QUERY_HANDLING = new String[]{"default-query-handling", "view-table-data", "execute-query", "view-table-history", "list-database-views", "list-queries", "view-database-view-data", @@ -4056,8 +4056,6 @@ public abstract class BaseTest { public final static String IDENTIFIER_1_TITLE_MODIFY = "Austrian weather some data"; public final static String IDENTIFIER_1_DOI = null; public final static String IDENTIFIER_1_DOI_NOT_NULL = "10.1000/183"; - public final static VisibilityType IDENTIFIER_1_VISIBILITY = VisibilityType.EVERYONE; - public final static VisibilityTypeDto IDENTIFIER_1_VISIBILITY_DTO = VisibilityTypeDto.EVERYONE; public final static Instant IDENTIFIER_1_CREATED = Instant.ofEpochSecond(1641588352) /* 2022-01-07 20:45:52 */; public final static Instant IDENTIFIER_1_MODIFIED = Instant.ofEpochSecond(1541588352) /* 2022-01-07 20:45:52 */; public final static Instant IDENTIFIER_1_EXECUTION = Instant.ofEpochSecond(1541588352) /* 2022-01-07 20:45:52 */; @@ -4102,7 +4100,6 @@ public abstract class BaseTest { .description(IDENTIFIER_1_DESCRIPTION) .title(IDENTIFIER_1_TITLE) .doi(IDENTIFIER_1_DOI) - .visibility(IDENTIFIER_1_VISIBILITY) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .execution(IDENTIFIER_1_EXECUTION) @@ -4128,7 +4125,6 @@ public abstract class BaseTest { .description(IDENTIFIER_1_DESCRIPTION) .title(IDENTIFIER_1_TITLE) .doi(IDENTIFIER_1_DOI) - .visibility(IDENTIFIER_1_VISIBILITY) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .execution(IDENTIFIER_1_EXECUTION) @@ -4154,7 +4150,6 @@ public abstract class BaseTest { .description(IDENTIFIER_1_DESCRIPTION) .title(IDENTIFIER_1_TITLE) .doi(IDENTIFIER_1_DOI_NOT_NULL) - .visibility(IDENTIFIER_1_VISIBILITY) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .execution(IDENTIFIER_1_EXECUTION) @@ -4180,7 +4175,6 @@ public abstract class BaseTest { .description(IDENTIFIER_1_DESCRIPTION) .title(IDENTIFIER_1_TITLE) .doi(IDENTIFIER_1_DOI) - .visibility(IDENTIFIER_1_VISIBILITY_DTO) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .execution(IDENTIFIER_1_EXECUTION) @@ -4205,7 +4199,6 @@ public abstract class BaseTest { .description(IDENTIFIER_1_DESCRIPTION) .title(IDENTIFIER_1_TITLE) .doi(IDENTIFIER_1_DOI_NOT_NULL) - .visibility(IDENTIFIER_1_VISIBILITY_DTO) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .execution(IDENTIFIER_1_EXECUTION) @@ -4229,8 +4222,6 @@ public abstract class BaseTest { public final static String IDENTIFIER_2_DESCRIPTION = "Selecting all from the weather Austria table"; public final static String IDENTIFIER_2_TITLE = "Australian weather data"; public final static String IDENTIFIER_2_DOI = null; - public final static VisibilityType IDENTIFIER_2_VISIBILITY = VisibilityType.EVERYONE; - public final static VisibilityTypeDto IDENTIFIER_2_VISIBILITY_DTO = VisibilityTypeDto.EVERYONE; public final static Instant IDENTIFIER_2_CREATED = Instant.ofEpochSecond(1641588352); public final static Instant IDENTIFIER_2_MODIFIED = Instant.ofEpochSecond(1541588352); public final static Instant IDENTIFIER_2_EXECUTION = Instant.ofEpochSecond(1541588352); @@ -4294,7 +4285,6 @@ public abstract class BaseTest { .description(IDENTIFIER_2_DESCRIPTION) .title(IDENTIFIER_2_TITLE) .doi(IDENTIFIER_2_DOI) - .visibility(IDENTIFIER_2_VISIBILITY) .created(IDENTIFIER_2_CREATED) .lastModified(IDENTIFIER_2_MODIFIED) .execution(IDENTIFIER_2_EXECUTION) @@ -4321,7 +4311,6 @@ public abstract class BaseTest { .description(IDENTIFIER_2_DESCRIPTION) .title(IDENTIFIER_2_TITLE) .doi(IDENTIFIER_2_DOI) - .visibility(IDENTIFIER_2_VISIBILITY) .created(IDENTIFIER_2_CREATED) .lastModified(IDENTIFIER_2_MODIFIED) .execution(IDENTIFIER_2_EXECUTION) @@ -4348,7 +4337,6 @@ public abstract class BaseTest { .description(IDENTIFIER_2_DESCRIPTION) .title(IDENTIFIER_2_TITLE) .doi(IDENTIFIER_2_DOI) - .visibility(IDENTIFIER_2_VISIBILITY_DTO) .created(IDENTIFIER_2_CREATED) .lastModified(IDENTIFIER_2_MODIFIED) .execution(IDENTIFIER_2_EXECUTION) @@ -4444,7 +4432,6 @@ public abstract class BaseTest { .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .type(IDENTIFIER_1_TYPE_DTO) - .visibility(IDENTIFIER_1_VISIBILITY_DTO) .created(IDENTIFIER_1_CREATED) .lastModified(IDENTIFIER_1_MODIFIED) .creators(List.of(CREATOR_1_DTO)) @@ -4534,8 +4521,6 @@ public abstract class BaseTest { public final static String IDENTIFIER_3_DESCRIPTION = "Selecting all from the weather Norwegian table"; public final static String IDENTIFIER_3_TITLE = "Norwegian weather data"; public final static String IDENTIFIER_3_DOI = null; - public final static VisibilityType IDENTIFIER_3_VISIBILITY = VisibilityType.EVERYONE; - public final static VisibilityTypeDto IDENTIFIER_3_VISIBILITY_DTO = VisibilityTypeDto.EVERYONE; public final static Instant IDENTIFIER_3_CREATED = Instant.ofEpochSecond(1641588352); public final static Instant IDENTIFIER_3_MODIFIED = Instant.ofEpochSecond(1541588352); public final static Instant IDENTIFIER_3_EXECUTION = Instant.ofEpochSecond(1541588352); @@ -4618,7 +4603,6 @@ public abstract class BaseTest { .description(IDENTIFIER_3_DESCRIPTION) .title(IDENTIFIER_3_TITLE) .doi(IDENTIFIER_3_DOI) - .visibility(IDENTIFIER_3_VISIBILITY) .created(IDENTIFIER_3_CREATED) .lastModified(IDENTIFIER_3_MODIFIED) .execution(IDENTIFIER_3_EXECUTION) @@ -4645,7 +4629,6 @@ public abstract class BaseTest { .description(IDENTIFIER_3_DESCRIPTION) .title(IDENTIFIER_3_TITLE) .doi(IDENTIFIER_3_DOI) - .visibility(IDENTIFIER_3_VISIBILITY) .created(IDENTIFIER_3_CREATED) .lastModified(IDENTIFIER_3_MODIFIED) .execution(IDENTIFIER_3_EXECUTION) @@ -4672,7 +4655,6 @@ public abstract class BaseTest { .description(IDENTIFIER_3_DESCRIPTION) .title(IDENTIFIER_3_TITLE) .doi(IDENTIFIER_3_DOI) - .visibility(IDENTIFIER_3_VISIBILITY_DTO) .created(IDENTIFIER_3_CREATED) .lastModified(IDENTIFIER_3_MODIFIED) .execution(IDENTIFIER_3_EXECUTION) @@ -4736,7 +4718,6 @@ public abstract class BaseTest { public final static String IDENTIFIER_4_DESCRIPTION = "Selecting all from the weather Sweden table"; public final static String IDENTIFIER_4_TITLE = "Sweden weather data"; public final static String IDENTIFIER_4_DOI = null; - public final static VisibilityType IDENTIFIER_4_VISIBILITY = VisibilityType.EVERYONE; public final static Instant IDENTIFIER_4_CREATED = Instant.ofEpochSecond(1641588352); public final static Instant IDENTIFIER_4_MODIFIED = Instant.ofEpochSecond(1541588352); public final static Instant IDENTIFIER_4_EXECUTION = Instant.ofEpochSecond(1541588352); @@ -4760,7 +4741,6 @@ public abstract class BaseTest { .description(IDENTIFIER_4_DESCRIPTION) .title(IDENTIFIER_4_TITLE) .doi(IDENTIFIER_4_DOI) - .visibility(IDENTIFIER_4_VISIBILITY) .created(IDENTIFIER_4_CREATED) .lastModified(IDENTIFIER_4_MODIFIED) .execution(IDENTIFIER_4_EXECUTION) @@ -4786,7 +4766,6 @@ public abstract class BaseTest { .description(IDENTIFIER_4_DESCRIPTION) .title(IDENTIFIER_4_TITLE) .doi(IDENTIFIER_4_DOI) - .visibility(IDENTIFIER_4_VISIBILITY) .created(IDENTIFIER_4_CREATED) .lastModified(IDENTIFIER_4_MODIFIED) .execution(IDENTIFIER_4_EXECUTION) -- GitLab