Skip to content

Commit

Permalink
Merge pull request DSpace#9396 from uniba-ub/issue-9390
Browse files Browse the repository at this point in the history
Delete sync settings when disconnect from orcid
  • Loading branch information
tdonohue authored Jun 11, 2024
2 parents 4c5a91f + 4bb32a8 commit 1ef6178
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ public void unlinkProfile(Context context, Item profile) throws SQLException {
itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY);
itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY);

if (!configurationService.getBooleanProperty("orcid.disconnection.remain-sync", false)) {
clearSynchronizationSettings(context, profile);
}

orcidTokenService.deleteByProfileItem(context, profile);

updateItem(context, profile);
Expand Down Expand Up @@ -267,6 +271,17 @@ private boolean updatePreferenceForSynchronizingWithOrcid(Context context, Item

}

private void clearSynchronizationSettings(Context context, Item profile)
throws SQLException {
itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-mode", Item.ANY);
itemService.clearMetadata(context, profile, "dspace", "orcid", "sync-profile", Item.ANY);

for (OrcidEntityType entityType : OrcidEntityType.values()) {
itemService.clearMetadata(context, profile, "dspace", "orcid",
"sync-" + entityType.name().toLowerCase() + "s", Item.ANY);
}
}

private boolean containsSameValues(List<String> firstList, List<String> secondList) {
return new HashSet<>(firstList).equals(new HashSet<>(secondList));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.dspace.app.rest.matcher.ResourcePolicyMatcher.matchResourcePolicyProperties;
import static org.dspace.builder.RelationshipTypeBuilder.createRelationshipTypeBuilder;
import static org.dspace.profile.OrcidEntitySyncPreference.ALL;
import static org.dspace.profile.OrcidEntitySyncPreference.DISABLED;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
Expand Down Expand Up @@ -2231,6 +2232,156 @@ public void testAnotherUserPatchToDisconnectProfileFromOrcidWithAdminAndOwnerCon
assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4"));
}

@Test
public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemoved() throws Exception {

configurationService.setProperty("orcid.disconnection.allowed-users", "only_owner");
configurationService.setProperty("orcid.disconnection.remain-sync", "false");

context.turnOffAuthorisationSystem();

EPerson ePerson = EPersonBuilder.createEPerson(context)
.withCanLogin(true)
.withOrcid("0000-1111-2222-3333")
.withOrcidScope("/read")
.withOrcidScope("/write")
.withEmail("[email protected]")
.withPassword(password)
.withNameInMetadata("Test", "User")
.build();

OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();

Item profile = createProfile(ePerson);

assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty()));
assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty()));
assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty()));
assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4"));

context.restoreAuthSystemState();

String authToken = getAuthToken(ePerson.getEmail(), password);
String ePersonId = ePerson.getID().toString();
List<Operation> operations = asList(new ReplaceOperation("/orcid/mode", "BATCH"),
new ReplaceOperation("/orcid/publications", "DISABLED"),
new ReplaceOperation("/orcid/fundings", "ALL"),
new ReplaceOperation("/orcid/profile", "BIOGRAPHICAL,IDENTIFIERS"));

getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId)
.content(getPatchContent(operations))
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.orcidSynchronization.mode", is("BATCH")))
.andExpect(jsonPath("$.orcidSynchronization.profilePreferences",
containsInAnyOrder("IDENTIFIERS", "BIOGRAPHICAL")))
.andExpect(jsonPath("$.orcidSynchronization.fundingsPreference", is(ALL.name())))
.andExpect(jsonPath("$.orcidSynchronization.publicationsPreference", is(DISABLED.name())));

profile = context.reloadEntity(profile);
List<MetadataValue> metadata = profile.getMetadata();
assertThat(metadata, hasItem(with("dspace.orcid.sync-mode","BATCH")));
assertThat(metadata, hasItem(with("dspace.orcid.sync-publications",DISABLED.name())));
assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name())));
assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2));

getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId)
.content(getPatchContent(asList(new RemoveOperation("/orcid"))))
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(ePersonId)))
.andExpect(jsonPath("$.visible", is(false)))
.andExpect(jsonPath("$.type", is("profile")))
.andExpect(jsonPath("$.orcid").doesNotExist())
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());

profile = context.reloadEntity(profile);

assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.scope"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.sync-mode"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.sync-fundings"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.sync-publications"), empty());
assertThat(getOrcidAccessToken(profile), nullValue());
}

