From d137e91143aa8c2e64f65acfa76e842c4275cf83 Mon Sep 17 00:00:00 2001 From: nivethika Date: Tue, 3 Jul 2018 17:11:44 +0200 Subject: [PATCH 1/7] Add overriding PhysicalNamingStrategy with caseInsensitive false --- .../hibernate/RadarPhysicalNamingStrategy.java | 12 ++++++++++++ src/main/resources/config/application.yml | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java diff --git a/src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java b/src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java new file mode 100644 index 000000000..c1f0bb9b1 --- /dev/null +++ b/src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java @@ -0,0 +1,12 @@ +package org.radarcns.management.hibernate; + +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; + +public class RadarPhysicalNamingStrategy extends SpringPhysicalNamingStrategy { + + @Override + protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) { + return false; + } +} diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index 0658d0fdb..646c6d028 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -58,7 +58,7 @@ spring: hibernate: ddl-auto: none naming: - physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy + physical-strategy: org.radarcns.management.hibernate.RadarPhysicalNamingStrategy implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy messages: basename: i18n/messages From 8fa8d0a12094cca560b939e50db59f572217dcca Mon Sep 17 00:00:00 2001 From: nivethika Date: Tue, 3 Jul 2018 17:12:52 +0200 Subject: [PATCH 2/7] Add custom ApprovalStore with queries with escape characters for uppercase columns --- .../config/OAuth2ServerConfiguration.java | 4 +- .../security/RadarApprovalStore.java | 227 ++++++++++++++++++ 2 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/radarcns/management/security/RadarApprovalStore.java diff --git a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java index 0a32130a9..b4fb1feec 100644 --- a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java +++ b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java @@ -7,6 +7,7 @@ import javax.sql.DataSource; import org.radarcns.auth.authorization.AuthoritiesConstants; import org.radarcns.management.security.ClaimsTokenEnhancer; +import org.radarcns.management.security.RadarApprovalStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; @@ -32,7 +33,6 @@ import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.approval.ApprovalStore; -import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; @@ -174,7 +174,7 @@ protected AuthorizationCodeServices authorizationCodeServices() { @Bean public ApprovalStore approvalStore() { - return new JdbcApprovalStore(dataSource); + return new RadarApprovalStore(dataSource); } @Bean diff --git a/src/main/java/org/radarcns/management/security/RadarApprovalStore.java b/src/main/java/org/radarcns/management/security/RadarApprovalStore.java new file mode 100644 index 000000000..c97f724d6 --- /dev/null +++ b/src/main/java/org/radarcns/management/security/RadarApprovalStore.java @@ -0,0 +1,227 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.radarcns.management.security; + +import static org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus.APPROVED; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.security.oauth2.provider.approval.Approval; +import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; +import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.util.Assert; + +/** + * @author Dave Syer + * + */ +public class RadarApprovalStore implements ApprovalStore { + + private final JdbcTemplate jdbcTemplate; + + private final Log logger = LogFactory.getLog(getClass()); + + private final RowMapper rowMapper = new AuthorizationRowMapper(); + + private static final String TABLE_NAME = "oauth_approvals"; + + private static final String FIELDS = "\"expiresAt\", \"status\",\"lastModifiedAt\",\"userId\"," + + "\"clientId\"," + + "\"scope\""; + + private static final String WHERE_KEY = "where \"userId\"=? and \"clientId\"=?"; + + private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and \"scope\"=?"; + + private static final String DEFAULT_ADD_APPROVAL_STATEMENT = String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, + FIELDS); + + private static final String DEFAULT_REFRESH_APPROVAL_STATEMENT = String.format( + "update %s set \"expiresAt\"=?, \"status\"=?, \"lastModifiedAt\"=? " + WHERE_KEY_AND_SCOPE, + TABLE_NAME); + + private static final String DEFAULT_GET_APPROVAL_SQL = String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); + + private static final String DEFAULT_DELETE_APPROVAL_SQL = String.format("delete from %s " + WHERE_KEY_AND_SCOPE, + TABLE_NAME); + + private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = String.format("update %s set " + + "\"expiresAt\" = ? " + WHERE_KEY_AND_SCOPE, + TABLE_NAME); + + private String addApprovalStatement = DEFAULT_ADD_APPROVAL_STATEMENT; + + private String refreshApprovalStatement = DEFAULT_REFRESH_APPROVAL_STATEMENT; + + private String findApprovalStatement = DEFAULT_GET_APPROVAL_SQL; + + private String deleteApprovalStatment = DEFAULT_DELETE_APPROVAL_SQL; + + private String expireApprovalStatement = DEFAULT_EXPIRE_APPROVAL_STATEMENT; + + private boolean handleRevocationsAsExpiry = false; + + public RadarApprovalStore(DataSource dataSource) { + Assert.notNull(dataSource); + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + public void setHandleRevocationsAsExpiry(boolean handleRevocationsAsExpiry) { + this.handleRevocationsAsExpiry = handleRevocationsAsExpiry; + } + + public void setAddApprovalStatement(String addApprovalStatement) { + this.addApprovalStatement = addApprovalStatement; + } + + public void setFindApprovalStatement(String findApprovalStatement) { + this.findApprovalStatement = findApprovalStatement; + } + + public void setDeleteApprovalStatment(String deleteApprovalStatment) { + this.deleteApprovalStatment = deleteApprovalStatment; + } + + public void setExpireApprovalStatement(String expireApprovalStatement) { + this.expireApprovalStatement = expireApprovalStatement; + } + + public void setRefreshApprovalStatement(String refreshApprovalStatement) { + this.refreshApprovalStatement = refreshApprovalStatement; + } + + @Override + public boolean addApprovals(final Collection approvals) { + logger.debug(String.format("adding approvals: [%s]", approvals)); + boolean success = true; + for (Approval approval : approvals) { + if (!updateApproval(refreshApprovalStatement, approval)) { + if (!updateApproval(addApprovalStatement, approval)) { + success = false; + } + } + } + return success; + } + + @Override + public boolean revokeApprovals(Collection approvals) { + logger.debug(String.format("Revoking approvals: [%s]", approvals)); + boolean success = true; + for (final Approval approval : approvals) { + if (handleRevocationsAsExpiry) { + int refreshed = jdbcTemplate.update(expireApprovalStatement, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + ps.setString(2, approval.getUserId()); + ps.setString(3, approval.getClientId()); + ps.setString(4, approval.getScope()); + } + }); + if (refreshed != 1) { + success = false; + } + } + else { + int refreshed = jdbcTemplate.update(deleteApprovalStatment, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setString(1, approval.getUserId()); + ps.setString(2, approval.getClientId()); + ps.setString(3, approval.getScope()); + } + }); + if (refreshed != 1) { + success = false; + } + } + } + return success; + } + + public boolean purgeExpiredApprovals() { + logger.debug("Purging expired approvals from database"); + try { + int deleted = jdbcTemplate.update(deleteApprovalStatment + " where expiresAt <= ?", + new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(new Date().getTime())); + } + }); + logger.debug(deleted + " expired approvals deleted"); + } + catch (DataAccessException ex) { + logger.error("Error purging expired approvals", ex); + return false; + } + return true; + } + + @Override + public List getApprovals(String userName, String clientId) { + return jdbcTemplate.query(findApprovalStatement, rowMapper, userName, clientId); + } + + private boolean updateApproval(final String sql, final Approval approval) { + logger.debug(String.format("refreshing approval: [%s]", approval)); + int refreshed = jdbcTemplate.update(sql, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); + ps.setString(2, (approval.getStatus() == null ? APPROVED : approval.getStatus()).toString()); + ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); + ps.setString(4, approval.getUserId()); + ps.setString(5, approval.getClientId()); + ps.setString(6, approval.getScope()); + } + }); + if (refreshed != 1) { + return false; + } + return true; + } + + private static class AuthorizationRowMapper implements RowMapper { + + @Override + public Approval mapRow(ResultSet rs, int rowNum) throws SQLException { + String userName = rs.getString(4); + String clientId = rs.getString(5); + String scope = rs.getString(6); + Date expiresAt = rs.getTimestamp(1); + String status = rs.getString(2); + Date lastUpdatedAt = rs.getTimestamp(3); + + return new Approval(userName, clientId, scope, expiresAt, ApprovalStatus.valueOf(status), lastUpdatedAt); + } + } +} From 85b336f585927904f95dd3dc87b757b0baaa8880 Mon Sep 17 00:00:00 2001 From: nivethika Date: Tue, 3 Jul 2018 17:14:16 +0200 Subject: [PATCH 3/7] add authorization-code instead of client-credentials to dashboard --- src/main/docker/etc/config/oauth_client_details.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/docker/etc/config/oauth_client_details.csv b/src/main/docker/etc/config/oauth_client_details.csv index 41f8f2653..18bd59795 100644 --- a/src/main/docker/etc/config/oauth_client_details.csv +++ b/src/main/docker/etc/config/oauth_client_details.csv @@ -4,4 +4,4 @@ aRMT;res_ManagementPortal,res_gateway;secret;MEASUREMENT.CREATE,SUBJECT.UPDATE,S THINC-IT;res_ManagementPortal,res_gateway;secret;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;refresh_token,authorization_code;;;43200;7948800;{"dynamic_registration": true}; radar_restapi;res_ManagementPortal;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;client_credentials;;;43200;259200;{}; radar_redcap_integrator;res_ManagementPortal;secret;PROJECT.READ,SUBJECT.CREATE,SUBJECT.READ,SUBJECT.UPDATE;client_credentials;;;43200;259200;{}; -radar_dashboard;res_ManagementPortal,res_RestApi;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;client_credentials;;;43200;259200;{}; +radar_dashboard;res_ManagementPortal,res_RestApi;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;authorization_code;;;43200;259200;{}; From ff3d4672f3123f84850d90627fd65d920fc245ad Mon Sep 17 00:00:00 2001 From: nivethika Date: Tue, 3 Jul 2018 18:59:52 +0200 Subject: [PATCH 4/7] add custom approval store if the database is recognized as POSTGRES and use JDBCApprovalStore as the default to have support for H2 --- .../config/OAuth2ServerConfiguration.java | 15 +++++++++++++-- ...rovalStore.java => PostgresApprovalStore.java} | 5 +++-- 2 files changed, 16 insertions(+), 4 deletions(-) rename src/main/java/org/radarcns/management/security/{RadarApprovalStore.java => PostgresApprovalStore.java} (98%) diff --git a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java index b4fb1feec..d39b3ec6a 100644 --- a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java +++ b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java @@ -1,5 +1,7 @@ package org.radarcns.management.config; +import static org.springframework.orm.jpa.vendor.Database.POSTGRESQL; + import io.github.jhipster.security.AjaxLogoutSuccessHandler; import io.github.jhipster.security.Http401UnauthorizedEntryPoint; import java.security.KeyPair; @@ -7,9 +9,10 @@ import javax.sql.DataSource; import org.radarcns.auth.authorization.AuthoritiesConstants; import org.radarcns.management.security.ClaimsTokenEnhancer; -import org.radarcns.management.security.RadarApprovalStore; +import org.radarcns.management.security.PostgresApprovalStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -33,6 +36,7 @@ import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.approval.ApprovalStore; +import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; @@ -157,6 +161,9 @@ public void publishAuthenticationSuccess(Authentication authentication) { protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { + @Autowired + private JpaProperties jpaProperties; + @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @@ -174,7 +181,11 @@ protected AuthorizationCodeServices authorizationCodeServices() { @Bean public ApprovalStore approvalStore() { - return new RadarApprovalStore(dataSource); + if(jpaProperties.getDatabase().equals(POSTGRESQL)) { + return new PostgresApprovalStore(dataSource); + } else { + return new JdbcApprovalStore(dataSource); + } } @Bean diff --git a/src/main/java/org/radarcns/management/security/RadarApprovalStore.java b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java similarity index 98% rename from src/main/java/org/radarcns/management/security/RadarApprovalStore.java rename to src/main/java/org/radarcns/management/security/PostgresApprovalStore.java index c97f724d6..b376c7a4c 100644 --- a/src/main/java/org/radarcns/management/security/RadarApprovalStore.java +++ b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java @@ -40,9 +40,10 @@ /** * @author Dave Syer + * Modified by Nivethika * */ -public class RadarApprovalStore implements ApprovalStore { +public class PostgresApprovalStore implements ApprovalStore { private final JdbcTemplate jdbcTemplate; @@ -88,7 +89,7 @@ public class RadarApprovalStore implements ApprovalStore { private boolean handleRevocationsAsExpiry = false; - public RadarApprovalStore(DataSource dataSource) { + public PostgresApprovalStore(DataSource dataSource) { Assert.notNull(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource); } From 23c698c22b79de3b4a0287bf7cca8b4d53cd7784 Mon Sep 17 00:00:00 2001 From: nivethika Date: Tue, 3 Jul 2018 19:24:18 +0200 Subject: [PATCH 5/7] add custom approval store if the database is recognized as POSTGRES and use JDBCApprovalStore as the default to have support for H2 --- .../config/OAuth2ServerConfiguration.java | 2 +- .../security/PostgresApprovalStore.java | 122 +++++++++--------- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java index d39b3ec6a..d9449fac4 100644 --- a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java +++ b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java @@ -181,7 +181,7 @@ protected AuthorizationCodeServices authorizationCodeServices() { @Bean public ApprovalStore approvalStore() { - if(jpaProperties.getDatabase().equals(POSTGRESQL)) { + if (jpaProperties.getDatabase().equals(POSTGRESQL)) { return new PostgresApprovalStore(dataSource); } else { return new JdbcApprovalStore(dataSource); diff --git a/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java index b376c7a4c..86078387a 100644 --- a/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java +++ b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.radarcns.management.security; import static org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus.APPROVED; @@ -24,11 +25,10 @@ import java.util.Collection; import java.util.Date; import java.util.List; - import javax.sql.DataSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementSetter; @@ -39,49 +39,52 @@ import org.springframework.util.Assert; /** - * @author Dave Syer - * Modified by Nivethika + * This class will be used to execute functions related to token approval. It is an duplicate of + * JdbcApprovalStore with escaped case sensitive fields to query. * + * @author Dave Syer + * @modifiedBy Nivethika */ public class PostgresApprovalStore implements ApprovalStore { private final JdbcTemplate jdbcTemplate; - private final Log logger = LogFactory.getLog(getClass()); + private final Logger logger = LoggerFactory.getLogger(PostgresApprovalStore.class); private final RowMapper rowMapper = new AuthorizationRowMapper(); private static final String TABLE_NAME = "oauth_approvals"; - private static final String FIELDS = "\"expiresAt\", \"status\",\"lastModifiedAt\",\"userId\"," - + "\"clientId\"," - + "\"scope\""; + private static final String FIELDS = + "\"expiresAt\", \"status\",\"lastModifiedAt\",\"userId\"," + "\"clientId\"," + + "\"scope\""; private static final String WHERE_KEY = "where \"userId\"=? and \"clientId\"=?"; - private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and \"scope\"=?"; + private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and \"scope\"=?"; - private static final String DEFAULT_ADD_APPROVAL_STATEMENT = String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, - FIELDS); + private static final String DEFAULT_ADD_APPROVAL_STATEMENT = + String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, FIELDS); private static final String DEFAULT_REFRESH_APPROVAL_STATEMENT = String.format( - "update %s set \"expiresAt\"=?, \"status\"=?, \"lastModifiedAt\"=? " + WHERE_KEY_AND_SCOPE, - TABLE_NAME); + "update %s set \"expiresAt\"=?, \"status\"=?, \"lastModifiedAt\"=? " + + WHERE_KEY_AND_SCOPE, TABLE_NAME); - private static final String DEFAULT_GET_APPROVAL_SQL = String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); + private static final String DEFAULT_GET_APPROVAL_SQL = + String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); - private static final String DEFAULT_DELETE_APPROVAL_SQL = String.format("delete from %s " + WHERE_KEY_AND_SCOPE, - TABLE_NAME); + private static final String DEFAULT_DELETE_APPROVAL_SQL = + String.format("delete from %s " + WHERE_KEY_AND_SCOPE, TABLE_NAME); - private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = String.format("update %s set " - + "\"expiresAt\" = ? " + WHERE_KEY_AND_SCOPE, - TABLE_NAME); + private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = + String.format("update %s set " + "\"expiresAt\" = ? " + + WHERE_KEY_AND_SCOPE, TABLE_NAME); private String addApprovalStatement = DEFAULT_ADD_APPROVAL_STATEMENT; private String refreshApprovalStatement = DEFAULT_REFRESH_APPROVAL_STATEMENT; - private String findApprovalStatement = DEFAULT_GET_APPROVAL_SQL; + private String findApprovalStatement = DEFAULT_GET_APPROVAL_SQL; private String deleteApprovalStatment = DEFAULT_DELETE_APPROVAL_SQL; @@ -123,10 +126,9 @@ public boolean addApprovals(final Collection approvals) { logger.debug(String.format("adding approvals: [%s]", approvals)); boolean success = true; for (Approval approval : approvals) { - if (!updateApproval(refreshApprovalStatement, approval)) { - if (!updateApproval(addApprovalStatement, approval)) { - success = false; - } + if (!updateApproval(refreshApprovalStatement, approval) && !updateApproval( + addApprovalStatement, approval)) { + success = false; } } return success; @@ -138,28 +140,29 @@ public boolean revokeApprovals(Collection approvals) { boolean success = true; for (final Approval approval : approvals) { if (handleRevocationsAsExpiry) { - int refreshed = jdbcTemplate.update(expireApprovalStatement, new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); - ps.setString(2, approval.getUserId()); - ps.setString(3, approval.getClientId()); - ps.setString(4, approval.getScope()); - } - }); + int refreshed = jdbcTemplate + .update(expireApprovalStatement, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + ps.setString(2, approval.getUserId()); + ps.setString(3, approval.getClientId()); + ps.setString(4, approval.getScope()); + } + }); if (refreshed != 1) { success = false; } - } - else { - int refreshed = jdbcTemplate.update(deleteApprovalStatment, new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setString(1, approval.getUserId()); - ps.setString(2, approval.getClientId()); - ps.setString(3, approval.getScope()); - } - }); + } else { + int refreshed = jdbcTemplate + .update(deleteApprovalStatment, new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setString(1, approval.getUserId()); + ps.setString(2, approval.getClientId()); + ps.setString(3, approval.getScope()); + } + }); if (refreshed != 1) { success = false; } @@ -168,19 +171,22 @@ public void setValues(PreparedStatement ps) throws SQLException { return success; } + /** + * Purges expired approvals from database. + * @return {@code true} if removed successfully, {@code false} otherwise. + */ public boolean purgeExpiredApprovals() { logger.debug("Purging expired approvals from database"); try { int deleted = jdbcTemplate.update(deleteApprovalStatment + " where expiresAt <= ?", - new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setTimestamp(1, new Timestamp(new Date().getTime())); - } - }); + new PreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps) throws SQLException { + ps.setTimestamp(1, new Timestamp(new Date().getTime())); + } + }); logger.debug(deleted + " expired approvals deleted"); - } - catch (DataAccessException ex) { + } catch (DataAccessException ex) { logger.error("Error purging expired approvals", ex); return false; } @@ -198,17 +204,16 @@ private boolean updateApproval(final String sql, final Approval approval) { @Override public void setValues(PreparedStatement ps) throws SQLException { ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); - ps.setString(2, (approval.getStatus() == null ? APPROVED : approval.getStatus()).toString()); + ps.setString(2, + (approval.getStatus() == null ? APPROVED : + approval.getStatus()).toString()); ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); ps.setString(4, approval.getUserId()); ps.setString(5, approval.getClientId()); ps.setString(6, approval.getScope()); } }); - if (refreshed != 1) { - return false; - } - return true; + return refreshed != 1; } private static class AuthorizationRowMapper implements RowMapper { @@ -222,7 +227,8 @@ public Approval mapRow(ResultSet rs, int rowNum) throws SQLException { String status = rs.getString(2); Date lastUpdatedAt = rs.getTimestamp(3); - return new Approval(userName, clientId, scope, expiresAt, ApprovalStatus.valueOf(status), lastUpdatedAt); + return new Approval(userName, clientId, scope, expiresAt, + ApprovalStatus.valueOf(status), lastUpdatedAt); } } } From 9d5600004c18d62e66ca7a2c71cb2b28293f973a Mon Sep 17 00:00:00 2001 From: nivethika Date: Wed, 4 Jul 2018 09:03:50 +0200 Subject: [PATCH 6/7] improvements --- src/main/docker/etc/config/oauth_client_details.csv | 2 +- ...ngStrategy.java => CaseSensitivePhysicalNamingStrategy.java} | 2 +- src/main/resources/config/application.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/main/java/org/radarcns/management/hibernate/{RadarPhysicalNamingStrategy.java => CaseSensitivePhysicalNamingStrategy.java} (77%) diff --git a/src/main/docker/etc/config/oauth_client_details.csv b/src/main/docker/etc/config/oauth_client_details.csv index 18bd59795..0db7fb977 100644 --- a/src/main/docker/etc/config/oauth_client_details.csv +++ b/src/main/docker/etc/config/oauth_client_details.csv @@ -4,4 +4,4 @@ aRMT;res_ManagementPortal,res_gateway;secret;MEASUREMENT.CREATE,SUBJECT.UPDATE,S THINC-IT;res_ManagementPortal,res_gateway;secret;MEASUREMENT.CREATE,SUBJECT.UPDATE,SUBJECT.READ,PROJECT.READ,SOURCETYPE.READ,SOURCE.READ,SOURCETYPE.READ,SOURCEDATA.READ,USER.READ,ROLE.READ;refresh_token,authorization_code;;;43200;7948800;{"dynamic_registration": true}; radar_restapi;res_ManagementPortal;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;client_credentials;;;43200;259200;{}; radar_redcap_integrator;res_ManagementPortal;secret;PROJECT.READ,SUBJECT.CREATE,SUBJECT.READ,SUBJECT.UPDATE;client_credentials;;;43200;259200;{}; -radar_dashboard;res_ManagementPortal,res_RestApi;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;authorization_code;;;43200;259200;{}; +radar_dashboard;res_ManagementPortal,res_RestApi;secret;SUBJECT.READ,PROJECT.READ,SOURCE.READ,SOURCETYPE.READ;refresh_token,authorization_code;;;43200;259200;{}; diff --git a/src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java b/src/main/java/org/radarcns/management/hibernate/CaseSensitivePhysicalNamingStrategy.java similarity index 77% rename from src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java rename to src/main/java/org/radarcns/management/hibernate/CaseSensitivePhysicalNamingStrategy.java index c1f0bb9b1..6f8fec783 100644 --- a/src/main/java/org/radarcns/management/hibernate/RadarPhysicalNamingStrategy.java +++ b/src/main/java/org/radarcns/management/hibernate/CaseSensitivePhysicalNamingStrategy.java @@ -3,7 +3,7 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; -public class RadarPhysicalNamingStrategy extends SpringPhysicalNamingStrategy { +public class CaseSensitivePhysicalNamingStrategy extends SpringPhysicalNamingStrategy { @Override protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) { diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index 646c6d028..0636757ea 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -58,7 +58,7 @@ spring: hibernate: ddl-auto: none naming: - physical-strategy: org.radarcns.management.hibernate.RadarPhysicalNamingStrategy + physical-strategy: org.radarcns.management.hibernate.CaseSensitivePhysicalNamingStrategy implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy messages: basename: i18n/messages From c3c37f3f0876187fe7fa308588b8735325589b9b Mon Sep 17 00:00:00 2001 From: nivethika Date: Wed, 4 Jul 2018 09:46:01 +0200 Subject: [PATCH 7/7] small code improvements --- .../config/OAuth2ServerConfiguration.java | 1 + .../security/PostgresApprovalStore.java | 64 ++++++++----------- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java index d9449fac4..07a27fdba 100644 --- a/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java +++ b/src/main/java/org/radarcns/management/config/OAuth2ServerConfiguration.java @@ -184,6 +184,7 @@ public ApprovalStore approvalStore() { if (jpaProperties.getDatabase().equals(POSTGRESQL)) { return new PostgresApprovalStore(dataSource); } else { + // to have compatibility for other databases including H2 return new JdbcApprovalStore(dataSource); } } diff --git a/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java index 86078387a..e1bcefbad 100644 --- a/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java +++ b/src/main/java/org/radarcns/management/security/PostgresApprovalStore.java @@ -18,7 +18,6 @@ import static org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus.APPROVED; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; @@ -31,7 +30,6 @@ import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.oauth2.provider.approval.Approval; import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus; @@ -63,6 +61,8 @@ public class PostgresApprovalStore implements ApprovalStore { private static final String WHERE_KEY_AND_SCOPE = WHERE_KEY + " and \"scope\"=?"; + private static final String AND_LESS_THAN_EXPIRE_AT = " and \"expiresAt\" <= ?"; + private static final String DEFAULT_ADD_APPROVAL_STATEMENT = String.format("insert into %s ( %s ) values (?,?,?,?,?,?)", TABLE_NAME, FIELDS); @@ -74,7 +74,8 @@ public class PostgresApprovalStore implements ApprovalStore { String.format("select %s from %s " + WHERE_KEY, FIELDS, TABLE_NAME); private static final String DEFAULT_DELETE_APPROVAL_SQL = - String.format("delete from %s " + WHERE_KEY_AND_SCOPE, TABLE_NAME); + String.format("delete from %s " + WHERE_KEY_AND_SCOPE + AND_LESS_THAN_EXPIRE_AT, + TABLE_NAME); private static final String DEFAULT_EXPIRE_APPROVAL_STATEMENT = String.format("update %s set " + "\"expiresAt\" = ? " @@ -141,27 +142,21 @@ public boolean revokeApprovals(Collection approvals) { for (final Approval approval : approvals) { if (handleRevocationsAsExpiry) { int refreshed = jdbcTemplate - .update(expireApprovalStatement, new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); - ps.setString(2, approval.getUserId()); - ps.setString(3, approval.getClientId()); - ps.setString(4, approval.getScope()); - } + .update(expireApprovalStatement, (ps) -> { + ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); + ps.setString(2, approval.getUserId()); + ps.setString(3, approval.getClientId()); + ps.setString(4, approval.getScope()); }); if (refreshed != 1) { success = false; } } else { int refreshed = jdbcTemplate - .update(deleteApprovalStatment, new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setString(1, approval.getUserId()); - ps.setString(2, approval.getClientId()); - ps.setString(3, approval.getScope()); - } + .update(deleteApprovalStatment, (ps) -> { + ps.setString(1, approval.getUserId()); + ps.setString(2, approval.getClientId()); + ps.setString(3, approval.getScope()); }); if (refreshed != 1) { success = false; @@ -178,13 +173,9 @@ public void setValues(PreparedStatement ps) throws SQLException { public boolean purgeExpiredApprovals() { logger.debug("Purging expired approvals from database"); try { - int deleted = jdbcTemplate.update(deleteApprovalStatment + " where expiresAt <= ?", - new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setTimestamp(1, new Timestamp(new Date().getTime())); - } - }); + int deleted = jdbcTemplate.update(deleteApprovalStatment, (ps) -> { + ps.setTimestamp(1, new Timestamp(new Date().getTime())); + }); logger.debug(deleted + " expired approvals deleted"); } catch (DataAccessException ex) { logger.error("Error purging expired approvals", ex); @@ -195,25 +186,22 @@ public void setValues(PreparedStatement ps) throws SQLException { @Override public List getApprovals(String userName, String clientId) { + logger.debug("Finding approvals for userName {} and cliendId {}", userName, clientId); return jdbcTemplate.query(findApprovalStatement, rowMapper, userName, clientId); } private boolean updateApproval(final String sql, final Approval approval) { logger.debug(String.format("refreshing approval: [%s]", approval)); - int refreshed = jdbcTemplate.update(sql, new PreparedStatementSetter() { - @Override - public void setValues(PreparedStatement ps) throws SQLException { - ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); - ps.setString(2, - (approval.getStatus() == null ? APPROVED : - approval.getStatus()).toString()); - ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); - ps.setString(4, approval.getUserId()); - ps.setString(5, approval.getClientId()); - ps.setString(6, approval.getScope()); - } + int refreshed = jdbcTemplate.update(sql, (ps) -> { + ps.setTimestamp(1, new Timestamp(approval.getExpiresAt().getTime())); + ps.setString(2, (approval.getStatus() == null ? APPROVED + : approval.getStatus()).toString()); + ps.setTimestamp(3, new Timestamp(approval.getLastUpdatedAt().getTime())); + ps.setString(4, approval.getUserId()); + ps.setString(5, approval.getClientId()); + ps.setString(6, approval.getScope()); }); - return refreshed != 1; + return refreshed == 1; } private static class AuthorizationRowMapper implements RowMapper {