mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
[CST-14905] Orcid revoke token feature
This commit is contained in:
@@ -10,6 +10,7 @@ package org.dspace.orcid.client;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.exception.OrcidClientException;
|
||||
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.orcid.jaxb.model.v3.release.record.Person;
|
||||
@@ -161,4 +162,11 @@ public interface OrcidClient {
|
||||
*/
|
||||
OrcidResponse deleteByPutCode(String accessToken, String orcid, String putCode, String path);
|
||||
|
||||
/**
|
||||
* Revokes the given {@param accessToken} with a POST method.
|
||||
* @param orcidToken the access token to revoke
|
||||
* @throws OrcidClientException if some error occurs during the search
|
||||
*/
|
||||
void revokeToken(OrcidToken orcidToken);
|
||||
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@ import org.apache.http.client.methods.RequestBuilder;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.exception.OrcidClientException;
|
||||
import org.dspace.orcid.model.OrcidEntityType;
|
||||
import org.dspace.orcid.model.OrcidProfileSectionType;
|
||||
@@ -178,6 +179,16 @@ public class OrcidClientImpl implements OrcidClient {
|
||||
return execute(buildDeleteUriRequest(accessToken, "/" + orcid + path + "/" + putCode), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeToken(OrcidToken orcidToken) {
|
||||
List<NameValuePair> params = new ArrayList<>();
|
||||
params.add(new BasicNameValuePair("client_id", orcidConfiguration.getClientId()));
|
||||
params.add(new BasicNameValuePair("client_secret", orcidConfiguration.getClientSecret()));
|
||||
params.add(new BasicNameValuePair("token", orcidToken.getAccessToken()));
|
||||
|
||||
executeSuccessful(buildPostForRevokeToken(new UrlEncodedFormEntity(params, Charset.defaultCharset())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrcidTokenResponseDTO getReadPublicAccessToken() {
|
||||
return getClientCredentialsAccessToken("/read-public");
|
||||
@@ -220,6 +231,14 @@ public class OrcidClientImpl implements OrcidClient {
|
||||
.build();
|
||||
}
|
||||
|
||||
private HttpUriRequest buildPostForRevokeToken(HttpEntity entity) {
|
||||
return post(orcidConfiguration.getRevokeUrl())
|
||||
.addHeader("Accept", "application/json")
|
||||
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.setEntity(entity)
|
||||
.build();
|
||||
}
|
||||
|
||||
private HttpUriRequest buildPutUriRequest(String accessToken, String relativePath, Object object) {
|
||||
return put(orcidConfiguration.getApiUrl() + relativePath.trim())
|
||||
.addHeader("Content-Type", "application/vnd.orcid+xml")
|
||||
@@ -234,6 +253,24 @@ public class OrcidClientImpl implements OrcidClient {
|
||||
.build();
|
||||
}
|
||||
|
||||
private void executeSuccessful(HttpUriRequest httpUriRequest) {
|
||||
try {
|
||||
HttpClient client = HttpClientBuilder.create().build();
|
||||
HttpResponse response = client.execute(httpUriRequest);
|
||||
|
||||
if (isNotSuccessfull(response)) {
|
||||
throw new OrcidClientException(
|
||||
getStatusCode(response),
|
||||
"Operation " + httpUriRequest.getMethod() + " for the resource " + httpUriRequest.getURI() +
|
||||
" was not successful: " + new String(response.getEntity().getContent().readAllBytes(),
|
||||
StandardCharsets.UTF_8)
|
||||
);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T executeAndParseJson(HttpUriRequest httpUriRequest, Class<T> clazz) {
|
||||
|
||||
HttpClient client = HttpClientBuilder.create().build();
|
||||
|
@@ -35,6 +35,8 @@ public final class OrcidConfiguration {
|
||||
|
||||
private String scopes;
|
||||
|
||||
private String revokeUrl;
|
||||
|
||||
public String getApiUrl() {
|
||||
return apiUrl;
|
||||
}
|
||||
@@ -111,4 +113,11 @@ public final class OrcidConfiguration {
|
||||
return !StringUtils.isAnyBlank(clientId, clientSecret);
|
||||
}
|
||||
|
||||
public String getRevokeUrl() {
|
||||
return revokeUrl;
|
||||
}
|
||||
|
||||
public void setRevokeUrl(String revokeUrl) {
|
||||
this.revokeUrl = revokeUrl;
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ import org.dspace.discovery.indexobject.IndexableItem;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.client.OrcidClient;
|
||||
import org.dspace.orcid.model.OrcidEntityType;
|
||||
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.dspace.orcid.service.OrcidSynchronizationService;
|
||||
@@ -47,6 +48,8 @@ import org.dspace.profile.OrcidProfileSyncPreference;
|
||||
import org.dspace.profile.OrcidSynchronizationMode;
|
||||
import org.dspace.profile.service.ResearcherProfileService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
@@ -57,6 +60,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
*/
|
||||
public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OrcidSynchronizationServiceImpl.class);
|
||||
@Autowired
|
||||
private ItemService itemService;
|
||||
|
||||
@@ -75,6 +79,9 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ
|
||||
@Autowired
|
||||
private ResearcherProfileService researcherProfileService;
|
||||
|
||||
@Autowired
|
||||
private OrcidClient orcidClient;
|
||||
|
||||
@Override
|
||||
public void linkProfile(Context context, Item profile, OrcidTokenResponseDTO token) throws SQLException {
|
||||
|
||||
@@ -118,7 +125,14 @@ public class OrcidSynchronizationServiceImpl implements OrcidSynchronizationServ
|
||||
itemService.clearMetadata(context, profile, "dspace", "orcid", "scope", Item.ANY);
|
||||
itemService.clearMetadata(context, profile, "dspace", "orcid", "authenticated", Item.ANY);
|
||||
|
||||
OrcidToken profileToken = orcidTokenService.findByProfileItem(context, profile);
|
||||
if (profileToken == null) {
|
||||
log.warn("Cannot find any token related to the user profile: {}", profile.getID());
|
||||
return;
|
||||
}
|
||||
|
||||
orcidTokenService.deleteByProfileItem(context, profile);
|
||||
orcidClient.revokeToken(profileToken);
|
||||
|
||||
updateItem(context, profile);
|
||||
|
||||
|
@@ -30,7 +30,10 @@ import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -44,6 +47,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -79,11 +83,13 @@ import org.dspace.orcid.client.OrcidClient;
|
||||
import org.dspace.orcid.exception.OrcidClientException;
|
||||
import org.dspace.orcid.model.OrcidTokenResponseDTO;
|
||||
import org.dspace.orcid.service.OrcidQueueService;
|
||||
import org.dspace.orcid.service.OrcidSynchronizationService;
|
||||
import org.dspace.orcid.service.OrcidTokenService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.util.UUIDUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
@@ -114,7 +120,11 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
@Autowired
|
||||
private OrcidClient orcidClient;
|
||||
|
||||
private OrcidClient orcidClientMock = mock(OrcidClient.class);
|
||||
@Mock
|
||||
private OrcidClient orcidClientMock;
|
||||
|
||||
@Autowired
|
||||
private OrcidSynchronizationService orcidSynchronizationService;
|
||||
|
||||
private EPerson user;
|
||||
|
||||
@@ -158,16 +168,36 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
researcherProfileAddOrcidOperation.setOrcidClient(orcidClientMock);
|
||||
|
||||
useInstanceForBean(orcidSynchronizationService, orcidClientMock);
|
||||
useInstanceForBean(researcherProfileAddOrcidOperation, orcidClientMock);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
orcidTokenService.deleteAll(context);
|
||||
researcherProfileAddOrcidOperation.setOrcidClient(orcidClient);
|
||||
useInstanceForBean(orcidSynchronizationService, orcidClient);
|
||||
useInstanceForBean(researcherProfileAddOrcidOperation, orcidClient);
|
||||
}
|
||||
|
||||
private <B, I> void useInstanceForBean(B bean, I instance) {
|
||||
Field[] fields = bean.getClass().getDeclaredFields();
|
||||
|
||||
for (Field field : fields) {
|
||||
if (field.getType().isAssignableFrom(instance.getClass())) {
|
||||
boolean accessible = field.isAccessible();
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(bean, instance);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
field.setAccessible(accessible);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verify that the findById endpoint returns the own profile.
|
||||
*
|
||||
@@ -608,30 +638,38 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.withOrcidAuthenticated("authenticated")
|
||||
.build();
|
||||
|
||||
String id = user.getID().toString();
|
||||
String authToken = getAuthToken(user.getEmail(), password);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
getClient(authToken).perform(get("/api/eperson/profiles/{id}", id))
|
||||
String id = user.getID().toString();
|
||||
String authToken = getAuthToken(user.getEmail(), password);
|
||||
OrcidToken orcidToken = orcidTokenService.findByProfileItem(context, profileItem);
|
||||
|
||||
getClient(authToken)
|
||||
.perform(get("/api/eperson/profiles/{id}", id))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(profileItem.getMetadata(), hasItem(with("person.identifier.orcid", "0000-1111-2222-3333")));
|
||||
assertThat(profileItem.getMetadata(), hasItem(with("dspace.orcid.authenticated", "authenticated")));
|
||||
assertThat(getOrcidAccessToken(profileItem), notNullValue());
|
||||
assertThat(orcidToken.getAccessToken(), notNullValue());
|
||||
|
||||
getClient(authToken).perform(get("/api/eperson/profiles/{id}/item", id))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$", hasJsonPath("$.metadata", matchMetadataNotEmpty("dspace.object.owner"))));
|
||||
|
||||
|
||||
getClient(authToken).perform(delete("/api/eperson/profiles/{id}", id))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profileItem = context.reloadEntity(profileItem);
|
||||
|
||||
orcidToken = orcidTokenService.findByProfileItem(context, profileItem);
|
||||
|
||||
assertThat(profileItem.getMetadata(), not(hasItem(with("person.identifier.orcid", "0000-1111-2222-3333"))));
|
||||
assertThat(profileItem.getMetadata(), not(hasItem(with("dspace.orcid.authenticated", "authenticated"))));
|
||||
assertThat(getOrcidAccessToken(profileItem), nullValue());
|
||||
assertThat(orcidToken, nullValue());
|
||||
|
||||
}
|
||||
|
||||
@@ -1850,7 +1888,8 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.withNameInMetadata("Test", "User")
|
||||
.build();
|
||||
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
OrcidToken orcidToken =
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
|
||||
Item profile = createProfile(ePerson);
|
||||
|
||||
@@ -1872,6 +1911,9 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.andExpect(jsonPath("$.orcid").doesNotExist())
|
||||
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profile = context.reloadEntity(profile);
|
||||
|
||||
assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
|
||||
@@ -1880,6 +1922,54 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
assertThat(getOrcidAccessToken(profile), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchToDisconnectProfileFromOrcidDoesntRevokeOrcidToken() throws Exception {
|
||||
|
||||
configurationService.setProperty("orcid.disconnection.allowed-users", "admin_and_owner");
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
EPerson ePerson = EPersonBuilder.createEPerson(context)
|
||||
.withCanLogin(true)
|
||||
.withOrcid("0000-1111-2222-3333")
|
||||
.withOrcidScope("/read")
|
||||
.withOrcidScope("/write")
|
||||
.withEmail("test@email.it")
|
||||
.withPassword(password)
|
||||
.withNameInMetadata("Test", "User")
|
||||
.build();
|
||||
|
||||
OrcidToken orcidToken =
|
||||
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();
|
||||
|
||||
doThrow(new OrcidClientException(403, "")).when(orcidClientMock).revokeToken(any(OrcidToken.class));
|
||||
|
||||
getClient(getAuthToken(ePerson.getEmail(), password))
|
||||
.perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString())
|
||||
.content(getPatchContent(asList(new RemoveOperation("/orcid"))))
|
||||
.contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(status().isInternalServerError());
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profile = context.reloadEntity(profile);
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminPatchToDisconnectProfileFromOrcidWithOnlyOwnerConfiguration() throws Exception {
|
||||
|
||||
@@ -2023,7 +2113,8 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.withNameInMetadata("Test", "User")
|
||||
.build();
|
||||
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
OrcidToken orcidToken =
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
|
||||
Item profile = createProfile(ePerson);
|
||||
|
||||
@@ -2034,6 +2125,7 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
|
||||
getClient(getAuthToken(admin.getEmail(), password))
|
||||
.perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString())
|
||||
.content(getPatchContent(asList(new RemoveOperation("/orcid"))))
|
||||
@@ -2045,6 +2137,9 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.andExpect(jsonPath("$.orcid").doesNotExist())
|
||||
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profile = context.reloadEntity(profile);
|
||||
|
||||
assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
|
||||
@@ -2111,17 +2206,18 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.withPassword(password)
|
||||
.withNameInMetadata("Test", "User")
|
||||
.build();
|
||||
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
OrcidToken orcidToken =
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
|
||||
Item profile = createProfile(ePerson);
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
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();
|
||||
|
||||
getClient(getAuthToken(ePerson.getEmail(), password))
|
||||
.perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString())
|
||||
@@ -2134,6 +2230,9 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.andExpect(jsonPath("$.orcid").doesNotExist())
|
||||
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profile = context.reloadEntity(profile);
|
||||
|
||||
assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
|
||||
@@ -2159,7 +2258,8 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.withNameInMetadata("Test", "User")
|
||||
.build();
|
||||
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
OrcidToken orcidToken =
|
||||
OrcidTokenBuilder.create(context, ePerson, "3de2e370-8aa9-4bbe-8d7e-f5b1577bdad4").build();
|
||||
|
||||
Item profile = createProfile(ePerson);
|
||||
|
||||
@@ -2170,6 +2270,7 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
|
||||
getClient(getAuthToken(admin.getEmail(), password))
|
||||
.perform(patch("/api/eperson/profiles/{id}", ePerson.getID().toString())
|
||||
.content(getPatchContent(asList(new RemoveOperation("/orcid"))))
|
||||
@@ -2181,6 +2282,10 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
.andExpect(jsonPath("$.orcid").doesNotExist())
|
||||
.andExpect(jsonPath("$.orcidSynchronization").doesNotExist());
|
||||
|
||||
|
||||
verify(orcidClientMock, times(1)).revokeToken(matchesToken(orcidToken));
|
||||
verifyNoMoreInteractions(orcidClientMock);
|
||||
|
||||
profile = context.reloadEntity(profile);
|
||||
|
||||
assertThat(getMetadataValues(profile, "person.identifier.orcid"), empty());
|
||||
@@ -2627,4 +2732,13 @@ public class ResearcherProfileRestRepositoryIT extends AbstractControllerIntegra
|
||||
return token;
|
||||
}
|
||||
|
||||
private static OrcidToken matchesToken(OrcidToken orcidToken) {
|
||||
return argThat(
|
||||
token ->
|
||||
token != null &&
|
||||
orcidToken.getAccessToken().equals(token.getAccessToken()) &&
|
||||
orcidToken.getID().equals(token.getID())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ orcid.disconnection.allowed-users = admin_and_owner
|
||||
# ORCID API (https://github.com/ORCID/ORCID-Source/tree/master/orcid-api-web#endpoints)
|
||||
orcid.domain-url= https://sandbox.orcid.org
|
||||
orcid.authorize-url = ${orcid.domain-url}/oauth/authorize
|
||||
orcid.revoke-url = ${orcid.domain-url}/oauth/revoke
|
||||
orcid.token-url = ${orcid.domain-url}/oauth/token
|
||||
orcid.api-url = https://api.sandbox.orcid.org/v3.0
|
||||
orcid.public-url = https://pub.sandbox.orcid.org/v3.0
|
||||
|
@@ -30,6 +30,7 @@
|
||||
<property name="tokenEndpointUrl" value="${orcid.token-url}" />
|
||||
<property name="authorizeEndpointUrl" value="${orcid.authorize-url}" />
|
||||
<property name="scopes" value="${orcid.scope}" />
|
||||
<property name="revokeUrl" value="${orcid.revoke-url}" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.dspace.orcid.client.OrcidClientImpl" />
|
||||
|
Reference in New Issue
Block a user