Skip to content

Commit

Permalink
Merge branch 'main' into 9455-orgbug-the-other-names-json-not-saved-i…
Browse files Browse the repository at this point in the history
…n-the-db-for-new-ror-orgs-added-in-db
  • Loading branch information
amontenegro authored Oct 30, 2024
2 parents e646f26 + 739fc89 commit 4e10fd0
Show file tree
Hide file tree
Showing 24 changed files with 888 additions and 40 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## v2.67.2 - 2024-10-30

[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.67.1...v2.67.2)

## v2.67.1 - 2024-10-29

[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.67.0...v2.67.1)

## v2.67.0 - 2024-10-29

[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.66.6...v2.67.0)

## v2.66.6 - 2024-10-28

[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.66.5...v2.66.6)
Expand Down
13 changes: 12 additions & 1 deletion orcid-activemq/src/main/resources/message-listener.properties
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,15 @@ org.orcid.message-listener.index.s3.search.max_elements=5
org.orcid.message-listener.index.summaries.bucket_name=v2.0-summaries-dev
org.orcid.message-listener.index.activities.bucket_name=v2.0-activities-dev
org.orcid.message-listener.index.summaries.v3.bucket_name=v3.0-summaries-dev
org.orcid.message-listener.index.activities.v3.bucket_name=v3.0-activities-dev
org.orcid.message-listener.index.activities.v3.bucket_name=v3.0-activities-dev


