/** * ============================================================================= * * ORCID (R) Open Source * http://orcid.org * * Copyright (c) 2012-2014 ORCID, Inc. * Licensed under an MIT-Style License (MIT) * http://orcid.org/open-source-license * * This copyright and license information (including a link to the full license) * shall be included in its entirety in all copies or substantial portion of * the software. * * ============================================================================= */ 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.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.persistence.NoResultException; import javax.ws.rs.core.Response; import org.orcid.test.DBUnitTest; import org.orcid.test.helper.Utils; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.orcid.core.exception.ActivityIdentifierValidationException; import org.orcid.core.exception.OrcidAccessControlException; import org.orcid.core.exception.OrcidUnauthorizedException; import org.orcid.core.exception.OrcidVisibilityException; import org.orcid.core.exception.VisibilityMismatchException; import org.orcid.core.exception.WrongSourceException; import org.orcid.core.utils.SecurityContextTestUtils; import org.orcid.jaxb.model.common_v2.LastModifiedDate; import org.orcid.jaxb.model.common_v2.Url; import org.orcid.jaxb.model.common_v2.Visibility; import org.orcid.jaxb.model.groupid_v2.GroupIdRecord; import org.orcid.jaxb.model.message.FundingExternalIdentifierType; import org.orcid.jaxb.model.message.ScopePathType; import org.orcid.jaxb.model.record.summary_v2.ActivitiesSummary; import org.orcid.jaxb.model.record.summary_v2.FundingGroup; import org.orcid.jaxb.model.record.summary_v2.FundingSummary; import org.orcid.jaxb.model.record.summary_v2.Fundings; import org.orcid.jaxb.model.record_v2.Address; import org.orcid.jaxb.model.record_v2.Education; import org.orcid.jaxb.model.record_v2.Employment; import org.orcid.jaxb.model.record_v2.ExternalID; import org.orcid.jaxb.model.record_v2.ExternalIDs; import org.orcid.jaxb.model.record_v2.Funding; import org.orcid.jaxb.model.record_v2.Keyword; import org.orcid.jaxb.model.record_v2.OtherName; import org.orcid.jaxb.model.record_v2.PeerReview; import org.orcid.jaxb.model.record_v2.PersonExternalIdentifier; import org.orcid.jaxb.model.record_v2.Relationship; import org.orcid.jaxb.model.record_v2.ResearcherUrl; import org.orcid.jaxb.model.record_v2.Work; import org.orcid.jaxb.model.record_v2.WorkBulk; import org.orcid.test.OrcidJUnit4ClassRunner; import org.springframework.test.context.ContextConfiguration; @RunWith(OrcidJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:orcid-api-web-context.xml", "classpath:orcid-api-security-context.xml" }) public class MemberV2ApiServiceDelegator_FundingTest extends DBUnitTest { protected static final List<String> DATA_FILES = Arrays.asList("/data/EmptyEntityData.xml", "/data/SecurityQuestionEntityData.xml", "/data/SourceClientDetailsEntityData.xml", "/data/ProfileEntityData.xml", "/data/WorksEntityData.xml", "/data/ClientDetailsEntityData.xml", "/data/Oauth2TokenDetailsData.xml", "/data/OrgsEntityData.xml", "/data/ProfileFundingEntityData.xml", "/data/OrgAffiliationEntityData.xml", "/data/PeerReviewEntityData.xml", "/data/GroupIdRecordEntityData.xml", "/data/RecordNameEntityData.xml", "/data/BiographyEntityData.xml"); // Now on, for any new test, PLAESE USER THIS ORCID ID protected final String ORCID = "0000-0000-0000-0003"; @Resource(name = "memberV2ApiServiceDelegator") protected MemberV2ApiServiceDelegator<Education, Employment, PersonExternalIdentifier, Funding, GroupIdRecord, OtherName, PeerReview, ResearcherUrl, Work, WorkBulk, Address, Keyword> serviceDelegator; @BeforeClass public static void initDBUnitData() throws Exception { initDBUnitData(DATA_FILES); } @AfterClass public static void removeDBUnitData() throws Exception { Collections.reverse(DATA_FILES); removeDBUnitData(DATA_FILES); } @Test(expected = OrcidUnauthorizedException.class) public void testViewFundingWrongToken() { SecurityContextTestUtils.setUpSecurityContext("some-other-user", ScopePathType.READ_LIMITED); serviceDelegator.viewFunding(ORCID, 10L); } @Test(expected = OrcidUnauthorizedException.class) public void testViewFundingSummaryWrongToken() { SecurityContextTestUtils.setUpSecurityContext("some-other-user", ScopePathType.READ_LIMITED); serviceDelegator.viewFundingSummary(ORCID, 10L); } @Test public void testViewFundingReadPublic() { SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_PUBLIC); Response r = serviceDelegator.viewFunding(ORCID, 10L); Funding element = (Funding) r.getEntity(); assertNotNull(element); assertEquals("/0000-0000-0000-0003/funding/10", element.getPath()); Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); } @Test public void testViewFundingSummaryReadPublic() { SecurityContextTestUtils.setUpSecurityContextForClientOnly("APP-5555555555555555", ScopePathType.READ_PUBLIC); Response r = serviceDelegator.viewFundingSummary(ORCID, 10L); FundingSummary element = (FundingSummary) r.getEntity(); assertNotNull(element); assertEquals("/0000-0000-0000-0003/funding/10", element.getPath()); Utils.assertIsPublicOrSource(element, "APP-5555555555555555"); } @Test public void testAddFundingWithInvalidExtIdTypeFail() { String orcid = "4444-4444-4444-4499"; SecurityContextTestUtils.setUpSecurityContext(orcid, ScopePathType.ACTIVITIES_READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Funding funding = Utils.getFunding(); try { funding.getExternalIdentifiers().getExternalIdentifier().get(0).setType("INVALID"); serviceDelegator.createFunding(orcid, funding); fail(); } catch (ActivityIdentifierValidationException e) { } catch (Exception e) { fail(); } funding.getExternalIdentifiers().getExternalIdentifier().get(0).setType("grant_number"); Response response = serviceDelegator.createFunding(orcid, funding); assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus()); Map<?, ?> map = response.getMetadata(); assertNotNull(map); assertTrue(map.containsKey("Location")); List<?> resultWithPutCode = (List<?>) map.get("Location"); Long putCode = Long.valueOf(String.valueOf(resultWithPutCode.get(0))); // Delete it to roll back the test data response = serviceDelegator.deleteFunding(orcid, putCode); assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus()); } @Test public void testViewPublicFunding() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4446", ScopePathType.READ_LIMITED); Response response = serviceDelegator.viewFunding("4444-4444-4444-4446", 5L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); Utils.verifyLastModified(funding.getLastModifiedDate()); assertNotNull(funding.getTitle()); assertNotNull(funding.getTitle().getTitle()); assertEquals(Long.valueOf(5), funding.getPutCode()); assertEquals("/4444-4444-4444-4446/funding/5", funding.getPath()); assertEquals("Public Funding", funding.getTitle().getTitle().getContent()); assertEquals(Visibility.PUBLIC.value(), funding.getVisibility().value()); } @Test public void testViewLimitedFunding() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4443", ScopePathType.READ_LIMITED); Response response = serviceDelegator.viewFunding("4444-4444-4444-4443", 1L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); Utils.verifyLastModified(funding.getLastModifiedDate()); assertNotNull(funding.getTitle()); assertNotNull(funding.getTitle().getTitle()); assertEquals(Long.valueOf(1), funding.getPutCode()); assertEquals("/4444-4444-4444-4443/funding/1", funding.getPath()); assertEquals("Grant # 1", funding.getTitle().getTitle().getContent()); assertEquals(Visibility.LIMITED.value(), funding.getVisibility().value()); } @Test public void testViewPrivateFunding() { // Use the smallest scope in the pyramid to verify that you can read // your own limited and protected data SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4446", ScopePathType.READ_LIMITED); Response response = serviceDelegator.viewFunding("4444-4444-4444-4446", 4L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); Utils.verifyLastModified(funding.getLastModifiedDate()); assertNotNull(funding.getTitle()); assertNotNull(funding.getTitle().getTitle()); assertEquals(Long.valueOf(4), funding.getPutCode()); assertEquals("/4444-4444-4444-4446/funding/4", funding.getPath()); assertEquals("Private Funding", funding.getTitle().getTitle().getContent()); assertEquals(Visibility.PRIVATE.value(), funding.getVisibility().value()); } @Test(expected = OrcidVisibilityException.class) public void testViewPrivateFundingWhereYouAreNotTheSource() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4443", ScopePathType.READ_LIMITED); serviceDelegator.viewFunding("4444-4444-4444-4443", 3L); fail(); } @Test(expected = NoResultException.class) public void testViewFundingThatDontBelongToTheUser() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4446", ScopePathType.READ_LIMITED); // Funding 1 belongs to 4444-4444-4444-4443 serviceDelegator.viewFunding("4444-4444-4444-4446", 1L); fail(); } @Test public void testViewFundings() { SecurityContextTestUtils.setUpSecurityContext(ORCID, ScopePathType.READ_LIMITED); Response r = serviceDelegator.viewFundings(ORCID); assertNotNull(r); Fundings fundings = (Fundings) r.getEntity(); assertNotNull(fundings); assertEquals("/0000-0000-0000-0003/fundings", fundings.getPath()); assertNotNull(fundings.getPath()); Utils.verifyLastModified(fundings.getLastModifiedDate()); assertNotNull(fundings.getFundingGroup()); assertEquals(4, fundings.getFundingGroup().size()); boolean found1 = false, found2 = false, found3 = false, found4 = false; for (FundingGroup fundingGroup : fundings.getFundingGroup()) { Utils.verifyLastModified(fundingGroup.getLastModifiedDate()); assertNotNull(fundingGroup.getIdentifiers()); assertNotNull(fundingGroup.getIdentifiers().getExternalIdentifier()); assertEquals(1, fundingGroup.getIdentifiers().getExternalIdentifier().size()); assertNotNull(fundingGroup.getFundingSummary()); assertEquals(1, fundingGroup.getFundingSummary().size()); FundingSummary summary = fundingGroup.getFundingSummary().get(0); Utils.verifyLastModified(summary.getLastModifiedDate()); assertNotNull(summary.getTitle()); assertNotNull(summary.getTitle().getTitle()); switch (fundingGroup.getIdentifiers().getExternalIdentifier().get(0).getValue()) { case "1": assertEquals("PUBLIC", summary.getTitle().getTitle().getContent()); assertEquals(Long.valueOf(10), summary.getPutCode()); found1 = true; break; case "2": assertEquals("LIMITED", summary.getTitle().getTitle().getContent()); assertEquals(Long.valueOf(11), summary.getPutCode()); found2 = true; break; case "3": assertEquals("PRIVATE", summary.getTitle().getTitle().getContent()); assertEquals(Long.valueOf(12), summary.getPutCode()); found3 = true; break; case "4": assertEquals("SELF LIMITED", summary.getTitle().getTitle().getContent()); assertEquals(Long.valueOf(13), summary.getPutCode()); found4 = true; break; default: fail("Invalid external id found: " + fundingGroup.getIdentifiers().getExternalIdentifier().get(0).getValue()); } } assertTrue(found1); assertTrue(found2); assertTrue(found3); assertTrue(found4); } @Test public void testReadPublicScope_Funding() { SecurityContextTestUtils.setUpSecurityContext(ORCID, ScopePathType.READ_PUBLIC); // Public works Response r = serviceDelegator.viewFunding(ORCID, 10L); assertNotNull(r); assertEquals(Funding.class.getName(), r.getEntity().getClass().getName()); r = serviceDelegator.viewFundingSummary(ORCID, 10L); assertNotNull(r); assertEquals(FundingSummary.class.getName(), r.getEntity().getClass().getName()); // Limited that am the source of should work serviceDelegator.viewFunding(ORCID, 11L); serviceDelegator.viewFundingSummary(ORCID, 11L); // Limited that am not the source of should fail try { serviceDelegator.viewFunding(ORCID, 13L); fail(); } catch (OrcidAccessControlException e) { } catch (Exception e) { fail(); } try { serviceDelegator.viewFundingSummary(ORCID, 13L); fail(); } catch (OrcidAccessControlException e) { } catch (Exception e) { fail(); } // Private that am the source of should work serviceDelegator.viewFunding(ORCID, 12L); serviceDelegator.viewFundingSummary(ORCID, 12L); // Private am not the source of should fail try { serviceDelegator.viewFunding(ORCID, 14L); fail(); } catch (OrcidAccessControlException e) { } catch (Exception e) { fail(); } try { serviceDelegator.viewFundingSummary(ORCID, 14L); fail(); } catch (OrcidAccessControlException e) { } catch (Exception e) { fail(); } } @Test public void testAddFunding() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4447", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewActivities("4444-4444-4444-4447"); assertNotNull(response); ActivitiesSummary summary = (ActivitiesSummary) response.getEntity(); assertNotNull(summary); Utils.verifyLastModified(summary.getLastModifiedDate()); assertNotNull(summary.getFundings()); Utils.verifyLastModified(summary.getFundings().getLastModifiedDate()); assertNotNull(summary.getFundings().getFundingGroup()); assertNotNull(summary.getFundings().getFundingGroup().get(0)); Utils.verifyLastModified(summary.getLastModifiedDate()); assertNotNull(summary.getFundings().getFundingGroup().get(0).getFundingSummary()); assertEquals(1, summary.getFundings().getFundingGroup().get(0).getFundingSummary().size()); assertNotNull(summary.getFundings().getFundingGroup().get(0).getFundingSummary().get(0)); Utils.verifyLastModified(summary.getLastModifiedDate()); assertNotNull(summary.getFundings().getFundingGroup().get(0).getFundingSummary().get(0).getTitle()); assertNotNull(summary.getFundings().getFundingGroup().get(0).getFundingSummary().get(0).getTitle().getTitle()); assertEquals("Public Funding # 1", summary.getFundings().getFundingGroup().get(0).getFundingSummary().get(0).getTitle().getTitle().getContent()); Funding newFunding = Utils.getFunding(); response = serviceDelegator.createFunding("4444-4444-4444-4447", newFunding); assertNotNull(response); assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus()); response = serviceDelegator.viewActivities("4444-4444-4444-4447"); assertNotNull(response); summary = (ActivitiesSummary) response.getEntity(); assertNotNull(summary); Utils.verifyLastModified(summary.getLastModifiedDate()); assertNotNull(summary.getFundings()); assertNotNull(summary.getFundings().getFundingGroup()); assertEquals(2, summary.getFundings().getFundingGroup().size()); boolean haveOld = false; boolean haveNew = false; for (FundingGroup group : summary.getFundings().getFundingGroup()) { assertNotNull(group.getFundingSummary().get(0)); assertNotNull(group.getFundingSummary().get(0).getTitle()); assertNotNull(group.getFundingSummary().get(0).getTitle().getTitle()); assertNotNull(group.getFundingSummary().get(0).getTitle().getTitle().getContent()); if ("Public Funding # 1".equals(group.getFundingSummary().get(0).getTitle().getTitle().getContent())) { haveOld = true; } else if ("Public Funding # 2".equals(group.getFundingSummary().get(0).getTitle().getTitle().getContent())) { haveNew = true; } } assertTrue(haveOld); assertTrue(haveNew); } @Test public void testUpdateFunding() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4447", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewFunding("4444-4444-4444-4447", 6L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); assertEquals("Public Funding # 1", funding.getTitle().getTitle().getContent()); assertEquals("This is the description for funding with id 6", funding.getDescription()); LastModifiedDate before = funding.getLastModifiedDate(); funding.getTitle().getTitle().setContent("Updated funding title"); funding.setDescription("This is an updated description"); ExternalID fExtId = new ExternalID(); fExtId.setRelationship(Relationship.PART_OF); fExtId.setType(FundingExternalIdentifierType.GRANT_NUMBER.value()); fExtId.setUrl(new Url("http://fundingExtId.com")); fExtId.setValue("new-funding-ext-id"); ExternalIDs fExtIds = new ExternalIDs(); fExtIds.getExternalIdentifier().add(fExtId); funding.setExternalIdentifiers(fExtIds); response = serviceDelegator.updateFunding("4444-4444-4444-4447", 6L, funding); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); response = serviceDelegator.viewFunding("4444-4444-4444-4447", 6L); assertNotNull(response); funding = (Funding) response.getEntity(); assertNotNull(funding); Utils.verifyLastModified(funding.getLastModifiedDate()); assertTrue(funding.getLastModifiedDate().after(before)); assertEquals("Updated funding title", funding.getTitle().getTitle().getContent()); assertEquals("This is an updated description", funding.getDescription()); // Rollback changes funding.getTitle().getTitle().setContent("Public Funding # 1"); funding.setDescription("This is the description for funding with id 6"); response = serviceDelegator.updateFunding("4444-4444-4444-4447", 6L, funding); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); } @Test(expected = WrongSourceException.class) public void testUpdateFundingYouAreNotTheSourceOf() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4446", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewFunding("4444-4444-4444-4446", 5L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); funding.getTitle().getTitle().setContent("Updated funding title"); ExternalID fExtId = new ExternalID(); fExtId.setRelationship(Relationship.PART_OF); fExtId.setType(FundingExternalIdentifierType.GRANT_NUMBER.value()); fExtId.setUrl(new Url("http://fundingExtId.com")); fExtId.setValue("new-funding-ext-id"); ExternalIDs fExtIds = new ExternalIDs(); fExtIds.getExternalIdentifier().add(fExtId); funding.setExternalIdentifiers(fExtIds); serviceDelegator.updateFunding("4444-4444-4444-4446", 5L, funding); fail(); } @Test(expected = VisibilityMismatchException.class) public void testUpdateFundingChangingVisibilityTest() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4447", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewFunding("4444-4444-4444-4447", 6L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); assertEquals(Visibility.PUBLIC, funding.getVisibility()); funding.setVisibility(Visibility.PRIVATE); response = serviceDelegator.updateFunding("4444-4444-4444-4447", 6L, funding); fail(); } @Test public void testUpdateFundingLeavingVisibilityNullTest() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4447", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewFunding("4444-4444-4444-4447", 6L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); assertEquals(Visibility.PUBLIC, funding.getVisibility()); funding.setVisibility(null); response = serviceDelegator.updateFunding("4444-4444-4444-4447", 6L, funding); assertNotNull(response); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); funding = (Funding) response.getEntity(); assertEquals(Visibility.PUBLIC, funding.getVisibility()); } @Test(expected = NoResultException.class) public void testDeleteFunding() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4442", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); Response response = serviceDelegator.viewFunding("4444-4444-4444-4442", 7L); assertNotNull(response); Funding funding = (Funding) response.getEntity(); assertNotNull(funding); response = serviceDelegator.deleteFunding("4444-4444-4444-4442", 7L); assertNotNull(response); assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus()); serviceDelegator.viewFunding("4444-4444-4444-4442", 7L); } @Test(expected = WrongSourceException.class) public void testDeleteFundingYouAreNotTheSourceOf() { SecurityContextTestUtils.setUpSecurityContext("4444-4444-4444-4446", ScopePathType.READ_LIMITED, ScopePathType.ACTIVITIES_UPDATE); serviceDelegator.deleteFunding("4444-4444-4444-4446", 5L); fail(); } }