diff --git a/pom.xml b/pom.xml
index b5381d6..455ff75 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,7 +38,7 @@
1.68
4.9.1
4.23.0
- 0.5.0
+ 1.1.1
3.1.2
3.6.1.1688
@@ -134,7 +134,11 @@
-
+
+ eu.europa.ec.dgc
+ dgc-lib
+ ${dgc.lib.version}
+
org.springframework.boot
spring-boot-starter
@@ -265,6 +269,11 @@
com.sap.hcp.cf.logging
cf-java-logging-support-logback
+
+ com.nimbusds
+ nimbus-jose-jwt
+ 9.9.2
+
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/DgcBusinessRuleServiceApplication.java b/src/main/java/eu/europa/ec/dgc/businessrule/DgcBusinessRuleServiceApplication.java
index a2e4103..3f32e62 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/DgcBusinessRuleServiceApplication.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/DgcBusinessRuleServiceApplication.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/DgcConfigProperties.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/DgcConfigProperties.java
index 9a8b12e..962da8a 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/config/DgcConfigProperties.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/DgcConfigProperties.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
@@ -29,12 +29,18 @@
@ConfigurationProperties("dgc")
public class DgcConfigProperties {
- private final CertificatesDownloader certificatesDownloader = new CertificatesDownloader();
+ private final GatewayDownload businessRulesDownload = new GatewayDownload();
+
+ private final GatewayDownload valueSetsDownload = new GatewayDownload();
+
+ private final GatewayDownload countryListDownload = new GatewayDownload();
@Getter
@Setter
- public static class CertificatesDownloader {
+ public static class GatewayDownload {
private Integer timeInterval;
private Integer lockLimit;
}
+
+
}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/ErrorHandler.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/ErrorHandler.java
index f3e0e78..0fd7dab 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/config/ErrorHandler.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/ErrorHandler.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/OpenApiConfig.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/OpenApiConfig.java
index 2252e59..98fe27e 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/config/OpenApiConfig.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/OpenApiConfig.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.config;
import io.swagger.v3.oas.models.OpenAPI;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/SchedulerConfig.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/SchedulerConfig.java
index c1ddb8f..c475149 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/config/SchedulerConfig.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/SchedulerConfig.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/ShedLockConfig.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/ShedLockConfig.java
index 765295f..8e7415f 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/config/ShedLockConfig.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/ShedLockConfig.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/config/btp/SapCredentialStoreCfEnvProcessor.java b/src/main/java/eu/europa/ec/dgc/businessrule/config/btp/SapCredentialStoreCfEnvProcessor.java
new file mode 100644
index 0000000..d4a5231
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/config/btp/SapCredentialStoreCfEnvProcessor.java
@@ -0,0 +1,68 @@
+package eu.europa.ec.dgc.businessrule.config.btp;
+
+import io.pivotal.cfenv.core.CfCredentials;
+import io.pivotal.cfenv.core.CfService;
+import io.pivotal.cfenv.spring.boot.CfEnvProcessor;
+import io.pivotal.cfenv.spring.boot.CfEnvProcessorProperties;
+import java.util.Map;
+
+/**
+ * Custom implementation of {@link CfEnvProcessor} for reading the SAP credential store parameters from the
+ * VCAP_SERVICES
environment variable and making them available as properties in the spring context.
+ *
+ * The following properties are available in the context after the processor is done:
+ *
+ *
+ * - sap.btp.credstore.url
+ * - sap.btp.credstore.password
+ * - sap.btp.credstore.username
+ * - sap.btp.credstore.clientPrivateKey
+ * - sap.btp.credstore.serverPublicKey
+ *
+ *
+ *
+ * @see CfEnvProcessor
+ */
+public class SapCredentialStoreCfEnvProcessor implements CfEnvProcessor {
+
+ private static final String CRED_STORE_SCHEME = "credstore";
+ private static final String CRED_STORE_PROPERTY_PREFIX = "sap.btp.credstore";
+
+ @Override
+ public boolean accept(CfService service) {
+ return service.existsByTagIgnoreCase(CRED_STORE_SCHEME, "securestore", "keystore", "credentials")
+ || service.existsByLabelStartsWith(CRED_STORE_SCHEME)
+ || service.existsByUriSchemeStartsWith(CRED_STORE_SCHEME);
+ }
+
+ @Override
+ public void process(CfCredentials cfCredentials, Map properties) {
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".url", cfCredentials.getString("url"));
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".password", cfCredentials.getString("password"));
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".username", cfCredentials.getString("username"));
+
+ @SuppressWarnings("unchecked")
+ Map encryption = (Map) cfCredentials.getMap().get("encryption");
+ if (encryption == null) {
+ // Encryption features have been disabled on this BTP instance.
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".clientPrivateKey", "encryption-disabled");
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".serverPublicKey", "encryption-disabled");
+ return;
+ }
+
+ String clientPrivateKey = encryption.get("client_private_key").toString();
+ String serverPublicKey = encryption.get("server_public_key").toString();
+
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".clientPrivateKey", clientPrivateKey);
+ properties.put(CRED_STORE_PROPERTY_PREFIX + ".serverPublicKey", serverPublicKey);
+ }
+
+ @Override
+ public CfEnvProcessorProperties getProperties() {
+ return CfEnvProcessorProperties.builder()
+ .propertyPrefixes(CRED_STORE_PROPERTY_PREFIX)
+ .serviceName("CredentialStore")
+ .build();
+ }
+
+}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/entity/BusinessRuleEntity.java b/src/main/java/eu/europa/ec/dgc/businessrule/entity/BusinessRuleEntity.java
index bf931d2..b6cc511 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/entity/BusinessRuleEntity.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/entity/BusinessRuleEntity.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.entity;
import javax.persistence.Column;
@@ -31,7 +51,7 @@ public class BusinessRuleEntity {
private String identifier;
@Column(name = "version", nullable = false)
- String version = "1.0.0";
+ String version;
@Column(name = "country_code", nullable = false, length = 2)
String country;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/entity/CountryListEntity.java b/src/main/java/eu/europa/ec/dgc/businessrule/entity/CountryListEntity.java
index d4b3b97..62e1c3a 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/entity/CountryListEntity.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/entity/CountryListEntity.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.entity;
import javax.persistence.Column;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/entity/ShedlockEntity.java b/src/main/java/eu/europa/ec/dgc/businessrule/entity/ShedlockEntity.java
index 926548f..750af02 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/entity/ShedlockEntity.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/entity/ShedlockEntity.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/entity/ValueSetEntity.java b/src/main/java/eu/europa/ec/dgc/businessrule/entity/ValueSetEntity.java
index c137094..409f727 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/entity/ValueSetEntity.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/entity/ValueSetEntity.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.entity;
import javax.persistence.Column;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/exception/DgcaBusinessRulesResponseException.java b/src/main/java/eu/europa/ec/dgc/businessrule/exception/DgcaBusinessRulesResponseException.java
index 05e1242..af583aa 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/exception/DgcaBusinessRulesResponseException.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/exception/DgcaBusinessRulesResponseException.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.exception;
import lombok.Getter;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/model/BusinessRuleItem.java b/src/main/java/eu/europa/ec/dgc/businessrule/model/BusinessRuleItem.java
new file mode 100644
index 0000000..4ba9f75
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/model/BusinessRuleItem.java
@@ -0,0 +1,19 @@
+package eu.europa.ec.dgc.businessrule.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class BusinessRuleItem {
+
+ private String hash;
+
+ private String identifier;
+
+ private String version;
+
+ private String country;
+
+ private String rawData;
+}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/model/ValueSetItem.java b/src/main/java/eu/europa/ec/dgc/businessrule/model/ValueSetItem.java
new file mode 100644
index 0000000..a665c3a
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/model/ValueSetItem.java
@@ -0,0 +1,15 @@
+package eu.europa.ec.dgc.businessrule.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ValueSetItem {
+
+ private String hash;
+
+ private String id;
+
+ private String rawData;
+}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/repository/BusinessRuleRepository.java b/src/main/java/eu/europa/ec/dgc/businessrule/repository/BusinessRuleRepository.java
index f39828d..98bbd05 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/repository/BusinessRuleRepository.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/repository/BusinessRuleRepository.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.repository;
import eu.europa.ec.dgc.businessrule.entity.BusinessRuleEntity;
@@ -14,4 +34,6 @@ public interface BusinessRuleRepository extends JpaRepository findAllByCountryOrderByIdentifierAsc(String country);
BusinessRuleEntity findOneByCountryAndHash(String country, String hash);
+
+ void deleteByHashNotIn(List hashes);
}
\ No newline at end of file
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/repository/CountryListRepository.java b/src/main/java/eu/europa/ec/dgc/businessrule/repository/CountryListRepository.java
index 9b3d14e..bcaba7e 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/repository/CountryListRepository.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/repository/CountryListRepository.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.repository;
import eu.europa.ec.dgc.businessrule.entity.CountryListEntity;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/repository/ValueSetRepository.java b/src/main/java/eu/europa/ec/dgc/businessrule/repository/ValueSetRepository.java
index 65e9f3b..0c358e2 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/repository/ValueSetRepository.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/repository/ValueSetRepository.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.repository;
import eu.europa.ec.dgc.businessrule.entity.ValueSetEntity;
@@ -10,4 +30,6 @@ public interface ValueSetRepository extends JpaRepository findAllByOrderByIdAsc();
ValueSetEntity findOneByHash(String hash);
+
+ void deleteByHashNotIn(List hashes);
}
\ No newline at end of file
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/BusinessRuleController.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/BusinessRuleController.java
index 254570f..5d9789d 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/BusinessRuleController.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/BusinessRuleController.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
@@ -22,9 +22,11 @@
import eu.europa.ec.dgc.businessrule.entity.BusinessRuleEntity;
import eu.europa.ec.dgc.businessrule.exception.DgcaBusinessRulesResponseException;
+import eu.europa.ec.dgc.businessrule.model.BusinessRuleItem;
import eu.europa.ec.dgc.businessrule.restapi.dto.BusinessRuleListItemDto;
import eu.europa.ec.dgc.businessrule.restapi.dto.ProblemReportDto;
import eu.europa.ec.dgc.businessrule.service.BusinessRuleService;
+import eu.europa.ec.dgc.businessrule.utils.BusinessRulesUtils;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -35,6 +37,7 @@
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Locale;
import javax.validation.Valid;
@@ -58,10 +61,14 @@
@RequiredArgsConstructor
public class BusinessRuleController {
- private final BusinessRuleService businessRuleService;
+ private static final String API_VERSION_HEADER = "X-VERSION";
private static final String X_SIGNATURE_HEADER = "X-SIGNATURE";
+ private final BusinessRuleService businessRuleService;
+
+ private final BusinessRulesUtils businessRulesUtils;
+
/**
* Http Method for getting the business rules list.
*/
@@ -84,17 +91,14 @@ public class BusinessRuleController {
@ApiResponse(
responseCode = "200",
description = "Returns a list of all business rule ids country codes and hash values.",
- headers = {
- @Header(
- name = "X-SIGNATURE",
- description = "ECDSA signature of the returned value, if configured.")
- },
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = BusinessRuleListItemDto.class))))
}
)
- public ResponseEntity> getRules() {
+ public ResponseEntity> getRules(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion
+ ) {
return ResponseEntity.ok(businessRuleService.getBusinessRulesList());
}
@@ -123,11 +127,6 @@ public ResponseEntity> getRules() {
@ApiResponse(
responseCode = "200",
description = "Returns a list of all business rule ids country codes and hash values for a country.",
- headers = {
- @Header(
- name = "X-SIGNATURE",
- description = "ECDSA signature of the returned value, if configured.")
- },
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = BusinessRuleListItemDto.class)))),
@@ -140,6 +139,7 @@ public ResponseEntity> getRules() {
}
)
public ResponseEntity> getRulesForCountry(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion,
@Valid @PathVariable("country") String country
) {
validateCountryParameter(country);
@@ -220,7 +220,8 @@ public ResponseEntity> getRulesForCountry(
mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ProblemReportDto.class)))
})
- public ResponseEntity getRuleByHash(
+ public ResponseEntity getRuleByCountryAndHash(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion,
@Valid @PathVariable("country") String country,
@Valid @PathVariable("hash") String hash
) {
@@ -247,15 +248,31 @@ public ResponseEntity getRuleByHash(
public ResponseEntity createRule(
@RequestHeader(value = "X_COUNTRY") String country,
@RequestHeader(value = "X_ID") String id,
+ @RequestHeader(value = "X_VER") String version,
@RequestBody String ruleData) {
+ String hash;
validateCountryParameter(country);
if (id == null || id.isBlank()) {
throw new DgcaBusinessRulesResponseException(HttpStatus.BAD_REQUEST, "0x003", "Possible reasons: "
+ "The id of the rule is not set.", id,"");
}
- businessRuleService.saveBusinessRule(id, country.toUpperCase(Locale.ROOT), ruleData);
+
+ try {
+ hash = businessRulesUtils.calculateHash(ruleData);
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Calculation of hash failed:", e);
+ throw new DgcaBusinessRulesResponseException(HttpStatus.INTERNAL_SERVER_ERROR, "0x500",
+ "Internal Server Error","","");
+ }
+ BusinessRuleItem bri = new BusinessRuleItem();
+ bri.setHash(hash);
+ bri.setIdentifier(id);
+ bri. setCountry(country);
+ bri.setVersion(version);
+ bri.setRawData(ruleData);
+ businessRuleService.saveBusinessRule(bri);
return ResponseEntity.ok("Upload: OK");
}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/CountryListController.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/CountryListController.java
index a654c54..0361dc1 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/CountryListController.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/CountryListController.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
@@ -38,6 +38,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -48,6 +49,8 @@
@RequiredArgsConstructor
public class CountryListController {
+ private static final String API_VERSION_HEADER = "X-VERSION";
+
private final CountryListService countryListService;
/**
@@ -70,11 +73,6 @@ public class CountryListController {
@ApiResponse(
responseCode = "200",
description = "Returns a JSON list, with all onboarded member states as country code.",
- headers = {
- @Header(
- name = "X-SIGNATURE",
- description = "ECDSA signature of the returned value, if configured.")
- },
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = String.class)),
@@ -86,7 +84,9 @@ public class CountryListController {
}))
}
)
- public ResponseEntity getCountryList() {
+ public ResponseEntity getCountryList(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion
+ ) {
return ResponseEntity.ok(countryListService.getCountryList());
}
@@ -95,7 +95,7 @@ public ResponseEntity getCountryList() {
*/
@PostMapping(path = "", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@Hidden
- public ResponseEntity createRule(
+ public ResponseEntity createCountryList(
@RequestBody String countryListData) {
countryListService.saveCountryList(countryListData);
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/ValueSetController.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/ValueSetController.java
index 3f7d585..8d0f962 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/ValueSetController.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/controller/ValueSetController.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
@@ -53,6 +53,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -62,6 +63,8 @@
@RequiredArgsConstructor
public class ValueSetController {
+ private static final String API_VERSION_HEADER = "X-VERSION";
+
private final BusinessRulesUtils businessRulesUtils;
private final ValueSetService valueSetService;
@@ -89,11 +92,6 @@ public class ValueSetController {
@ApiResponse(
responseCode = "200",
description = "Returns a list of all value set ids and there hash values.",
- headers = {
- @Header(
- name = "X-SIGNATURE",
- description = "ECDSA signature of the returned value, if configured.")
- },
content = @Content(
mediaType = MediaType.APPLICATION_JSON_VALUE,
array = @ArraySchema(schema = @Schema(implementation = ValueSetListItemDto.class)),
@@ -135,8 +133,9 @@ public class ValueSetController {
}))
}
)
- public ResponseEntity> getValueSetList() {
-
+ public ResponseEntity> getValueSetList(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion
+ ) {
return ResponseEntity.ok(valueSetService.getValueSetsList());
}
@@ -194,6 +193,7 @@ public ResponseEntity> getValueSetList() {
))
})
public ResponseEntity getValueSet(
+ @RequestHeader(value = API_VERSION_HEADER, required = false) String apiVersion,
@Valid @PathVariable("hash") String hash
) {
ValueSetEntity vse = valueSetService.getValueSetByHash(hash);
@@ -226,12 +226,21 @@ public ResponseEntity loadDummyData() {
private void loadValuesetFile(String filename, String valueSetName) {
Resource resource = new ClassPathResource(filename);
+ String rawData;
+ String hash;
try {
- valueSetService.saveValueSet(valueSetName,
- IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8));
+ rawData = IOUtils.toString(resource.getInputStream(), StandardCharsets.UTF_8);
+ hash = businessRulesUtils.calculateHash(rawData);
+
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Calculation of hash failed:", e);
+ return;
} catch (IOException e) {
log.error("Could not read file: " + valueSetName);
+ return;
}
+
+ valueSetService.saveValueSet(hash, valueSetName, rawData);
}
}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/BusinessRuleListItemDto.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/BusinessRuleListItemDto.java
index 6ab6f2c..6d38830 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/BusinessRuleListItemDto.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/BusinessRuleListItemDto.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.restapi.dto;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ProblemReportDto.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ProblemReportDto.java
index 836c219..b0db429 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ProblemReportDto.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ProblemReportDto.java
@@ -1,6 +1,6 @@
/*-
* ---license-start
- * eu-digital-green-certificates / dgca-verifier-service
+ * eu-digital-green-certificates / dgca-businessrule-service
* ---
* Copyright (C) 2021 T-Systems International GmbH and all other contributors
* ---
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ValueSetListItemDto.java b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ValueSetListItemDto.java
index 705356a..e9cc7d5 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ValueSetListItemDto.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/restapi/dto/ValueSetListItemDto.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.restapi.dto;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/service/BusinessRuleService.java b/src/main/java/eu/europa/ec/dgc/businessrule/service/BusinessRuleService.java
index 23fdf5d..9319c82 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/service/BusinessRuleService.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/service/BusinessRuleService.java
@@ -1,12 +1,36 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.service;
import eu.europa.ec.dgc.businessrule.entity.BusinessRuleEntity;
+import eu.europa.ec.dgc.businessrule.model.BusinessRuleItem;
import eu.europa.ec.dgc.businessrule.repository.BusinessRuleRepository;
import eu.europa.ec.dgc.businessrule.restapi.dto.BusinessRuleListItemDto;
import eu.europa.ec.dgc.businessrule.utils.BusinessRulesUtils;
+import eu.europa.ec.dgc.gateway.connector.model.ValidationRule;
import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -18,35 +42,13 @@
@Service
public class BusinessRuleService {
- private final BusinessRulesUtils businessRulesUtils;
-
private final BusinessRuleRepository businessRuleRepository;
- /**
- * Saves a Business rule.
- *
- */
- @Transactional
- public void saveBusinessRule(String ruleId, String ruleCountry, String ruleData) {
- String hash;
- try {
- hash = businessRulesUtils.calculateHash(ruleData);
- } catch (NoSuchAlgorithmException e) {
- log.error("Calculation of hash failed:", e);
- return;
- }
-
- BusinessRuleEntity bre = new BusinessRuleEntity();
- bre.setIdentifier(ruleId);
- bre.setCountry(ruleCountry);
- bre.setRawData(ruleData.toUpperCase(Locale.ROOT));
- bre.setHash(hash);
-
- businessRuleRepository.save(bre);
- }
+ private final BusinessRulesUtils businessRulesUtils;
/**
* Gets list of all business rules ids and hashes.
+ *
*/
public List getBusinessRulesList() {
@@ -64,7 +66,6 @@ public List getBusinessRulesListForCountry(String count
return rulesItems;
}
-
/**f
* Gets a business rule by hash.
*/
@@ -73,4 +74,77 @@ public BusinessRuleEntity getBusinessRuleByCountryAndHash(String country, String
return businessRuleRepository.findOneByCountryAndHash(country, hash);
}
+
+ /**
+ * Updates the list of business rules.
+ * @param businessRules list of actual value sets
+ */
+ @Transactional
+ public void updateBusinesRules(List businessRules) {
+ List ruleHashes =
+ businessRules.stream().map(BusinessRuleItem::getHash).collect(Collectors.toList());
+ List alreadyStoredRules = getBusinessRulesHashList();
+
+ if (ruleHashes.isEmpty()) {
+ businessRuleRepository.deleteAll();
+ } else {
+ businessRuleRepository.deleteByHashNotIn(ruleHashes);
+ }
+
+ for (BusinessRuleItem rule : businessRules) {
+ if (!alreadyStoredRules.contains(rule.getHash())) {
+ saveBusinessRule(rule);
+ }
+ }
+
+ }
+
+ /**
+ * Saves a Business rule.
+ * @param rule The rule to be saved.
+ */
+ @Transactional
+ public void saveBusinessRule(BusinessRuleItem rule) {
+ BusinessRuleEntity bre = new BusinessRuleEntity();
+ bre.setHash(rule.getHash());
+ bre.setIdentifier(rule.getIdentifier());
+ bre.setCountry(rule.getCountry().toUpperCase(Locale.ROOT));
+ bre.setVersion(rule.getVersion());
+ bre.setRawData(rule.getRawData());
+
+ businessRuleRepository.save(bre);
+ }
+
+ /**
+ * Creates a List of business rule items from a list of validation rules.
+ * @param validationRules the list containing the validation rules.
+ * @return List of BusinessRuleItems.
+ */
+ public List createBusinessRuleItemList(List validationRules)
+ throws NoSuchAlgorithmException {
+ List businessRuleItems = new ArrayList<>();
+
+ for (ValidationRule validationRule: validationRules) {
+ BusinessRuleItem businessRuleItem = new BusinessRuleItem();
+
+ businessRuleItem.setHash(businessRulesUtils.calculateHash(validationRule.getRawJson()));
+ businessRuleItem.setIdentifier(validationRule.getIdentifier());
+ businessRuleItem.setCountry(validationRule.getCountry());
+ businessRuleItem.setVersion(validationRule.getVersion());
+ businessRuleItem.setRawData(validationRule.getRawJson());
+
+ businessRuleItems.add(businessRuleItem);
+ }
+
+ return businessRuleItems;
+ }
+
+
+ /**
+ * Gets a list of hash values of all stored business rules.
+ * @return List of hash values
+ */
+ private List getBusinessRulesHashList() {
+ return getBusinessRulesList().stream().map(BusinessRuleListItemDto::getHash).collect(Collectors.toList());
+ }
}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/service/CountryListService.java b/src/main/java/eu/europa/ec/dgc/businessrule/service/CountryListService.java
index 94d3ed6..2b99a83 100644
--- a/src/main/java/eu/europa/ec/dgc/businessrule/service/CountryListService.java
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/service/CountryListService.java
@@ -1,3 +1,23 @@
+/*-
+ * ---license-start
+ * eu-digital-green-certificates / dgca-businessrule-service
+ * ---
+ * Copyright (C) 2021 T-Systems International GmbH and all other contributors
+ * ---
+ * 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.
+ * ---license-end
+ */
+
package eu.europa.ec.dgc.businessrule.service;
import eu.europa.ec.dgc.businessrule.entity.CountryListEntity;
@@ -17,7 +37,8 @@ public class CountryListService {
private final CountryListRepository countryListRepository;
/**
- * returns the country list.
+ * Gets the actual country list.
+ * @return the country list.
*/
@Transactional
public String getCountryList() {
@@ -29,8 +50,23 @@ public String getCountryList() {
}
}
+
/**
- * Saves a country list by replacing an old one.
+ * Updates a country List, if it is different from the old one.
+ * @param newCountryListData new country list data
+ */
+ @Transactional
+ public void updateCountryList(String newCountryListData) {
+ String oldList = getCountryList();
+ if (!newCountryListData.equals(oldList)) {
+ saveCountryList(newCountryListData);
+ }
+ }
+
+
+ /**
+ * Saves a country list by replacing an old one.
+ * @param listData the country list to be saved.
*/
@Transactional
@@ -40,4 +76,6 @@ public void saveCountryList(String listData) {
}
+
+
}
diff --git a/src/main/java/eu/europa/ec/dgc/businessrule/service/GatewayDataDownloadBtpServiceImpl.java b/src/main/java/eu/europa/ec/dgc/businessrule/service/GatewayDataDownloadBtpServiceImpl.java
new file mode 100644
index 0000000..240e7b2
--- /dev/null
+++ b/src/main/java/eu/europa/ec/dgc/businessrule/service/GatewayDataDownloadBtpServiceImpl.java
@@ -0,0 +1,364 @@
+package eu.europa.ec.dgc.businessrule.service;
+
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.FieldNamingStrategy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
+import com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor;
+import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
+import eu.europa.ec.dgc.businessrule.model.BusinessRuleItem;
+import eu.europa.ec.dgc.businessrule.model.ValueSetItem;
+import eu.europa.ec.dgc.businessrule.utils.btp.JsonNodeDeserializer;
+import eu.europa.ec.dgc.gateway.connector.dto.TrustListItemDto;
+import eu.europa.ec.dgc.gateway.connector.dto.ValidationRuleDto;
+import eu.europa.ec.dgc.gateway.connector.model.ValidationRule;
+import eu.europa.ec.dgc.signing.SignedStringMessageParser;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.util.EntityUtils;
+import org.bouncycastle.cert.X509CertificateHolder;
+import org.slf4j.MDC;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@RequiredArgsConstructor
+@Component
+@Profile("btp")
+public class GatewayDataDownloadBtpServiceImpl implements GatewayDataDownloadService {
+
+ private static final String DGCG_DESTINATION = "dgcg-destination";
+ private static final String DCCG_UPLOAD_CERTS_ENDPOINT = "/trustList/UPLOAD";
+ private static final String DCCG_BUSINESS_RULES_ENDPOINT = "/rules";
+ private static final String DCCG_VALUE_SETS_ENDPOINT = "/valuesets";
+ private static final String DCCG_COUNTRY_LIST_ENDPOINT = "/countrylist";
+
+ private final BusinessRuleService businessRuleService;
+ private final ValueSetService valueSetService;
+ private final CountryListService countryListService;
+
+ @Override
+ @Scheduled(fixedDelayString = "${dgc.businessRulesDownload.timeInterval}")
+ @SchedulerLock(name = "GatewayDataDownloadService_downloadBusinessRules", lockAtLeastFor = "PT0S",
+ lockAtMostFor = "${dgc.businessRulesDownload.lockLimit}")
+ public void downloadBusinessRules() {
+ try {
+ initializeLogging();
+ log.debug("Business rules download started.");
+
+ //List uploadCerts = fetchUploadCerts(httpClient);
+ List countryCodes = fetchCountryList();
+
+ List ruleItems = new ArrayList<>();
+ try {
+ ruleItems = businessRuleService.createBusinessRuleItemList(fetchValidationRulesAndVerify(countryCodes));
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Could not create business rule item list: {}", e.getMessage(), e);
+ }
+
+ if (!ruleItems.isEmpty()) {
+ businessRuleService.updateBusinesRules(ruleItems);
+ } else {
+ log.warn("The download of the business rules seems to fail, as the download connector "
+ + "returns an empty list. No data will be changed.");
+ }
+
+ log.info("Business rules download finished.");
+ } finally {
+ cleanLogging();
+ }
+
+ }
+
+ @Override
+ @Scheduled(fixedDelayString = "${dgc.valueSetsDownload.timeInterval}")
+ @SchedulerLock(name = "GatewayDataDownloadService_downloadValueSets", lockAtLeastFor = "PT0S",
+ lockAtMostFor = "${dgc.valueSetsDownload.lockLimit}")
+ public void downloadValueSets() {
+ try {
+ initializeLogging();
+ log.debug("Value sets download started.");
+ List valueSetItems;
+ List valueSetIds = fetchValueSetIds();
+
+ try {
+ valueSetItems = valueSetService.createValueSetItemListFromMap(fetchValueSets(valueSetIds));
+ log.debug("Downloaded {} value set items.", valueSetItems.size());
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Failed to hash value set on download.",e);
+ return;
+ }
+
+ if (!valueSetItems.isEmpty()) {
+ valueSetService.updateValueSets(valueSetItems);
+ } else {
+ log.warn("The download of the value sets seems to fail, as the download connector "
+ + "returns an empty list. No data will be changed.");
+ }
+
+ log.debug("Value sets download finished.");
+ } finally {
+ cleanLogging();
+ }
+ }
+
+ @Override
+ @Scheduled(fixedDelayString = "${dgc.countryListDownload.timeInterval}")
+ @SchedulerLock(name = "GatewayDataDownloadService_downloadCountryList", lockAtLeastFor = "PT0S",
+ lockAtMostFor = "${dgc.countryListDownload.lockLimit}")
+ public void downloadCountryList() {
+ try {
+ initializeLogging();
+ log.debug("Country list download started.");
+
+ List countryList = fetchCountryList();
+ log.debug("Downloaded {} country codes.", countryList.size());
+
+ if (!countryList.isEmpty()) {
+ countryListService.updateCountryList(gson().toJson(countryList));
+ } else {
+ log.warn("The download of the country list seems to fail as the gateway "
+ + "returns an empty list. No data will be changed.");
+ }
+
+ log.debug("Country list download finished.");
+ } finally {
+ cleanLogging();
+ }
+ }
+
+ private List fetchUploadCerts(HttpClient httpClient) {
+ List listOfUploadCerts = new ArrayList<>();
+
+ try {
+ HttpResponse response = httpClient.execute(RequestBuilder.get(DCCG_UPLOAD_CERTS_ENDPOINT).build());
+ List trustListItems = gson().fromJson(toJsonString(response.getEntity()),
+ new TypeToken>() {}.getType());
+
+ listOfUploadCerts = trustListItems.stream()
+ .filter(this::checkThumbprintIntegrity)
+ .filter(this::checkTrustAnchorSignature)
+ .map(this::getCertificateFromTrustListItem)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ log.error("Fetching upload verts from gateway failed: {}", e.getMessage(), e);
+ }
+
+ return listOfUploadCerts;
+ }
+
+ private List fetchCountryList() {
+ HttpDestination httpDestination = DestinationAccessor.getDestination(DGCG_DESTINATION).asHttp();
+ HttpClient httpClient = HttpClientAccessor.getHttpClient(httpDestination);
+ List countryList = new ArrayList<>();
+
+ try {
+ HttpResponse response = httpClient.execute(RequestBuilder.get(DCCG_COUNTRY_LIST_ENDPOINT).build());
+ countryList = new ArrayList<>(gson().fromJson(toJsonString(response.getEntity()),
+ new TypeToken>() {}.getType()));
+ } catch (IOException e) {
+ log.error("Could not fetch country list from gateway: {}", e.getMessage(), e);
+ }
+
+ return countryList;
+ }
+
+ private List fetchValueSetIds() {
+ HttpDestination httpDestination = DestinationAccessor.getDestination(DGCG_DESTINATION).asHttp();
+ HttpClient httpClient = HttpClientAccessor.getHttpClient(httpDestination);
+ List valueSetIds = new ArrayList<>();
+
+ try {
+ HttpResponse response = httpClient.execute(RequestBuilder.get(DCCG_VALUE_SETS_ENDPOINT).build());
+ valueSetIds = new ArrayList<>(gson().fromJson(toJsonString(response.getEntity()),
+ new TypeToken>() {}.getType()));
+ } catch (IOException e) {
+ log.error("Could not fetch value set IDs from gateway: {}", e.getMessage());
+ }
+
+ return valueSetIds;
+ }
+
+ private Gson gson() {
+ return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new TypeAdapter() {
+ @Override
+ public void write(JsonWriter out, ZonedDateTime value) throws IOException {
+ out.value(value.toString());
+ }
+
+ @Override
+ public ZonedDateTime read(JsonReader in) throws IOException {
+ return ZonedDateTime.parse(in.nextString());
+ }
+ })
+ .enableComplexMapKeySerialization()
+ .create();
+ }
+
+ private Gson gsonForValidationRule() {
+ return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new TypeAdapter() {
+ @Override
+ public void write(JsonWriter out, ZonedDateTime value) throws IOException {
+ out.value(value.toString());
+ }
+
+ @Override
+ public ZonedDateTime read(JsonReader in) throws IOException {
+ return ZonedDateTime.parse(in.nextString());
+ }
+ })
+ .registerTypeAdapter(JsonNode.class, new JsonNodeDeserializer())
+ .setFieldNamingStrategy(FieldNamingPolicy.UPPER_CAMEL_CASE)
+ .enableComplexMapKeySerialization()
+ .create();
+ }
+
+ private String toJsonString(HttpEntity entity) throws IOException {
+ return EntityUtils.toString(entity);
+ }
+
+ private boolean checkThumbprintIntegrity(TrustListItemDto trustListItem) {
+ byte[] certificateRawData = Base64.getDecoder().decode(trustListItem.getRawData());
+
+ try {
+ if (trustListItem.getThumbprint()
+ .equals(this.getCertThumbprint(new X509CertificateHolder(certificateRawData)))) {
+ return true;
+ } else {
+ log.debug("Thumbprint of trust list item '{}' did not match.", trustListItem.getKid());
+ return false;
+ }
+ } catch (IOException e) {
+ log.error("Could not parse certificate raw data: {}", e.getMessage());
+ return false;
+ }
+ }
+
+ private String getCertThumbprint(X509CertificateHolder x509CertificateHolder) {
+ try {
+ byte[] data = x509CertificateHolder.getEncoded();
+ byte[] certHashBytes = MessageDigest.getInstance("SHA-256").digest(data);
+ String hexString = (new BigInteger(1, certHashBytes)).toString(16);
+ if (hexString.length() == 63) {
+ hexString = "0" + hexString;
+ }
+ return hexString;
+ } catch (NoSuchAlgorithmException | IOException e) {
+ log.error("Could not calculate thumbprint of certificate '{}': {}.",
+ x509CertificateHolder.getSubject(), e.getMessage());
+ return null;
+ }
+ }
+
+ private X509CertificateHolder getCertificateFromTrustListItem(TrustListItemDto trustListItem) {
+ byte[] decodedBytes = Base64.getDecoder().decode(trustListItem.getRawData());
+ try {
+ return new X509CertificateHolder(decodedBytes);
+ } catch (IOException e) {
+ log.error("Failed to parse Certificate Raw Data. KID: {}, Country: {}", trustListItem.getKid(),
+ trustListItem.getCountry());
+ return null;
+ }
+ }
+
+ private boolean checkTrustAnchorSignature(TrustListItemDto trustListItemDto) {
+ // Implement me...
+ return true;
+ }
+
+ private List fetchValidationRulesAndVerify(List countryCodes) {
+ HttpDestination httpDestination = DestinationAccessor.getDestination(DGCG_DESTINATION).asHttp();
+ HttpClient httpClient = HttpClientAccessor.getHttpClient(httpDestination);
+ List allRules = new ArrayList<>();
+
+ for (String countryCode : countryCodes) {
+ log.debug("Fetching rules for country '{}'...", countryCode);
+ try {
+ HttpResponse response = httpClient
+ .execute(RequestBuilder.get(DCCG_BUSINESS_RULES_ENDPOINT + "/" + countryCode).build());
+ Map fetchedForCountry = gson().fromJson(toJsonString(response.getEntity()),
+ new TypeToken