diff --git a/orcid-api-web/src/main/java/org/orcid/api/memberV2/server/delegator/impl/MemberV2ApiServiceDelegatorImpl.java b/orcid-api-web/src/main/java/org/orcid/api/memberV2/server/delegator/impl/MemberV2ApiServiceDelegatorImpl.java index 0654b266661..da96bc53de5 100644 --- a/orcid-api-web/src/main/java/org/orcid/api/memberV2/server/delegator/impl/MemberV2ApiServiceDelegatorImpl.java +++ b/orcid-api-web/src/main/java/org/orcid/api/memberV2/server/delegator/impl/MemberV2ApiServiceDelegatorImpl.java @@ -251,6 +251,7 @@ public Response viewRecord(String orcid) { Record record = recordManagerReadOnly.getRecord(orcid); orcidSecurityManager.checkAndFilter(orcid, record); if (record.getPerson() != null) { + emailDomainManager.processProfessionalEmailsForV2API(record.getPerson().getEmails()); sourceUtils.setSourceName(record.getPerson()); } if (record.getActivitiesSummary() != null) { @@ -797,8 +798,7 @@ public Response viewEmails(String orcid) { orcidSecurityManager.checkAndFilter(orcid, emails.getEmails(), ScopePathType.ORCID_BIO_READ_LIMITED); } - processProfessionalEmails(emails); - + emailDomainManager.processProfessionalEmailsForV2API(emails); ElementUtils.setPathToEmail(emails, orcid); Api2_0_LastModifiedDatesHelper.calculateLastModified(emails); sourceUtils.setSourceName(emails); @@ -1066,6 +1066,7 @@ public Response viewPersonalDetails(String orcid) { public Response viewPerson(String orcid) { Person person = personDetailsManagerReadOnly.getPersonDetails(orcid); orcidSecurityManager.checkAndFilter(orcid, person); + emailDomainManager.processProfessionalEmailsForV2API(person.getEmails()); ElementUtils.setPathToPerson(person, orcid); Api2_0_LastModifiedDatesHelper.calculateLastModified(person); sourceUtils.setSourceName(person); @@ -1113,22 +1114,6 @@ private void validateSearchParams(Map> queryMap) { } } - private void processProfessionalEmails(Emails emails) { - for (Email email : emails.getEmails()) { - if (email.isVerified()) { - String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - if(email.getSource() == null) { - email.setSource(new Source()); - } - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); - } - } - } - } - @Override public Response viewClient(String clientId) { orcidSecurityManager.checkScopes(ScopePathType.READ_PUBLIC); diff --git a/orcid-api-web/src/main/java/org/orcid/api/memberV3/server/delegator/impl/MemberV3ApiServiceDelegatorImpl.java b/orcid-api-web/src/main/java/org/orcid/api/memberV3/server/delegator/impl/MemberV3ApiServiceDelegatorImpl.java index 64c5828c38f..5df29f5eede 100644 --- a/orcid-api-web/src/main/java/org/orcid/api/memberV3/server/delegator/impl/MemberV3ApiServiceDelegatorImpl.java +++ b/orcid-api-web/src/main/java/org/orcid/api/memberV3/server/delegator/impl/MemberV3ApiServiceDelegatorImpl.java @@ -307,6 +307,7 @@ public Response viewRecord(String orcid) { Record record = recordManagerReadOnly.getRecord(orcid, filterVersionOfIdentifiers); orcidSecurityManager.checkAndFilter(orcid, record); if (record.getPerson() != null) { + emailDomainManager.processProfessionalEmailsForV3API(record.getPerson().getEmails()); sourceUtils.setSourceName(record.getPerson()); } if (record.getActivitiesSummary() != null) { @@ -885,7 +886,7 @@ public Response viewEmails(String orcid) { orcidSecurityManager.checkAndFilter(orcid, emails.getEmails(), ScopePathType.ORCID_BIO_READ_LIMITED); } - processProfessionalEmails(emails); + emailDomainManager.processProfessionalEmailsForV3API(emails); ElementUtils.setPathToEmail(emails, orcid); Api3_0LastModifiedDatesHelper.calculateLastModified(emails); @@ -1165,6 +1166,7 @@ public Response viewPerson(String orcid) { checkProfileStatus(orcid, true); Person person = personDetailsManagerReadOnly.getPersonDetails(orcid, false); orcidSecurityManager.checkAndFilter(orcid, person); + emailDomainManager.processProfessionalEmailsForV3API(person.getEmails()); ElementUtils.setPathToPerson(person, orcid); Api3_0LastModifiedDatesHelper.calculateLastModified(person); sourceUtils.setSourceName(person); @@ -1227,19 +1229,6 @@ private void validateSearchParams(Map> queryMap) { } } - private void processProfessionalEmails(Emails emails) { - for (Email email : emails.getEmails()) { - if (email.isVerified()) { - String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); - } - } - } - } - @Override public Response viewClient(String clientId) { orcidSecurityManager.checkScopes(ScopePathType.READ_PUBLIC); diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_EmailsTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_EmailsTest.java index 3768a1cb475..480892d05de 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_EmailsTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_EmailsTest.java @@ -1,10 +1,6 @@ package org.orcid.api.memberV2.server.delegator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -39,6 +35,8 @@ import org.orcid.test.helper.Utils; import org.springframework.test.context.ContextConfiguration; +import static org.junit.Assert.*; + @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-orcid-api-web-context.xml" }) public class MemberV2ApiServiceDelegator_EmailsTest extends DBUnitTest { @@ -69,13 +67,51 @@ public void testViewEmailsWrongToken() { } @Test - public void testViewEmailsReadPublic() { + public void testViewEmailsReadPublic_withSourceClient() { SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_PUBLIC); Response r = serviceDelegator.viewEmails(ORCID); Emails element = (Emails) r.getEntity(); assertNotNull(element); assertEquals("/0000-0000-0000-0003/email", element.getPath()); - Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); + assertEquals(4, element.getEmails().size()); + + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : element.getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + + assertTrue(emails.isEmpty()); + } + + @Test + public void testViewEmailsReadPublic_withOtherClient() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555556", ScopePathType.READ_PUBLIC); + Response r = serviceDelegator.viewEmails(ORCID); + Emails element = (Emails) r.getEntity(); + assertNotNull(element); + assertEquals("/0000-0000-0000-0003/email", element.getPath()); + assertEquals(2, element.getEmails().size()); + + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + + for(Email e : element.getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + + assertTrue(emails.isEmpty()); } @Test @@ -154,4 +190,32 @@ public void testViewEmails() { assertEquals(true, email.isVerified()); assertEquals(false, email.isPrimary()); } + + @Test + public void checkSourceOnEmail_EmailEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewEmails(orcid); + Emails emails = (Emails) r.getEntity(); + checkEmails(emails); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on verified professional email addresses should change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadPersonTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadPersonTest.java index 863aefb1011..00f70fc0f38 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadPersonTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadPersonTest.java @@ -1,10 +1,6 @@ package org.orcid.api.memberV2.server.delegator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -46,6 +42,8 @@ import org.orcid.test.helper.Utils; import org.springframework.test.context.ContextConfiguration; +import static org.junit.Assert.*; + @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-orcid-api-web-context.xml" }) public class MemberV2ApiServiceDelegator_ReadPersonTest extends DBUnitTest { @@ -84,6 +82,22 @@ public void testViewPersonReadPublic() { assertNotNull(element); assertEquals("/0000-0000-0000-0003/person", element.getPath()); Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); + assertNotNull(element.getEmails()); + assertEquals(4, element.getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : element.getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + + assertTrue(emails.isEmpty()); } @Test @@ -617,4 +631,33 @@ private void assertAllPublicButEmails(Person p) { assertEquals(Long.valueOf(13), ru.getResearcherUrls().get(0).getPutCode()); assertEquals(Visibility.PUBLIC, ru.getResearcherUrls().get(0).getVisibility()); } + + @Test + public void checkSourceOnEmail_PersonEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewPerson(orcid); + Person p = (Person) r.getEntity(); + assertNotNull(p.getEmails()); + checkEmails(p.getEmails()); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on verified professional email addresses should change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadRecordTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadRecordTest.java index 411910f718e..a09cce6c243 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadRecordTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV2/server/delegator/MemberV2ApiServiceDelegator_ReadRecordTest.java @@ -1,11 +1,6 @@ package org.orcid.api.memberV2.server.delegator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -65,6 +60,8 @@ import org.orcid.test.helper.Utils; import org.springframework.test.context.ContextConfiguration; +import static org.junit.Assert.*; + @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-orcid-api-web-context.xml" }) public class MemberV2ApiServiceDelegator_ReadRecordTest extends DBUnitTest { @@ -115,6 +112,51 @@ public void testViewRecordReadPublic() { Utils.assertIsPublicOrSource(record.getActivitiesSummary(), "APP-5555555555555555"); assertEquals("/0000-0000-0000-0003/person", record.getPerson().getPath()); Utils.assertIsPublicOrSource(record.getPerson(), "APP-5555555555555555"); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + assertEquals(4, record.getPerson().getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : record.getPerson().getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + + assertTrue(emails.isEmpty()); + } + + @Test + public void testViewRecordReadPublic_clientThatIsNotTheSourceOfEmails() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555556", ScopePathType.READ_PUBLIC); + Response r = serviceDelegator.viewRecord(ORCID); + Record record = (Record) r.getEntity(); + assertNotNull(record); + assertEquals("/0000-0000-0000-0003", record.getPath()); + assertEquals("/0000-0000-0000-0003/activities", record.getActivitiesSummary().getPath()); + Utils.assertIsPublicOrSource(record.getActivitiesSummary(), "APP-5555555555555556"); + assertEquals("/0000-0000-0000-0003/person", record.getPerson().getPath()); + Utils.assertIsPublicOrSource(record.getPerson(), "APP-5555555555555556"); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + assertEquals(2, record.getPerson().getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + + for(Email e : record.getPerson().getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + + assertTrue(emails.isEmpty()); } @Test(expected = OrcidUnauthorizedException.class) @@ -227,28 +269,23 @@ public void testViewRecord() { for (Email email : person.getEmails().getEmails()) { Utils.verifyLastModified(email.getLastModifiedDate()); if (email.getEmail().equals("public_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PUBLIC.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("limited_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.LIMITED.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("private_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PRIVATE.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("self_limited_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("0000-0000-0000-0003", email.getSource().retrieveSourcePath()); - assertNotNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.LIMITED.value(), email.getVisibility().value()); - assertEquals("Credit Name", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("public_0000-0000-0000-0003@orcid.org")) { assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PUBLIC.value(), email.getVisibility().value()); assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else { @@ -1118,4 +1155,34 @@ private void assertAllPublicButEmails(Person p) { assertEquals(Long.valueOf(13), ru.getResearcherUrls().get(0).getPutCode()); assertEquals(Visibility.PUBLIC, ru.getResearcherUrls().get(0).getVisibility()); } + + @Test + public void checkSourceOnEmail_RecordEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewRecord(orcid); + Record record = (Record) r.getEntity(); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + checkEmails(record.getPerson().getEmails()); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on verified professional email addresses should change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_EmailsTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_EmailsTest.java index 2319a2fdcb6..1739604bfef 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_EmailsTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_EmailsTest.java @@ -2,12 +2,9 @@ import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -86,7 +83,41 @@ public void testViewEmailsReadPublic() { Emails element = (Emails) r.getEntity(); assertNotNull(element); assertEquals("/0000-0000-0000-0003/email", element.getPath()); - Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); + assertEquals(4, element.getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : element.getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); + } + + @Test + public void testViewEmailsReadPublic_ClientNotSourceOfAnyEmail() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555556", ScopePathType.READ_PUBLIC); + Response r = serviceDelegator.viewEmails(ORCID); + Emails element = (Emails) r.getEntity(); + assertNotNull(element); + assertEquals("/0000-0000-0000-0003/email", element.getPath()); + assertEquals(2, element.getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + + for(Email e : element.getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); } @Test @@ -162,4 +193,32 @@ public void testViewEmails() { assertEquals(true, email.isVerified()); assertEquals(false, email.isPrimary()); } + + @Test + public void checkSourceOnEmail_EmailEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.EMAIL_READ_PRIVATE); + Response r = serviceDelegator.viewEmails(orcid); + Emails emails = (Emails) r.getEntity(); + checkEmails(emails); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on non verified professional email addresses should not change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadPersonTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadPersonTest.java index 3a70f980461..cf9dcee9c58 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadPersonTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadPersonTest.java @@ -1,10 +1,6 @@ package org.orcid.api.memberV3.server.delegator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -21,37 +17,14 @@ import org.orcid.jaxb.model.groupid_v2.GroupIdRecord; import org.orcid.jaxb.model.message.ScopePathType; import org.orcid.jaxb.model.v3.release.common.Visibility; -import org.orcid.jaxb.model.v3.release.record.Address; -import org.orcid.jaxb.model.v3.release.record.Addresses; -import org.orcid.jaxb.model.v3.release.record.Biography; -import org.orcid.jaxb.model.v3.release.record.Distinction; -import org.orcid.jaxb.model.v3.release.record.Education; -import org.orcid.jaxb.model.v3.release.record.Email; -import org.orcid.jaxb.model.v3.release.record.Emails; -import org.orcid.jaxb.model.v3.release.record.Employment; -import org.orcid.jaxb.model.v3.release.record.Funding; -import org.orcid.jaxb.model.v3.release.record.InvitedPosition; -import org.orcid.jaxb.model.v3.release.record.Keyword; -import org.orcid.jaxb.model.v3.release.record.Keywords; -import org.orcid.jaxb.model.v3.release.record.Membership; -import org.orcid.jaxb.model.v3.release.record.OtherName; -import org.orcid.jaxb.model.v3.release.record.OtherNames; -import org.orcid.jaxb.model.v3.release.record.PeerReview; -import org.orcid.jaxb.model.v3.release.record.Person; -import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifier; -import org.orcid.jaxb.model.v3.release.record.PersonExternalIdentifiers; -import org.orcid.jaxb.model.v3.release.record.Qualification; -import org.orcid.jaxb.model.v3.release.record.ResearchResource; -import org.orcid.jaxb.model.v3.release.record.ResearcherUrl; -import org.orcid.jaxb.model.v3.release.record.ResearcherUrls; -import org.orcid.jaxb.model.v3.release.record.Service; -import org.orcid.jaxb.model.v3.release.record.Work; -import org.orcid.jaxb.model.v3.release.record.WorkBulk; +import org.orcid.jaxb.model.v3.release.record.*; import org.orcid.test.DBUnitTest; import org.orcid.test.OrcidJUnit4ClassRunner; import org.orcid.test.helper.v3.Utils; import org.springframework.test.context.ContextConfiguration; +import static org.junit.Assert.*; + @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-orcid-api-web-context.xml" }) public class MemberV3ApiServiceDelegator_ReadPersonTest extends DBUnitTest { @@ -90,6 +63,46 @@ public void testViewPersonReadPublic() { assertNotNull(element); assertEquals("/0000-0000-0000-0003/person", element.getPath()); Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); + assertNotNull(element.getEmails()); + assertNotNull(element.getEmails().getEmails()); + assertEquals(4, element.getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : element.getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); + } + + @Test + public void testViewPersonReadPublic_ClientNotSourceOfAnyEmail() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555556", ScopePathType.READ_PUBLIC); + Response r = serviceDelegator.viewPerson(ORCID); + Person element = (Person) r.getEntity(); + assertNotNull(element); + assertEquals("/0000-0000-0000-0003/person", element.getPath()); + Utils.assertIsPublicOrSource(element, "APP-5555555555555556"); + assertNotNull(element.getEmails()); + assertNotNull(element.getEmails().getEmails()); + assertEquals(2, element.getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + + for(Email e : element.getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); } @Test @@ -625,4 +638,33 @@ private void assertAllPublicButEmails(Person p) { assertEquals(Long.valueOf(13), ru.getResearcherUrls().get(0).getPutCode()); assertEquals(Visibility.PUBLIC, ru.getResearcherUrls().get(0).getVisibility()); } + + @Test + public void checkSourceOnEmail_PersonEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewPerson(orcid); + Person p = (Person) r.getEntity(); + assertNotNull(p.getEmails()); + checkEmails(p.getEmails()); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on non verified professional email addresses should not change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadRecordTest.java b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadRecordTest.java index 48ad1611ad1..c64cb0978d2 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadRecordTest.java +++ b/orcid-api-web/src/test/java/org/orcid/api/memberV3/server/delegator/MemberV3ApiServiceDelegator_ReadRecordTest.java @@ -1,11 +1,6 @@ package org.orcid.api.memberV3.server.delegator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -77,6 +72,8 @@ import org.orcid.test.helper.v3.Utils; import org.springframework.test.context.ContextConfiguration; +import static org.junit.Assert.*; + @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:test-orcid-api-web-context.xml" }) public class MemberV3ApiServiceDelegator_ReadRecordTest extends DBUnitTest { @@ -103,30 +100,61 @@ public static void removeDBUnitData() throws Exception { } @Test - public void testViewRecordWrongScope() { - SecurityContextTestUtils.setUpSecurityContext(ORCID, ScopePathType.READ_PUBLIC); - Response response = serviceDelegator.viewRecord(ORCID); - // Verify everything inside is public - Record record = (Record) response.getEntity(); + public void testViewRecordReadPublic() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_PUBLIC); + Response r = serviceDelegator.viewRecord(ORCID); + Record record = (Record) r.getEntity(); assertNotNull(record); assertEquals("/0000-0000-0000-0003", record.getPath()); assertEquals("/0000-0000-0000-0003/activities", record.getActivitiesSummary().getPath()); - Utils.assertIsPublicOrSource(record.getActivitiesSummary(), SecurityContextTestUtils.DEFAULT_CLIENT_ID); + Utils.assertIsPublicOrSource(record.getActivitiesSummary(), "APP-5555555555555555"); assertEquals("/0000-0000-0000-0003/person", record.getPerson().getPath()); - Utils.assertIsPublicOrSource(record.getPerson(), SecurityContextTestUtils.DEFAULT_CLIENT_ID); + Utils.assertIsPublicOrSource(record.getPerson(), "APP-5555555555555555"); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + assertNotNull(record.getPerson().getEmails().getEmails()); + assertEquals(4, record.getPerson().getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + emails.add("limited_0000-0000-0000-0003@test.orcid.org"); + emails.add("private_0000-0000-0000-0003@test.orcid.org"); + + for(Email e : record.getPerson().getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); } @Test - public void testViewRecordReadPublic() { - SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_PUBLIC); + public void testViewRecordReadPublic_ClientNotSourceOfAnyEmail() { + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555556", ScopePathType.READ_PUBLIC); Response r = serviceDelegator.viewRecord(ORCID); Record record = (Record) r.getEntity(); assertNotNull(record); assertEquals("/0000-0000-0000-0003", record.getPath()); assertEquals("/0000-0000-0000-0003/activities", record.getActivitiesSummary().getPath()); - Utils.assertIsPublicOrSource(record.getActivitiesSummary(), "APP-5555555555555555"); + Utils.assertIsPublicOrSource(record.getActivitiesSummary(), "APP-5555555555555556"); assertEquals("/0000-0000-0000-0003/person", record.getPerson().getPath()); - Utils.assertIsPublicOrSource(record.getPerson(), "APP-5555555555555555"); + Utils.assertIsPublicOrSource(record.getPerson(), "APP-5555555555555556"); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + assertNotNull(record.getPerson().getEmails().getEmails()); + assertEquals(2, record.getPerson().getEmails().getEmails().size()); + List emails = new ArrayList<>(); + emails.add("public_0000-0000-0000-0003@test.orcid.org"); + emails.add("public_0000-0000-0000-0003@orcid.org"); + + for(Email e : record.getPerson().getEmails().getEmails()) { + if(!emails.contains(e.getEmail())) { + fail(e.getEmail() + " is not in the email list"); + } + emails.remove(e.getEmail()); + } + assertTrue(emails.isEmpty()); } @Test(expected = OrcidUnauthorizedException.class) @@ -239,28 +267,23 @@ public void testViewRecord() { for (Email email : person.getEmails().getEmails()) { Utils.verifyLastModified(email.getLastModifiedDate()); if (email.getEmail().equals("public_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PUBLIC.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("limited_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.LIMITED.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("private_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PRIVATE.value(), email.getVisibility().value()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("self_limited_0000-0000-0000-0003@test.orcid.org")) { - assertEquals("0000-0000-0000-0003", email.getSource().retrieveSourcePath()); - assertNotNull(email.getSource().getSourceOrcid()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.LIMITED.value(), email.getVisibility().value()); - assertEquals("Credit Name", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else if (email.getEmail().equals("public_0000-0000-0000-0003@orcid.org")) { assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); - assertNull(email.getSource().getSourceOrcid()); assertEquals(org.orcid.jaxb.model.common_v2.Visibility.PUBLIC.value(), email.getVisibility().value()); assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); } else { @@ -1323,4 +1346,34 @@ private void assertAllPublicButEmails(Person p) { assertEquals(Long.valueOf(13), ru.getResearcherUrls().get(0).getPutCode()); assertEquals(Visibility.PUBLIC, ru.getResearcherUrls().get(0).getVisibility()); } + + @Test + public void checkSourceOnEmail_RecordEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.EMAIL_READ_PRIVATE); + Response r = serviceDelegator.viewRecord(orcid); + Record record = (Record) r.getEntity(); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + checkEmails(record.getPerson().getEmails()); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("limited_verified_0000-0000-0000-0001@test.orcid.org")) { + assertTrue(e.isVerified()); + // The source and name on non verified professional email addresses should not change + assertEquals("0000-0000-0000-0000", e.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-api-web/src/test/java/org/orcid/test/helper/Utils.java b/orcid-api-web/src/test/java/org/orcid/test/helper/Utils.java index 291879b117d..8f1750d0391 100644 --- a/orcid-api-web/src/test/java/org/orcid/test/helper/Utils.java +++ b/orcid-api-web/src/test/java/org/orcid/test/helper/Utils.java @@ -151,12 +151,12 @@ public static void assertIsPublicOrSource(Person p, String sourceId) { } assertIsPublicOrSource(p.getAddresses(), sourceId); assertIsPublicOrSource(p.getBiography(), sourceId); - assertIsPublicOrSource(p.getEmails(), sourceId); assertIsPublicOrSource(p.getExternalIdentifiers(), sourceId); assertIsPublicOrSource(p.getKeywords(), sourceId); assertIsPublicOrSource(p.getName(), sourceId); assertIsPublicOrSource(p.getOtherNames(), sourceId); assertIsPublicOrSource(p.getResearcherUrls(), sourceId); + // EMAILS ARE NOT TESTED! Source on professional emails is overwritten, so, you must verify the email on each test! } public static void verifyLastModified(LastModifiedDate l) { diff --git a/orcid-api-web/src/test/java/org/orcid/test/helper/v3/Utils.java b/orcid-api-web/src/test/java/org/orcid/test/helper/v3/Utils.java index d5332778b71..c1832e0cd58 100644 --- a/orcid-api-web/src/test/java/org/orcid/test/helper/v3/Utils.java +++ b/orcid-api-web/src/test/java/org/orcid/test/helper/v3/Utils.java @@ -162,12 +162,12 @@ public static void assertIsPublicOrSource(Person p, String sourceId) { } assertIsPublicOrSource(p.getAddresses(), sourceId); assertIsPublicOrSource(p.getBiography(), sourceId); - assertIsPublicOrSource(p.getEmails(), sourceId); assertIsPublicOrSource(p.getExternalIdentifiers(), sourceId); assertIsPublicOrSource(p.getKeywords(), sourceId); assertIsPublicOrSource(p.getName(), sourceId); assertIsPublicOrSource(p.getOtherNames(), sourceId); assertIsPublicOrSource(p.getResearcherUrls(), sourceId); + // EMAILS ARE NOT TESTED! Source on professional emails is overwritten, so, you must verify the email on each test! } public static void verifyLastModified(LastModifiedDate l) { diff --git a/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java b/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java index 838e3a0c4f9..02a51765f4e 100644 --- a/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java +++ b/orcid-core/src/main/java/org/orcid/core/common/manager/EmailDomainManager.java @@ -10,9 +10,13 @@ public interface EmailDomainManager { boolean updateCategory(long id, EmailDomainEntity.DomainCategory category); - EmailDomainEntity findByEmailDomain(String emailDomain); + List findByEmailDomain(String emailDomain); List findByCategory(EmailDomainEntity.DomainCategory category); STATUS createOrUpdateEmailDomain(String emailDomain, String rorId); + + void processProfessionalEmailsForV2API(org.orcid.jaxb.model.record_v2.Emails emails); + + void processProfessionalEmailsForV3API(org.orcid.jaxb.model.v3.release.record.Emails emails); } diff --git a/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java b/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java index 73f34bd4ca8..99d63846bed 100644 --- a/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/common/manager/impl/EmailDomainManagerImpl.java @@ -4,7 +4,13 @@ import javax.annotation.Resource; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; import org.orcid.core.common.manager.EmailDomainManager; +import org.orcid.core.utils.SourceEntityUtils; +import org.orcid.core.utils.emailDomain.EmailDomainValidator; +import org.orcid.jaxb.model.common_v2.Source; +import org.orcid.jaxb.model.record_v2.Email; +import org.orcid.jaxb.model.record_v2.Emails; import org.orcid.persistence.dao.EmailDomainDao; import org.orcid.persistence.jpa.entities.EmailDomainEntity; import org.orcid.persistence.jpa.entities.EmailDomainEntity.DomainCategory; @@ -21,6 +27,9 @@ public enum STATUS {CREATED, UPDATED}; @Resource(name = "emailDomainDaoReadOnly") private EmailDomainDao emailDomainDaoReadOnly; + @Resource + private SourceEntityUtils sourceEntityUtils; + private void validateEmailDomain(String emailDomain) { if (emailDomain == null || emailDomain.isBlank()) { throw new IllegalArgumentException("Email Domain must not be empty"); @@ -48,11 +57,24 @@ public boolean updateCategory(long id, DomainCategory category) { } @Override - public EmailDomainEntity findByEmailDomain(String emailDomain) { + public List findByEmailDomain(String emailDomain) { if (emailDomain == null || emailDomain.isBlank()) { throw new IllegalArgumentException("Email Domain must not be empty"); } - return emailDomainDaoReadOnly.findByEmailDomain(emailDomain); + + // Fetch entries for the current email domain + List results = emailDomainDaoReadOnly.findByEmailDomain(emailDomain); + + // If no results and domain contains a dot, strip the first subdomain and recurse + if (results.isEmpty() && emailDomain.contains(".")) { + String strippedDomain = emailDomain.substring(emailDomain.indexOf(".") + 1); + if(EmailDomainValidator.getInstance().isValidEmailDomain(strippedDomain)) { + return findByEmailDomain(strippedDomain); // Recursive call with stripped domain + } + } + + // Return the results (either found or empty if no more subdomains) + return results; } @Override @@ -65,12 +87,14 @@ public List findByCategory(DomainCategory category) { @Override public STATUS createOrUpdateEmailDomain(String emailDomain, String rorId) { - EmailDomainEntity existingEntity = emailDomainDaoReadOnly.findByEmailDomain(emailDomain); - if(existingEntity != null) { - if(!rorId.equals(existingEntity.getRorId())) { - boolean updated = emailDomainDao.updateRorId(existingEntity.getId(), rorId); - if(updated) - return STATUS.UPDATED; + List existingEntities = emailDomainDaoReadOnly.findByEmailDomain(emailDomain); + if(existingEntities != null && !existingEntities.isEmpty()) { + if(existingEntities.size() == 1) { + if(!rorId.equals(existingEntities.get(0).getRorId())) { + boolean updated = emailDomainDao.updateRorId(existingEntities.get(0).getId(), rorId); + if(updated) + return STATUS.UPDATED; + } } } else { EmailDomainEntity newEntity = emailDomainDao.createEmailDomain(emailDomain, DomainCategory.PROFESSIONAL, rorId); @@ -81,4 +105,67 @@ public STATUS createOrUpdateEmailDomain(String emailDomain, String rorId) { return null; } + @Override + public void processProfessionalEmailsForV2API(org.orcid.jaxb.model.record_v2.Emails emails) { + if(emails == null || emails.getEmails() == null) { + return; + } + for (org.orcid.jaxb.model.record_v2.Email email : emails.getEmails()) { + if (email.isVerified()) { + String domain = email.getEmail().split("@")[1]; + List domainsInfo = findByEmailDomain(domain); + String category = EmailDomainEntity.DomainCategory.UNDEFINED.name(); + // Set appropriate source name and source id for professional + // emails + if (domainsInfo != null) { + for (EmailDomainEntity domainInfo : domainsInfo) { + category = domainInfo.getCategory().name(); + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + break; + } + } + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + if(email.getSource() == null) { + email.setSource(new org.orcid.jaxb.model.common_v2.Source()); + } + email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); + } + } + } + } + } + + @Override + public void processProfessionalEmailsForV3API(org.orcid.jaxb.model.v3.release.record.Emails emails) { + if(emails == null || emails.getEmails() == null) { + return; + } + for (org.orcid.jaxb.model.v3.release.record.Email email : emails.getEmails()) { + if (email.isVerified()) { + String domain = email.getEmail().split("@")[1]; + List domainsInfo = findByEmailDomain(domain); + String category = EmailDomainEntity.DomainCategory.UNDEFINED.name(); + // Set appropriate source name and source id for professional + // emails + if (domainsInfo != null) { + for (EmailDomainEntity domainInfo : domainsInfo) { + category = domainInfo.getCategory().name(); + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + break; + } + } + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + if(email.getSource() == null) { + email.setSource(new org.orcid.jaxb.model.v3.release.common.Source()); + } + email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); + } + } + } + } + } + + // TODO: processProfessionalEmailsForV2API and processProfessionalEmailsForV3API can be merged if we make + // org.orcid.jaxb.model.record_v2.Emails and org.orcid.jaxb.model.v3.release.record.Emails implement from an + // interface that we can call EmailDomainsHolder } diff --git a/orcid-core/src/main/java/org/orcid/core/manager/read_only/impl/PersonDetailsManagerReadOnlyImpl.java b/orcid-core/src/main/java/org/orcid/core/manager/read_only/impl/PersonDetailsManagerReadOnlyImpl.java index 718750953cb..2663944909d 100644 --- a/orcid-core/src/main/java/org/orcid/core/manager/read_only/impl/PersonDetailsManagerReadOnlyImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/manager/read_only/impl/PersonDetailsManagerReadOnlyImpl.java @@ -1,6 +1,7 @@ package org.orcid.core.manager.read_only.impl; import java.util.ArrayList; +import java.util.List; import java.util.stream.Collectors; import org.orcid.core.common.manager.EmailDomainManager; @@ -33,6 +34,8 @@ import org.orcid.jaxb.model.record_v2.ResearcherUrls; import org.orcid.persistence.jpa.entities.EmailDomainEntity; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; + import javax.annotation.Resource; public class PersonDetailsManagerReadOnlyImpl extends ManagerReadOnlyBaseImpl implements PersonDetailsManagerReadOnly { @@ -139,7 +142,6 @@ public Person getPersonDetails(String orcid) { if (emails.getEmails() != null) { Emails filteredEmails = new Emails(); filteredEmails.setEmails(new ArrayList(emails.getEmails().stream().filter(e -> e.isVerified()).collect(Collectors.toList()))); - processProfessionalEmails(filteredEmails); person.setEmails(filteredEmails); } return person; @@ -198,26 +200,9 @@ public Person getPublicPersonDetails(String orcid) { if (emails.getEmails() != null) { Emails filteredEmails = new Emails(); filteredEmails.setEmails(new ArrayList(emails.getEmails())); - processProfessionalEmails(filteredEmails); person.setEmails(filteredEmails); } return person; } - - private void processProfessionalEmails(Emails emails) { - for (Email email : emails.getEmails()) { - if (email.isVerified()) { - String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - if(email.getSource() == null) { - email.setSource(new Source()); - } - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); - } - } - } - } } diff --git a/orcid-core/src/main/java/org/orcid/core/manager/v3/impl/ProfileEmailDomainManagerImpl.java b/orcid-core/src/main/java/org/orcid/core/manager/v3/impl/ProfileEmailDomainManagerImpl.java index e4adee923e8..7402b76400c 100644 --- a/orcid-core/src/main/java/org/orcid/core/manager/v3/impl/ProfileEmailDomainManagerImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/manager/v3/impl/ProfileEmailDomainManagerImpl.java @@ -17,6 +17,8 @@ import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Transactional; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; + import javax.annotation.Resource; import java.util.*; @@ -83,9 +85,19 @@ public void processDomain(String orcid, String email) { } String domain = email.split("@")[1]; - EmailDomainEntity domainInfo = emailDomainDao.findByEmailDomain(domain); + List domainsInfo = emailDomainDao.findByEmailDomain(domain); + String category = EmailDomainEntity.DomainCategory.UNDEFINED.name(); + + // Check if email is professional - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { + if (domainsInfo != null) { + for(EmailDomainEntity domainInfo: domainsInfo) { + category = domainInfo.getCategory().name(); + if(StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + break; + } + } + if(StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { ProfileEmailDomainEntity existingDomain = profileEmailDomainDao.findByEmailDomain(orcid, domain); // ADD NEW DOMAIN IF ONE DOESN'T EXIST if (existingDomain == null) { @@ -94,6 +106,7 @@ public void processDomain(String orcid, String email) { String domainVisibility = profile.getActivitiesVisibilityDefault(); profileEmailDomainDao.addEmailDomain(orcid, domain, domainVisibility); } + } } } } diff --git a/orcid-core/src/main/java/org/orcid/core/manager/v3/read_only/impl/PersonDetailsManagerReadOnlyImpl.java b/orcid-core/src/main/java/org/orcid/core/manager/v3/read_only/impl/PersonDetailsManagerReadOnlyImpl.java index f41687b6ee7..a31f7905ad4 100644 --- a/orcid-core/src/main/java/org/orcid/core/manager/v3/read_only/impl/PersonDetailsManagerReadOnlyImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/manager/v3/read_only/impl/PersonDetailsManagerReadOnlyImpl.java @@ -1,6 +1,7 @@ package org.orcid.core.manager.v3.read_only.impl; import java.util.ArrayList; +import java.util.List; import java.util.stream.Collectors; import org.orcid.core.common.manager.EmailDomainManager; @@ -32,6 +33,8 @@ import org.orcid.jaxb.model.v3.release.record.ResearcherUrls; import org.orcid.persistence.jpa.entities.EmailDomainEntity; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; + import javax.annotation.Resource; public class PersonDetailsManagerReadOnlyImpl extends ManagerReadOnlyBaseImpl implements PersonDetailsManagerReadOnly { @@ -143,7 +146,6 @@ public Person getPersonDetails(String orcid, boolean includeUnverifiedEmails) { } else { filteredEmails.setEmails(new ArrayList(emails.getEmails().stream().filter(e -> e.isVerified()).collect(Collectors.toList()))); } - processProfessionalEmails(filteredEmails); person.setEmails(filteredEmails); } return person; @@ -202,23 +204,9 @@ public Person getPublicPersonDetails(String orcid) { if (emails.getEmails() != null) { Emails filteredEmails = new Emails(); filteredEmails.setEmails(new ArrayList(emails.getEmails())); - processProfessionalEmails(filteredEmails); person.setEmails(filteredEmails); } return person; } - - private void processProfessionalEmails(Emails emails) { - for (Email email : emails.getEmails()) { - if (email.isVerified()) { - String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); - } - } - } - } } diff --git a/orcid-core/src/main/java/org/orcid/core/utils/emailDomain/EmailDomainValidator.java b/orcid-core/src/main/java/org/orcid/core/utils/emailDomain/EmailDomainValidator.java new file mode 100644 index 00000000000..cf2442438b7 --- /dev/null +++ b/orcid-core/src/main/java/org/orcid/core/utils/emailDomain/EmailDomainValidator.java @@ -0,0 +1,59 @@ +package org.orcid.core.utils.emailDomain; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +public class EmailDomainValidator { + + private static final String PUBLIC_TLDS_LIST_URL = "https://publicsuffix.org/list/public_suffix_list.dat"; + private static EmailDomainValidator instance; + private final Set validTlds; + + // Private constructor to enforce singleton + private EmailDomainValidator() { + validTlds = new HashSet<>(); + loadTlds(); + } + + // Public method to get the singleton instance + public static synchronized EmailDomainValidator getInstance() { + if (instance == null) { + instance = new EmailDomainValidator(); + } + return instance; + } + + // Load TLDs from the public suffix list + private void loadTlds() { + try { + URL tldUrl = new URL(PUBLIC_TLDS_LIST_URL); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(tldUrl.openStream()))) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!line.isEmpty() && !line.startsWith("//")) { + validTlds.add(line); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to load TLD list"); + } + } + + // Check if the email domain has a valid TLD + public boolean isValidEmailDomain(String emailDomain) { + for (String tld : validTlds) { + if (emailDomain.endsWith("." + tld)) { + return true; + } + } + return false; + } +} + + diff --git a/orcid-core/src/test/java/org/orcid/core/common/manager/EmailDomainManagerTest.java b/orcid-core/src/test/java/org/orcid/core/common/manager/EmailDomainManagerTest.java index 5eb7cde5b30..2c8d75db1a9 100644 --- a/orcid-core/src/test/java/org/orcid/core/common/manager/EmailDomainManagerTest.java +++ b/orcid-core/src/test/java/org/orcid/core/common/manager/EmailDomainManagerTest.java @@ -14,6 +14,7 @@ import static org.mockito.Mockito.when; import static org.junit.Assert.fail; +import java.util.ArrayList; import java.util.List; import org.junit.Before; @@ -50,10 +51,10 @@ public void before() { when(emailDomainDaoReadOnlyMock.findByCategory(eq(DomainCategory.PERSONAL))).thenReturn(List.of(e1, e2)); when(emailDomainDaoReadOnlyMock.findByCategory(eq(DomainCategory.PROFESSIONAL))).thenReturn(List.of(e3)); - when(emailDomainDaoReadOnlyMock.findByEmailDomain("gmail.com")).thenReturn(e1); - when(emailDomainDaoReadOnlyMock.findByEmailDomain("orcid.org")).thenReturn(e3); - - when(emailDomainDaoMock.createEmailDomain(eq("new.domain"), eq(DomainCategory.PROFESSIONAL), eq("https://ror.org/0"))).thenReturn(new EmailDomainEntity("new.domain", DomainCategory.PROFESSIONAL, "https://ror.org/0")); + when(emailDomainDaoReadOnlyMock.findByEmailDomain("gmail.com")).thenReturn(List.of(e1)); + when(emailDomainDaoReadOnlyMock.findByEmailDomain("orcid.org")).thenReturn(List.of(e3)); + + when(emailDomainDaoMock.createEmailDomain(eq("new.domain.com"), eq(DomainCategory.PROFESSIONAL), eq("https://ror.org/0"))).thenReturn(new EmailDomainEntity("new.domain.com", DomainCategory.PROFESSIONAL, "https://ror.org/0")); when(emailDomainDaoMock.updateRorId(1000L, "https://ror.org/0")).thenReturn(true); } @@ -106,15 +107,17 @@ public void findByEmailDomain_EmptyDomainTest() { @Test public void findByEmailDomain_NothingFoundTest() { - assertNull(edm.findByEmailDomain("other.com")); + assert(edm.findByEmailDomain("other.com").isEmpty()); } @Test public void findByEmailDomainTest() { - EmailDomainEntity ede = edm.findByEmailDomain("gmail.com"); + List ede = edm.findByEmailDomain("gmail.com"); assertNotNull(ede); - assertEquals("gmail.com", ede.getEmailDomain()); - assertEquals(DomainCategory.PERSONAL, ede.getCategory()); + if(ede !=null) { + assertEquals("gmail.com", ede.get(0).getEmailDomain()); + assertEquals(DomainCategory.PERSONAL, ede.get(0).getCategory()); + } } @Test(expected = IllegalArgumentException.class) @@ -149,9 +152,9 @@ public void findByCategory_TwoResultsTest() { @Test public void createOrUpdateEmailDomain_CreateTest() { - STATUS s = edm.createOrUpdateEmailDomain("new.domain", "https://ror.org/0"); + STATUS s = edm.createOrUpdateEmailDomain("new.domain.com", "https://ror.org/0"); assertEquals(STATUS.CREATED, s); - verify(emailDomainDaoMock, times(1)).createEmailDomain(eq("new.domain"), eq(DomainCategory.PROFESSIONAL), eq("https://ror.org/0")); + verify(emailDomainDaoMock, times(1)).createEmailDomain(eq("new.domain.com"), eq(DomainCategory.PROFESSIONAL), eq("https://ror.org/0")); verify(emailDomainDaoMock, never()).updateRorId(anyLong(), anyString()); } diff --git a/orcid-core/src/test/java/org/orcid/core/manager/v3/EmailManagerReadOnlyTest.java b/orcid-core/src/test/java/org/orcid/core/manager/v3/EmailManagerReadOnlyTest.java index f382472d194..37947008c9c 100644 --- a/orcid-core/src/test/java/org/orcid/core/manager/v3/EmailManagerReadOnlyTest.java +++ b/orcid-core/src/test/java/org/orcid/core/manager/v3/EmailManagerReadOnlyTest.java @@ -71,7 +71,7 @@ public void isPrimaryEmailVerifiedTest() { public void haveAnyEmailVerifiedTest() { assertTrue(emailManagerReadOnly.haveAnyEmailVerified("0000-0000-0000-0003")); assertTrue(emailManagerReadOnly.haveAnyEmailVerified("4444-4444-4444-4442")); - assertFalse(emailManagerReadOnly.haveAnyEmailVerified("0000-0000-0000-0001")); + assertTrue(emailManagerReadOnly.haveAnyEmailVerified("0000-0000-0000-0001")); assertFalse(emailManagerReadOnly.haveAnyEmailVerified("4444-4444-4444-4445")); } diff --git a/orcid-core/src/test/java/org/orcid/core/manager/v3/ProfileEmailDomainManagerTest.java b/orcid-core/src/test/java/org/orcid/core/manager/v3/ProfileEmailDomainManagerTest.java index f50a938efdd..1762d6c0773 100644 --- a/orcid-core/src/test/java/org/orcid/core/manager/v3/ProfileEmailDomainManagerTest.java +++ b/orcid-core/src/test/java/org/orcid/core/manager/v3/ProfileEmailDomainManagerTest.java @@ -110,7 +110,7 @@ public void processDomain_domainAlreadyAdded() { EmailDomainEntity professionalEmailDomain = new EmailDomainEntity(); professionalEmailDomain.setCategory(DomainCategory.PROFESSIONAL); professionalEmailDomain.setEmailDomain(EMAIL_DOMAIN); - when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN))).thenReturn(professionalEmailDomain); + when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN))).thenReturn(List.of(professionalEmailDomain)); pedm.processDomain(ORCID, "email@orcid.org"); verify(profileEmailDomainDaoMock, times(1)).findByEmailDomain(eq(ORCID), eq(EMAIL_DOMAIN)); verify(profileEmailDomainDaoMock, never()).addEmailDomain(anyString(), anyString(), anyString()); @@ -129,7 +129,7 @@ public void processDomain_doNotAddPersonalDomain() { EmailDomainEntity professionalEmailDomain = new EmailDomainEntity(); professionalEmailDomain.setCategory(DomainCategory.PERSONAL); professionalEmailDomain.setEmailDomain(EMAIL_DOMAIN); - when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN))).thenReturn(professionalEmailDomain); + when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN))).thenReturn(List.of(professionalEmailDomain)); pedm.processDomain(ORCID, "email@orcid.org"); verify(profileEmailDomainDaoMock, never()).findByEmailDomain(anyString(), anyString()); verify(profileEmailDomainDaoMock, never()).addEmailDomain(anyString(), anyString(), anyString()); @@ -140,7 +140,7 @@ public void processDomain_addDomain() { EmailDomainEntity professionalEmailDomain = new EmailDomainEntity(); professionalEmailDomain.setCategory(DomainCategory.PROFESSIONAL); professionalEmailDomain.setEmailDomain(EMAIL_DOMAIN_THREE); - when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN_THREE))).thenReturn(professionalEmailDomain); + when(emailDomainDaoMock.findByEmailDomain(eq(EMAIL_DOMAIN_THREE))).thenReturn(List.of(professionalEmailDomain)); pedm.processDomain(ORCID, "email@domain.net"); verify(profileEmailDomainDaoMock, times(1)).findByEmailDomain(eq(ORCID), eq(EMAIL_DOMAIN_THREE)); verify(profileEmailDomainDaoMock, times(1)).addEmailDomain(ORCID, EMAIL_DOMAIN_THREE, Visibility.PUBLIC.value()); diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java index 9c7dc02e213..47efaf0d06b 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/EmailDomainDao.java @@ -13,7 +13,7 @@ public interface EmailDomainDao extends GenericDao { boolean updateRorId(long id, String rorId); - EmailDomainEntity findByEmailDomain(String emailDomain); + List findByEmailDomain(String emailDomain); List findByCategory(EmailDomainEntity.DomainCategory category); } diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java index c23525ea716..d571f7c8dbb 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/EmailDomainDaoImpl.java @@ -65,11 +65,11 @@ public boolean updateRorId(long id, String rorId) { } @Override - public EmailDomainEntity findByEmailDomain(String emailDomain) { + public List findByEmailDomain(String emailDomain) { TypedQuery query = entityManager.createQuery("from EmailDomainEntity where emailDomain = :emailDomain", EmailDomainEntity.class); query.setParameter("emailDomain", emailDomain); try { - return query.getSingleResult(); + return query.getResultList(); } catch(NoResultException nre) { // Ignore this exception } catch(Exception e) { diff --git a/orcid-pub-web/src/main/java/org/orcid/api/publicV2/server/delegator/impl/PublicV2ApiServiceDelegatorImpl.java b/orcid-pub-web/src/main/java/org/orcid/api/publicV2/server/delegator/impl/PublicV2ApiServiceDelegatorImpl.java index f4b5ac9eecd..60505bedda2 100644 --- a/orcid-pub-web/src/main/java/org/orcid/api/publicV2/server/delegator/impl/PublicV2ApiServiceDelegatorImpl.java +++ b/orcid-pub-web/src/main/java/org/orcid/api/publicV2/server/delegator/impl/PublicV2ApiServiceDelegatorImpl.java @@ -74,6 +74,7 @@ import org.springframework.stereotype.Component; import de.undercouch.citeproc.csl.CSLItemData; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; /** *

@@ -157,7 +158,7 @@ public class PublicV2ApiServiceDelegatorImpl @Resource private OrcidSearchManager orcidSearchManager; - + @Resource private OrcidSecurityManager orcidSecurityManager; @@ -169,10 +170,10 @@ public class PublicV2ApiServiceDelegatorImpl @Resource private OpenIDConnectKeyService openIDConnectKeyService; - + @Resource private ClientManagerReadOnly clientManagerReadOnly; - + @Resource private RecordNameManagerReadOnly recordNameManagerReadOnly; @@ -182,9 +183,6 @@ public class PublicV2ApiServiceDelegatorImpl @Resource private EmailDomainManager emailDomainManager; - @Resource - private SourceEntityUtils sourceEntityUtils; - @Value("${org.orcid.core.baseUri}") private String baseUrl; @@ -218,7 +216,7 @@ public Response viewActivities(String orcid) { public Response viewWork(String orcid, Long putCode) { Work w = workManagerReadOnly.getWork(orcid, putCode); publicAPISecurityManagerV2.checkIsPublic(w); - contributorUtilsReadOnly.filterContributorPrivateData(w); + contributorUtilsReadOnly.filterContributorPrivateData(w); ActivityUtils.cleanEmptyFields(w); ActivityUtils.setPathToActivity(w, orcid); @@ -228,10 +226,10 @@ public Response viewWork(String orcid, Long putCode) { @Override public Response viewWorks(String orcid) { - List works = workManagerReadOnly.getWorksSummaryList(orcid); + List works = workManagerReadOnly.getWorksSummaryList(orcid); Works publicWorks = workManagerReadOnly.groupWorks(works, true); publicAPISecurityManagerV2.filter(publicWorks); - + ActivityUtils.cleanEmptyFields(publicWorks); ActivityUtils.setPathToWorks(publicWorks, orcid); Api2_0_LastModifiedDatesHelper.calculateLastModified(publicWorks); @@ -427,7 +425,7 @@ public Response viewResearcherUrl(String orcid, Long putCode) { public Response viewEmails(String orcid) { Emails emails = emailManagerReadOnly.getPublicEmails(orcid); publicAPISecurityManagerV2.filter(emails); - processProfessionalEmails(emails); + emailDomainManager.processProfessionalEmailsForV2API(emails); ElementUtils.setPathToEmail(emails, orcid); Api2_0_LastModifiedDatesHelper.calculateLastModified(emails); sourceUtilsReadOnly.setSourceName(emails); @@ -533,6 +531,7 @@ public Response viewAddress(String orcid, Long putCode) { public Response viewPerson(String orcid) { Person person = personDetailsManagerReadOnly.getPublicPersonDetails(orcid); publicAPISecurityManagerV2.filter(person); + emailDomainManager.processProfessionalEmailsForV2API(person.getEmails()); ElementUtils.setPathToPerson(person, orcid); Api2_0_LastModifiedDatesHelper.calculateLastModified(person); sourceUtilsReadOnly.setSourceName(person); @@ -544,6 +543,7 @@ public Response viewRecord(String orcid) { Record record = recordManagerReadOnly.getPublicRecord(orcid); publicAPISecurityManagerV2.filter(record); if (record.getPerson() != null) { + emailDomainManager.processProfessionalEmailsForV2API(record.getPerson().getEmails()); sourceUtilsReadOnly.setSourceName(record.getPerson()); } if (record.getActivitiesSummary() != null) { @@ -570,7 +570,7 @@ public Response viewBulkWorks(String orcid, String putCodes) { } WorkBulk workBulk = workManagerReadOnly.findWorkBulk(orcid, putCodes); publicAPISecurityManagerV2.filter(workBulk); - contributorUtilsReadOnly.filterContributorPrivateData(workBulk); + contributorUtilsReadOnly.filterContributorPrivateData(workBulk); ActivityUtils.cleanEmptyFields(workBulk); ActivityUtils.setPathToBulk(workBulk, orcid); sourceUtils.setSourceName(workBulk); @@ -584,7 +584,7 @@ private void validateSearchParams(Map> queryMap) { private void validateStart(Map> queryMap) { String clientId = orcidSecurityManager.getClientIdFromAPIRequest(); - if (clientId == null) { + if (clientId == null) { // only validate start param where no client credentials List startList = queryMap.get("start"); if (startList != null && !startList.isEmpty()) { @@ -622,22 +622,6 @@ private void validateRows(Map> queryMap) { } } - private void processProfessionalEmails(Emails emails) { - for (Email email : emails.getEmails()) { - if (email.isVerified()) { - String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - if(email.getSource() == null) { - email.setSource(new Source()); - } - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); - } - } - } - } - @Override public Response viewClient(String clientId) { ClientSummary client = clientManagerReadOnly.getSummary(clientId); diff --git a/orcid-pub-web/src/main/java/org/orcid/api/publicV3/server/delegator/impl/PublicV3ApiServiceDelegatorImpl.java b/orcid-pub-web/src/main/java/org/orcid/api/publicV3/server/delegator/impl/PublicV3ApiServiceDelegatorImpl.java index 61350aa5bde..562f293b7d8 100644 --- a/orcid-pub-web/src/main/java/org/orcid/api/publicV3/server/delegator/impl/PublicV3ApiServiceDelegatorImpl.java +++ b/orcid-pub-web/src/main/java/org/orcid/api/publicV3/server/delegator/impl/PublicV3ApiServiceDelegatorImpl.java @@ -90,10 +90,11 @@ import org.springframework.stereotype.Component; import de.undercouch.citeproc.csl.CSLItemData; +import liquibase.repackaged.org.apache.commons.lang3.StringUtils; @Component -public class PublicV3ApiServiceDelegatorImpl - implements PublicV3ApiServiceDelegator { +public class PublicV3ApiServiceDelegatorImpl implements + PublicV3ApiServiceDelegator { // Activities managers @Resource(name = "workManagerReadOnlyV3") @@ -167,7 +168,7 @@ public class PublicV3ApiServiceDelegatorImpl @Resource(name = "orcidSearchManagerV3") private OrcidSearchManager orcidSearchManager; - + @Resource(name = "orcidSecurityManagerV3") private OrcidSecurityManager orcidSecurityManager; @@ -182,10 +183,10 @@ public class PublicV3ApiServiceDelegatorImpl @Resource private OpenIDConnectKeyService openIDConnectKeyService; - + @Resource private StatusManager statusManager; - + @Resource(name = "recordNameManagerReadOnlyV3") private RecordNameManagerReadOnly recordNameManagerReadOnlyV3; @@ -210,7 +211,7 @@ public Boolean getFilterVersionOfIdentifiers() { public void setFilterVersionOfIdentifiers(Boolean filterVersionOfIdentifiers) { this.filterVersionOfIdentifiers = filterVersionOfIdentifiers; } - + @Override public Response viewStatusSimple() { Map statusMap = statusManager.createStatusMapSimple(); @@ -251,7 +252,7 @@ public Response viewWork(String orcid, Long putCode) { checkProfileStatus(orcid); Work w = workManagerReadOnly.getWork(orcid, putCode); publicAPISecurityManagerV3.checkIsPublic(w); - contributorUtilsReadOnly.filterContributorPrivateData(w); + contributorUtilsReadOnly.filterContributorPrivateData(w); ActivityUtils.cleanEmptyFields(w); ActivityUtils.setPathToActivity(w, orcid); sourceUtilsReadOnly.setSourceName(w); @@ -263,13 +264,13 @@ public Response viewWorks(String orcid) { checkProfileStatus(orcid); List works = workManagerReadOnly.getWorksSummaryList(orcid); // Should we filter the version-of identifiers before grouping? - if(filterVersionOfIdentifiers) { - for(WorkSummary w : works) { - if(w.getExternalIdentifiers() != null && !w.getExternalIdentifiers().getExternalIdentifier().isEmpty()) { + if (filterVersionOfIdentifiers) { + for (WorkSummary w : works) { + if (w.getExternalIdentifiers() != null && !w.getExternalIdentifiers().getExternalIdentifier().isEmpty()) { Iterator it = w.getExternalIdentifiers().getExternalIdentifier().iterator(); - while(it.hasNext()) { + while (it.hasNext()) { ExternalID extId = it.next(); - if(Relationship.VERSION_OF.equals(extId.getRelationship())) { + if (Relationship.VERSION_OF.equals(extId.getRelationship())) { it.remove(); } } @@ -366,7 +367,7 @@ public Response viewEducations(String orcid) { publicEducations.add(summary); } } - + Educations groupedEducations = new Educations(affiliationsManagerReadOnly.groupAffiliations(publicEducations, true)); Api3_0LastModifiedDatesHelper.calculateLastModified(groupedEducations); ActivityUtils.setPathToAffiliations(groupedEducations, orcid); @@ -398,7 +399,7 @@ public Response viewEmployment(String orcid, Long putCode) { public Response viewEmployments(String orcid) { checkProfileStatus(orcid); List employments = affiliationsManagerReadOnly.getEmploymentSummaryList(orcid); - List publicEmployments = new ArrayList<>(); + List publicEmployments = new ArrayList<>(); for (EmploymentSummary summary : employments) { if (Visibility.PUBLIC.equals(summary.getVisibility())) { ActivityUtils.setPathToActivity(summary, orcid); @@ -612,6 +613,7 @@ public Response viewPerson(String orcid) { checkProfileStatus(orcid); Person person = personDetailsManagerReadOnly.getPublicPersonDetails(orcid); publicAPISecurityManagerV3.filter(person); + emailDomainManager.processProfessionalEmailsForV3API(person.getEmails()); ElementUtils.setPathToPerson(person, orcid); Api3_0LastModifiedDatesHelper.calculateLastModified(person); sourceUtilsReadOnly.setSourceName(person); @@ -624,6 +626,7 @@ public Response viewRecord(String orcid) { Record record = recordManagerReadOnly.getPublicRecord(orcid, filterVersionOfIdentifiers); publicAPISecurityManagerV3.filter(record); if (record.getPerson() != null) { + emailDomainManager.processProfessionalEmailsForV3API(record.getPerson().getEmails()); sourceUtilsReadOnly.setSourceName(record.getPerson()); } if (record.getActivitiesSummary() != null) { @@ -641,14 +644,14 @@ public Response searchByQuery(Map> solrParams) { Search search = orcidSearchManager.findOrcidIds(solrParams); return Response.ok(search).build(); } - + @Override public Response searchByQueryCSV(Map> solrParams) { validateSearchParams(solrParams); String search = orcidSearchManager.findOrcidIdsAsCSV(solrParams); return Response.ok(search).build(); } - + @Override public Response expandedSearchByQuery(Map> solrParams) { validateSearchParams(solrParams); @@ -664,7 +667,7 @@ public Response viewBulkWorks(String orcid, String putCodes) { } WorkBulk workBulk = workManagerReadOnly.findWorkBulk(orcid, putCodes); publicAPISecurityManagerV3.filter(workBulk); - contributorUtilsReadOnly.filterContributorPrivateData(workBulk); + contributorUtilsReadOnly.filterContributorPrivateData(workBulk); ActivityUtils.cleanEmptyFields(workBulk); ActivityUtils.setPathToBulk(workBulk, orcid); sourceUtils.setSourceName(workBulk); @@ -678,7 +681,7 @@ private void validateSearchParams(Map> queryMap) { private void validateStart(Map> queryMap) { String clientId = orcidSecurityManager.getClientIdFromAPIRequest(); - if (clientId == null) { + if (clientId == null) { // only validate start param where no client credentials List startList = queryMap.get("start"); if (startList != null && !startList.isEmpty()) { @@ -720,10 +723,20 @@ private void processProfessionalEmails(Emails emails) { for (Email email : emails.getEmails()) { if (email.isVerified()) { String domain = email.getEmail().split("@")[1]; - EmailDomainEntity domainInfo = emailDomainManager.findByEmailDomain(domain); - // Set appropriate source name and source id for professional emails - if (domainInfo != null && domainInfo.getCategory().equals(EmailDomainEntity.DomainCategory.PROFESSIONAL)) { - email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); + List domainsInfo = emailDomainManager.findByEmailDomain(domain); + String category = EmailDomainEntity.DomainCategory.UNDEFINED.name(); + // Set appropriate source name and source id for professional + // emails + if (domainsInfo != null) { + for (EmailDomainEntity domainInfo : domainsInfo) { + category = domainInfo.getCategory().name(); + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + break; + } + } + if (StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + email.setSource(sourceEntityUtils.convertEmailSourceToOrcidValidator(email.getSource())); + } } } } @@ -786,13 +799,13 @@ public Response viewInvitedPosition(String orcid, Long putCode) { @Override public Response viewInvitedPositions(String orcid) { List invitedPositions = affiliationsManagerReadOnly.getInvitedPositionSummaryList(orcid); - List publicInvitedPositions = new ArrayList<>(); + List publicInvitedPositions = new ArrayList<>(); for (InvitedPositionSummary summary : invitedPositions) { - if (Visibility.PUBLIC.equals(summary.getVisibility())) { - ActivityUtils.setPathToActivity(summary, orcid); - sourceUtilsReadOnly.setSourceName(summary); - publicInvitedPositions.add(summary); - } + if (Visibility.PUBLIC.equals(summary.getVisibility())) { + ActivityUtils.setPathToActivity(summary, orcid); + sourceUtilsReadOnly.setSourceName(summary); + publicInvitedPositions.add(summary); + } } ActivityUtils.cleanOrganizationEmptyFields(publicInvitedPositions); InvitedPositions groupedInvitedPositions = new InvitedPositions(affiliationsManagerReadOnly.groupAffiliations(publicInvitedPositions, true)); @@ -826,13 +839,13 @@ public Response viewMemberships(String orcid) { List memberships = affiliationsManagerReadOnly.getMembershipSummaryList(orcid); List publicMemberships = new ArrayList<>(); for (MembershipSummary summary : memberships) { - if (Visibility.PUBLIC.equals(summary.getVisibility())) { - ActivityUtils.setPathToActivity(summary, orcid); - sourceUtilsReadOnly.setSourceName(summary); - publicMemberships.add(summary); - } + if (Visibility.PUBLIC.equals(summary.getVisibility())) { + ActivityUtils.setPathToActivity(summary, orcid); + sourceUtilsReadOnly.setSourceName(summary); + publicMemberships.add(summary); + } } - + ActivityUtils.cleanOrganizationEmptyFields(publicMemberships); Memberships groupedMemberships = new Memberships(affiliationsManagerReadOnly.groupAffiliations(publicMemberships, true)); Api3_0LastModifiedDatesHelper.calculateLastModified(groupedMemberships); @@ -863,13 +876,13 @@ public Response viewQualification(String orcid, Long putCode) { @Override public Response viewQualifications(String orcid) { List qualifications = affiliationsManagerReadOnly.getQualificationSummaryList(orcid); - List publicQualifications = new ArrayList<>(); + List publicQualifications = new ArrayList<>(); for (QualificationSummary summary : qualifications) { - if (Visibility.PUBLIC.equals(summary.getVisibility())) { - ActivityUtils.setPathToActivity(summary, orcid); - sourceUtilsReadOnly.setSourceName(summary); - publicQualifications.add(summary); - } + if (Visibility.PUBLIC.equals(summary.getVisibility())) { + ActivityUtils.setPathToActivity(summary, orcid); + sourceUtilsReadOnly.setSourceName(summary); + publicQualifications.add(summary); + } } ActivityUtils.cleanOrganizationEmptyFields(publicQualifications); Qualifications groupedQualifications = new Qualifications(affiliationsManagerReadOnly.groupAffiliations(publicQualifications, true)); @@ -903,11 +916,11 @@ public Response viewServices(String orcid) { List services = affiliationsManagerReadOnly.getServiceSummaryList(orcid); List publicServices = new ArrayList<>(); for (ServiceSummary summary : services) { - if (Visibility.PUBLIC.equals(summary.getVisibility())) { - ActivityUtils.setPathToActivity(summary, orcid); - sourceUtilsReadOnly.setSourceName(summary); - publicServices.add(summary); - } + if (Visibility.PUBLIC.equals(summary.getVisibility())) { + ActivityUtils.setPathToActivity(summary, orcid); + sourceUtilsReadOnly.setSourceName(summary); + publicServices.add(summary); + } } ActivityUtils.cleanOrganizationEmptyFields(publicServices); Services groupedServices = new Services(affiliationsManagerReadOnly.groupAffiliations(publicServices, true)); @@ -925,9 +938,9 @@ public Response viewServiceSummary(String orcid, Long putCode) { sourceUtilsReadOnly.setSourceName(s); return Response.ok(s).build(); } - + private void checkProfileStatus(String orcid) { - orcidSecurityManager.checkProfile(orcid); + orcidSecurityManager.checkProfile(orcid); } @Override @@ -944,9 +957,9 @@ public Response viewResearchResources(String orcid) { List researchResources = researchResourceManagerReadOnly.getResearchResourceSummaryList(orcid); List publicResearchResources = new ArrayList<>(); for (ResearchResourceSummary summary : researchResources) { - if (Visibility.PUBLIC.equals(summary.getVisibility())) { - publicResearchResources.add(summary); - } + if (Visibility.PUBLIC.equals(summary.getVisibility())) { + publicResearchResources.add(summary); + } } ResearchResources rr = researchResourceManagerReadOnly.groupResearchResources(publicResearchResources, true); Api3_0LastModifiedDatesHelper.calculateLastModified(rr); diff --git a/orcid-pub-web/src/test/java/org/orcid/api/publicV2/server/PublicV2ApiServiceDelegatorTest.java b/orcid-pub-web/src/test/java/org/orcid/api/publicV2/server/PublicV2ApiServiceDelegatorTest.java index 8e784e8b5a0..071f65f5c15 100644 --- a/orcid-pub-web/src/test/java/org/orcid/api/publicV2/server/PublicV2ApiServiceDelegatorTest.java +++ b/orcid-pub-web/src/test/java/org/orcid/api/publicV2/server/PublicV2ApiServiceDelegatorTest.java @@ -25,7 +25,6 @@ import org.orcid.api.publicV2.server.delegator.PublicV2ApiServiceDelegator; import org.orcid.api.publicV2.server.delegator.impl.PublicV2ApiServiceDelegatorImpl; import org.orcid.core.api.OrcidApiConstants; -import org.orcid.core.exception.DeactivatedException; import org.orcid.core.exception.OrcidBadRequestException; import org.orcid.core.exception.OrcidNonPublicElementException; import org.orcid.core.exception.SearchStartParameterLimitExceededException; @@ -108,13 +107,13 @@ public class PublicV2ApiServiceDelegatorTest extends DBUnitTest { private final String ORCID = "0000-0000-0000-0003"; private String deactivatedUserOrcid = "0000-0000-0000-0007"; - + @Resource(name = "publicV2ApiServiceDelegator") PublicV2ApiServiceDelegator serviceDelegator; @Resource SchemaOrgMBWriterV2 writerV2; - + @BeforeClass public static void initDBUnitData() throws Exception { initDBUnitData(DATA_FILES); @@ -185,7 +184,7 @@ public void testViewBulkWorks() { assertNotNull(workBulk); assertNotNull(workBulk.getBulk()); assertEquals(3, workBulk.getBulk().size()); - assertTrue(workBulk.getBulk().get(0) instanceof Work); + assertTrue(workBulk.getBulk().get(0) instanceof Work); assertTrue(workBulk.getBulk().get(1) instanceof OrcidError); assertTrue(workBulk.getBulk().get(2) instanceof OrcidError); Work work = (Work) workBulk.getBulk().get(0); @@ -224,7 +223,7 @@ public void testViewFunding() { assertEquals("APP-5555555555555555", funding.getSource().retrieveSourcePath()); assertNotNull(funding.getContributors().getContributor().get(0).getContributorOrcid()); assertEquals("0000-0000-0000-0000", funding.getContributors().getContributor().get(0).getContributorOrcid().getPath()); - assertNull(funding.getContributors().getContributor().get(0).getCreditName()); + assertNull(funding.getContributors().getContributor().get(0).getCreditName()); } @Test @@ -467,7 +466,7 @@ public void testViewExternalIdentifiers() { assertNotNull(extIds.getLastModifiedDate().getValue()); assertEquals("/0000-0000-0000-0003/external-identifiers", extIds.getPath()); assertEquals(3, extIds.getExternalIdentifiers().size()); - + PersonExternalIdentifier extId = extIds.getExternalIdentifiers().get(0); assertNotNull(extId); assertNotNull(extId.getLastModifiedDate()); @@ -479,7 +478,7 @@ public void testViewExternalIdentifiers() { assertEquals(Visibility.PUBLIC.value(), extId.getVisibility().value()); assertEquals("/0000-0000-0000-0003/external-identifiers/19", extId.getPath()); assertEquals("APP-5555555555555558", extId.getSource().retrieveSourcePath()); - + extId = extIds.getExternalIdentifiers().get(1); assertNotNull(extId); assertNotNull(extId.getLastModifiedDate()); @@ -491,7 +490,7 @@ public void testViewExternalIdentifiers() { assertEquals(Visibility.PUBLIC.value(), extId.getVisibility().value()); assertEquals("/0000-0000-0000-0003/external-identifiers/18", extId.getPath()); assertEquals("0000-0000-0000-0003", extId.getSource().retrieveSourcePath()); - + extId = extIds.getExternalIdentifiers().get(2); assertNotNull(extId); assertNotNull(extId.getLastModifiedDate()); @@ -570,8 +569,8 @@ public void testViewEmails() { assertEquals(Visibility.PUBLIC.value(), email.getVisibility().value()); assertEquals(Visibility.PUBLIC.value(), email2.getVisibility().value()); assertEquals("/0000-0000-0000-0003/email", emails.getPath()); - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); assertNull(email.getSource().getSourceOrcid()); assertEquals("0000-0000-0000-0000", email2.getSource().retrieveSourcePath()); assertEquals("ORCID email validation", email2.getSource().getSourceName().getContent()); @@ -1185,11 +1184,11 @@ public void testSearchByQuery() { result.setOrcidIdentifier(new OrcidIdentifier("some-orcid-id")); search.getResults().add(result); OrcidSearchManager orcidSearchManager = Mockito.mock(OrcidSearchManagerImpl.class); - Mockito.when(orcidSearchManager.findOrcidIds(Matchers.>> any())).thenReturn(search); + Mockito.when(orcidSearchManager.findOrcidIds(Matchers.>>any())).thenReturn(search); PublicV2ApiServiceDelegatorImpl delegator = new PublicV2ApiServiceDelegatorImpl(); ReflectionTestUtils.setField(delegator, "orcidSearchManager", orcidSearchManager); - + OrcidSecurityManager orcidSecurityManager = Mockito.mock(OrcidSecurityManagerImpl.class); Mockito.when(orcidSecurityManager.getClientIdFromAPIRequest()).thenReturn(null); ReflectionTestUtils.setField(delegator, "orcidSecurityManager", orcidSecurityManager); @@ -1223,7 +1222,7 @@ public void testSearchByQueryIllegalStart() { LocaleManager localeManager = Mockito.mock(LocaleManagerImpl.class); Mockito.when(localeManager.resolveMessage(Mockito.anyString())).thenReturn("a message"); - + OrcidSecurityManager orcidSecurityManager = Mockito.mock(OrcidSecurityManagerImpl.class); Mockito.when(orcidSecurityManager.getClientIdFromAPIRequest()).thenReturn(null); @@ -1243,7 +1242,7 @@ public void testSearchByQueryLegalStart() { OrcidSearchManager orcidSearchManager = Mockito.mock(OrcidSearchManagerImpl.class); Mockito.when(orcidSearchManager.findOrcidIds(Mockito.anyMap())).thenReturn(new Search()); - + OrcidSecurityManager orcidSecurityManager = Mockito.mock(OrcidSecurityManagerImpl.class); Mockito.when(orcidSecurityManager.getClientIdFromAPIRequest()).thenReturn(null); @@ -1305,8 +1304,8 @@ private void validatePerson(Person person) { assertNotNull(email.getLastModifiedDate().getValue()); assertNotNull(email2.getLastModifiedDate()); assertNotNull(email2.getLastModifiedDate().getValue()); - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); assertNull(email.getSource().getSourceOrcid()); assertEquals("0000-0000-0000-0000", email2.getSource().retrieveSourcePath()); assertEquals("ORCID email validation", email2.getSource().getSourceName().getContent()); @@ -1318,9 +1317,9 @@ private void validatePerson(Person person) { assertNotNull(person.getExternalIdentifiers().getLastModifiedDate().getValue()); assertEquals("/0000-0000-0000-0003/external-identifiers", person.getExternalIdentifiers().getPath()); assertEquals(3, person.getExternalIdentifiers().getExternalIdentifiers().size()); - + PersonExternalIdentifiers extIds = person.getExternalIdentifiers(); - + assertNotNull(extIds); PersonExternalIdentifier extId = extIds.getExternalIdentifiers().get(0); assertNotNull(extId); @@ -1333,7 +1332,7 @@ private void validatePerson(Person person) { assertEquals(Visibility.PUBLIC.value(), extId.getVisibility().value()); assertEquals("/0000-0000-0000-0003/external-identifiers/19", extId.getPath()); assertEquals("APP-5555555555555558", extId.getSource().retrieveSourcePath()); - + extId = extIds.getExternalIdentifiers().get(1); assertNotNull(extId); assertNotNull(extId.getLastModifiedDate()); @@ -1345,7 +1344,7 @@ private void validatePerson(Person person) { assertEquals(Visibility.PUBLIC.value(), extId.getVisibility().value()); assertEquals("/0000-0000-0000-0003/external-identifiers/18", extId.getPath()); assertEquals("0000-0000-0000-0003", extId.getSource().retrieveSourcePath()); - + extId = extIds.getExternalIdentifiers().get(2); assertNotNull(extId); assertNotNull(extId.getLastModifiedDate()); @@ -1357,7 +1356,7 @@ private void validatePerson(Person person) { assertEquals(Visibility.PUBLIC.value(), extId.getVisibility().value()); assertEquals("/0000-0000-0000-0003/external-identifiers/13", extId.getPath()); assertEquals("APP-5555555555555555", extId.getSource().retrieveSourcePath()); - + assertNotNull(person.getKeywords()); assertNotNull(person.getKeywords().getLastModifiedDate()); assertNotNull(person.getKeywords().getLastModifiedDate().getValue()); @@ -1507,9 +1506,9 @@ private void validateRecord(Record record) { OrcidIdentifier id = record.getOrcidIdentifier(); assertEquals("0000-0000-0000-0003", id.getPath()); } - + @Test - public void testSchemaOrgMBWriterV2() throws WebApplicationException, IOException{ + public void testSchemaOrgMBWriterV2() throws WebApplicationException, IOException { Response response = serviceDelegator.viewRecord(ORCID); Record record = (Record) response.getEntity(); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -1518,22 +1517,70 @@ public void testSchemaOrgMBWriterV2() throws WebApplicationException, IOExceptio objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); SchemaOrgDocument doc = objectMapper.readerFor(SchemaOrgDocument.class).readValue(out.toString()); assertTrue(doc.id.endsWith(ORCID)); - assertEquals("Person",doc.type); - assertEquals("http://schema.org",doc.context); - assertEquals("Credit Name",doc.name); - assertEquals("Given Names",doc.givenName); - assertEquals("Family Name",doc.familyName); - assertEquals("Other Name PUBLIC",doc.alternateName.get(0)); - assertEquals("WDB",doc.alumniOf.iterator().next().identifier.iterator().next().propertyID); - assertEquals("WDB",doc.affiliation.iterator().next().identifier.iterator().next().propertyID); + assertEquals("Person", doc.type); + assertEquals("http://schema.org", doc.context); + assertEquals("Credit Name", doc.name); + assertEquals("Given Names", doc.givenName); + assertEquals("Family Name", doc.familyName); + assertEquals("Other Name PUBLIC", doc.alternateName.get(0)); + assertEquals("WDB", doc.alumniOf.iterator().next().identifier.iterator().next().propertyID); + assertEquals("WDB", doc.affiliation.iterator().next().identifier.iterator().next().propertyID); Set fundingIds = Sets.newHashSet(); - for (SchemaOrgExternalID i: doc.worksAndFunding.funder.iterator().next().identifier) + for (SchemaOrgExternalID i : doc.worksAndFunding.funder.iterator().next().identifier) fundingIds.add(i.propertyID); - assertEquals(Sets.newHashSet("WDB","grant_number"),fundingIds); - assertEquals("PUBLIC",doc.worksAndFunding.creator.iterator().next().name); - assertEquals("http://www.researcherurl.com?id=13",doc.url.get(0)); - assertEquals("self_public_user_obo_type",doc.identifier.get(0).propertyID); - assertEquals( "self_public_user_obo_ref",doc.identifier.get(0).value); - } - -} + assertEquals(Sets.newHashSet("WDB", "grant_number"), fundingIds); + assertEquals("PUBLIC", doc.worksAndFunding.creator.iterator().next().name); + assertEquals("http://www.researcherurl.com?id=13", doc.url.get(0)); + assertEquals("self_public_user_obo_type", doc.identifier.get(0).propertyID); + assertEquals("self_public_user_obo_ref", doc.identifier.get(0).value); + } + + @Test + public void checkSourceOnEmail_RecordEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewRecord(orcid); + Record record = (Record) r.getEntity(); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + checkEmails(record.getPerson().getEmails()); + } + + @Test + public void checkSourceOnEmail_PersonEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewPerson(orcid); + Person p = (Person) r.getEntity(); + assertNotNull(p.getEmails()); + checkEmails(p.getEmails()); + } + + @Test + public void checkSourceOnEmail_EmailEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewEmails(orcid); + Emails emails = (Emails) r.getEntity(); + checkEmails(emails); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("public_0000-0000-0000-0001@test.orcid.org")) { + assertFalse(e.isVerified()); + // The source and name on non verified professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } +} \ No newline at end of file diff --git a/orcid-pub-web/src/test/java/org/orcid/api/publicV3/server/PublicV3ApiServiceDelegatorTest.java b/orcid-pub-web/src/test/java/org/orcid/api/publicV3/server/PublicV3ApiServiceDelegatorTest.java index 75c3d0220a8..429718189c0 100644 --- a/orcid-pub-web/src/test/java/org/orcid/api/publicV3/server/PublicV3ApiServiceDelegatorTest.java +++ b/orcid-pub-web/src/test/java/org/orcid/api/publicV3/server/PublicV3ApiServiceDelegatorTest.java @@ -597,8 +597,8 @@ public void testViewEmails() { assertEquals(Visibility.PUBLIC.value(), email.getVisibility().value()); assertEquals(Visibility.PUBLIC.value(), email2.getVisibility().value()); assertEquals("/0000-0000-0000-0003/email", emails.getPath()); - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); assertNull(email.getSource().getSourceOrcid()); assertEquals("0000-0000-0000-0000", email2.getSource().retrieveSourcePath()); assertEquals("ORCID email validation", email2.getSource().getSourceName().getContent()); @@ -1836,9 +1836,9 @@ private void validatePerson(Person person) { assertNotNull(email.getLastModifiedDate().getValue()); assertNotNull(email2.getLastModifiedDate()); assertNotNull(email2.getLastModifiedDate().getValue()); - assertEquals("APP-5555555555555555", email.getSource().retrieveSourcePath()); + assertEquals("0000-0000-0000-0000", email.getSource().retrieveSourcePath()); assertNull(email.getSource().getSourceOrcid()); - assertEquals("Source Client 1", email.getSource().getSourceName().getContent()); + assertEquals("ORCID email validation", email.getSource().getSourceName().getContent()); assertEquals("0000-0000-0000-0000", email2.getSource().retrieveSourcePath()); assertNull(email2.getSource().getSourceOrcid()); assertEquals("ORCID email validation", email2.getSource().getSourceName().getContent()); @@ -2187,4 +2187,53 @@ public void testExpandedSearchByQueryNoRowsParamSet() { ReflectionTestUtils.setField(serviceDelegator, "orcidSearchManager", orcidSearchManager); } + + @Test + public void checkSourceOnEmail_RecordEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewRecord(orcid); + Record record = (Record) r.getEntity(); + assertNotNull(record.getPerson()); + assertNotNull(record.getPerson().getEmails()); + checkEmails(record.getPerson().getEmails()); + } + + @Test + public void checkSourceOnEmail_PersonEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewPerson(orcid); + Person p = (Person) r.getEntity(); + assertNotNull(p.getEmails()); + checkEmails(p.getEmails()); + } + + @Test + public void checkSourceOnEmail_EmailEndpointTest() { + String orcid = "0000-0000-0000-0001"; + SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_LIMITED); + Response r = serviceDelegator.viewEmails(orcid); + Emails emails = (Emails) r.getEntity(); + checkEmails(emails); + } + + private void checkEmails(Emails emails) { + assertEquals(2, emails.getEmails().size()); + for(Email e : emails.getEmails()) { + if(e.getEmail().equals("public_0000-0000-0000-0001@test.orcid.org")) { + assertFalse(e.isVerified()); + // The source and name on non verified professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else if(e.getEmail().equals("verified_non_professional@nonprofessional.org")) { + assertTrue(e.isVerified()); + // The source and name on non professional email addresses should not change + assertEquals("APP-5555555555555555", e.getSource().retrieveSourcePath()); + assertEquals("Source Client 1", e.getSource().getSourceName().getContent()); + } else { + fail("Unexpected email " + e.getEmail()); + } + } + } } diff --git a/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainLoader.java b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainLoader.java index d01ee877f4f..874987637b6 100644 --- a/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainLoader.java +++ b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/loader/cli/EmailDomainLoader.java @@ -76,7 +76,7 @@ private void process() { for (List row : emailDomainData) { String elementDomain = row.get(0); String elementCategory = row.get(1); - EmailDomainEntity ede = emailDomainManager.findByEmailDomain(elementDomain); + List ede = emailDomainManager.findByEmailDomain(elementDomain); EmailDomainEntity.DomainCategory category = EmailDomainEntity.DomainCategory.valueOf(elementCategory.toUpperCase()); if(ede == null) { try { @@ -87,12 +87,6 @@ private void process() { LOG.error("Invalid domain: {}", elementDomain); invalidDomains.add(elementDomain); } - } else if(!elementCategory.equalsIgnoreCase(ede.getCategory().toString())) { - boolean updated = emailDomainManager.updateCategory(ede.getId(), category); - if(updated) { - LOG.info("Email category has been update for email domain {} from {} to {}", elementDomain, ede.getCategory(), elementCategory); - updatedEntities += 1; - } } total += 1; } diff --git a/orcid-test/src/main/resources/data/ProfileEntityData.xml b/orcid-test/src/main/resources/data/ProfileEntityData.xml index 11c74d195ba..ff5cf1c412d 100644 --- a/orcid-test/src/main/resources/data/ProfileEntityData.xml +++ b/orcid-test/src/main/resources/data/ProfileEntityData.xml @@ -1800,9 +1800,9 @@ source_id="4444-4444-4444-4441" date_created="2016-01-01 00:00:00.00" last_modified="2016-01-01 00:00:00.00" - /> - - + + + /> + + + + - + /> + ede = emailDomainManager.findByEmailDomain(domain); + String category = EmailDomainEntity.DomainCategory.UNDEFINED.name(); if(ede == null) { ObjectNode response = mapper.createObjectNode(); response.put("category", EmailDomainEntity.DomainCategory.UNDEFINED.name()); return response; } else { - ObjectNode response = mapper.createObjectNode(); - response.put("category", ede.getCategory().name()); - response.put("rorId", ede.getRorId()); + ObjectNode response = mapper.createObjectNode(); + if(ede.size() == 1) { + response.put("rorId", ede.get(0).getRorId()); + response.put("category", ede.get(0).getCategory().name()); + } else { + for(EmailDomainEntity ed:ede) { + category = ed.getCategory().name(); + if(StringUtils.equalsIgnoreCase(category, EmailDomainEntity.DomainCategory.PROFESSIONAL.name())) { + break; + } + } + response.put("category", category); + } return response; } @@ -60,9 +75,10 @@ public class EmailDomainController { } domain = OrcidStringUtils.stripHtml(domain); - EmailDomainEntity ede = emailDomainManager.findByEmailDomain(domain); - if(ede != null) { - String rorId = ede.getRorId(); + List ede = emailDomainManager.findByEmailDomain(domain); + //return the org if there was exactly one match + if(ede != null && ede.size()== 1) { + String rorId = ede.get(0).getRorId(); if(rorId != null && !rorId.isBlank()) { OrgDisambiguatedSolrDocument orgInfo = orcidSolrOrgsClient.getOrgByRorId(rorId); if(orgInfo != null) {