diff --git a/dspace-api/src/test/java/org/dspace/builder/ItemBuilder.java b/dspace-api/src/test/java/org/dspace/builder/ItemBuilder.java index b9eedd2fcf42..88acf447e928 100644 --- a/dspace-api/src/test/java/org/dspace/builder/ItemBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/ItemBuilder.java @@ -593,6 +593,15 @@ public ItemBuilder withOrcidSynchronizationFundingsPreference(String value) { return setMetadataSingleValue(item, "dspace", "orcid", "sync-fundings", value); } + public ItemBuilder withOrcidSynchronizationProductsPreference(OrcidEntitySyncPreference value) { + return withOrcidSynchronizationProductsPreference(value.name()); + } + + public ItemBuilder withOrcidSynchronizationProductsPreference(String value) { + return setMetadataSingleValue(item, "dspace", "orcid", "sync-products", value); + } + + public ItemBuilder withOrcidSynchronizationProfilePreference(OrcidProfileSyncPreference value) { return withOrcidSynchronizationProfilePreference(value.name()); } diff --git a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java index a1ebec2197e4..4fb9de54e153 100644 --- a/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java +++ b/dspace-api/src/test/java/org/dspace/orcid/OrcidQueueConsumerIT.java @@ -586,6 +586,41 @@ public void testOrcidQueueRecordCreationForFunding() throws Exception { assertThat(orcidQueueRecords.get(0), equalTo(newOrcidQueueRecords.get(0))); } + @Test + public void testOrcidQueueRecordCreationForProduct() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationProductsPreference(ALL) + .build(); + + Collection productCollection = createCollection("Products", "Product"); + + Item product = ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + .withAuthor("Test User", profile.getID().toString()) + .build(); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, product, "Product", null, INSERT)); + + addMetadata(product, "dc", "type", null, "http://purl.org/coar/resource_type/scheme/c_12cc", null); + context.commit(); + + List newOrcidQueueRecords = orcidQueueService.findAll(context); + assertThat(newOrcidQueueRecords, hasSize(1)); + + assertThat(orcidQueueRecords.get(0), equalTo(newOrcidQueueRecords.get(0))); + } + @Test public void testOrcidQueueRecordCreationToUpdateFunding() throws Exception { @@ -618,6 +653,38 @@ public void testOrcidQueueRecordCreationToUpdateFunding() throws Exception { assertThat(orcidQueueRecords.get(0), matches(profile, funding, "Funding", "123456", UPDATE)); } + @Test + public void testOrcidQueueRecordCreationToUpdateProduct() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .withOrcidSynchronizationProductsPreference(ALL) + .build(); + + Collection productCollection = createCollection("Products", "Product"); + + Item product = ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + .build(); + + createOrcidHistory(context, profile, product) + .withPutCode("123456") + .build(); + + addMetadata(product, "dc", "contributor", "author", "Test User", profile.getID().toString()); + + context.restoreAuthSystemState(); + context.commit(); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords.get(0), matches(profile, product, "Product", "123456", UPDATE)); + } + @Test public void testNoOrcidQueueRecordCreationOccursIfFundingSynchronizationIsDisabled() throws Exception { @@ -648,6 +715,36 @@ public void testNoOrcidQueueRecordCreationOccursIfFundingSynchronizationIsDisabl assertThat(orcidQueueService.findAll(context), empty()); } + @Test + public void testNoOrcidQueueRecordCreationOccursIfProductSynchronizationIsDisabled() throws Exception { + + context.turnOffAuthorisationSystem(); + + Item profile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) + .build(); + + Collection productCollection = createCollection("Products", "Product"); + + Item product = ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + .withAuthor("Test User", profile.getID().toString()) + .build(); + + context.restoreAuthSystemState(); + context.commit(); + + assertThat(orcidQueueService.findAll(context), empty()); + + addMetadata(profile, "dspace", "orcid", "sync-products", DISABLED.name(), null); + addMetadata(product, "dc", "description", "abstract", "Product Poduct Pduct Puct Pct Pt P", null); + context.commit(); + + assertThat(orcidQueueService.findAll(context), empty()); + } + @Test public void testNoOrcidQueueRecordCreationOccursIfProfileHasNotOrcidIdentifier() throws Exception { @@ -657,6 +754,7 @@ public void testNoOrcidQueueRecordCreationOccursIfProfileHasNotOrcidIdentifier() .withTitle("Test User") .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) .withOrcidSynchronizationFundingsPreference(ALL) + .withOrcidSynchronizationProductsPreference(ALL) .build(); Collection fundingCollection = createCollection("Fundings", "Funding"); @@ -666,6 +764,13 @@ public void testNoOrcidQueueRecordCreationOccursIfProfileHasNotOrcidIdentifier() .withFundingInvestigator("Test User", profile.getID().toString()) .build(); + Collection productCollection = createCollection("Products", "Product"); + + ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + .withAuthor("Test User", profile.getID().toString()) + .build(); + context.restoreAuthSystemState(); context.commit(); @@ -834,6 +939,7 @@ public void testWithMetadataFieldToIgnore() throws Exception { .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", eperson) .withOrcidSynchronizationFundingsPreference(ALL) .withOrcidSynchronizationPublicationsPreference(ALL) + .withOrcidSynchronizationProductsPreference(ALL) .build(); Collection publicationCollection = createCollection("Publications", "Publication"); @@ -866,6 +972,13 @@ public void testWithMetadataFieldToIgnore() throws Exception { .withFundingCoInvestigator("Test User", profile.getID().toString()) .build(); + Collection productCollection = createCollection("Products", "Product"); + + Item firstProduct = ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + .withAuthor("Test User", profile.getID().toString()) + .build(); + context.restoreAuthSystemState(); List records = orcidQueueService.findAll(context); @@ -873,7 +986,6 @@ public void testWithMetadataFieldToIgnore() throws Exception { assertThat(records, hasItem(matches(profile, firstPublication, "Publication", null, INSERT))); assertThat(records, hasItem(matches(profile, secondPublication, "Publication", null, INSERT))); assertThat(records, hasItem(matches(profile, firstFunding, "Funding", null, INSERT))); - } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index f3877445895a..2d6cead4fabb 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -4166,6 +4166,94 @@ public void testDeletionOfFundingToBeSynchronizedWithOrcid() throws Exception { } + @Test + public void testDeletionOfProductToBeSynchronizedWithOrcid() throws Exception { + + context.turnOffAuthorisationSystem(); + + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + Collection profileCollection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Profiles") + .withEntityType("Person") + .build(); + + Collection productCollection = CollectionBuilder.createCollection(context, parentCommunity) + .withName("Products") + .withEntityType("Product") + .build(); + + EPerson firstOwner = EPersonBuilder.createEPerson(context) + .withEmail("owner2@test.com") + .build(); + + EPerson secondOwner = EPersonBuilder.createEPerson(context) + .withEmail("owner3@test.com") + .build(); + + EPerson thirdOwner = EPersonBuilder.createEPerson(context) + .withEmail("owner1@test.com") + .build(); + + Item firstProfile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withDspaceObjectOwner(firstOwner.getFullName(), firstOwner.getID().toString()) + .withOrcidIdentifier("0000-1111-2222-3333") + .withOrcidAccessToken("ab4d18a0-8d9a-40f1-b601-a417255c8d20", firstOwner) + .withOrcidSynchronizationProductsPreference(ALL) + .build(); + + Item secondProfile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withDspaceObjectOwner(secondOwner.getFullName(), secondOwner.getID().toString()) + .withOrcidIdentifier("4444-1111-2222-3333") + .withOrcidAccessToken("bb4d18a0-8d9a-40f1-b601-a417255c8d20", secondOwner) + .build(); + + Item thirdProfile = ItemBuilder.createItem(context, profileCollection) + .withTitle("Test User") + .withDspaceObjectOwner(thirdOwner.getFullName(), thirdOwner.getID().toString()) + .withOrcidIdentifier("5555-1111-2222-3333") + .withOrcidAccessToken("cb4d18a0-8d9a-40f1-b601-a417255c8d20", thirdOwner) + .withOrcidSynchronizationProductsPreference(ALL) + .build(); + + Item product = ItemBuilder.createItem(context, productCollection) + .withTitle("Test product") + + .build(); + + createOrcidQueue(context, firstProfile, product).build(); + createOrcidQueue(context, secondProfile, product).build(); + + List historyRecords = new ArrayList<>(); + historyRecords.add(createOrcidHistory(context, firstProfile, product).build()); + historyRecords.add(createOrcidHistory(context, firstProfile, product).withPutCode("12345").build()); + historyRecords.add(createOrcidHistory(context, secondProfile, product).build()); + historyRecords.add(createOrcidHistory(context, secondProfile, product).withPutCode("67891").build()); + historyRecords.add(createOrcidHistory(context, thirdProfile, product).build()); + + context.restoreAuthSystemState(); + + String token = getAuthToken(admin.getEmail(), password); + + getClient(token).perform(delete("/api/core/items/" + product.getID())) + .andExpect(status().is(204)); + + List orcidQueueRecords = orcidQueueService.findAll(context); + assertThat(orcidQueueRecords, hasSize(1)); + assertThat(orcidQueueRecords, hasItem(matches(firstProfile, null, "Product", "12345", DELETE))); + + for (OrcidHistory historyRecord : historyRecords) { + historyRecord = context.reloadEntity(historyRecord); + assertThat(historyRecord, notNullValue()); + assertThat(historyRecord.getEntity(), nullValue()); + } + + } + private void initPublicationAuthorsRelationships() throws SQLException { context.turnOffAuthorisationSystem(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java index 092b4e47479a..b0328b3a73dd 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ResearcherProfileRestRepositoryIT.java @@ -1171,6 +1171,7 @@ public void testOrcidMetadataOfEpersonAreCopiedOnProfile() throws Exception { .andExpect(jsonPath("$.orcidSynchronization.mode", is("MANUAL"))) .andExpect(jsonPath("$.orcidSynchronization.publicationsPreference", is("DISABLED"))) .andExpect(jsonPath("$.orcidSynchronization.fundingsPreference", is("DISABLED"))) + .andExpect(jsonPath("$.orcidSynchronization.productsPreference", is("DISABLED"))) .andExpect(jsonPath("$.orcidSynchronization.profilePreferences", empty())); String itemId = getItemIdByProfileId(authToken, ePersonId); @@ -1307,6 +1308,65 @@ public void testPatchToSetOrcidSynchronizationPreferenceForFundings() throws Exc } + @Test + public void testPatchToSetOrcidSynchronizationPreferenceForProduct() throws Exception { + + context.turnOffAuthorisationSystem(); + + EPerson ePerson = EPersonBuilder.createEPerson(context) + .withCanLogin(true) + .withOrcid("0000-1111-2222-3333") + .withEmail("test@email.it") + .withPassword(password) + .withNameInMetadata("Test", "User") + .withOrcidScope("/first-scope") + .withOrcidScope("/second-scope") + .build(); + + OrcidTokenBuilder.create(context, ePerson, "af097328-ac1c-4a3e-9eb4-069897874910").build(); + + context.restoreAuthSystemState(); + + String ePersonId = ePerson.getID().toString(); + String authToken = getAuthToken(ePerson.getEmail(), password); + + getClient(authToken).perform(post("/api/eperson/profiles/") + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isCreated()); + + List operations = asList(new ReplaceOperation("/orcid/products", ALL.name())); + + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) + .content(getPatchContent(operations)) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.orcidSynchronization.productsPreference", is(ALL.name()))); + + getClient(authToken).perform(get("/api/eperson/profiles/{id}", ePersonId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.orcidSynchronization.productsPreference", is(ALL.name()))); + + operations = asList(new ReplaceOperation("/orcid/products", MINE.name())); + + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) + .content(getPatchContent(operations)) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.orcidSynchronization.productsPreference", is(MINE.name()))); + + getClient(authToken).perform(get("/api/eperson/profiles/{id}", ePersonId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.orcidSynchronization.productsPreference", is(MINE.name()))); + + operations = asList(new ReplaceOperation("/orcid/products", "INVALID_VALUE")); + + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId) + .content(getPatchContent(operations)) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isUnprocessableEntity()); + + } + @Test public void testPatchToSetOrcidSynchronizationPreferenceForProfile() throws Exception { @@ -2144,8 +2204,12 @@ public void testOrcidSynchronizationPreferenceUpdateForceOrcidQueueRecalculation Collection publications = createCollection("Publications", "Publication"); + Collection products = createCollection("Products", "Product"); + Item publication = createPublication(publications, "Test publication", profile); + Item product = createProduct(products, "Test product", profile); + Collection fundings = createCollection("Fundings", "Funding"); Item firstFunding = createFundingWithInvestigator(fundings, "First funding", profile); @@ -2178,21 +2242,43 @@ public void testOrcidSynchronizationPreferenceUpdateForceOrcidQueueRecalculation assertThat(queueRecords, has(orcidQueueRecordWithEntity(firstFunding))); assertThat(queueRecords, has(orcidQueueRecordWithEntity(secondFunding))); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId.toString()) + .content(getPatchContent(asList(new ReplaceOperation("/orcid/products", "ALL")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()); + + queueRecords = orcidQueueService.findByProfileItemId(context, profileItemId); + assertThat(queueRecords, hasSize(4)); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(publication))); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(firstFunding))); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(secondFunding))); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(product))); + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId.toString()) .content(getPatchContent(asList(new ReplaceOperation("/orcid/publications", "DISABLED")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk()); queueRecords = orcidQueueService.findByProfileItemId(context, profileItemId); - assertThat(queueRecords, hasSize(2)); + assertThat(queueRecords, hasSize(3)); assertThat(queueRecords, has(orcidQueueRecordWithEntity(firstFunding))); assertThat(queueRecords, has(orcidQueueRecordWithEntity(secondFunding))); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(product))); getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId.toString()) .content(getPatchContent(asList(new ReplaceOperation("/orcid/fundings", "DISABLED")))) .contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk()); + queueRecords = orcidQueueService.findByProfileItemId(context, profileItemId); + assertThat(queueRecords, hasSize(1)); + assertThat(queueRecords, has(orcidQueueRecordWithEntity(product))); + + getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId.toString()) + .content(getPatchContent(asList(new ReplaceOperation("/orcid/products", "DISABLED")))) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()); + assertThat(orcidQueueService.findByProfileItemId(context, profileItemId), empty()); configurationService.setProperty("orcid.linkable-metadata-fields.ignore", "crisfund.coinvestigators"); @@ -2615,6 +2701,13 @@ private Item createPublication(Collection collection, String title, Item author) .build(); } + private Item createProduct(Collection collection, String title, Item author) { + return ItemBuilder.createItem(context, collection) + .withTitle(title) + .withAuthor(author.getName(), author.getID().toString()) + .build(); + } + private Item createFundingWithInvestigator(Collection collection, String title, Item investigator) { return ItemBuilder.createItem(context, collection) .withTitle(title)