org.orcid.persistence.panoply.cleanup.production=false
# Panoply redshift database
org.orcid.core.utils.panoply.driver=com.amazon.redshift.jdbc.Driver
org.orcid.core.utils.panoply.maxPoolSize=20
org.orcid.core.utils.panoply.password=xxx
org.orcid.core.utils.panoply.idleConnectionTimeout=3600
org.orcid.core.utils.panoply.connectionTimeout=36000
org.orcid.core.utils.panoply.jdbcUrl=xxx
org.orcid.core.utils.panoply.username=xxx
5 changes: 4 additions & 1 deletion orcid-core/src/main/java/org/orcid/core/togglz/Features.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ public enum Features implements Feature {
EMAIL_DOMAINS,

@Label("Enable email domains in the UI")
EMAIL_DOMAINS_UI;
EMAIL_DOMAINS_UI,

@Label("Enforce rate limiting for public API when disabled the rate monitoring is on. When disabled is the mode is monitoring only.")
ENABLE_PAPI_RATE_LIMITING;

public boolean isActive() {
return FeatureContext.getFeatureManager().isActive(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,29 @@
import org.springframework.web.filter.OncePerRequestFilter;

/**
*
* @author Robert Peters (rcpeters)
*
*/

public class CorsFilterWeb extends OncePerRequestFilter {

@Resource
CrossDomainWebManger crossDomainWebManger;

private static final String LOCALHOST_BASE_URI= "https://localhost";
private static final String LOCALHOST_ORCID_WEB_BASE_URI = "https://localhost:8443/orcid-web";


@Value("${org.orcid.core.baseUri}")
private String baseUri;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Pattern p = Pattern.compile("^/userStatus\\.json|^/oauth/userinfo|^/oauth/jwks|^/\\.well-known/openid-configuration");
Matcher m = p.matcher(OrcidUrlManager.getPathWithoutContextPath(request));
// Allow CORS for all paths from Angular frontend only if we are in local dev env
// All other envs allow CORS only if request path matches one of:
// userStatus.json
// /oauth/userinfo
// /oauth/jwks
// /.well-known/openid-configuration
if (baseUri.equals(LOCALHOST_BASE_URI) || baseUri.equals(LOCALHOST_ORCID_WEB_BASE_URI) || m.matches()) {
if (crossDomainWebManger.allowed(request)) {
String origin = request.getHeader("origin");
response.addHeader("Access-Control-Allow-Origin", origin);
response.addHeader("Access-Control-Allow-Credentials", "true");

if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
// CORS "pre-flight" request
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization,x-csrf-token");
}
if (crossDomainWebManger.allowed(request)) {
String origin = request.getHeader("origin");
response.addHeader("Access-Control-Allow-Origin", origin);
response.addHeader("Access-Control-Allow-Credentials", "true");

if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
// CORS "pre-flight" request
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type,Accept,Authorization,x-csrf-token");
}

}

filterChain.doFilter(request, response);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<#import "email_macros.ftl" as emailMacros />
Dear ${emailName},

This is an important message to let you know that you have exceeded our daily Public API usage limit with your integration:

Client Name: ${clientName}
Client ID: ${clientId}

Please remember that the ORCID Public API is free for non-commercial use by individuals as stated in the Public APIs Terms of Service (https://info.orcid.org/public-client-terms-of-service/). By “non-commercial” we mean that you may not charge any re-use fees for the Public API, and you may not make use of the Public API in connection with any revenue-generating product or service

If you need access to an ORCID API for commercial use, need a higher usage quota, organizational administration of your API credentials, or the ability to write data to or access Trusted Party data in ORCID records, our Member API (https://info.orcid.org/documentation/features/member-api/) is available to ORCID member organizations.

To minimize any disruption to your ORCID integration in the future, we would recommend that you reach out to our Engagement Team by replying to this email to discuss our ORCID membership options.

Warm Regards,
ORCID Support Team
https://support.orcid.org
<@emailMacros.msg "email.common.you_have_received_this_email" />
<#include "email_footer.ftl"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<#import "email_macros.ftl" as emailMacros />
<#escape x as x?html>
<!DOCTYPE html>
<html>
<head>
<title>${subject}</title>
</head>
<body>
<div style="padding: 20px; padding-top: 10px; width: 700px; margin: auto;">
<img src="https://orcid.org/sites/all/themes/orcid/img/orcid-logo.png" alt="ORCID.org"/>
<hr />
<span style="font-family: arial, helvetica, sans-serif; font-size: 15px; color: #494A4C; font-weight: bold;">Dear ${emailName},</span>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">This is an important message to let you know that you have exceeded our daily Public API usage limit with your integration:</p>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">Client Name: ${clientName}</p>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">Client ID: ${clientId}</p>
<br/>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">Please remember that the ORCID Public API is free for non-commercial use by individuals as stated in the Public APIs Terms of Service (https://info.orcid.org/public-client-terms-of-service/). By “non-commercial” we mean that you may not charge any re-use fees for the Public API, and you may not make use of the Public API in connection with any revenue-generating product or service.</p>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">If you need access to an ORCID API for commercial use, need a higher usage quota, organizational administration of your API credentials, or the ability to write data to or access Trusted Party data in ORCID records, our Member API (https://info.orcid.org/documentation/features/member-api/) is available to ORCID member organizations.</p>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">To minimize any disruption to your ORCID integration in the future, we would recommend that you reach out to our Engagement Team by replying to this email to discuss our ORCID membership options.
<br/>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C; white-space: pre;">
Warm Regards,
ORCID Support Team
https://support.orcid.org
</p>

<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C;">
<@emailMacros.msg "email.common.you_have_received_this_email" />
</p>
<p style="font-family: arial, helvetica, sans-serif;font-size: 15px;color: #494A4C;">
<#include "email_footer_html.ftl"/>
</p>
</div>
</body>
</html>
</#escape>
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,24 @@
</bean>

<bean id="ORCIDMarshaller" class="org.orcid.utils.jersey.marshaller.ORCIDMarshaller" />

<!-- Panoply Redshift -->
<bean id="panoplyRedshiftDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<property name="driverClassName" value="\${org.orcid.core.utils.panoply.driver:com.amazon.redshift.jdbc.Driver}" />
<property name="jdbcUrl" value="\${org.orcid.core.utils.panoply.jdbcUrl}" />
<property name="username" value="\${org.orcid.core.utils.panoply.username}" />
<property name="password" value="\${org.orcid.core.utils.panoply.password}" />
<property name="maximumPoolSize" value="\${org.orcid.core.utils.panoply.maxPoolSize:5}" />
<property name="idleTimeout" value="\${org.orcid.core.utils.panoply.idleConnectionTimeout:3600}" />
<property name="connectionTimeout" value="\${org.orcid.core.utils.panoply.connectionTimeout:3600}" />
</bean>

<!-- Panoply JdbcTemplate Bean Definition -->
<bean id="panoplyJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="panoplyRedshiftDataSource" />
</bean>

<!-- Redshift panoply -->
<bean id="panoplyClient" class="org.orcid.utils.panoply.PanoplyRedshiftClient" />

</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.orcid.persistence.dao;

import java.time.LocalDate;

import org.orcid.persistence.jpa.entities.PublicApiDailyRateLimitEntity;

public interface PublicApiDailyRateLimitDao extends GenericDao<PublicApiDailyRateLimitEntity, Long> {

PublicApiDailyRateLimitEntity findByClientIdAndRequestDate(String clientId, LocalDate requestDate);
PublicApiDailyRateLimitEntity findByIpAddressAndRequestDate(String ipAddress, LocalDate requestDate);
int countClientRequestsWithLimitExceeded(LocalDate requestDate, int limit);
int countAnonymousRequestsWithLimitExceeded(LocalDate requestDate, int limit);
boolean updatePublicApiDailyRateLimit(PublicApiDailyRateLimitEntity papiRateLimitingEntity, boolean isClient);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.orcid.persistence.dao.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Query;

import org.orcid.persistence.dao.PublicApiDailyRateLimitDao;
import org.orcid.persistence.jpa.entities.PublicApiDailyRateLimitEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

public class PublicApiDailyRateLimitDaoImpl extends GenericDaoImpl<PublicApiDailyRateLimitEntity, Long> implements PublicApiDailyRateLimitDao {
private static final Logger LOG = LoggerFactory.getLogger(PublicApiDailyRateLimitDaoImpl.class);

public PublicApiDailyRateLimitDaoImpl() {
super(PublicApiDailyRateLimitEntity.class);
}

@Override
public PublicApiDailyRateLimitEntity findByClientIdAndRequestDate(String clientId, LocalDate requestDate) {
Query nativeQuery = entityManager.createNativeQuery("SELECT * FROM public_api_daily_rate_limit p client_id=:clientId and requestDate=:requestDate",
PublicApiDailyRateLimitEntity.class);
nativeQuery.setParameter("clientId", clientId);
nativeQuery.setParameter("requestDate", requestDate);
List<PublicApiDailyRateLimitEntity> papiRateList = (List<PublicApiDailyRateLimitEntity>) nativeQuery.getResultList();
if (papiRateList != null && papiRateList.size() > 0) {
if (papiRateList.size() > 1) {
LOG.warn("Found more than one entry for the daily papi rate limiting the client: " + clientId + " and request date: " + requestDate.toString());
}
return (PublicApiDailyRateLimitEntity) papiRateList.get(0);
}
return null;
}

@Override
public PublicApiDailyRateLimitEntity findByIpAddressAndRequestDate(String ipAddress, LocalDate requestDate) {
String baseQuery = "SELECT * FROM public_api_daily_rate_limit p where p.ip_address=:ipAddress and p.request_date=:requestDate";

Query nativeQuery = entityManager.createNativeQuery(baseQuery, PublicApiDailyRateLimitEntity.class);
nativeQuery.setParameter("ipAddress", ipAddress);
nativeQuery.setParameter("requestDate", requestDate);

List<PublicApiDailyRateLimitEntity> papiRateList = (List<PublicApiDailyRateLimitEntity>) nativeQuery.getResultList();
if (papiRateList != null && papiRateList.size() > 0) {
LOG.debug("found results ....");
if (papiRateList.size() > 1) {
LOG.warn("Found more than one entry for the daily papi rate limiting, the IP Address: " + ipAddress + " and request date: " + requestDate.toString());
}
return (PublicApiDailyRateLimitEntity) papiRateList.get(0);
}
return null;
}

public int countClientRequestsWithLimitExceeded(LocalDate requestDate, int limit) {
Query nativeQuery = entityManager.createNativeQuery(
"SELECT count(*) FROM public_api_daily_rate_limit p WHERE NOT ((p.client_id = '' OR p.client_id IS NULL)) and p.request_date=:requestDate and p.request_count >=:requestCount");
nativeQuery.setParameter("requestDate", requestDate);
nativeQuery.setParameter("requestCount", limit);
List<java.math.BigInteger> tsList = nativeQuery.getResultList();
if (tsList != null && !tsList.isEmpty()) {
return tsList.get(0).intValue();
}
return 0;

}

public int countAnonymousRequestsWithLimitExceeded(LocalDate requestDate, int limit) {
Query nativeQuery = entityManager.createNativeQuery(
"SELECT count(*) FROM public_api_daily_rate_limit p WHERE ((p.client_id = '' OR p.client_id IS NULL)) and p.request_date=:requestDate and p.request_count >=:requestCount");
nativeQuery.setParameter("requestDate", requestDate);
nativeQuery.setParameter("requestCount", limit);
List<java.math.BigInteger> tsList = nativeQuery.getResultList();
if (tsList != null && !tsList.isEmpty()) {
return tsList.get(0).intValue();
}
return 0;
}

@Override
@Transactional
public boolean updatePublicApiDailyRateLimit(PublicApiDailyRateLimitEntity papiRateLimitingEntity, boolean isClient) {
Query query;
if (isClient) {
query = entityManager.createNativeQuery("update public_api_daily_rate_limit set request_count = :requestCount, last_modified = now() where "
+ "client_id = :clientId and request_date =:requestDate");
query.setParameter("clientId", papiRateLimitingEntity.getClientId());
} else {
query = entityManager.createNativeQuery("update public_api_daily_rate_limit set request_count = :requestCount, last_modified = now() where "
+ "ip_address = :ipAddress and request_date =:requestDate");
query.setParameter("ipAddress", papiRateLimitingEntity.getIpAddress());
}
query.setParameter("requestCount", papiRateLimitingEntity.getRequestCount());
query.setParameter("requestDate", papiRateLimitingEntity.getRequestDate().toString());
return query.executeUpdate() > 0;
}

@Override
@Transactional
public void persist(PublicApiDailyRateLimitEntity papiRateLimitingEntity) {
String insertQuery = "INSERT INTO public_api_daily_rate_limit " + "(id, client_id, ip_address, request_count, request_date, date_created, last_modified)"
+ " VALUES ( NEXTVAL('papi_daily_limit_seq'), :clientId , :ipAddress, :requestCount," + " :requestDate, now(), now())";

Query query = entityManager.createNativeQuery(insertQuery);
query.setParameter("clientId", papiRateLimitingEntity.getClientId());
query.setParameter("ipAddress", papiRateLimitingEntity.getIpAddress());
query.setParameter("requestCount", papiRateLimitingEntity.getRequestCount());
query.setParameter("requestDate", papiRateLimitingEntity.getRequestDate());
query.executeUpdate();
return;
}

private static String logQueryWithParams(String baseQuery, Map<String, Object> params) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
String paramPlaceholder = ":" + entry.getKey();
String paramValue = (entry.getValue() instanceof String) ? "'" + entry.getValue() + "'" : entry.getValue().toString();
baseQuery = baseQuery.replace(paramPlaceholder, paramValue);
}
return baseQuery;
}

}
Loading

0 comments on commit 4e10fd0

Please sign in to comment.