diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..99b2d28
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,17 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ call-workflow:
+ uses: 42BV/42-github-workflows/.github/workflows/maven-test.yml@main
+ with:
+ java-version: 21
+ secrets: inherit
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..8658ccc
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,24 @@
+name: Publish package to the Maven Central Repository
+
+on:
+ workflow_dispatch:
+ inputs:
+ release-version:
+ required: false
+ description: Release-version (not required)
+ next-version:
+ required: false
+ description: Next development-version. (not required)
+ java-version:
+ required: true
+ default: '21'
+ description: Java-version to use for the deployment.
+
+jobs:
+ call-workflow:
+ uses: 42BV/42-github-workflows/.github/workflows/maven-release.yml@main
+ secrets: inherit
+ with:
+ release-version: ${{ github.event.inputs.release-version }}
+ next-version: ${{ github.event.inputs.next-version }}
+ java-version: ${{ github.event.inputs.java-version }}
diff --git a/README.md b/README.md
index 463c08a..24ae76d 100644
--- a/README.md
+++ b/README.md
@@ -17,16 +17,16 @@ Add the Maven dependency:
nl.42.restzilla
restzilla
- 2.0.0
+ 5.0.0
```
Required dependencies:
-* Spring MVC (5.1+)
-* Spring Data JPA (2.1+)
-* Jackson (2.9+)
-* Java (1.8+)
+* Spring MVC (7+)
+* Spring Data JPA (4+)
+* Jackson (2.21+)
+* Java (21+)
Annotate your Spring Configuration with `@EnableRest`:
diff --git a/owasp-suppressions.xml b/owasp-suppressions.xml
new file mode 100644
index 0000000..442d77a
--- /dev/null
+++ b/owasp-suppressions.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 90f718f..8863f33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,12 +36,20 @@
${maven.build.timestamp}
UTF-8
- 17
+ 21
- 3.0.5
+ 4.0.6
5.0.0
3.18.0
+
+
+ 12.2.2
+ 0.8.14
+ 0.9.0
+ 3.2.8
+ 3.4.0
+ 3.12.0
@@ -74,6 +82,11 @@
commons-lang3
${commons-lang.version}
+
+ com.google.guava
+ guava
+ 33.6.0-jre
+
@@ -154,102 +167,123 @@
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.10.1
-
- ${java.version}
- ${java.version}
- ${project.build.sourceEncoding}
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.22.1
-
-
-
- org.apache.maven.plugins
- maven-deploy-plugin
- 3.0.0
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.5.3
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.13
- true
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.15.0
- sonatype-nexus-staging
- https://oss.sonatype.org/
- false
+ ${java.version}
+ ${java.version}
+ ${java.version}
+
+
+ org.projectlombok
+ lombok
+
+
org.apache.maven.plugins
- maven-javadoc-plugin
- 3.4.1
-
-
- attach-javadocs
-
- jar
-
-
-
+ maven-surefire-plugin
+ 3.5.5
- org.apache.maven.plugins
- maven-source-plugin
- 3.2.1
+ org.owasp
+ dependency-check-maven
+ ${dependency-check-maven.version}
+
+ 0
+ true
+ true
+ true
+ false
+ owasp-suppressions.xml
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco-maven-plugin.version}
- attach-sources
- jar-no-fork
+ prepare-agent
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 3.0.1
-
- sign-artifacts
- verify
+ report
+ test
- sign
+ report
-
- org.owasp
- dependency-check-maven
- 8.1.2
-
- true
- true
- true
- true
- false
- owasp-suppressions.xml
-
-
+
+
+ release
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ ${maven-javadoc-plugin.version}
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ ${maven-source-plugin.version}
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ ${maven-gpg-plugin.version}
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ ${central-publishing-maven-plugin.version}
+ true
+
+ central
+
+
+
+
+
+
+
diff --git a/src/main/java/nl/_42/restzilla/web/security/SpelSecurityProvider.java b/src/main/java/nl/_42/restzilla/web/security/SpelSecurityProvider.java
index ea13f5d..a9325af 100644
--- a/src/main/java/nl/_42/restzilla/web/security/SpelSecurityProvider.java
+++ b/src/main/java/nl/_42/restzilla/web/security/SpelSecurityProvider.java
@@ -13,11 +13,14 @@
import org.springframework.expression.ExpressionParser;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
-import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
+import org.springframework.security.web.access.expression.DefaultHttpSecurityExpressionHandler;
+import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
/**
* Implementation that evaluates SPEL expressions.
@@ -26,11 +29,6 @@
* @since Sep 8, 2015
*/
public class SpelSecurityProvider implements SecurityProvider {
-
- /**
- * Web security expression handler.
- */
- private DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
/**
* {@inheritDoc}
@@ -39,13 +37,13 @@ public class SpelSecurityProvider implements SecurityProvider {
public boolean isAuthorized(String[] expressions, HttpServletRequest request) {
boolean authorized = true;
if (expressions.length > 0) {
+ RequestAuthorizationContext context = new RequestAuthorizationContext(request);
Authentication authentication = getAuthentication(request);
- FilterInvocation invocation = new FilterInvocation(request.getServletPath(), request.getMethod());
- EvaluationContext context = handler.createEvaluationContext(authentication, invocation);
for (String expression : expressions) {
if (StringUtils.isNotBlank(expression)) {
- ExpressionParser parser = handler.getExpressionParser();
- if (!ExpressionUtils.evaluateAsBoolean(parser.parseExpression(expression), context)) {
+ WebExpressionAuthorizationManager manager = new WebExpressionAuthorizationManager(expression);
+ AuthorizationResult result = manager.authorize(() -> authentication, context);
+ if (!result.isGranted()) {
return false;
}
}
@@ -56,8 +54,8 @@ public boolean isAuthorized(String[] expressions, HttpServletRequest request) {
private Authentication getAuthentication(HttpServletRequest request) {
Principal principal = request.getUserPrincipal();
- if (principal instanceof Authentication) {
- return (Authentication) principal;
+ if (principal instanceof Authentication authentication) {
+ return authentication;
} else {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
@@ -70,14 +68,5 @@ private Authentication getAuthentication(HttpServletRequest request) {
private AnonymousAuthenticationToken annonymous() {
return new AnonymousAuthenticationToken("anonymousUser", "anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
}
-
- /**
- * Configure the default web security expression handler.
- * @param handler the handler to set
- */
- @Autowired(required = false)
- public void setHandler(DefaultWebSecurityExpressionHandler handler) {
- this.handler = handler;
- }
}
diff --git a/src/test/java/nl/_42/restzilla/ApplicationConfig.java b/src/test/java/nl/_42/restzilla/ApplicationConfig.java
index 00881f9..4bc3a56 100644
--- a/src/test/java/nl/_42/restzilla/ApplicationConfig.java
+++ b/src/test/java/nl/_42/restzilla/ApplicationConfig.java
@@ -8,7 +8,6 @@
import io.beanmapper.config.BeanMapperBuilder;
import nl._42.restzilla.config.EnableRest;
import nl._42.restzilla.web.GlobalExceptionHandler;
-import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
@@ -77,7 +76,6 @@ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
Map jpaProperties = new HashMap();
- jpaProperties.put("hibernate.ejb.naming_strategy", ImprovedNamingStrategy.class.getName());
jpaProperties.put("hibernate.dialect", hibernateDialect);
jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop");
jpaProperties.put("hibernate.jdbc.use_get_generated_keys", true);
@@ -120,11 +118,6 @@ private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
return converter;
}
- @Bean
- public Validator validator() {
- return new CustomValidatorBean();
- }
-
@Bean
public Cache cache() {
return new ConcurrentMapCache("test");
diff --git a/src/test/java/nl/_42/restzilla/web/GlobalExceptionHandler.java b/src/test/java/nl/_42/restzilla/web/GlobalExceptionHandler.java
index c8ad414..12c90a3 100644
--- a/src/test/java/nl/_42/restzilla/web/GlobalExceptionHandler.java
+++ b/src/test/java/nl/_42/restzilla/web/GlobalExceptionHandler.java
@@ -8,10 +8,12 @@
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
@ControllerAdvice
@@ -19,6 +21,12 @@ public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+ @ExceptionHandler(NoHandlerFoundException.class)
+ public ModelAndView handleNoHandlerFound(HttpServletResponse response, NoHandlerFoundException ex) {
+ logger.error("Handler not found", ex);
+ return error(response, NOT_FOUND);
+ }
+
@ExceptionHandler(SecurityException.class)
public ModelAndView handleSecurityException(HttpServletResponse response, SecurityException ex) {
logger.error("Security exception", ex);