diff --git a/.circleci/config.yml b/.circleci/config.yml
index b6f0cb24d..b27d67287 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -2516,7 +2516,7 @@ commands:
orbs:
maven: circleci/maven@1.0.1
openjdk-install: cloudesire/openjdk-install@1.2.3
- sonarcloud: sonarsource/sonarcloud@1.0.2
+ sonarcloud: sonarsource/sonarcloud@2.0.0
executors:
# https://hub.docker.com/u/cimg (circleci next-gen docker images)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 0c61ec775..93a9bbf20 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -12,3 +12,8 @@ updates:
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ # Check for updates to GitHub Actions every week
+ interval: "weekly"
diff --git a/.github/workflows/build-multiarch-image-latest.yml b/.github/workflows/build-multiarch-image-latest.yml
index b39c0e823..81b0a7f6a 100644
--- a/.github/workflows/build-multiarch-image-latest.yml
+++ b/.github/workflows/build-multiarch-image-latest.yml
@@ -15,19 +15,19 @@ jobs:
steps:
-
name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
-
name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
- uses: docker/login-action@v1
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push (AMD64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
@@ -35,7 +35,7 @@ jobs:
tags: ehrbase/ehrbase:latest-amd64
-
name: Build and push (ARM64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/arm64
diff --git a/.github/workflows/build-multiarch-image-next.yml b/.github/workflows/build-multiarch-image-next.yml
index 1cef434db..aa174566b 100644
--- a/.github/workflows/build-multiarch-image-next.yml
+++ b/.github/workflows/build-multiarch-image-next.yml
@@ -31,19 +31,19 @@ jobs:
# Set as Environment for all further steps
echo "TAG=${v}" >> $GITHUB_ENV
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
- uses: docker/login-action@v1
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push (AMD64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
@@ -51,7 +51,7 @@ jobs:
tags: ehrbase/ehrbase:${{env.TAG}}-amd64
- name: Build and push (ARM64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/arm64
diff --git a/.github/workflows/build-multiarch-image-tag.yml b/.github/workflows/build-multiarch-image-tag.yml
index d54fdff92..97af6f8b8 100644
--- a/.github/workflows/build-multiarch-image-tag.yml
+++ b/.github/workflows/build-multiarch-image-tag.yml
@@ -15,7 +15,7 @@ jobs:
steps:
-
name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
-
name: Create TAG ENV from version of release Branch
run: |
@@ -27,16 +27,16 @@ jobs:
echo "TAG=$TAG" >> $GITHUB_ENV
-
name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
- uses: docker/login-action@v1
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push (AMD64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
@@ -44,7 +44,7 @@ jobs:
tags: ehrbase/ehrbase:tag-amd64
-
name: Build and push (ARM64)
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v5
with:
context: .
platforms: linux/arm64
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0bda9b39d..50afb708f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -33,12 +33,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
@@ -48,7 +48,7 @@ jobs:
run: mvn -B verify
- name: Setup Maven Central
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index f37a46eb2..a136aaa05 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -53,10 +53,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup Java
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
diff --git a/.github/workflows/jdk-compat-robot.yml b/.github/workflows/jdk-compat-robot.yml
index f4a2c2b26..019e58934 100644
--- a/.github/workflows/jdk-compat-robot.yml
+++ b/.github/workflows/jdk-compat-robot.yml
@@ -36,12 +36,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
@@ -69,7 +69,7 @@ jobs:
cat /var/tmp/log.txt
- name: Checkout robot
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
repository: ehrbase/integration-tests
diff --git a/.github/workflows/jdk-compat.yml b/.github/workflows/jdk-compat.yml
index 4451da9c6..5c2f312d5 100644
--- a/.github/workflows/jdk-compat.yml
+++ b/.github/workflows/jdk-compat.yml
@@ -28,12 +28,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a97109fed..9de8fb8cb 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,7 +14,7 @@ jobs:
steps:
# Install the sdk main in the local repo so maven version plugin can find them
- name: Checkout SDK main
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
repository: ehrbase/openEHR_SDK
@@ -33,7 +33,7 @@ jobs:
run: mvn install -Dmaven.test.skip=true
# Install the sdk dev in the local repo so maven version plugin can find them
- name: Checkout SDK dev
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
repository: ehrbase/openEHR_SDK
@@ -46,7 +46,7 @@ jobs:
run: mvn install
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
# This will be used by git in all further steps
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2144c585f..f4552ceb6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.31.0]
+ ### Added
+ ### Changed
+ - Upgrade openEHR_SDK to version 2.3.0 see https://github.com/ehrbase/openEHR_SDK/blob/develop/CHANGELOG.md
+ - Migrated to spring boot 3 ([#1174](https://github.com/ehrbase/ehrbase/pull/1174))
+ - Removed authorization scopes from endpoints and added support for overwriting controllers ([#1157](https://github.com/ehrbase/ehrbase/pull/1157))
+ ### Fixed
+ - Fix audit logs location ([#1160](https://github.com/ehrbase/ehrbase/pull/1160))
+ - Address AQL query security vulnerabilities ([#1190](https://github.com/ehrbase/ehrbase/pull/1190))
+
## [0.30.0]
### Added
### Changed
@@ -685,3 +695,4 @@ the next release this file will provide a proper overview.
[0.28.0]: https://github.com/ehrbase/ehrbase/compare/v0.27.4...v0.28.0
[0.29.0]: https://github.com/ehrbase/ehrbase/compare/v0.28.0...v0.29.0
[0.30.0]: https://github.com/ehrbase/ehrbase/compare/v0.29.0...v0.30.0
+[0.31.0]: https://github.com/ehrbase/ehrbase/compare/v0.30.0...v0.31.0
diff --git a/api/pom.xml b/api/pom.xml
index 458fa405f..923e2d544 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -26,7 +26,7 @@
org.ehrbase.openehr
server
- 0.30.0
+ 0.31.0
api
diff --git a/api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorizations.java b/api/src/main/java/org/ehrbase/api/annotations/EhrbaseSecurity.java
similarity index 78%
rename from api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorizations.java
rename to api/src/main/java/org/ehrbase/api/annotations/EhrbaseSecurity.java
index d2894cb88..3c929fda1 100644
--- a/api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorizations.java
+++ b/api/src/main/java/org/ehrbase/api/annotations/EhrbaseSecurity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 vitasystems GmbH and Hannover Medical School.
+ * Copyright (c) 2023 vitasystems GmbH and Hannover Medical School.
*
* This file is part of project EHRbase
*
@@ -15,18 +15,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.ehrbase.api.authorization;
+package org.ehrbase.api.annotations;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
-@Inherited
@Retention(RUNTIME)
@Target(ElementType.METHOD)
-public @interface EhrbaseAuthorizations {
- EhrbaseAuthorization[] value();
-}
+public @interface EhrbaseSecurity {}
diff --git a/api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorization.java b/api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorization.java
deleted file mode 100644
index b7e27105c..000000000
--- a/api/src/main/java/org/ehrbase/api/authorization/EhrbaseAuthorization.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2022 vitasystems GmbH and Hannover Medical School.
- *
- * This file is part of project EHRbase
- *
- * 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
- *
- * https://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.ehrbase.api.authorization;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Inherited
-@Retention(RUNTIME)
-@Repeatable(EhrbaseAuthorizations.class)
-@Target(ElementType.METHOD)
-public @interface EhrbaseAuthorization {
- EhrbasePermission permission();
-}
diff --git a/application/pom.xml b/application/pom.xml
index 53d6e662d..07f10a93e 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -26,16 +26,18 @@
org.ehrbase.openehr
server
- 0.30.0
+ 0.31.0
application
+ jar
vitasystems/hip-openehr
+
org.springframework.boot
spring-boot-starter-web
diff --git a/application/src/main/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRoot.java b/application/src/main/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRoot.java
index 88bf2da66..b9d679bee 100644
--- a/application/src/main/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRoot.java
+++ b/application/src/main/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRoot.java
@@ -188,7 +188,7 @@ private boolean checkAbac(String type, String subject, Object payload, String co
}
// Check and extract JWT
- var jwt = getJwtAuthenticationToken(this.authentication);
+ var jwt = getJwtAuthenticationToken(this.getAuthentication());
// Request body map. will result in simple JSON like {"patient_id":"...", ...}
// but requires "Object" for template handling, which can have a Set for multiple IDs
diff --git a/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java b/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java
index 1ba494b8f..e09d2a8c0 100644
--- a/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java
+++ b/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java
@@ -17,8 +17,8 @@
*/
package org.ehrbase.application.config;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
diff --git a/application/src/main/java/org/ehrbase/application/config/SwaggerConfiguration.java b/application/src/main/java/org/ehrbase/application/config/SwaggerConfiguration.java
index 43f4f7d65..da0e7db60 100644
--- a/application/src/main/java/org/ehrbase/application/config/SwaggerConfiguration.java
+++ b/application/src/main/java/org/ehrbase/application/config/SwaggerConfiguration.java
@@ -21,7 +21,7 @@
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
-import org.springdoc.core.GroupedOpenApi;
+import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/application/src/main/java/org/ehrbase/application/config/security/BasicAuthSecurityConfiguration.java b/application/src/main/java/org/ehrbase/application/config/security/BasicAuthSecurityConfiguration.java
index 30caf0395..28c2fdc9d 100644
--- a/application/src/main/java/org/ehrbase/application/config/security/BasicAuthSecurityConfiguration.java
+++ b/application/src/main/java/org/ehrbase/application/config/security/BasicAuthSecurityConfiguration.java
@@ -18,18 +18,22 @@
package org.ehrbase.application.config.security;
import static org.ehrbase.application.config.security.SecurityProperties.ADMIN;
-import static org.ehrbase.application.config.security.SecurityProperties.USER;
+import static org.springframework.security.config.Customizer.withDefaults;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
/**
@@ -42,55 +46,43 @@
@Configuration
@ConditionalOnProperty(prefix = "security", name = "authType", havingValue = "basic")
@EnableWebSecurity
-public class BasicAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {
+public class BasicAuthSecurityConfiguration {
private final Logger logger = LoggerFactory.getLogger(getClass());
- private final SecurityProperties properties;
-
- public BasicAuthSecurityConfiguration(SecurityProperties securityProperties) {
- this.properties = securityProperties;
- }
-
@PostConstruct
public void initialize() {
logger.info("Using basic authentication");
}
- @Override
- public void configure(AuthenticationManagerBuilder auth) throws Exception {
- // @formatter:off
- auth.inMemoryAuthentication()
- .withUser(properties.getAuthUser())
- .password("{noop}" + properties.getAuthPassword())
- .roles(USER)
- .and()
- .withUser(properties.getAuthAdminUser())
- .password("{noop}" + properties.getAuthAdminPassword())
- .roles(ADMIN);
- // @formatter:on
+ @Bean
+ public InMemoryUserDetailsManager inMemoryUserDetailsManager(
+ SecurityProperties properties, ObjectProvider passwordEncoder) {
+
+ return new InMemoryUserDetailsManager(
+ User.withUsername(properties.getAuthUser())
+ .password("{noop}" + properties.getAuthPassword())
+ .roles(SecurityProperties.USER)
+ .build(),
+ User.withUsername(properties.getAuthAdminUser())
+ .password("{noop}" + properties.getAuthAdminPassword())
+ .roles(SecurityProperties.ADMIN)
+ .build());
}
- @Override
- protected void configure(HttpSecurity http) throws Exception {
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(new SecurityFilter(), BasicAuthenticationFilter.class);
- // @formatter:off
- http.cors()
- .and()
- .csrf()
- .ignoringAntMatchers("/rest/**")
- .and()
- .authorizeRequests()
- .antMatchers("/rest/admin/**", "/management/**")
- .hasRole(ADMIN)
- .anyRequest()
- .hasAnyRole(ADMIN, USER)
- .and()
- .sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- .httpBasic();
- // @formatter:on
+ http.cors(withDefaults())
+ .csrf(c -> c.ignoringRequestMatchers("/rest/**"))
+ .authorizeHttpRequests(auth -> auth.requestMatchers("/rest/admin/**", "/management/**")
+ .hasRole(ADMIN)
+ .anyRequest()
+ .hasAnyRole(ADMIN, SecurityProperties.USER))
+ .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .httpBasic(withDefaults());
+
+ return http.build();
}
}
diff --git a/application/src/main/java/org/ehrbase/application/config/security/OAuth2SecurityConfiguration.java b/application/src/main/java/org/ehrbase/application/config/security/OAuth2SecurityConfiguration.java
index 7dd490974..42335a9a5 100644
--- a/application/src/main/java/org/ehrbase/application/config/security/OAuth2SecurityConfiguration.java
+++ b/application/src/main/java/org/ehrbase/application/config/security/OAuth2SecurityConfiguration.java
@@ -17,12 +17,14 @@
*/
package org.ehrbase.application.config.security;
+import static org.ehrbase.application.config.security.SecurityProperties.ADMIN;
+import static org.springframework.security.config.Customizer.withDefaults;
+
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,17 +32,19 @@
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
-import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
+import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
+import org.springframework.security.web.SecurityFilterChain;
/**
* {@link Configuration} for OAuth2 authentication.
@@ -48,11 +52,10 @@
* @author Jake Smolka
* @since 1.0.0
*/
-@Deprecated
@Configuration
@EnableWebSecurity
@ConditionalOnProperty(prefix = "security", name = "auth-type", havingValue = "oauth")
-public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
+public class OAuth2SecurityConfiguration {
private static final String PUBLIC = "PUBLIC";
private static final String PRIVATE = "PRIVATE";
@@ -87,48 +90,43 @@ public void initialize() {
logger.debug("Using admin role: {}", securityProperties.getOauth2AdminRole());
}
- @Override
- protected void configure(HttpSecurity http) throws Exception {
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
String userRole = securityProperties.getOauth2UserRole();
String adminRole = securityProperties.getOauth2AdminRole();
http.addFilterBefore(new SecurityFilter(), BearerTokenAuthenticationFilter.class);
- // @formatter:off
- var registry = http.cors()
- .and()
- .authorizeRequests()
- .antMatchers("/rest/admin/**")
- .hasRole(adminRole)
- .antMatchers("/swagger-ui/**", "/v3/api-docs/**")
- .permitAll();
-
- var managementAuthorizedUrl = registry.and()
- .authorizeRequests()
- .antMatchers(this.managementWebEndpointProperties.getBasePath() + "/**");
-
- switch (managementEndpointsAccessType) {
- case ADMIN_ONLY ->
- // management endpoints are locked behind an authorization
- // and are only available for users with the admin role
- managementAuthorizedUrl.hasRole(adminRole);
- case PRIVATE ->
- // management endpoints are locked behind an authorization, but are available to any role
- managementAuthorizedUrl.hasAnyRole(adminRole, userRole, PROFILE_SCOPE);
- case PUBLIC ->
- // management endpoints can be accessed without an authorization
- managementAuthorizedUrl.permitAll();
- default -> throw new IllegalStateException(String.format(
- "Unexpected management endpoints access control type %s", managementEndpointsAccessType));
- }
-
- registry.anyRequest()
- .hasAnyRole(adminRole, userRole, PROFILE_SCOPE)
- .and()
- .oauth2ResourceServer()
- .jwt()
- .jwtAuthenticationConverter(getJwtAuthenticationConverter());
- // @formatter:on
+ http.cors(withDefaults())
+ .authorizeHttpRequests(auth -> {
+ AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry =
+ auth.requestMatchers("/rest/admin/**", "/management/**")
+ .hasRole(ADMIN);
+
+ var managementAuthorizedUrl =
+ registry.requestMatchers(this.managementWebEndpointProperties.getBasePath() + "/**");
+
+ switch (managementEndpointsAccessType) {
+ case ADMIN_ONLY ->
+ // management endpoints are locked behind an authorization
+ // and are only available for users with the admin role
+ managementAuthorizedUrl.hasRole(adminRole);
+ case PRIVATE ->
+ // management endpoints are locked behind an authorization, but are available to any role
+ managementAuthorizedUrl.hasAnyRole(adminRole, userRole, PROFILE_SCOPE);
+ case PUBLIC ->
+ // management endpoints can be accessed without an authorization
+ managementAuthorizedUrl.permitAll();
+ default -> throw new IllegalStateException(String.format(
+ "Unexpected management endpoints access control type %s",
+ managementEndpointsAccessType));
+ }
+
+ registry.anyRequest().hasAnyRole(adminRole, userRole, PROFILE_SCOPE);
+ })
+ .oauth2ResourceServer(o -> o.jwt(j -> j.jwtAuthenticationConverter(getJwtAuthenticationConverter())));
+
+ return http.build();
}
// Converter creates list of "ROLE_*" (upper case) authorities for each "realm access" role
@@ -146,7 +144,7 @@ private Converter getJwtAuthenticationConverte
.stream()
.map(roleName -> "ROLE_" + roleName.toUpperCase())
.map(SimpleGrantedAuthority::new)
- .collect(Collectors.toList()));
+ .toList());
}
if (jwt.getClaims().containsKey("scope")) {
@@ -154,7 +152,7 @@ private Converter getJwtAuthenticationConverte
Arrays.stream(jwt.getClaims().get("scope").toString().split(" "))
.map(roleName -> "ROLE_" + roleName.toUpperCase())
.map(SimpleGrantedAuthority::new)
- .collect(Collectors.toList()));
+ .toList());
}
return authority;
});
diff --git a/application/src/main/java/org/ehrbase/application/config/security/SecurityFilter.java b/application/src/main/java/org/ehrbase/application/config/security/SecurityFilter.java
index 3427c0339..4618c0b65 100644
--- a/application/src/main/java/org/ehrbase/application/config/security/SecurityFilter.java
+++ b/application/src/main/java/org/ehrbase/application/config/security/SecurityFilter.java
@@ -17,8 +17,8 @@
*/
package org.ehrbase.application.config.security;
+import jakarta.servlet.*;
import java.io.IOException;
-import javax.servlet.*;
import org.springframework.security.core.context.SecurityContextHolder;
public class SecurityFilter implements Filter {
diff --git a/application/src/main/java/org/ehrbase/application/config/web/AuditHandlerInterceptorDelegator.java b/application/src/main/java/org/ehrbase/application/config/web/AuditHandlerInterceptorDelegator.java
index d7bd181fe..bae34fc20 100644
--- a/application/src/main/java/org/ehrbase/application/config/web/AuditHandlerInterceptorDelegator.java
+++ b/application/src/main/java/org/ehrbase/application/config/web/AuditHandlerInterceptorDelegator.java
@@ -17,8 +17,8 @@
*/
package org.ehrbase.application.config.web;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.ehrbase.api.audit.interceptor.AuditInterceptor;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
diff --git a/application/src/main/java/org/ehrbase/application/config/web/WebConfiguration.java b/application/src/main/java/org/ehrbase/application/config/web/WebConfiguration.java
index c7eb93f43..35d78bb48 100644
--- a/application/src/main/java/org/ehrbase/application/config/web/WebConfiguration.java
+++ b/application/src/main/java/org/ehrbase/application/config/web/WebConfiguration.java
@@ -24,6 +24,7 @@
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
@@ -56,4 +57,9 @@ public void addCorsMappings(CorsRegistry registry) {
public void addInterceptors(@NonNull InterceptorRegistry registry) {
auditInterceptorHandler.registerAuditInterceptors(registry);
}
+
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ configurer.setUseTrailingSlashMatch(true);
+ }
}
diff --git a/application/src/main/java/org/ehrbase/application/web/LoggingContextFilter.java b/application/src/main/java/org/ehrbase/application/web/LoggingContextFilter.java
index b01c53203..715c9fc31 100644
--- a/application/src/main/java/org/ehrbase/application/web/LoggingContextFilter.java
+++ b/application/src/main/java/org/ehrbase/application/web/LoggingContextFilter.java
@@ -17,12 +17,12 @@
*/
package org.ehrbase.application.web;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
diff --git a/application/src/main/resources/application.yml b/application/src/main/resources/application.yml
index 4a8eb86f7..d482723ff 100644
--- a/application/src/main/resources/application.yml
+++ b/application/src/main/resources/application.yml
@@ -37,7 +37,8 @@ spring:
type: CAFFEINE # change to type redis if usage of redis distributed cache is intended
# the following redis properties are only used if the cache.type=redis
- redis:
+ data:
+ redis:
host: localhost
port: 6379
@@ -190,15 +191,10 @@ management:
# Enable / disable metrics endpoint
enabled: false
# Prometheus metric endpoint - Special metrics format to display in microservice observer solutions
- prometheus:
- # Enable / disable prometheus endpoint
- enabled: false
- # Metrics settings
- metrics:
- export:
- prometheus:
+ prometheus:
+ metrics:
+ export:
enabled: true
-
# External Terminology Validation Properties
validation:
external-terminology:
diff --git a/base/pom.xml b/base/pom.xml
index 016c12639..0c1b27865 100644
--- a/base/pom.xml
+++ b/base/pom.xml
@@ -28,7 +28,7 @@
org.ehrbase.openehr
server
- 0.30.0
+ 0.31.0
base
diff --git a/bom/pom.xml b/bom/pom.xml
index 9b8ef6780..11d272194 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -24,7 +24,7 @@
org.ehrbase.openehr
bom
- 0.30.0
+ 0.31.0
pom
EHRbase
@@ -103,7 +103,7 @@
3.3.0
2.13.0
3.13.0
- 2.2.0
+ 2.3.0
8.5.13
2.15.0
1.95.0
@@ -118,9 +118,9 @@
1.6.13
3.1.2
42.5.3
- 1.11.2
- 2.7.14
- 1.6.6
+ 1.11.4
+ 3.1.4
+ 2.2.0
2.20.0
1.4.13
@@ -180,6 +180,29 @@
pom
import
+
+
+ org.ehrbase.openehr.sdk
+ serialisation
+ ${ehrbase.sdk.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.ehrbase.openehr.sdk
+ validation
+ ${ehrbase.sdk.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
commons-io
commons-io
@@ -302,7 +325,7 @@
org.springdoc
- springdoc-openapi-ui
+ springdoc-openapi-starter-webmvc-ui
${springdoc-openapi.version}
@@ -354,6 +377,12 @@
java-jwt
${java-jwt.version}
+
+ com.sun.xml.bind
+ jaxb-impl
+ 2.3.6
+
+
diff --git a/jooq-pq/pom.xml b/jooq-pq/pom.xml
index 148e374f8..524c9fc8c 100644
--- a/jooq-pq/pom.xml
+++ b/jooq-pq/pom.xml
@@ -28,7 +28,7 @@
org.ehrbase.openehr
server
- 0.30.0
+ 0.31.0
jooq-pg
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 14c7c1b59..30c682ccf 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -5,7 +5,7 @@
server
org.ehrbase.openehr
- 0.30.0
+ 0.31.0
4.0.0
@@ -16,6 +16,7 @@
+
com.nedap.healthcare.archie
openehr-rm
diff --git a/plugin/src/main/java/org/ehrbase/plugin/security/PluginSecurityConfiguration.java b/plugin/src/main/java/org/ehrbase/plugin/security/PluginSecurityConfiguration.java
index df62f628f..a30f9fbb2 100644
--- a/plugin/src/main/java/org/ehrbase/plugin/security/PluginSecurityConfiguration.java
+++ b/plugin/src/main/java/org/ehrbase/plugin/security/PluginSecurityConfiguration.java
@@ -17,6 +17,7 @@
*/
package org.ehrbase.plugin.security;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
@@ -26,11 +27,12 @@
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.SourceLocation;
import org.aspectj.runtime.internal.AroundClosure;
+import org.ehrbase.api.annotations.EhrbaseSecurity;
import org.ehrbase.api.annotations.TenantAware;
import org.ehrbase.api.aspect.AnnotationAspect;
import org.ehrbase.api.aspect.AuthorizationAspect;
import org.ehrbase.api.aspect.TenantAspect;
-import org.ehrbase.api.authorization.EhrbaseAuthorization;
+import org.ehrbase.plugin.security.AuthorizationInfo.AuthorizationEnabled;
import org.springframework.aop.Advisor;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
@@ -124,15 +126,18 @@ public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
}
@Bean
- @ConditionalOnBean(value = {AuthorizationAspect.class, AuthorizationInfo.AuthorizationEnabled.class})
+ @ConditionalOnBean(value = {AuthorizationAspect.class, AuthorizationEnabled.class})
public Advisor authorizationAspect() {
ApplicationContext parentCtx = applicationContext.getParent();
AuthorizationAspect theAspect = parentCtx.getBean(AuthorizationAspect.class);
return new DefaultPointcutAdvisor(
- new AnnotationMatchingPointcut(null, EhrbaseAuthorization.class, true), new AspectAdapter(theAspect) {
+ new AnnotationMatchingPointcut(null, EhrbaseSecurity.class, true), new AspectAdapter(theAspect) {
public Object invoke(MethodInvocation invocation) throws Throwable {
- return getAspect().action(new ProceedingJoinPointAdapter(invocation), null);
+ Method method = invocation.getMethod();
+
+ Annotation[] annotations = method.getDeclaredAnnotations();
+ return getAspect().action(new ProceedingJoinPointAdapter(invocation), List.of(annotations));
}
});
}
diff --git a/pom.xml b/pom.xml
index 69cba80d1..fb84da02a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,12 +28,12 @@
org.ehrbase.openehr
bom
- 0.30.0
+ 0.31.0
/bom/pom.xml
server
- 0.30.0
+ 0.31.0
pom
@@ -172,7 +172,7 @@
org.apache.maven.plugins
maven-enforcer-plugin
- 3.3.0
+ 3.4.1
diff --git a/rest-ehr-scape/pom.xml b/rest-ehr-scape/pom.xml
index 41f8864da..d84023f31 100644
--- a/rest-ehr-scape/pom.xml
+++ b/rest-ehr-scape/pom.xml
@@ -28,7 +28,7 @@
org.ehrbase.openehr
server
- 0.30.0
+ 0.31.0
rest-ehr-scape
@@ -56,7 +56,7 @@
org.springdoc
- springdoc-openapi-ui
+ springdoc-openapi-starter-webmvc-ui
org.junit.vintage
diff --git a/rest-ehr-scape/src/main/java/org/ehrbase/rest/ehrscape/EhrScapeExceptionHandler.java b/rest-ehr-scape/src/main/java/org/ehrbase/rest/ehrscape/EhrScapeExceptionHandler.java
index 5e01dc39d..0498975a2 100644
--- a/rest-ehr-scape/src/main/java/org/ehrbase/rest/ehrscape/EhrScapeExceptionHandler.java
+++ b/rest-ehr-scape/src/main/java/org/ehrbase/rest/ehrscape/EhrScapeExceptionHandler.java
@@ -35,6 +35,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
+import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
@@ -126,7 +127,7 @@ public ResponseEntity