Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.stereotype.Repository;

@Repository
public interface OrcidRecordRepository extends MongoRepository<OrcidRecord, String> {
public interface OrcidRecordRepository extends MongoRepository<OrcidRecord, String>, OrcidRecordRepositoryCustom {

Optional<OrcidRecord> findOneByEmail(String email);

Expand All @@ -20,4 +20,5 @@ public interface OrcidRecordRepository extends MongoRepository<OrcidRecord, Stri

@Query("{tokens: {salesforce_id: ?0}}")
Page<OrcidRecord> findBySalesforceId(String salesforceId, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.orcid.memberportal.service.assertion.repository;

import org.orcid.memberportal.service.assertion.domain.Assertion;
import org.orcid.memberportal.service.assertion.domain.MemberAssertionStatusCount;
import org.springframework.data.domain.Pageable;

import java.util.Iterator;
import java.util.List;

public interface OrcidRecordRepositoryCustom {

void updateTokenSalesforceIds(String oldSalesforceId, String newSalesforceId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.orcid.memberportal.service.assertion.repository.impl;

import com.mongodb.MongoClient;
import com.mongodb.client.DistinctIterable;
import com.mongodb.client.model.Filters;
import org.orcid.memberportal.service.assertion.domain.Assertion;
import org.orcid.memberportal.service.assertion.domain.MemberAssertionStatusCount;
import org.orcid.memberportal.service.assertion.domain.OrcidRecord;
import org.orcid.memberportal.service.assertion.domain.enumeration.AssertionStatus;
import org.orcid.memberportal.service.assertion.repository.AssertionRepositoryCustom;
import org.orcid.memberportal.service.assertion.repository.OrcidRecordRepositoryCustom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import java.util.Iterator;
import java.util.List;

@Repository
public class OrcidRecordRepositoryCustomImpl implements OrcidRecordRepositoryCustom {

@Autowired
private MongoTemplate mongoTemplate;

public OrcidRecordRepositoryCustomImpl(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}


@Override
public void updateTokenSalesforceIds(String oldSalesforceId, String newSalesforceId) {
mongoTemplate.updateMulti(Query.query(Criteria.where("tokens.salesforce_id").is(oldSalesforceId)),
new Update().set("tokens.$.salesforce_id", newSalesforceId), OrcidRecord.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ private String getAssertionStatus(Assertion assertion) {
}

public boolean updateAssertionsSalesforceId(String from, String to) {
return updateAssertionsSalesforceId(from, to, true);
boolean updated = updateAssertionsSalesforceId(from, to, true);
updated = updated && orcidRecordService.updateTokenSalesforceIds(from, to);
return updated;
}

private boolean updateAssertionsSalesforceId(String from, String to, boolean rollback) {
Expand Down Expand Up @@ -495,13 +497,15 @@ private void deleteAssertionFromOrcidRegistry(Assertion assertion) throws Regist
} catch (DeactivatedException | DeprecatedException e) {
handleDeactivatedOrDeprecated(orcidId, assertion);
} catch (ORCIDAPIException oae) {
if (oae.getStatusCode() != 404) {
if (oae.getStatusCode() != 404 && !AssertionStatus.USER_REVOKED_ACCESS.name().equals(assertion.getStatus())) {
storeError(assertion, oae.getStatusCode(), oae.getError(), AssertionStatus.ERROR_DELETING_IN_ORCID);
throw new RegistryDeleteFailureException();
}
} catch (Exception e) {
storeError(assertion, 0, e.getMessage(), AssertionStatus.ERROR_DELETING_IN_ORCID);
throw new RegistryDeleteFailureException();
if (!AssertionStatus.USER_REVOKED_ACCESS.name().equals(assertion.getStatus())) {
storeError(assertion, 0, e.getMessage(), AssertionStatus.ERROR_DELETING_IN_ORCID);
throw new RegistryDeleteFailureException();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

@Service
Expand Down Expand Up @@ -117,7 +118,7 @@ public String generateLinkForEmail(String email) {
String salesforceId = assertionsUserService.getLoggedInUserSalesforceId();
return generateLinkForEmailAndSalesforceId(email, salesforceId);
}

public String generateLinkForEmailAndSalesforceId(String email, String salesforceId) {
String landingPageUrl = applicationProperties.getLandingPageUrl();
Optional<OrcidRecord> record = orcidRecordRepository.findOneByEmail(email);
Expand Down Expand Up @@ -178,14 +179,18 @@ public void deleteOrcidRecordTokenByEmailAndSalesforceId(String email, String sa
}
}
}

public boolean userHasGrantedOrDeniedPermission(String email, String salesforceId) {
Optional<OrcidRecord> orcidRecordOptional = findOneByEmail(email);
if (orcidRecordOptional.isEmpty()) {
return false;
}

return !StringUtils.isBlank(orcidRecordOptional.get().getToken(salesforceId, true));
}

public boolean updateTokenSalesforceIds(String salesforceId, String newSalesforceId) {
orcidRecordRepository.updateTokenSalesforceIds(salesforceId, newSalesforceId);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public class AssertionResource {

@Autowired
private NotificationService notificationService;

@Autowired
private MemberService memberService;

Expand Down Expand Up @@ -452,6 +452,7 @@ private String encodeUrl(String urlString) throws MalformedURLException, URISynt
public ResponseEntity<Void> updateSalesforceId(@PathVariable String salesforceId, @PathVariable String newSalesforceId) {
LOG.debug("REST request to update Assertions by salesforce : {}", salesforceId);
boolean success = assertionService.updateAssertionsSalesforceId(salesforceId, newSalesforceId);
success = success && orcidRecordService.updateTokenSalesforceIds(salesforceId, newSalesforceId);
if (success) {
return ResponseEntity.ok().headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, "assertion", salesforceId)).build();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,33 @@ void testDeleteByIdWithRegistryDeleteAndNoOtherAssertionsForUser()
Mockito.verify(orcidAPIClient, Mockito.times(1)).deleteAffiliation(Mockito.anyString(), Mockito.eq("exchange-token"), Mockito.any(Assertion.class));
}

@Test
void testDeleteByIdWithUserRevokedAccessStatus()
throws org.json.JSONException, ClientProtocolException, IOException, RegistryDeleteFailureException, DeactivatedException, DeprecatedException {
Assertion assertion = getAssertionWithEmailAndPutCode("test@orcid.org", "1001");
assertion.setSalesforceId("salesforce-id");
assertion.setStatus(AssertionStatus.USER_REVOKED_ACCESS.name());

Mockito.when(assertionRepository.findById(Mockito.eq("id"))).thenReturn(Optional.of(assertion));
Mockito.when(assertionsUserService.getLoggedInUserSalesforceId()).thenReturn("salesforce-id");
Mockito.when(orcidRecordService.findOneByEmail(Mockito.eq("test@orcid.org"))).thenReturn(getOptionalOrcidRecordWithIdToken());
Mockito.when(orcidAPIClient.exchangeToken(Mockito.anyString(), Mockito.anyString())).thenReturn("exchange-token");
Mockito.doThrow(new RuntimeException("some kind of exception")).when(orcidAPIClient).deleteAffiliation(Mockito.anyString(), Mockito.eq("exchange-token"), Mockito.any(Assertion.class));
Mockito.when(assertionRepository.countByEmailAndSalesforceId(Mockito.eq("test@orcid.org"), Mockito.eq(DEFAULT_SALESFORCE_ID))).thenReturn(0l);

Mockito.doNothing().when(assertionRepository).deleteById(Mockito.eq("id"));

assertionService.deleteById("id", getUser());

Mockito.verify(assertionRepository, Mockito.times(1)).deleteById(Mockito.eq("id"));
Mockito.verify(orcidRecordService).deleteOrcidRecordTokenByEmailAndSalesforceId(Mockito.eq("test@orcid.org"), Mockito.eq(DEFAULT_SALESFORCE_ID));

Mockito.verify(assertionRepository, Mockito.times(1)).findById(Mockito.eq("id"));
Mockito.verify(orcidRecordService, Mockito.atLeastOnce()).findOneByEmail(Mockito.eq("test@orcid.org"));
Mockito.verify(orcidAPIClient, Mockito.times(1)).exchangeToken(Mockito.anyString(), Mockito.anyString());
Mockito.verify(orcidAPIClient, Mockito.times(1)).deleteAffiliation(Mockito.anyString(), Mockito.eq("exchange-token"), Mockito.any(Assertion.class));
}

@Test
void testDeleteByIdWithoutRegistryDeleteAndOtherAssertionsForUser()
throws org.json.JSONException, ClientProtocolException, IOException, RegistryDeleteFailureException, DeactivatedException, DeprecatedException {
Expand Down Expand Up @@ -1835,10 +1862,13 @@ void testUpdateAssertionsSalesforceId() {
;
Mockito.when(assertionRepository.findBySalesforceId(Mockito.eq("salesforce-id"), Mockito.any(Pageable.class))).thenReturn(new PageImpl<Assertion>(firstPage))
.thenReturn(new PageImpl<Assertion>(secondPage)).thenReturn(new PageImpl<Assertion>(thirdPage)).thenReturn(new PageImpl<Assertion>(new ArrayList<>()));
Mockito.when(orcidRecordService.updateTokenSalesforceIds(Mockito.anyString(), Mockito.anyString())).thenReturn(true);

boolean success = assertionService.updateAssertionsSalesforceId("salesforce-id", "new-salesforce-id");
assertThat(success).isTrue();

Mockito.verify(assertionRepository, Mockito.times((AssertionService.REGISTRY_SYNC_BATCH_SIZE * 3) - 10)).save(assertionCaptor.capture());
Mockito.verify(orcidRecordService).updateTokenSalesforceIds(Mockito.anyString(), Mockito.anyString());
List<Assertion> saved = assertionCaptor.getAllValues();
saved.forEach(a -> assertThat(a.getSalesforceId()).isEqualTo("new-salesforce-id"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ class AssertionResourceTest {

@Mock
private RorOrgValidator rorOrgValidator;

@Mock
private MemberService memberService;

@Mock
private NotificationService notificationService;

Expand All @@ -101,7 +101,7 @@ class AssertionResourceTest {

@Mock
private GridOrgValidator gridOrgValidator;

@InjectMocks
private AssertionResource assertionResource;

Expand All @@ -115,7 +115,7 @@ public void setUp() {
Mockito.when(assertionsUserService.getLoggedInUser()).thenReturn(getUser());
Mockito.when(assertionsUserService.getLoggedInUserSalesforceId()).thenReturn(DEFAULT_SALESFORCE_ID);
}

@Test
void testGetAssertionOfPendingStatus() {
Assertion pendingAssertion = new Assertion();
Expand All @@ -126,7 +126,7 @@ void testGetAssertionOfPendingStatus() {
Mockito.verify(assertionService).findById(Mockito.eq("test"));
Mockito.verify(assertionService).populatePermissionLink(Mockito.any(Assertion.class));
}

@Test
void testGetAssertionOfNotificationSentStatus() {
Assertion pendingAssertion = new Assertion();
Expand All @@ -137,7 +137,7 @@ void testGetAssertionOfNotificationSentStatus() {
Mockito.verify(assertionService).findById(Mockito.eq("test"));
Mockito.verify(assertionService).populatePermissionLink(Mockito.any(Assertion.class));
}

@Test
void testGetAssertionOfDeniedAccessStatus() {
Assertion pendingAssertion = new Assertion();
Expand All @@ -148,7 +148,7 @@ void testGetAssertionOfDeniedAccessStatus() {
Mockito.verify(assertionService).findById(Mockito.eq("test"));
Mockito.verify(assertionService).populatePermissionLink(Mockito.any(Assertion.class));
}

@Test
void testGetAssertionOfRevokedAccessStatus() {
Assertion pendingAssertion = new Assertion();
Expand All @@ -159,7 +159,7 @@ void testGetAssertionOfRevokedAccessStatus() {
Mockito.verify(assertionService).findById(Mockito.eq("test"));
Mockito.verify(assertionService).populatePermissionLink(Mockito.any(Assertion.class));
}

@Test
void testGetAssertionOfInOrcidStatus() {
Assertion pendingAssertion = new Assertion();
Expand All @@ -169,7 +169,7 @@ void testGetAssertionOfInOrcidStatus() {
Mockito.verify(assertionService).findById(Mockito.eq("test"));
Mockito.verify(assertionService, Mockito.never()).populatePermissionLink(Mockito.any(Assertion.class));
}

@Test
void testSendNotifications() {
Mockito.when(assertionsUserService.getLoggedInUser()).thenReturn(getUser());
Expand All @@ -180,23 +180,23 @@ void testSendNotifications() {
Mockito.verify(assertionService).markPendingAssertionsAsNotificationRequested(Mockito.eq(DEFAULT_SALESFORCE_ID));
Mockito.verify(memberService).updateMemberDefaultLanguage(Mockito.eq(DEFAULT_SALESFORCE_ID), Mockito.eq("en"));
}

@Test
void testGetNotificationRequestInProgress_inProgressIsTrue() {
Mockito.when(assertionsUserService.getLoggedInUserSalesforceId()).thenReturn(DEFAULT_SALESFORCE_ID);
Mockito.when(notificationService.requestInProgress(Mockito.eq(DEFAULT_SALESFORCE_ID))).thenReturn(true);

ResponseEntity<NotificationRequestInProgress> response = assertionResource.getNotificationRequestInProgress();
assertTrue(response.getStatusCode().is2xxSuccessful());
assertNotNull(response.getBody());
assertTrue(response.getBody().getInProgress());
}

@Test
void testGetNotificationRequestInProgress_inProgressIsFalse() {
Mockito.when(assertionsUserService.getLoggedInUserSalesforceId()).thenReturn(DEFAULT_SALESFORCE_ID);
Mockito.when(notificationService.requestInProgress(Mockito.eq(DEFAULT_SALESFORCE_ID))).thenReturn(false);

ResponseEntity<NotificationRequestInProgress> response = assertionResource.getNotificationRequestInProgress();
assertTrue(response.getStatusCode().is2xxSuccessful());
assertNotNull(response.getBody());
Expand Down Expand Up @@ -390,14 +390,15 @@ void testGetAssertions() throws BadRequestAlertException, org.codehaus.jettison.
ResponseEntity<List<Assertion>> page = assertionResource.getAssertions(Mockito.mock(Pageable.class), new HttpHeaders(), UriComponentsBuilder.newInstance(), "");
assertNotNull(page.getBody());
}

@Test
void testUpdateSalesforceId() {
Mockito.when(assertionService.updateAssertionsSalesforceId(Mockito.eq("salesforce-id"), Mockito.eq("new-salesforce-id"))).thenReturn(true);
Mockito.when(orcidRecordService.updateTokenSalesforceIds(Mockito.eq("salesforce-id"), Mockito.eq("new-salesforce-id"))).thenReturn(true);
ResponseEntity<Void> response = assertionResource.updateSalesforceId("salesforce-id", "new-salesforce-id");
assertTrue(response.getStatusCode().is2xxSuccessful());
}

@Test
void testUpdateSalesforceIdWithError() {
Mockito.when(assertionService.updateAssertionsSalesforceId(Mockito.eq("salesforce-id"), Mockito.eq("new-salesforce-id"))).thenReturn(false);
Expand Down Expand Up @@ -477,7 +478,7 @@ private AssertionServiceUser getUser() {
user.setLangKey("en");
return user;
}

private NotificationRequest getNotificationRequest() {
NotificationRequest request = new NotificationRequest();
request.setLanguage("en");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ public interface UserServiceClient {
ResponseEntity<Void> deleteUser(@PathVariable("loginOrId") String loginOrId,
@RequestParam(value = "noMainContactCheck", required = false) boolean noMainContactCheck);

@RequestMapping(method = RequestMethod.PUT, value = "/api/users/memberName/{salesforceId}/{newMemberName}", consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
@HystrixProperty(name = "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds", value = "50000")
ResponseEntity<String> updateUsersMemberNames(@PathVariable("salesforceId") String salesforceId, @PathVariable("newMemberName") String newMemberName);
}
Loading
Loading