patientSet = new HashSet<>();
- patientSet.add(tokenPatient);
- requestMap.put(PATIENT, patientSet);
- return true;
- } else throw new InternalServerException("ABAC: AQL audit patient data unavailable.");
- }
- }
-
- /**
- * Handles template ID extraction of specific payload.
- *
- * Payload will be a response body string, in case of @PostAuthorize.
- *
- * Payload will be request body string, or already deserialized object (e.g. EhrStatus), in case of @PreAuthorize.
- * @param type Object type of scope
- * @param payload Payload object, either request's input or response's output
- * @param contentType Content type from the scope
- * @param requestMap ABAC request attribute map to add the result
- * @param authType Pre- or PostAuthorize, determines payload style (string or object)
- */
- @SuppressWarnings("unchecked")
- private void templateHandling(
- String type, Object payload, String contentType, Map requestMap, String authType) {
- switch (type) {
- case BaseController.EHR:
- throw new IllegalArgumentException(
- "ABAC: Unsupported configuration: Can't set template ID for EHR type.");
- case BaseController.EHR_STATUS:
- throw new IllegalArgumentException(
- "ABAC: Unsupported configuration: Can't set template ID for EHR_STATUS type.");
- case BaseController.COMPOSITION:
- String content = "";
- if (authType.equals(POST)) {
- // @PostAuthorize gives a ResponseEntity type for "returnObject", so payload is of that type
- if (!(payload instanceof ResponseEntity> responseEntity)) {
- throw new InternalServerException("ABAC: unexpected payload type");
- }
- if (!responseEntity.hasBody()) {
- if (NO_CONTENT.equals(responseEntity.getStatusCode())) {
- return;
- }
- throw new InternalServerException("ABAC: unexpected empty response body");
- }
- Object body = responseEntity.getBody();
- if (NO_CONTENT.equals(responseEntity.getStatusCode())) {
- if (body instanceof Map) {
- Object error = ((Map, ?>) body).get("error");
- if (error != null && ((String) error).contains("delet")) {
- // composition was deleted, so nothing to check here, skip
- break;
- }
- }
- throw new InternalServerException("ABAC: Unexpected empty response from composition request");
- }
- if (body instanceof OriginalVersionResponseData) {
- // case of versioned_composition --> fast path, because template is easy to get
- Object data = ((OriginalVersionResponseData>) body).getData();
- if (data instanceof Composition composition) {
- String template = Objects.requireNonNull(
- composition.getArchetypeDetails().getTemplateId())
- .getValue();
- requestMap.put(TEMPLATE, template);
- break; // special case, so done here, exit
- }
- } else if (body instanceof String) {
- content = (String) body;
- } else {
- throw new InternalServerException("ABAC: unexpected composition payload object");
- }
- } else if (authType.equals(PRE)) {
- try {
- // try if this is the Delete composition case. Payload would contain the UUID of the compo.
- ObjectVersionId versionId = new ObjectVersionId((String) payload);
- UUID compositionUid =
- UUID.fromString(versionId.getRoot().getValue());
- Optional compoDto = compositionService.retrieve(
- compositionService.getEhrId(compositionUid), compositionUid, null);
- if (compoDto.isPresent()) {
- Composition c = compoDto.get();
- if (c.getArchetypeDetails() != null
- && c.getArchetypeDetails().getTemplateId() != null) {
- requestMap.put(
- TEMPLATE,
- c.getArchetypeDetails().getTemplateId().getValue());
- }
- break; // special case, so done here, exit
- } else {
- throw new InternalServerException(
- "ABAC: unexpected empty response from composition delete");
- }
- } catch (IllegalArgumentException e) {
- // if not an UUID, the payload is a composition itself so continue
- content = (String) payload;
- }
- } else {
- throw new InternalServerException("ABAC: invalid auth type given.");
- }
- String templateId;
- if (MediaType.parseMediaType(contentType).isCompatibleWith(MediaType.APPLICATION_JSON)) {
- templateId = compositionService.getTemplateIdFromInputComposition(content, CompositionFormat.JSON);
- } else if (MediaType.parseMediaType(contentType).isCompatibleWith(MediaType.APPLICATION_XML)) {
- templateId = compositionService.getTemplateIdFromInputComposition(content, CompositionFormat.XML);
- } else {
- throw new IllegalArgumentException("ABAC: Only JSON and XML composition are supported.");
- }
- requestMap.put(TEMPLATE, templateId);
- break;
- case BaseController.CONTRIBUTION:
- CompositionFormat format;
- if (MediaType.parseMediaType(contentType).isCompatibleWith(MediaType.APPLICATION_JSON)) {
- format = CompositionFormat.JSON;
- } else if (MediaType.parseMediaType(contentType).isCompatibleWith(MediaType.APPLICATION_XML)) {
- format = CompositionFormat.XML;
- } else {
- throw new IllegalArgumentException("ABAC: Only JSON and XML composition are supported.");
- }
- if (payload instanceof String) {
- Set templates = contributionService.getListOfTemplates((String) payload, format);
- requestMap.put(TEMPLATE, templates);
- break;
- } else {
- throw new InternalServerException("ABAC: invalid POST contribution payload.");
- }
- case BaseController.QUERY:
- // special case of type QUERY, where multiple subjects are possible
- if (payload instanceof Map) {
- if (((Map, ?>) payload).containsKey(AuditVariables.TEMPLATE_PATH)) {
- Set templates = (Set) ((Map, ?>) payload).get(AuditVariables.TEMPLATE_PATH);
- Set templateSet = new HashSet<>(templates);
- // put result set into the requestMap and exit
- requestMap.put(TEMPLATE, templateSet);
- break;
- } else {
- throw new InternalServerException("ABAC: AQL audit template data unavailable.");
- }
- } else {
- throw new InternalServerException("ABAC: AQL audit template data malformed.");
- }
- default:
- throw new InternalServerException("ABAC: Invalid type given from Pre- or PostAuthorize");
- }
- }
-
- @SuppressWarnings("unchecked")
- private boolean abacCheckRequest(String url, Map bodyMap) throws IOException {
- // prepare request attributes and convert from to
- Map request = new HashMap<>();
- if (bodyMap.containsKey(ORGANIZATION)) {
- request.put(ORGANIZATION, (String) bodyMap.get(ORGANIZATION));
- }
- // check if patient attribues are available and see if it contains a Set or simple String
- if (bodyMap.containsKey(PATIENT)) {
- if (bodyMap.get(PATIENT) instanceof Set) {
- // check if templates are also configured
- if (bodyMap.containsKey(TEMPLATE)) {
- if (bodyMap.get(TEMPLATE) instanceof Set) {
- // multiple templates possible: need cartesian product of n patients and m templates
- // so: for each patient, go through templates and do a request each
- Set setP = (Set) bodyMap.get(PATIENT);
- for (String p : setP) {
- request.put(PATIENT, p);
- boolean success = sendRequestForEach(TEMPLATE, url, bodyMap, request);
- if (!success) {
- return false;
- }
- }
- // in case all combinations were validated successfully
- return true;
- }
- } else {
- // only patients (or + orga) set. So run request for each patient, without template.
- return sendRequestForEach(PATIENT, url, bodyMap, request);
- }
- } else if (bodyMap.get(PATIENT) instanceof String) {
- request.put(PATIENT, (String) bodyMap.get(PATIENT));
- } else {
- // if it is just a String, set it and continue normal
- throw new InternalServerException("ABAC: Invalid patient attribute content.");
- }
- }
- // check if template attributes are available and see if it contains a Set or simple String
- if (bodyMap.containsKey(TEMPLATE)) {
- if (bodyMap.get(TEMPLATE) instanceof Set) {
- // set each template and send separate ABAC requests
- return sendRequestForEach(TEMPLATE, url, bodyMap, request);
- } else if (bodyMap.get(TEMPLATE) instanceof String) {
- // if it is just a String, set it and continue normal
- request.put(TEMPLATE, (String) bodyMap.get(TEMPLATE));
- } else {
- throw new InternalServerException("ABAC: Invalid template attribute content.");
- }
- }
- return abacCheck.execute(url, request);
- }
-
- /**
- * Goes through all template IDs and sends an ABAC request for each.
- * @param type Type, either ORGANIZATION, TEMPLATE, PATIENT
- * @param url ABAC server request URL
- * @param bodyMap Unprocessed attributes for the request
- * @param request Processed attributes for the request
- * @return True on success, False if one combinations is rejected by the ABAC server
- * @throws IOException On error during attribute or HTTP handling
- */
- @SuppressWarnings("unchecked")
- private boolean sendRequestForEach(
- String type, String url, Map bodyMap, Map request) throws IOException {
- Set set = (Set) bodyMap.get(type);
- for (String s : set) {
- request.put(type, s);
- boolean allowed = abacCheck.execute(url, request);
- if (!allowed) {
- // if only one combination of attributes is rejected by ABAC return false for all
- return false;
- }
- }
- // in case all combinations were validated successfully
- return true;
- }
-
- /**
- * Extracts the JWT auth token.
- * @param auth Auth object.
- * @return JWT Auth Token
- */
- private AbstractAuthenticationToken getJwtAuthenticationToken(Authentication auth) {
- if (auth instanceof AbstractAuthenticationToken jwt) {
- return jwt;
- } else {
- throw new IllegalArgumentException("ABAC: Invalid authentication, no JWT available.");
- }
- }
-
- @Override
- public Object getFilterObject() {
- return this.filterObject;
- }
-
- @Override
- public void setFilterObject(Object filterObject) {
- this.filterObject = filterObject;
- }
-
- @Override
- public Object getReturnObject() {
- return this.returnObject;
- }
-
- @Override
- public void setReturnObject(Object returnObject) {
- this.returnObject = returnObject;
- }
-
- @Override
- public Object getThis() {
- return this;
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/abac/MethodSecurityConfig.java b/application/src/main/java/org/ehrbase/application/abac/MethodSecurityConfig.java
deleted file mode 100644
index f6fc4d874..000000000
--- a/application/src/main/java/org/ehrbase/application/abac/MethodSecurityConfig.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2021 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.application.abac;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
-
-@ConditionalOnProperty(name = "abac.enabled")
-@Configuration
-@EnableGlobalMethodSecurity(prePostEnabled = true)
-public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
-
- private final AbacConfig abacConfig;
-
- public MethodSecurityConfig(AbacConfig abacConfig) {
- this.abacConfig = abacConfig;
- }
-
- /**
- * Registration of custom SpEL expressions, here to include ABAC checks.
- */
- @Override
- protected MethodSecurityExpressionHandler createExpressionHandler() {
- // "null" for beans here, but autowiring will make the beans available on runtime
- return new CustomMethodSecurityExpressionHandler(abacConfig, null, null, null, null);
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/cli/EhrBaseCli.java b/application/src/main/java/org/ehrbase/application/cli/EhrBaseCli.java
new file mode 100644
index 000000000..8bf902a44
--- /dev/null
+++ b/application/src/main/java/org/ehrbase/application/cli/EhrBaseCli.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019-2024 vitasystems GmbH.
+ *
+ * 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.application.cli;
+
+import java.util.Map;
+import org.ehrbase.cli.CliConfiguration;
+import org.ehrbase.cli.CliRunner;
+import org.ehrbase.configuration.EhrBaseCliConfiguration;
+import org.springframework.boot.Banner;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.Import;
+
+@SpringBootApplication(exclude = {WebMvcAutoConfiguration.class, RedisAutoConfiguration.class})
+@Import({EhrBaseCliConfiguration.class, CliConfiguration.class})
+public class EhrBaseCli implements CommandLineRunner {
+
+ public static SpringApplication build(String[] args) {
+ return new SpringApplicationBuilder(EhrBaseCli.class)
+ .web(WebApplicationType.NONE)
+ .headless(true)
+ .properties(Map.of(
+ "spring.main.allow-bean-definition-overriding", "true",
+ "spring.banner.location", "classpath:banner-cli.txt"))
+ .bannerMode(Banner.Mode.CONSOLE)
+ .logStartupInfo(false)
+ .build(args);
+ }
+
+ private final CliRunner cliRunner;
+
+ public EhrBaseCli(CliRunner cliRunner) {
+ this.cliRunner = cliRunner;
+ }
+
+ @Override
+ public void run(String... args) {
+ cliRunner.run(args);
+ }
+}
diff --git a/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java b/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java
deleted file mode 100644
index e09d2a8c0..000000000
--- a/application/src/main/java/org/ehrbase/application/config/ServerConfigImp.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2020 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.application.config;
-
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@ConfigurationProperties(prefix = "server")
-public class ServerConfigImp implements org.ehrbase.api.definitions.ServerConfig {
-
- @Min(1025)
- @Max(65536)
- private int port;
-
- private String nodename = "local.ehrbase.org";
- private AqlConfig aqlConfig;
- private boolean disableStrictValidation = false;
-
- public int getPort() {
- return port;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public String getNodename() {
- return nodename;
- }
-
- public void setNodename(String nodename) {
- this.nodename = nodename;
- }
-
- @Override
- public String getAqlIterationSkipList() {
- return aqlConfig.getIgnoreIterativeNodeList();
- }
-
- @Override
- public Integer getAqlDepth() {
- return aqlConfig.getIterationScanDepth();
- }
-
- public AqlConfig getAqlConfig() {
- return aqlConfig;
- }
-
- public void setAqlConfig(AqlConfig aqlConfig) {
- this.aqlConfig = aqlConfig;
- }
-
- public static class AqlConfig {
-
- private String ignoreIterativeNodeList;
- private Integer iterationScanDepth = 1;
-
- public String getIgnoreIterativeNodeList() {
- return ignoreIterativeNodeList;
- }
-
- public Integer getIterationScanDepth() {
- return iterationScanDepth;
- }
-
- public void setIgnoreIterativeNodeList(String ignoreIterativeNodeList) {
- this.ignoreIterativeNodeList = ignoreIterativeNodeList;
- }
-
- public void setIterationScanDepth(Integer iterationScanDepth) {
- this.iterationScanDepth = iterationScanDepth;
- }
- }
-
- @Override
- public boolean isDisableStrictValidation() {
- return disableStrictValidation;
- }
-
- public void setDisableStrictValidation(boolean disableStrictValidation) {
- this.disableStrictValidation = disableStrictValidation;
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/config/cache/CacheConfiguration.java b/application/src/main/java/org/ehrbase/application/config/cache/CacheConfiguration.java
deleted file mode 100644
index 4a97ba476..000000000
--- a/application/src/main/java/org/ehrbase/application/config/cache/CacheConfiguration.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2021 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.application.config.cache;
-
-import com.github.benmanes.caffeine.cache.Caffeine;
-import java.util.concurrent.TimeUnit;
-import org.ehrbase.cache.CacheOptions;
-import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.cache.caffeine.CaffeineCacheManager;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * {@link Configuration} for EhCache using JCache.
- *
- * @author Renaud Subiger
- * @since 1.0.0
- */
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(CacheProperties.class)
-@EnableCaching
-public class CacheConfiguration {
-
- @Bean
- public CacheOptions cacheOptions(CacheProperties properties) {
- var options = new CacheOptions();
- options.setPreBuildQueries(properties.isPreBuildQueries());
- options.setPreBuildQueriesDepth(properties.getPreBuildQueriesDepth());
- options.setPreInitialize(properties.isInitOnStartup());
- return options;
- }
-
- @Bean
- @ConditionalOnExpression(
- "T(org.springframework.boot.autoconfigure.cache.CacheType).CAFFEINE.name().equalsIgnoreCase(\"${spring.cache.type}\")")
- public CacheManagerCustomizer cacheManagerCustomizer() {
- return cm -> {
- cm.registerCustomCache(
- CacheOptions.INTROSPECT_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.QUERY_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.FIELDS_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.MULTI_VALUE_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.CONCEPT_CACHE_ID, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.CONCEPT_CACHE_CONCEPT_ID, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.CONCEPT_CACHE_DESCRIPTION,
- Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.TERRITORY_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.LANGUAGE_CACHE, Caffeine.newBuilder().build());
- cm.registerCustomCache(
- CacheOptions.USER_ID_CACHE,
- Caffeine.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build());
- cm.registerCustomCache(
- CacheOptions.SYS_TENANT, Caffeine.newBuilder().build());
- };
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/config/cache/CacheProperties.java b/application/src/main/java/org/ehrbase/application/config/cache/CacheProperties.java
deleted file mode 100644
index 5bc9e3667..000000000
--- a/application/src/main/java/org/ehrbase/application/config/cache/CacheProperties.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2021 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.application.config.cache;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * {@link ConfigurationProperties} for EHRbase cache configuration.
- *
- * @author Renaud Subiger
- * @since 1.0.0
- */
-@ConfigurationProperties(prefix = "cache")
-public class CacheProperties {
-
- /**
- * Whether to initialize the caches during application startup.
- */
- private boolean initOnStartup = true;
-
- /**
- * Whether to pre-build queries when a new template is added.
- */
- private boolean preBuildQueries = true;
-
- /**
- * The default node depth for pre-built queries.
- */
- private Integer preBuildQueriesDepth = 4;
-
- public boolean isInitOnStartup() {
- return initOnStartup;
- }
-
- public void setInitOnStartup(boolean initOnStartup) {
- this.initOnStartup = initOnStartup;
- }
-
- public boolean isPreBuildQueries() {
- return preBuildQueries;
- }
-
- public void setPreBuildQueries(boolean preBuildQueries) {
- this.preBuildQueries = preBuildQueries;
- }
-
- public Integer getPreBuildQueriesDepth() {
- return preBuildQueriesDepth;
- }
-
- public void setPreBuildQueriesDepth(Integer preBuildQueriesDepth) {
- this.preBuildQueriesDepth = preBuildQueriesDepth;
- }
-}
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
deleted file mode 100644
index 23cf4bfb6..000000000
--- a/application/src/main/java/org/ehrbase/application/config/security/BasicAuthSecurityConfiguration.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2021-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.application.config.security;
-
-import static org.ehrbase.application.config.security.SecurityProperties.ADMIN;
-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.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-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;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-
-/**
- * {@link Configuration} for Basic authentication.
- *
- * @author Jake Smolka
- * @author Renaud Subiger
- * @since 1.0.0
- */
-@Configuration
-@ConditionalOnProperty(prefix = "security", name = "authType", havingValue = "basic")
-@EnableWebSecurity
-public class BasicAuthSecurityConfiguration {
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- @PostConstruct
- public void initialize() {
- logger.info("Using basic authentication");
- }
-
- @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());
- }
-
- @Bean
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- http.addFilterBefore(new SecurityFilter(), BasicAuthenticationFilter.class);
-
- http.cors(withDefaults())
- .csrf(c -> c.ignoringRequestMatchers(AntPathRequestMatcher.antMatcher("/rest/**")))
- .authorizeHttpRequests(auth -> auth.requestMatchers(
- AntPathRequestMatcher.antMatcher("/rest/admin/**"),
- AntPathRequestMatcher.antMatcher("/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/NoOpSecurityConfiguration.java b/application/src/main/java/org/ehrbase/application/config/security/NoOpSecurityConfiguration.java
deleted file mode 100644
index 3852476d4..000000000
--- a/application/src/main/java/org/ehrbase/application/config/security/NoOpSecurityConfiguration.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2021-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.application.config.security;
-
-import javax.annotation.PostConstruct;
-import org.ehrbase.service.IAuthenticationFacade;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-import org.springframework.security.authentication.AnonymousAuthenticationToken;
-import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
-
-/**
- * {@link Configuration} used when security is disabled.
- *
- * @author Renaud Subiger
- * @since 1.0.0
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnProperty(prefix = "security", name = "auth-type", havingValue = "none")
-public class NoOpSecurityConfiguration {
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- @PostConstruct
- public void initialize() {
- logger.warn("Security is disabled. Configure 'security.auth-type' to disable this warning.");
- }
-
- @Bean
- @Primary
- public IAuthenticationFacade anonymousAuthentication() {
- var filter = new AnonymousAuthenticationFilter("key");
- return () -> new AnonymousAuthenticationToken("key", filter.getPrincipal(), filter.getAuthorities());
- }
-}
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
deleted file mode 100644
index 89d4f5f99..000000000
--- a/application/src/main/java/org/ehrbase/application/config/security/OAuth2SecurityConfiguration.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2021-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.application.config.security;
-
-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 javax.annotation.PostConstruct;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-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.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.authentication.BearerTokenAuthenticationFilter;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-
-/**
- * {@link Configuration} for OAuth2 authentication.
- *
- * @author Jake Smolka
- * @since 1.0.0
- */
-@Configuration
-@EnableWebSecurity
-@ConditionalOnProperty(prefix = "security", name = "auth-type", havingValue = "oauth")
-public class OAuth2SecurityConfiguration {
-
- private static final String PUBLIC = "PUBLIC";
- private static final String PRIVATE = "PRIVATE";
- public static final String ADMIN_ONLY = "ADMIN_ONLY";
- public static final String PROFILE_SCOPE = "PROFILE";
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- @Value("${management.endpoints.web.access:ADMIN_ONLY}")
- private String managementEndpointsAccessType;
-
- private final SecurityProperties securityProperties;
-
- private final OAuth2ResourceServerProperties oAuth2Properties;
-
- private final WebEndpointProperties managementWebEndpointProperties;
-
- public OAuth2SecurityConfiguration(
- SecurityProperties securityProperties,
- OAuth2ResourceServerProperties oAuth2Properties,
- WebEndpointProperties managementWebEndpointProperties) {
- this.securityProperties = securityProperties;
- this.oAuth2Properties = oAuth2Properties;
- this.managementWebEndpointProperties = managementWebEndpointProperties;
- }
-
- @PostConstruct
- public void initialize() {
- logger.info("Using OAuth2 authentication");
- logger.debug("Using issuer URI: {}", oAuth2Properties.getJwt().getIssuerUri());
- logger.debug("Using user role: {}", securityProperties.getOauth2UserRole());
- logger.debug("Using admin role: {}", securityProperties.getOauth2AdminRole());
- }
-
- @Bean
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- String userRole = securityProperties.getOauth2UserRole();
- String adminRole = securityProperties.getOauth2AdminRole();
-
- http.addFilterBefore(new SecurityFilter(), BearerTokenAuthenticationFilter.class);
-
- http.cors(withDefaults())
- .authorizeHttpRequests(auth -> {
- AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry =
- auth.requestMatchers(AntPathRequestMatcher.antMatcher("/rest/admin/**"))
- .hasRole(adminRole);
-
- var managementAuthorizedUrl = registry.requestMatchers(AntPathRequestMatcher.antMatcher(
- 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
- // and "roles" role from JWT
- @SuppressWarnings("unchecked")
- private Converter getJwtAuthenticationConverter() {
- var converter = new JwtAuthenticationConverter();
- converter.setJwtGrantedAuthoritiesConverter(jwt -> {
- Map realmAccess;
- realmAccess = (Map) jwt.getClaims().get("realm_access");
-
- Collection authority = new HashSet<>();
- if (realmAccess != null && realmAccess.containsKey("roles")) {
- authority.addAll(((List) realmAccess.get("roles"))
- .stream()
- .map(roleName -> "ROLE_" + roleName.toUpperCase())
- .map(SimpleGrantedAuthority::new)
- .toList());
- }
-
- if (jwt.getClaims().containsKey("scope")) {
- authority.addAll(
- Arrays.stream(jwt.getClaims().get("scope").toString().split(" "))
- .map(roleName -> "ROLE_" + roleName.toUpperCase())
- .map(SimpleGrantedAuthority::new)
- .toList());
- }
- return authority;
- });
- return converter;
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/config/security/SecurityConfiguration.java b/application/src/main/java/org/ehrbase/application/config/security/SecurityConfiguration.java
deleted file mode 100644
index 9f3aebf7e..000000000
--- a/application/src/main/java/org/ehrbase/application/config/security/SecurityConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2020 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.application.config.security;
-
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(SecurityProperties.class)
-@Import({NoOpSecurityConfiguration.class, BasicAuthSecurityConfiguration.class})
-public class SecurityConfiguration {}
diff --git a/application/src/main/java/org/ehrbase/application/config/validation/ValidationConfiguration.java b/application/src/main/java/org/ehrbase/application/config/validation/ValidationConfiguration.java
deleted file mode 100644
index 4a1161faa..000000000
--- a/application/src/main/java/org/ehrbase/application/config/validation/ValidationConfiguration.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2021-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.application.config.validation;
-
-import com.nedap.archie.rm.datavalues.DvCodedText;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.apache.http.client.HttpClient;
-import org.ehrbase.openehr.sdk.util.functional.Try;
-import org.ehrbase.openehr.sdk.validation.ConstraintViolation;
-import org.ehrbase.openehr.sdk.validation.ConstraintViolationException;
-import org.ehrbase.openehr.sdk.validation.terminology.ExternalTerminologyValidation;
-import org.ehrbase.openehr.sdk.validation.terminology.ExternalTerminologyValidationChain;
-import org.ehrbase.openehr.sdk.validation.terminology.FhirTerminologyValidation;
-import org.ehrbase.openehr.sdk.validation.terminology.TerminologyParam;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * {@link Configuration} for external terminology validation.
- *
- * @author Renaud Subiger
- * @since 1.0.0
- */
-@Configuration
-@EnableConfigurationProperties(ValidationProperties.class)
-@SuppressWarnings("java:S6212")
-public class ValidationConfiguration {
- private static final String ERR_MSG = "External terminology validation is disabled, consider to enable it";
- private final Logger logger = LoggerFactory.getLogger(getClass());
- private final ValidationProperties properties;
- private final HttpClient httpClient;
-
- // @Autowired
- @Value("${validation.external-terminology.enabled}")
- private Boolean enableExternalValidation;
-
- public ValidationConfiguration(ValidationProperties properties, HttpClient httpClient) {
- this.properties = properties;
- this.httpClient = httpClient;
- }
-
- @Bean
- public ExternalTerminologyValidation externalTerminologyValidator() {
- if (!enableExternalValidation) {
- logger.warn(ERR_MSG);
- return new ExternalTerminologyValidation() {
- private final ConstraintViolation err = new ConstraintViolation(ERR_MSG);
-
- public Try validate(TerminologyParam param) {
- return Try.failure(new ConstraintViolationException(List.of(err)));
- }
-
- public boolean supports(TerminologyParam param) {
- return false;
- }
-
- public List expand(TerminologyParam param) {
- return Collections.emptyList();
- }
- };
- }
-
- Map providers = properties.getProvider();
-
- if (providers.isEmpty()) {
- throw new IllegalStateException("At least one external terminology provider must be defined "
- + "if 'validation.external-validation.enabled' is set to 'true'");
- } else if (providers.size() == 1) {
- Map.Entry provider =
- providers.entrySet().iterator().next();
- return buildExternalTerminologyValidation(provider);
- } else {
- ExternalTerminologyValidationChain chain = new ExternalTerminologyValidationChain();
- for (Map.Entry provider : providers.entrySet()) {
- chain.addExternalTerminologyValidationSupport(buildExternalTerminologyValidation(provider));
- }
- return chain;
- }
- }
-
- private ExternalTerminologyValidation buildExternalTerminologyValidation(
- Map.Entry provider) {
- logger.info(
- "Initializing '{}' external terminology provider (type: {})",
- provider.getKey(),
- provider.getValue().getType());
- if (provider.getValue().getType() == ValidationProperties.ProviderType.FHIR) {
- return fhirTerminologyValidation(provider.getValue().getUrl());
- }
- throw new IllegalArgumentException(
- "Invalid provider type: " + provider.getValue().getType());
- }
-
- private FhirTerminologyValidation fhirTerminologyValidation(String url) {
- return new FhirTerminologyValidation(url, properties.isFailOnError(), httpClient);
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/config/validation/ValidationProperties.java b/application/src/main/java/org/ehrbase/application/config/validation/ValidationProperties.java
deleted file mode 100644
index 2cc4f3aa3..000000000
--- a/application/src/main/java/org/ehrbase/application/config/validation/ValidationProperties.java
+++ /dev/null
@@ -1,82 +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.application.config.validation;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * {@link ConfigurationProperties} for external terminology validation.
- */
-@ConfigurationProperties(prefix = "validation.external-terminology")
-public class ValidationProperties {
-
- private boolean enabled = false;
-
- private boolean failOnError = false;
-
- private final Map provider = new HashMap<>();
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public boolean isFailOnError() {
- return failOnError;
- }
-
- public void setFailOnError(boolean failOnError) {
- this.failOnError = failOnError;
- }
-
- public Map getProvider() {
- return provider;
- }
-
- public enum ProviderType {
- FHIR
- }
-
- public static class Provider {
-
- private ProviderType type;
-
- private String url;
-
- public ProviderType getType() {
- return type;
- }
-
- public void setType(ProviderType type) {
- this.type = type;
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
- }
-}
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
deleted file mode 100644
index bae34fc20..000000000
--- a/application/src/main/java/org/ehrbase/application/config/web/AuditHandlerInterceptorDelegator.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2023 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.application.config.web;
-
-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;
-
-public class AuditHandlerInterceptorDelegator implements HandlerInterceptor {
- private final AuditInterceptor interceptor;
-
- public AuditHandlerInterceptorDelegator(AuditInterceptor interceptor) {
- this.interceptor = interceptor;
- }
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- return interceptor.preHandle(request, response, handler);
- }
-
- @Override
- public void afterCompletion(
- HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex)
- throws Exception {
- interceptor.afterCompletion(request, response, handler, ex);
- }
-}
diff --git a/application/src/main/java/org/ehrbase/application/config/web/AuditInterceptorHandler.java b/application/src/main/java/org/ehrbase/application/config/web/AuditInterceptorHandler.java
deleted file mode 100644
index e76c275b0..000000000
--- a/application/src/main/java/org/ehrbase/application/config/web/AuditInterceptorHandler.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2023 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.application.config.web;
-
-import static org.ehrbase.rest.BaseController.*;
-
-import java.util.Arrays;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.ehrbase.api.audit.interceptor.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-
-@Component
-public class AuditInterceptorHandler {
-
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- private static final String ANY_SEGMENT = "*";
- private static final String ROLLBACK = "rollback";
- private static final String ANY_TRAILING_SEGMENTS = "**";
-
- @Value(API_CONTEXT_PATH_WITH_VERSION)
- protected String apiContextPath;
-
- @Value(ADMIN_API_CONTEXT_PATH)
- protected String adminApiContextPath;
-
- @Autowired(required = false)
- AuditEhrInterceptor ehrInterceptor;
-
- @Autowired(required = false)
- AuditQueryInterceptor queryInterceptor;
-
- @Autowired(required = false)
- AuditEhrAdminInterceptor ehrAdminInterceptor;
-
- @Autowired(required = false)
- AuditEhrStatusInterceptor ehrStatusInterceptor;
-
- @Autowired(required = false)
- AuditCompositionInterceptor compositionInterceptor;
-
- @Autowired(required = false)
- AuditContributionInterceptor contributionInterceptor;
-
- @Autowired(required = false)
- AuditCompensationInterceptor compensationInterceptor;
-
- @Autowired(required = false)
- AuditDirectoryInterceptor directoryInterceptor;
-
- public void registerAuditInterceptors(InterceptorRegistry registry) {
- if (shouldRegisterInterceptors()) {
- registerEhrInterceptor(registry);
- registerQueryInterceptor(registry);
- registerEhrAdminInterceptor(registry);
- registerEhrStatusInterceptor(registry);
- registerCompositionInterceptor(registry);
- registerContributionInterceptor(registry);
- registerCompensationInterceptor(registry);
- registerDirectoryInterceptor(registry);
- }
- }
-
- private void registerEhrStatusInterceptor(InterceptorRegistry registry) {
- if (ehrStatusInterceptor != null) {
- // Ehr Status and Versioned Ehr Status endpoints
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(ehrStatusInterceptor))
- .addPathPatterns(
- contextPathPattern(EHR, ANY_SEGMENT, EHR_STATUS),
- contextPathPattern(EHR, ANY_SEGMENT, EHR_STATUS, ANY_TRAILING_SEGMENTS))
- .addPathPatterns(
- contextPathPattern(EHR, ANY_SEGMENT, EHR_STATUS),
- contextPathPattern(EHR, ANY_SEGMENT, VERSIONED_EHR_STATUS, ANY_TRAILING_SEGMENTS));
- } else {
- log.info("Ehr Status interceptor bean is not available.");
- }
- }
-
- private void registerQueryInterceptor(InterceptorRegistry registry) {
- if (queryInterceptor != null) {
- // Query endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(queryInterceptor))
- .addPathPatterns(contextPathPattern(QUERY, ANY_TRAILING_SEGMENTS))
- .addPathPatterns(contextPathPattern(DEFINITION, QUERY, ANY_TRAILING_SEGMENTS));
- } else {
- log.info("Query interceptor bean is not available.");
- }
- }
-
- private void registerEhrAdminInterceptor(InterceptorRegistry registry) {
- if (ehrAdminInterceptor != null) {
- // Ehr admin endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(ehrAdminInterceptor))
- .addPathPatterns(contextAdminPathPattern(EHR), contextAdminPathPattern(EHR, ANY_SEGMENT));
- } else {
- log.info("Ehr admin interceptor bean is not available.");
- }
- }
-
- private void registerEhrInterceptor(InterceptorRegistry registry) {
- if (ehrInterceptor != null) {
- // Ehr endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(ehrInterceptor))
- .addPathPatterns(contextPathPattern(EHR), contextPathPattern(EHR, ANY_SEGMENT));
- } else {
- log.info("Ehr interceptor bean is not available.");
- }
- }
-
- private void registerContributionInterceptor(InterceptorRegistry registry) {
- if (contributionInterceptor != null) {
- // Contribution endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(contributionInterceptor))
- .addPathPatterns(contextPathPattern(EHR, ANY_SEGMENT, CONTRIBUTION, ANY_TRAILING_SEGMENTS))
- .addPathPatterns(contextAdminPathPattern(EHR, ANY_SEGMENT, CONTRIBUTION, ANY_TRAILING_SEGMENTS));
- } else {
- log.info("Contribution interceptor bean is not available.");
- }
- }
-
- private void registerCompositionInterceptor(InterceptorRegistry registry) {
- if (compositionInterceptor != null) {
- // Composition endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(compositionInterceptor))
- .addPathPatterns(contextPathPattern(EHR, ANY_SEGMENT, COMPOSITION, ANY_TRAILING_SEGMENTS))
- .addPathPatterns(contextPathPattern(EHR, ANY_SEGMENT, VERSIONED_COMPOSITION, ANY_TRAILING_SEGMENTS))
- .addPathPatterns(contextAdminPathPattern(EHR, ANY_SEGMENT, COMPOSITION, ANY_SEGMENT));
- } else {
- log.info("Composition interceptor bean is not available.");
- }
- }
-
- private void registerCompensationInterceptor(InterceptorRegistry registry) {
- if (compensationInterceptor != null) {
- // Compensation plugin endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(compensationInterceptor))
- .addPathPatterns(getPathPattern("", EHR, ANY_SEGMENT, CONTRIBUTION, ANY_SEGMENT, ROLLBACK));
- } else {
- log.info("Compensation interceptor bean is not available.");
- }
- }
-
- private void registerDirectoryInterceptor(InterceptorRegistry registry) {
- if (directoryInterceptor != null) {
- // Directory plugin endpoint
- registry.addInterceptor(new AuditHandlerInterceptorDelegator(directoryInterceptor))
- .addPathPatterns(contextPathPattern(EHR, ANY_SEGMENT, DIRECTORY))
- .addPathPatterns(contextPathPattern(EHR, ANY_SEGMENT, DIRECTORY, ANY_SEGMENT))
- .addPathPatterns(contextAdminPathPattern(EHR, ANY_SEGMENT, DIRECTORY, ANY_SEGMENT));
- } else {
- log.info("Directory interceptor bean is not available.");
- }
- }
-
- private boolean shouldRegisterInterceptors() {
- return compositionInterceptor != null
- || ehrInterceptor != null
- || ehrAdminInterceptor != null
- || queryInterceptor != null
- || contributionInterceptor != null
- || ehrStatusInterceptor != null
- || directoryInterceptor != null
- || compensationInterceptor != null;
- }
-
- private String contextPathPattern(String... segments) {
- return getPathPattern(apiContextPath, segments);
- }
-
- private String contextAdminPathPattern(String... segments) {
- return getPathPattern(adminApiContextPath, segments);
- }
-
- private String getPathPattern(String apiContextPath, String... segments) {
- return Stream.concat(Stream.of(apiContextPath), Arrays.stream(segments)).collect(Collectors.joining("/"));
- }
-}
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
deleted file mode 100644
index 35d78bb48..000000000
--- a/application/src/main/java/org/ehrbase/application/config/web/WebConfiguration.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2023 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.application.config.web;
-
-import org.ehrbase.application.util.IsoDateTimeConverter;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.format.FormatterRegistry;
-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;
-
-/**
- * {@link Configuration} from Spring Web MVC.
- */
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(CorsProperties.class)
-public class WebConfiguration implements WebMvcConfigurer {
-
- private final CorsProperties properties;
-
- AuditInterceptorHandler auditInterceptorHandler;
-
- public WebConfiguration(CorsProperties properties, AuditInterceptorHandler auditInterceptorHandler) {
- this.properties = properties;
- this.auditInterceptorHandler = auditInterceptorHandler;
- }
-
- @Override
- public void addFormatters(FormatterRegistry registry) {
- registry.addConverter(new IsoDateTimeConverter()); // Converter for version_at_time and other ISO date params
- }
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**").combine(properties.toCorsConfiguration());
- }
-
- @Override
- 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/server/EhrBaseServer.java b/application/src/main/java/org/ehrbase/application/server/EhrBaseServer.java
new file mode 100644
index 000000000..e5559057a
--- /dev/null
+++ b/application/src/main/java/org/ehrbase/application/server/EhrBaseServer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019-2024 vitasystems GmbH.
+ *
+ * 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.application.server;
+
+import org.ehrbase.configuration.EhrBaseServerConfiguration;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.Import;
+
+@SpringBootApplication(
+ exclude = {
+ ManagementWebSecurityAutoConfiguration.class,
+ R2dbcAutoConfiguration.class,
+ SecurityAutoConfiguration.class
+ })
+@Import({EhrBaseServerConfiguration.class})
+@SuppressWarnings("java:S1118")
+public class EhrBaseServer {
+
+ public static SpringApplication build(String[] args) {
+ return new SpringApplicationBuilder(EhrBaseServer.class)
+ .web(WebApplicationType.SERVLET)
+ .build(args);
+ }
+}
diff --git a/application/src/main/resources/application-cloud.yml b/application/src/main/resources/application-cloud.yml
deleted file mode 100644
index e547842f9..000000000
--- a/application/src/main/resources/application-cloud.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-spring:
- datasource:
- url: jdbc:postgresql://localhost:5432/ehrbase
- username: ehrbase_restricted
- password: ehrbase_restricted
- hikari:
- maximum-pool-size: 50
- max-lifetime: 1800000
- minimum-idle: 10
- flyway:
- schemas: ehr
- user: ehrbase
- password: ehrbase
-
-security:
- authType: NONE
-
-
-server:
- port: 8080
- # Optional custom server nodename
- # nodename: 'local.test.org'
-
- aqlConfig:
- # if true, WHERE clause is using jsquery, false uses SQL only
- useJsQuery: false
- # ignore unbounded item in path starting with one of
- ignoreIterativeNodeList: 'events,activities,content'
- # how many embedded jsonb_array_elements(..) are acceptable? Recommended == 1
- iterationScanDepth: 1
-
- servlet:
- context-path: /ehrbase
diff --git a/application/src/main/resources/application-docker.yml b/application/src/main/resources/application-docker.yml
deleted file mode 100644
index fa2c63db4..000000000
--- a/application/src/main/resources/application-docker.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2019 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
-#
-# 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.
-
-spring:
- datasource:
- url: ${DB_URL}
- username: ${DB_USER}
- password: ${DB_PASS}
- hikari:
- maximum-pool-size: 50
- max-lifetime: 1800000
- minimum-idle: 10
- flyway:
- schemas: ehr
- user: ${DB_USER_ADMIN}
- password: ${DB_PASS_ADMIN}
-security:
- authType: NONE
-
-server:
- port: 8080
- # Optional custom server nodename
- # nodename: 'local.test.org'
- servlet:
- context-path: /ehrbase
-
- aqlConfig:
- # if true, WHERE clause is using jsquery, false uses SQL only
- useJsQuery: false
- # ignore unbounded item in path starting with one of
- ignoreIterativeNodeList: 'events,activities,content'
- # how many embedded jsonb_array_elements(..) are acceptable? Recommended == 1
- iterationScanDepth: 1
-
-admin-api:
- active: false
- allowDeleteAll: false
- context-path: /rest/admin
diff --git a/application/src/main/resources/application-local.yml b/application/src/main/resources/application-local.yml
deleted file mode 100644
index 3711ff92a..000000000
--- a/application/src/main/resources/application-local.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (c) 2019 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
-#
-# 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.
-spring:
- datasource:
- url: jdbc:postgresql://localhost:5432/ehrbase
- username: ehrbase_restricted
- password: ehrbase_restricted
- flyway:
- schemas: ehr
- user: ehrbase
- password: ehrbase
-
- tomcat:
- maxIdle: 10
- max-active: 50
- max-wait: 10000
-
- jpa:
- open-in-view: false
- generate-ddl: false
- properties:
- hibernate:
- format_sql: false
- show_sql: false
- dialect: org.hibernate.dialect.PostgreSQL10Dialect
- default_schema: ehr
- hbm2ddl:
- auto: " "
-server:
- port: 8080
- # Optional custom server nodename
- # nodename: 'local.test.org'
- servlet:
- context-path: /ehrbase
-
- aqlConfig:
- # if true, WHERE clause is using jsquery, false uses SQL only
- useJsQuery: false
- # ignore unbounded item in path starting with one of
- ignoreIterativeNodeList: 'dummy'
- # how many embedded jsonb_array_elements(..) are acceptable? Recommended == 2
- iterationScanDepth: 20
-
-security:
- authType: NONE
-
-#use admin for cleaning up the db during tests
-admin-api:
- active: true
- allowDeleteAll: true
-
-terminology_server:
- tsUrl: 'https://r4.ontoserver.csiro.au/fhir/'
- codePath: '$["expansion"]["contains"][*]["code"]'
- systemPath: '$["expansion"]["contains"][*]["system"]'
- displayPath: '$["expansion"]["contains"][*]["display"]'
\ No newline at end of file
diff --git a/application/src/main/resources/application.yml b/application/src/main/resources/application.yml
deleted file mode 100644
index d482723ff..000000000
--- a/application/src/main/resources/application.yml
+++ /dev/null
@@ -1,221 +0,0 @@
-# Copyright (c) 2019 Vitasystems GmbH and Jake Smolka (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
-#
-# 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.
-#
-# ------------------------------------------------------------------------------
-# General How-to:
-#
-# You can set all config values here or via an corresponding environment variable which is named as the property you
-# want to set. Replace camel case (aB) as all upper case (AB), dashes (-) and low dashes (_) just get ignored adn words
-# will be in one word. Each nesting step of properties will be separated by low dash in environment variable name.
-# E.g. if you want to allow the delete all endpoints in the admin api set an environment variable like this:
-# ADMINAPI_ALLOWDELETEALL=true
-#
-# See https://docs.spring.io/spring-boot/docs/2.5.0/reference/html/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables
-# for official documentation on this feature.
-#
-# Also see the documentation on externalized configuration in general:
-# https://docs.spring.io/spring-boot/docs/2.5.0/reference/html/features.html#features.external-config
-
-spring:
- application:
- name: ehrbase
-
- cache:
- 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
- data:
- redis:
- host: localhost
- port: 6379
-
- security:
- oauth2:
- resourceserver:
- jwt:
- issuer-uri: # http://localhost:8081/auth/realms/ehrbase # Example issuer URI - or set via env var
- profiles:
- active: local
- datasource:
- driver-class-name: org.postgresql.Driver
-
- flyway:
- schemas: ehr
- user: ehrbase
- password: ehrbase
-
- jackson:
- default-property-inclusion: NON_NULL
-
-security:
- authType: BASIC
- authUser: ehrbase-user
- authPassword: SuperSecretPassword
- authAdminUser: ehrbase-admin
- authAdminPassword: EvenMoreSecretPassword
- oauth2UserRole: USER
- oauth2AdminRole: ADMIN
-
-# Attribute Based Access Control
-abac:
- enabled: false
- # Server URL incl. trailing "/"!
- server: http://localhost:3001/rest/v1/policy/execute/name/
- # Definition of the JWT claim which contains the organization ID.
- organizationClaim: 'organization_id'
- # Definition of the JWT claim which contains the patient ID. Falls back to the EHR's subject.
- patientClaim: 'patient_id'
- # Policies need to be named and configured for each resource. Available parameters are
- # - organization
- # - patient
- # - template
- policy:
- ehr:
- name: 'has_consent_patient'
- parameters: 'organization, patient'
- ehrstatus:
- name: 'has_consent_patient'
- parameters: 'organization, patient'
- composition:
- name: 'has_consent_template'
- parameters: 'organization, patient, template'
- #parameters: 'template' # for manual testing, doesn't depend on real claims in JWT
- contribution:
- name: 'has_consent_template'
- parameters: 'organization, patient, template'
- query:
- name: 'has_consent_template'
- parameters: 'organization, patient, template'
-
-httpclient:
-#proxy: 'localhost'
-#proxyPort: 1234
-
-cache:
- init-on-startup: true
- pre-build-queries: true
- pre-build-queries-depth: 4
-
-system:
- allow-template-overwrite: false
-
-openehr-api:
- context-path: /rest/openehr
-admin-api:
- active: false
- allowDeleteAll: false
- context-path: /rest/admin
-
-# Logging Properties
-logging:
- level:
- org.ehcache: info
- org.jooq: info
- org.jooq.Constants: warn
- org.springframework: info
- pattern:
- console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr([%X]){faint} %clr(${PID}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wEx'
-
-server:
- # Optional custom server nodename
- # nodename: 'local.test.org'
-
- aqlConfig:
- # if true, WHERE clause is using jsquery, false uses SQL only
- useJsQuery: false
- # ignore unbounded item in path starting with one of
- ignoreIterativeNodeList: 'activities,content'
- # how many embedded jsonb_array_elements(..) are acceptable? Recommended == 2
- iterationScanDepth: 2
-
- tomcat:
- threads:
- min-spare: 200
- max: 200
-
- # Option to disable strict invariant validation.
- # disable-strict-validation: true
-
-
-# Configuration of actuator for reporting and health endpoints
-management:
- endpoints:
- # Disable all endpoint by default to opt-in enabled endpoints
- enabled-by-default: false
- web:
- base-path: '/management'
- exposure:
- include: 'env, health, info, metrics, prometheus'
- # The access to management endpoints can be controlled
- # ADMIN_ONLY - (default) endpoints are locked behind an authorization and are only available for users with the admin role
- # PRIVATE - endpoints are locked behind an authorization, but are available to any role
- # PUBLIC - endpoints can be accessed without an authorization
- access: ADMIN_ONLY
- # Per endpoint settings
- endpoint:
- # Env endpoint - Shows information on environment of EHRbase
- env:
- # Enable / disable env endpoint
- enabled: false
- # Health endpoint - Shows information on system status
- health:
- # Enable / disable health endpoint
- enabled: false
- # Show components in health endpoint. Can be "never", "when-authorized" or "always"
- show-components: 'when-authorized'
- # Show details in health endpoint. Can be "never", "when-authorized" or "always"
- show-details: 'when-authorized'
- # Show additional information on used systems. See https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-health-indicators for available keys
- datasource:
- # Enable / disable report if datasource connection could be established
- enabled: true
- # Info endpoint - Shows information on the application as build infor, etc.
- info:
- # Enable / disable info endpoint
- enabled: false
- # Metrics endpoint - Shows several metrics on running EHRbase
- metrics:
- # Enable / disable metrics endpoint
- enabled: false
- # Prometheus metric endpoint - Special metrics format to display in microservice observer solutions
- prometheus:
- metrics:
- export:
- enabled: true
-# External Terminology Validation Properties
-validation:
- external-terminology:
- enabled: false
- provider:
- fhir:
- type: FHIR
- url: https://r4.ontoserver.csiro.au/fhir/
-
-# SSL Properties (used by Spring WebClient and Apache HTTP Client)
-client:
- ssl:
- enabled: false
-
-# JavaMelody
-javamelody:
- enabled: false
-
-# plugin configuration
-plugin-manager:
- plugin-dir: ./plugin_dir
- plugin-config-dir: ./plugin_config_dir
- enable: true
- plugin-context-path: /plugin
diff --git a/application/src/main/resources/banner-cli.txt b/application/src/main/resources/banner-cli.txt
new file mode 100644
index 000000000..6a8b00f51
--- /dev/null
+++ b/application/src/main/resources/banner-cli.txt
@@ -0,0 +1 @@
+${AnsiColor.BLUE}EHRbase CLI (Spring Boot ${spring-boot.version} EHRbase ${application.formatted-version} https://ehrbase.org/)${AnsiBackground.DEFAULT}${AnsiColor.DEFAULT}
\ No newline at end of file
diff --git a/application/src/main/resources/static/img/ehrbase.png b/application/src/main/resources/static/img/ehrbase.png
new file mode 100644
index 000000000..684e11c78
Binary files /dev/null and b/application/src/main/resources/static/img/ehrbase.png differ
diff --git a/application/src/main/resources/static/img/favicons/apple-icon-120x120.png b/application/src/main/resources/static/img/favicons/apple-icon-120x120.png
new file mode 100644
index 000000000..d84a25a29
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/apple-icon-120x120.png differ
diff --git a/application/src/main/resources/static/img/favicons/apple-icon-152x152.png b/application/src/main/resources/static/img/favicons/apple-icon-152x152.png
new file mode 100644
index 000000000..7232b8bf5
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/apple-icon-152x152.png differ
diff --git a/application/src/main/resources/static/img/favicons/apple-icon-60x60.png b/application/src/main/resources/static/img/favicons/apple-icon-60x60.png
new file mode 100644
index 000000000..416ad41cc
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/apple-icon-60x60.png differ
diff --git a/application/src/main/resources/static/img/favicons/apple-icon-76x76.png b/application/src/main/resources/static/img/favicons/apple-icon-76x76.png
new file mode 100644
index 000000000..e8ba74a88
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/apple-icon-76x76.png differ
diff --git a/application/src/main/resources/static/img/favicons/favicon-16x16.png b/application/src/main/resources/static/img/favicons/favicon-16x16.png
new file mode 100644
index 000000000..6c5d99153
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/favicon-16x16.png differ
diff --git a/application/src/main/resources/static/img/favicons/favicon-32x32.png b/application/src/main/resources/static/img/favicons/favicon-32x32.png
new file mode 100644
index 000000000..0a49b0e9a
Binary files /dev/null and b/application/src/main/resources/static/img/favicons/favicon-32x32.png differ
diff --git a/application/src/main/resources/static/index.html b/application/src/main/resources/static/index.html
new file mode 100644
index 000000000..2c11459ef
--- /dev/null
+++ b/application/src/main/resources/static/index.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ EHRbase Open Source
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/src/test/java/org/ehrbase/application/abac/AbacIntegrationTest.java b/application/src/test/java/org/ehrbase/application/abac/AbacIntegrationTest.java
deleted file mode 100644
index 443c28fb4..000000000
--- a/application/src/test/java/org/ehrbase/application/abac/AbacIntegrationTest.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2021 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.application.abac;
-
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.anyMap;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import com.jayway.jsonpath.JsonPath;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import org.apache.commons.io.IOUtils;
-import org.ehrbase.openehr.sdk.test_data.composition.CompositionTestDataCanonicalJson;
-import org.ehrbase.openehr.sdk.test_data.operationaltemplate.OperationalTemplateTestData;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.info.BuildProperties;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
-import org.springframework.util.ResourceUtils;
-
-@SpringBootTest
-@ActiveProfiles({"local", "test"})
-// @EnabledIfEnvironmentVariable(named = "EHRBASE_ABAC_IT_TEST", matches = "true")
-@AutoConfigureMockMvc
-@Disabled("see https://jira.vitagroup.ag/browse/CDR-368")
-class AbacIntegrationTest {
-
- private static final String ORGA_ID = "f47bfc11-ec8d-412e-aebf-c6953cc23e7d";
-
- @MockBean
- private AbacConfig.AbacCheck abacCheck;
-
- @MockBean
- private BuildProperties buildProperties;
-
- @Autowired
- private MockMvc mockMvc;
-
- @Autowired
- private AbacConfig abacConfig;
-
- @Test
- /*
- * This test requires a new and clean DB state to run successfully.
- */
-
- void testAbacIntegrationTest() throws Exception {
- /*
- ----------------- TEST CONTEXT SETUP -----------------
- */
- // Configure the mock bean of the ABAC server, so we can test with this external service.
- given(this.abacCheck.execute(anyString(), anyMap())).willReturn(true);
-
- Map attributes = new HashMap<>();
- attributes.put("sub", "my-id");
- attributes.put("email", "test@test.org");
-
- // Counters to keep track of number of requests to mock ABAC server bean
- int hasConsentPatientCount = 0;
- int hasConsentTemplateCount = 0;
-
- String externalSubjectRef = UUID.randomUUID().toString();
-
- String ehrStatus = String.format(
- IOUtils.toString(ResourceUtils.getURL("classpath:ehr_status.json"), StandardCharsets.UTF_8),
- externalSubjectRef);
-
- MvcResult result = mockMvc.perform(post("/rest/openehr/v1/ehr")
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE)
- .contentType(MediaType.APPLICATION_JSON)
- .content(ehrStatus))
- .andExpectAll(status().isCreated(), jsonPath("$.ehr_id.value").exists())
- .andReturn();
-
- String ehrId = JsonPath.read(result.getResponse().getContentAsString(), "$.ehr_id.value");
- Assertions.assertNotNull(ehrId);
- assertNotEquals("", ehrId);
-
- InputStream stream = OperationalTemplateTestData.CORONA_ANAMNESE.getStream();
- Assertions.assertNotNull(stream);
- String streamString = IOUtils.toString(stream, StandardCharsets.UTF_8);
-
- mockMvc.perform(post("/rest/openehr/v1/definition/template/adl1.4/")
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content(streamString)
- .contentType(MediaType.APPLICATION_XML)
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_XML))
- .andExpect(r -> assertTrue(
- // created 201 or conflict 409 are okay
- r.getResponse().getStatus() == HttpStatus.CREATED.value()
- || r.getResponse().getStatus() == HttpStatus.CONFLICT.value()));
-
- stream = CompositionTestDataCanonicalJson.CORONA.getStream();
- Assertions.assertNotNull(stream);
- streamString = IOUtils.toString(stream, StandardCharsets.UTF_8);
-
- /*
- ----------------- TEST CASES -----------------
- */
-
- /*
- GET EHR
- */
- mockMvc.perform(get(String.format("/rest/openehr/v1/ehr/%s", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentPatientCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_patient", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- }
- });
- /*
- GET EHR_STATUS
- */
- result = mockMvc.perform(get(String.format("/rest/openehr/v1/ehr/%s/ehr_status", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk())
- .andReturn();
-
- verify(abacCheck, times(++hasConsentPatientCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_patient", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- }
- });
-
- String ehrStatusVersionUid = JsonPath.read(result.getResponse().getContentAsString(), "$.uid.value");
- Assertions.assertNotNull(ehrStatusVersionUid);
- assertNotEquals("", ehrStatusVersionUid);
-
- /*
- PUT EHR_STATUS
- */
- mockMvc.perform(put(String.format("/rest/openehr/v1/ehr/%s/ehr_status", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("If-Match", ehrStatusVersionUid)
- .header("PREFER", "return=representation")
- .content(ehrStatus)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentPatientCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_patient", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- }
- });
- /*
- GET VERSIONED_EHR_STATUS
- */
- mockMvc.perform(get(String.format("/rest/openehr/v1/ehr/%s/versioned_ehr_status/version", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentPatientCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_patient", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- }
- });
- /*
- POST COMPOSITION
- */
- result = mockMvc.perform(post(String.format("/rest/openehr/v1/ehr/%s/composition", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content(streamString)
- .contentType(MediaType.APPLICATION_JSON)
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isCreated())
- .andReturn();
-
- String compositionVersionUid = JsonPath.read(result.getResponse().getContentAsString(), "$.uid.value");
- Assertions.assertNotNull(compositionVersionUid);
- assertNotEquals("", compositionVersionUid);
- assertTrue(compositionVersionUid.contains("::"));
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
- /*
- GET VERSIONED_COMPOSITION
- */
- mockMvc.perform(get(String.format(
- "/rest/openehr/v1/ehr/%s/versioned_composition/%s/version/%s",
- ehrId, compositionVersionUid.split("::")[0], compositionVersionUid))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- /*
- GET COMPOSITION (here of deleted composition)
- */
- mockMvc.perform(get(String.format("/rest/openehr/v1/ehr/%s/composition/%s", ehrId, compositionVersionUid))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- // Failing: Does not call ABAC Server. Deleted composition does not need to call ABAC server?
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- /*
- DELETE COMPOSITION
- */
- mockMvc.perform(delete(String.format("/rest/openehr/v1/ehr/%s/composition/%s", ehrId, compositionVersionUid))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isNoContent());
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- String contribution = String.format(
- IOUtils.toString(ResourceUtils.getURL("classpath:contribution.json"), StandardCharsets.UTF_8),
- streamString);
- /*
- POST CONTRIBUTION
- */
- mockMvc.perform(post(String.format("/rest/openehr/v1/ehr/%s/contribution", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content(contribution)
- .contentType(MediaType.APPLICATION_JSON)
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isCreated())
- .andReturn();
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- /*
- POST QUERY
- */
- mockMvc.perform(post("/rest/openehr/v1/query/aql")
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content("{\n"
- + " \"q\": \"select e/ehr_id/value, c/uid/value, c/archetype_details/template_id/value, c/feeder_audit from EHR e CONTAINS composition c\"\n"
- + "}")
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- /*
- GET QUERY
- */
- String pathQuery =
- "select e/ehr_id/value, c/uid/value, c/archetype_details/template_id/value, c/feeder_audit from EHR e CONTAINS composition c";
-
- mockMvc.perform(get(String.format("/rest/openehr/v1/query/aql?q=%s", pathQuery))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID))))
- .andExpect(status().isOk());
-
- verify(abacCheck, times(++hasConsentTemplateCount))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "Corona_Anamnese");
- }
- });
-
- /*
- GET QUERY WITH MULTIPLE EHRs AND TEMPLATES (incl. posting those)
- */
- // post another template
- stream = OperationalTemplateTestData.MINIMAL_EVALUATION.getStream();
- Assertions.assertNotNull(stream);
- streamString = IOUtils.toString(stream, StandardCharsets.UTF_8);
-
- mockMvc.perform(post("/rest/openehr/v1/definition/template/adl1.4/")
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content(streamString)
- .contentType(MediaType.APPLICATION_XML)
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_XML))
- .andExpect(r -> assertTrue(
- // created 201 or conflict 409 are okay
- r.getResponse().getStatus() == HttpStatus.CREATED.value()
- || r.getResponse().getStatus() == HttpStatus.CONFLICT.value()));
-
- streamString = IOUtils.toString(ResourceUtils.getURL("classpath:composition.json"), StandardCharsets.UTF_8);
-
- mockMvc.perform(post(String.format("/rest/openehr/v1/ehr/%s/composition", ehrId))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID)))
- .content(streamString)
- .contentType(MediaType.APPLICATION_JSON)
- .header("PREFER", "return=representation")
- .accept(MediaType.APPLICATION_JSON_VALUE))
- .andExpect(status().isCreated())
- .andReturn();
-
- verify(abacCheck)
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "minimal_evaluation.en.v1");
- }
- });
-
- mockMvc.perform(get(String.format("/rest/openehr/v1/query/aql?q=%s", pathQuery))
- .with(jwt().authorities(new OAuth2UserAuthority("ROLE_USER", attributes))
- .jwt(token -> token.claim(abacConfig.getPatientClaim(), externalSubjectRef)
- .claim(abacConfig.getOrganizationClaim(), ORGA_ID))))
- .andExpect(status().isOk());
-
- // verify(abacCheck, times(++hasConsentTemplateCount)).execute(
- // "http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {{
- // put("patient", externalSubjectRef);
- // put("organization", ORGA_ID);
- // put("template", "Corona_Anamnese");
- // }});
-
- verify(abacCheck, times(3))
- .execute("http://localhost:3001/rest/v1/policy/execute/name/has_consent_template", new HashMap<>() {
- {
- put("patient", externalSubjectRef);
- put("organization", ORGA_ID);
- put("template", "minimal_evaluation.en.v1");
- }
- });
- }
-}
diff --git a/application/src/test/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRootTest.java b/application/src/test/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRootTest.java
deleted file mode 100644
index df0d11bd7..000000000
--- a/application/src/test/java/org/ehrbase/application/abac/CustomMethodSecurityExpressionRootTest.java
+++ /dev/null
@@ -1,89 +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.application.abac;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import org.ehrbase.api.service.EhrService;
-import org.ehrbase.aql.compiler.AuditVariables;
-import org.ehrbase.rest.BaseController;
-import org.junit.Assert;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.jwt.Jwt;
-import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-
-class CustomMethodSecurityExpressionRootTest {
-
- @Test
- void patientHandling() {
- String PAT_TOKEN = "myToken";
- Map reqMap = new HashMap<>();
- Assert.assertTrue(theTest(PAT_TOKEN, List.of(PAT_TOKEN, PAT_TOKEN), reqMap));
- Assert.assertTrue(reqMap.containsKey(CustomMethodSecurityExpressionRoot.PATIENT));
- }
-
- @Test
- void patientHandlingFail() {
- String PAT_TOKEN = "myToken";
- Assert.assertFalse(theTest("No_PAT_TOKEN", List.of(PAT_TOKEN, PAT_TOKEN), null));
- }
-
- @SuppressWarnings({"unchecked", "serial"})
- private boolean theTest(String theSubject, List subjectExtRef, Map reqMap) {
- final String CLAIM = "myClaim";
-
- AbacConfig cfg = anyAbacConfig(c -> c.setPatientClaim(CLAIM));
-
- var token = Mockito.mock(JwtAuthenticationToken.class);
- Jwt jwt = Jwt.withTokenValue("token")
- .header("alg", "none")
- .claim(CLAIM, theSubject)
- .build();
- Mockito.when(((Jwt) token.getCredentials())).thenReturn(jwt);
-
- EhrService service = Mockito.mock(EhrService.class);
- Mockito.when(service.getSubjectExtRefs(Mockito.isA(Collection.class))).thenReturn(subjectExtRef);
-
- CustomMethodSecurityExpressionRoot expr =
- new CustomMethodSecurityExpressionRoot(Mockito.mock(Authentication.class), cfg, null);
- expr.setEhrService(service);
-
- Map