Skip to content
Merged

PD-5278 #7495

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.orcid.api.common.util.v3;

import javax.annotation.Resource;

import org.orcid.api.publicV3.server.security.PublicAPISecurityManagerV3;
import org.orcid.core.manager.v3.OrcidSecurityManager;
import org.orcid.core.manager.v3.read_only.RecordManagerReadOnly;
import org.orcid.core.utils.v3.SourceUtils;
import org.orcid.core.version.impl.Api3_0LastModifiedDatesHelper;
import org.orcid.jaxb.model.v3.release.record.Record;
import org.springframework.stereotype.Component;

@Component
public class PublicRecordUtils {

@Resource(name = "recordManagerReadOnlyV3")
private RecordManagerReadOnly recordManagerReadOnly;

@Resource(name = "orcidSecurityManagerV3")
private OrcidSecurityManager orcidSecurityManager;

@Resource(name = "publicAPISecurityManagerV3")
private PublicAPISecurityManagerV3 publicAPISecurityManagerV3;

@Resource(name = "sourceUtilsReadOnlyV3")
private SourceUtils sourceUtilsReadOnly;

public Record getPublicRecord(String orcid, boolean filterVersionOfIdentifiers) {
orcidSecurityManager.checkProfile(orcid);
Record record = recordManagerReadOnly.getPublicRecord(orcid, filterVersionOfIdentifiers);
publicAPISecurityManagerV3.filter(record);
if (record.getPerson() != null) {
sourceUtilsReadOnly.setSourceName(record.getPerson());
}
if (record.getActivitiesSummary() != null) {
ActivityUtils.cleanEmptyFields(record.getActivitiesSummary());
sourceUtilsReadOnly.setSourceName(record.getActivitiesSummary());
}
ElementUtils.setPathToRecord(record, orcid);
Api3_0LastModifiedDatesHelper.calculateLastModified(record);
return record;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
<bean id="publicAPISecurityManagerV3" class="org.orcid.api.publicV3.server.security.impl.PublicAPISecurityManagerV3Impl" />
</beans>
1 change: 1 addition & 0 deletions orcid-api-web/src/main/resources/orcid-api-web-context.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<import resource="classpath*:orcid-core-context.xml"/>
<import resource="classpath*:orcid-api-common-public-v3-context.xml"/>
<import resource="classpath*:orcid-api-security-context.xml"/>

<context:component-scan base-package="org.orcid.api.common, org.orcid.api.member.common, org.orcid.core.security, org.orcid.api.filters"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<import resource="classpath*:orcid-core-context.xml"/>
<import resource="classpath*:orcid-api-common-public-v3-context.xml"/>
<import resource="classpath*:orcid-internal-api-security-context.xml"/>

<context:component-scan base-package="org.orcid.api.t2, org.orcid.api.common, org.orcid.core.security"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@

import org.orcid.api.common.util.v3.ActivityUtils;
import org.orcid.api.common.util.v3.ElementUtils;
import org.orcid.api.common.util.v3.PublicRecordUtils;
import org.orcid.api.publicV3.server.security.PublicAPISecurityManagerV3;
import org.orcid.api.common.writer.citeproc.V3WorkToCiteprocTranslator;
import org.orcid.api.publicV3.server.delegator.PublicV3ApiServiceDelegator;
import org.orcid.api.publicV3.server.security.PublicAPISecurityManagerV3;
import org.orcid.core.common.manager.EmailDomainManager;
import org.orcid.core.common.manager.EventManager;
import org.orcid.core.exception.OrcidBadRequestException;
Expand Down Expand Up @@ -84,13 +85,11 @@
import org.orcid.jaxb.model.v3.release.record.summary.Works;
import org.orcid.jaxb.model.v3.release.search.Search;
import org.orcid.jaxb.model.v3.release.search.expanded.ExpandedSearch;
import org.orcid.persistence.jpa.entities.EmailDomainEntity;
import org.orcid.persistence.jpa.entities.ProfileEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import de.undercouch.citeproc.csl.CSLItemData;
import liquibase.repackaged.org.apache.commons.lang3.StringUtils;

@Component
public class PublicV3ApiServiceDelegatorImpl implements
Expand Down Expand Up @@ -175,6 +174,9 @@ public class PublicV3ApiServiceDelegatorImpl implements
@Resource(name = "publicAPISecurityManagerV3")
private PublicAPISecurityManagerV3 publicAPISecurityManagerV3;

@Resource
private PublicRecordUtils publicRecordUtils;

@Resource
private LocaleManager localeManager;

Expand Down Expand Up @@ -619,22 +621,10 @@ public Response viewPerson(String orcid) {

@Override
public Response viewRecord(String orcid) {
checkProfileStatus(orcid);
Record record = recordManagerReadOnly.getPublicRecord(orcid, filterVersionOfIdentifiers);
publicAPISecurityManagerV3.filter(record);
if (record.getPerson() != null) {
sourceUtilsReadOnly.setSourceName(record.getPerson());
}
if (record.getActivitiesSummary() != null) {
ActivityUtils.cleanEmptyFields(record.getActivitiesSummary());
sourceUtilsReadOnly.setSourceName(record.getActivitiesSummary());
}
ElementUtils.setPathToRecord(record, orcid);
Api3_0LastModifiedDatesHelper.calculateLastModified(record);
return Response.ok(record).build();
return Response.ok(publicRecordUtils.getPublicRecord(orcid, filterVersionOfIdentifiers)).build();
}

@Override
@Override
public Response searchByQuery(Map<String, List<String>> solrParams) {
validateSearchParams(solrParams);
Search search = orcidSearchManager.findOrcidIds(solrParams);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@

<bean id="publicAPISecurityManagerV2" class="org.orcid.api.publicV2.server.security.impl.PublicAPISecurityManagerV2Impl" />

<bean id="publicAPISecurityManagerV3" class="org.orcid.api.publicV3.server.security.impl.PublicAPISecurityManagerV3Impl" />


<bean id="apiVersionFilter" class="org.orcid.api.common.filter.ApiVersionFilter" />
Expand Down
1 change: 1 addition & 0 deletions orcid-pub-web/src/main/resources/orcid-t1-web-context.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd">

<import resource="classpath*:orcid-core-context.xml"/>
<import resource="classpath*:orcid-api-common-public-v3-context.xml"/>
<import resource="classpath*:orcid-t1-security-context.xml"/>

<context:component-scan base-package="org.orcid.api.publicV3.server,org.orcid.api.config, org.orcid.api.t1, org.orcid.api.common, org.orcid.core.security, org.orcid.api.filters"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.junit.Test;
import org.junit.runner.RunWith;
import org.orcid.api.publicV3.server.security.PublicAPISecurityManagerV3;
import org.orcid.core.exception.OrcidNonPublicElementException;
import org.orcid.jaxb.model.v3.release.common.Filterable;
import org.orcid.jaxb.model.v3.release.common.Visibility;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.orcid.frontend.web.controllers;

import javax.annotation.Resource;

import org.orcid.api.common.util.v3.PublicRecordUtils;
import org.orcid.core.api.OrcidApiConstants;
import org.orcid.jaxb.model.v3.release.record.Record;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class PublicRecordApiController {

@Resource
private PublicRecordUtils publicRecordUtils;

private final boolean filterVersionOfIdentifiers = false;

@RequestMapping(value = "/{orcid:(?:\\d{4}-){3,}\\d{3}[\\dX]}/record", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE,
OrcidApiConstants.ORCID_JSON, OrcidApiConstants.VND_ORCID_JSON })
public @ResponseBody Record viewRecord(@PathVariable("orcid") String orcid) {
return publicRecordUtils.getPublicRecord(orcid, filterVersionOfIdentifiers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.orcid.frontend.web.controllers;

import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;

import org.orcid.core.exception.OrcidCoreExceptionMapper;
import org.orcid.core.exception.OrcidDeprecatedException;
import org.orcid.core.manager.impl.OrcidUrlManager;
import org.orcid.jaxb.model.v3.release.error.OrcidError;
import org.orcid.utils.OrcidStringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


@RestControllerAdvice(assignableTypes = PublicRecordApiController.class)
public class PublicRecordApiExceptionHandler {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cryptalith did you tested that this code runs? Im not sure if this code is necessary or not.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this can be tested by navigating to a deprecated orcid id print page.

As the PublicRecordApiController is a Spring MVC @controller. Requests to /{orcid}/record are handled by Spring’s not by the JAX-RS stack where OrcidExceptionMapper run for the public API.

So for this endpoint the @RestControllerAdvice is the Spring-side equivalent: it turns exceptions from that controller only into HTTP responses.


private static final String LOCATION_HEADER = "location";
private static final String PRIMARY_ORCID_HEADER = "x-orcid-primary";

@Resource
private OrcidCoreExceptionMapper orcidCoreExceptionMapper;

@ExceptionHandler(Throwable.class)
public ResponseEntity<Object> handleThrowable(Throwable t, HttpServletRequest request) {
if (OrcidDeprecatedException.class.isAssignableFrom(t.getClass())) {
return handleDeprecated((OrcidDeprecatedException) t, request);
}
Object orcidError = orcidCoreExceptionMapper.getOrcidError(t, OrcidCoreExceptionMapper.V3);
int statusCode = ((OrcidError) orcidError).getResponseCode();
return ResponseEntity.status(statusCode).body(orcidError);
}

private ResponseEntity<Object> handleDeprecated(OrcidDeprecatedException t, HttpServletRequest request) {
Object orcidError = orcidCoreExceptionMapper.getOrcidError(t, OrcidCoreExceptionMapper.V3);
Map<String, String> params = t.getParams();

int statusCode = Response.Status.MOVED_PERMANENTLY.getStatusCode();
String method = request.getMethod();
if (method != null && !"GET".equals(method)) {
statusCode = Response.Status.CONFLICT.getStatusCode();
OrcidError v3Error = (OrcidError) orcidError;
orcidError = orcidCoreExceptionMapper.getDeprecatedOrcidErrorV3(v3Error.getErrorCode(), statusCode, params);
}

HttpHeaders headers = new HttpHeaders();
if (params != null && params.containsKey(OrcidDeprecatedException.ORCID)) {
String primaryOrcid = OrcidStringUtils.getOrcidNumber(params.get(OrcidDeprecatedException.ORCID));
if (primaryOrcid != null) {
headers.add(PRIMARY_ORCID_HEADER, primaryOrcid);
}
String location = getPrimaryRecordLocation(request, params);
if (location != null) {
headers.add(LOCATION_HEADER, location);
}
}
return ResponseEntity.status(statusCode).headers(headers).body(orcidError);
}

private String getPrimaryRecordLocation(HttpServletRequest request, Map<String, String> params) {
String deprecatedOrcid = OrcidStringUtils.getOrcidNumber(request.getRequestURI());
String primaryOrcid = OrcidStringUtils.getOrcidNumber(params.get(OrcidDeprecatedException.ORCID));
String originalRequest = request.getRequestURL().toString();
if (OrcidUrlManager.isSecure(request)) {
if (originalRequest.startsWith("http:")) {
originalRequest = originalRequest.replaceFirst("http:", "https:");
}
}
return originalRequest.replace(deprecatedOrcid, primaryOrcid);
}
}

1 change: 1 addition & 0 deletions orcid-web/src/main/resources/orcid-frontend-security.xml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/allWorks.json(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/person.json(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/public-record.json(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/record(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/summary.json(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/affiliations.json(\?.*)?" security="none" create-session="stateless" />
<sec:http request-matcher="regex" pattern="/(\d{4}-){3,}\d{3}[\dX]/affiliationDetails.json(\?.*)?" security="none" create-session="stateless" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<import resource="classpath*:orcid-core-context.xml" />
<import resource="classpath*:orcid-api-common-public-v3-context.xml" />
<import resource="classpath*:orcid-frontend-security.xml" />

<tx:annotation-driven />
Expand Down
Loading