@Test
public void testOwnerPatchToDisconnectProfileFromOrcidWithSyncSettingsRemain() throws Exception {

configurationService.setProperty("orcid.disconnection.allowed-users", "only_owner");

context.turnOffAuthorisationSystem();

EPerson ePerson = EPersonBuilder.createEPerson(context)
.withCanLogin(true)
.withOrcid("0000-1111-2222-3333")
.withOrcidScope("/read")
.withOrcidScope("/write")
.withEmail("[email protected]")
.withPassword(password)
.withNameInMetadata("Test", "User")
.build();

OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();

Item profile = createProfile(ePerson);

assertThat(getMetadataValues(profile, "person.identifier.orcid"), not(empty()));
assertThat(getMetadataValues(profile, "dspace.orcid.scope"), not(empty()));
assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), not(empty()));
assertThat(getOrcidAccessToken(profile), is("3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4"));

context.restoreAuthSystemState();

String authToken = getAuthToken(ePerson.getEmail(), password);
String ePersonId = ePerson.getID().toString();
List<Operation> operations = asList(new ReplaceOperation("/orcid/mode", "BATCH"),
new ReplaceOperation("/orcid/publications", "DISABLED"),
new ReplaceOperation("/orcid/fundings", "ALL"),
new ReplaceOperation("/orcid/profile", "BIOGRAPHICAL,IDENTIFIERS"));

getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId)
.content(getPatchContent(operations))
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.orcidSynchronization.mode", is("BATCH")))
.andExpect(jsonPath("$.orcidSynchronization.profilePreferences",
containsInAnyOrder("IDENTIFIERS", "BIOGRAPHICAL")))
.andExpect(jsonPath("$.orcidSynchronization.fundingsPreference", is(ALL.name())))
.andExpect(jsonPath("$.orcidSynchronization.publicationsPreference", is(DISABLED.name())));

profile = context.reloadEntity(profile);
List<MetadataValue> metadata = profile.getMetadata();
assertThat(metadata, hasItem(with("dspace.orcid.sync-mode","BATCH")));
assertThat(metadata, hasItem(with("dspace.orcid.sync-publications",DISABLED.name())));
assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name())));
assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2));

getClient(authToken).perform(patch("/api/eperson/profiles/{id}", ePersonId)
.content(getPatchContent(asList(new RemoveOperation("/orcid"))))
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(ePersonId)))
.andExpect(jsonPath("$.visible", is(false)))
.andExpect(jsonPath("$.type", is("profile")))
.andExpect(jsonPath("$.orcid").doesNotExist())
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());

profile = context.reloadEntity(profile);

assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.scope"), empty());
assertThat(getMetadataValues(profile, "dspace.orcid.authenticated"), empty());
assertThat(metadata, hasItem(with("dspace.orcid.sync-mode","BATCH")));
assertThat(metadata, hasItem(with("dspace.orcid.sync-publications",DISABLED.name())));
assertThat(metadata, hasItem(with("dspace.orcid.sync-fundings",ALL.name())));
assertThat(getMetadataValues(profile, "dspace.orcid.sync-profile"), hasSize(2));
assertThat(getOrcidAccessToken(profile), nullValue());
}


@Test
public void testCloneFromExternalProfileAlreadyAssociated() throws Exception {

Expand Down
5 changes: 4 additions & 1 deletion dspace/config/modules/orcid.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# Allowed values are disabled, only_admin, only_owner or admin_and_owner
orcid.disconnection.allowed-users = admin_and_owner

# Configuration if the orcid sync settings should be remain on he profile when it is disconnected from orcid or not
orcid.disconnection.remain-sync = true

#------------------------------------------------------------------#
#--------------------ORCID CLIENT CONFIGURATIONS-------------------#
#------------------------------------------------------------------#
Expand Down Expand Up @@ -163,4 +166,4 @@ orcid.external-data.mapping.publication.external-ids = dc.identifier.doi::doi
orcid.external-data.mapping.publication.external-ids = dc.identifier.scopus::eid
orcid.external-data.mapping.publication.external-ids = dc.identifier.pmid::pmid
orcid.external-data.mapping.publication.external-ids = dc.identifier.isi::wosuid
orcid.external-data.mapping.publication.external-ids = dc.identifier.issn::issn
orcid.external-data.mapping.publication.external-ids = dc.identifier.issn::issn

0 comments on commit 1ef6178

Please sign in to comment.