Skip to content
This repository has been archived by the owner on Sep 15, 2023. It is now read-only.

Commit

Permalink
Release 2.0.0 (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolaKellerTIM authored Jun 23, 2021
1 parent 10669fe commit fbd011c
Show file tree
Hide file tree
Showing 48 changed files with 795 additions and 100 deletions.
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,19 @@
<version>2.16.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>4.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
14 changes: 10 additions & 4 deletions src/main/java/ch/admin/bag/covidcertificate/api/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Constants {
public static final String VERSION = "1.2.1";
public static final String VERSION = "1.3.0";
public static final String DEFAULT_DISEASE_OR_AGENT_TARGETED = "840539006";
public static final String DEFAULT_DISEASE_OR_AGENT_SYSTEM = "2.16.840.1.113883.6.96";
public static final String ISSUER = "Bundesamt für Gesundheit (BAG)";
public static final String PCR_TYPE_CODE = "LP6464-4";
public static final String NONE_PCR_TYPE_CODE = "LP217198-3";
public static final int MAX_STRING_LENGTH = 50;
public static final int MAX_STRING_LENGTH = 80;
public static final int DAYS_UNTIL_RECOVERY_VALID = 10;
public static final int RECOVERY_CERTIFICATE_VALIDITY_IN_DAYS = 179;

// KPI Logs constants
public static final String KPI_TYPE_VACCINATION = "v";
public static final String KPI_TYPE_TEST = "t";
public static final String KPI_TYPE_RECOVERY = "r";
public static final String KPI_TYPE_INAPP_DELIVERY = "ad";
public static final String USER_EXT_ID_CLAIM_KEY = "userExtId";
public static final String KPI_UUID_KEY = "uuid";
public static final String KPI_TIMESTAMP_KEY = "ts";
Expand All @@ -49,8 +50,8 @@ public class Constants {
public static final CreateCertificateError INVALID_DOSES = new CreateCertificateError(455, "Invalid number of doses", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_VACCINATION_DATE = new CreateCertificateError(456, "Invalid vaccination date! Date cannot be in the future", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_COUNTRY_OF_VACCINATION = new CreateCertificateError(457, "Invalid country of vaccination", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_GIVEN_NAME = new CreateCertificateError(458, "Invalid given name! Must not exceed 50 chars", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_FAMILY_NAME = new CreateCertificateError(459, "Invalid family name! Must not exceed 50 chars", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_GIVEN_NAME = new CreateCertificateError(458, "Invalid given name! Must not exceed 80 chars", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_FAMILY_NAME = new CreateCertificateError(459, "Invalid family name! Must not exceed 80 chars", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError NO_TEST_DATA = new CreateCertificateError(460, "No test data was specified", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_MEMBER_STATE_OF_TEST = new CreateCertificateError(461, "Invalid member state of test", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_TYP_OF_TEST = new CreateCertificateError(462, "Invalid type of test and manufacturer code combination! Must either be a PCR Test type and no manufacturer code or give a manufacturer code and the antigen test type code.", HttpStatus.BAD_REQUEST);
Expand All @@ -62,6 +63,10 @@ public class Constants {
public static final CreateCertificateError INVALID_LANGUAGE = new CreateCertificateError(469, "The given language does not match any of the supported languages: de, it, fr, rm!", HttpStatus.BAD_REQUEST);
public static final RevocationError INVALID_UVCI = new RevocationError(470, "Invalid UVCI format.", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_ADDRESS = new CreateCertificateError(474, "Paper-based delivery requires a valid address.", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError DUPLICATE_DELIVERY_METHOD = new CreateCertificateError(475, "Delivery method can either be InApp or print, but not both.", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_IN_APP_CODE = new CreateCertificateError(476, "InAppDelivery-Code is invalid.", HttpStatus.NOT_FOUND);
public static final CreateCertificateError INVALID_STANDARDISED_GIVEN_NAME = new CreateCertificateError(477, "Invalid given name! The standardised given name exceeds 80 chars", HttpStatus.BAD_REQUEST);
public static final CreateCertificateError INVALID_STANDARDISED_FAMILY_NAME = new CreateCertificateError(478, "Invalid family name! The standardised family name exceeds 80 chars", HttpStatus.BAD_REQUEST);

public static final RevocationError DUPLICATE_UVCI = new RevocationError(480, "Duplicate UVCI.", HttpStatus.CONFLICT);

Expand All @@ -79,4 +84,5 @@ public class Constants {
public static final CreateCertificateError CREATE_BARCODE_FAILED = new CreateCertificateError(555, "Creating barcode failed.", HttpStatus.INTERNAL_SERVER_ERROR);
public static final CreateCertificateError PRINTING_FAILED = new CreateCertificateError(556, "Printing failed.", HttpStatus.INTERNAL_SERVER_ERROR);
public static final CreateCertificateError WRITING_RETURN_CSV_FAILED = new CreateCertificateError(557, "Write CSV failed", HttpStatus.INTERNAL_SERVER_ERROR);
public static final CreateCertificateError INAPP_DELIVERY_FAILED = new CreateCertificateError(558, "InApp delivery failed.", HttpStatus.INTERNAL_SERVER_ERROR);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ch.admin.bag.covidcertificate.api.mapper;

import ch.admin.bag.covidcertificate.api.exception.CreateCertificateException;
import ch.admin.bag.covidcertificate.api.request.CovidCertificatePersonDto;
import ch.admin.bag.covidcertificate.api.request.CovidCertificatePersonNameDto;
import ch.admin.bag.covidcertificate.service.domain.CovidCertificatePerson;
Expand All @@ -8,6 +9,8 @@
import lombok.NoArgsConstructor;
import se.digg.dgc.transliteration.MrzEncoder;

import static ch.admin.bag.covidcertificate.api.Constants.*;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CovidCertificatePersonMapper {

Expand All @@ -19,7 +22,15 @@ public static CovidCertificatePerson toCovidCertificatePerson(CovidCertificatePe
}

private static CovidCertificatePersonName toCovidCertificatePersonName(CovidCertificatePersonNameDto name) {
return new CovidCertificatePersonName(name.getFamilyName(), standardiseName(name.getFamilyName()), name.getGivenName(), standardiseName(name.getGivenName()));
String standardisedFamilyName = standardiseName(name.getFamilyName());
if (standardisedFamilyName.length() > MAX_STRING_LENGTH) {
throw new CreateCertificateException(INVALID_STANDARDISED_FAMILY_NAME);
}
String standardisedGivenName = standardiseName(name.getGivenName());
if (standardisedGivenName.length() > MAX_STRING_LENGTH) {
throw new CreateCertificateException(INVALID_STANDARDISED_GIVEN_NAME);
}
return new CovidCertificatePersonName(name.getFamilyName(), standardisedFamilyName, name.getGivenName(), standardisedGivenName);
}

private static String standardiseName(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
import java.util.List;
import java.util.stream.Collectors;

import static ch.admin.bag.covidcertificate.api.Constants.ISSUER;
import static ch.admin.bag.covidcertificate.api.Constants.VERSION;
import static ch.admin.bag.covidcertificate.api.Constants.*;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TestCertificateQrCodeMapper {
Expand Down Expand Up @@ -50,7 +49,7 @@ private static TestCertificateData toTestCertificateData(
return new TestCertificateData(
CovidCertificateDiseaseOrAgentTargeted.getStandardInstance().getCode(),
testValueSet.getTypeCode(),
testValueSet.getName(),
getTrimmedTestName(testValueSet.getName()),
testValueSet.getManufacturerCodeEu(),
testCertificateDataDto.getSampleDateTime().truncatedTo(ChronoUnit.SECONDS),
NegativeTestResult.CODE,
Expand All @@ -60,4 +59,8 @@ private static TestCertificateData toTestCertificateData(
UVCI.generateUVCI(testCertificateDataDto.toString())
);
}

private static String getTrimmedTestName(String testName) {
return testName.substring(0, Math.min(testName.length(), MAX_STRING_LENGTH));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@
import ch.admin.bag.covidcertificate.api.valueset.AcceptedLanguages;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.*;
import org.springframework.util.StringUtils;

import static ch.admin.bag.covidcertificate.api.Constants.INVALID_LANGUAGE;
import static ch.admin.bag.covidcertificate.api.Constants.NO_PERSON_DATA;
import static ch.admin.bag.covidcertificate.api.Constants.*;

@Getter
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public abstract class CertificateCreateDto {
@JsonUnwrapped
private CovidCertificatePersonDto personData;
private String language;
private CovidCertificateAddressDto address;
private String appCode;

public CertificateCreateDto(CovidCertificatePersonDto personData, String language, CovidCertificateAddressDto address, String appCode) {
this.personData = personData;
this.language = language;
this.address = address;
this.appCode = appCode != null ? appCode.toUpperCase() : null;
}

public boolean sendToPrint() {
return this.address != null;
}

public boolean sendToApp() {
return this.appCode != null;
}

public void validate() {
if (personData == null) {
Expand All @@ -27,8 +42,23 @@ public void validate() {
if (!AcceptedLanguages.isAcceptedLanguage(language)) {
throw new CreateCertificateException(INVALID_LANGUAGE);
}
if (address != null) {
address.validate();
this.validateDeliveryMethod();
}

private void validateDeliveryMethod() {
if (this.address != null && StringUtils.hasText(this.appCode)) {
throw new CreateCertificateException(DUPLICATE_DELIVERY_METHOD);
} else {
if (this.address != null) {
this.address.validate();
}
if (StringUtils.hasText(this.appCode)) {
var isAlphaNumeric = org.apache.commons.lang3.StringUtils.isAlphanumeric(this.appCode);
var isNineCharsLong = this.appCode.length() == 9;
if (!isAlphaNumeric || !isNineCharsLong) {
throw new CreateCertificateException(INVALID_IN_APP_CODE);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public abstract class CertificateCsvBean {
private String cantonCodeSender;
@CsvBindByName(column = "error")
private String error;
@CsvBindByName(column = "inAppDeliveryCode")
private String inAppDeliveryCode;

public abstract CertificateCreateDto mapToCreateDto();

Expand All @@ -50,7 +52,8 @@ protected VaccinationCertificateCreateDto mapToCreateDto(VaccinationCertificateD
mapToPersonDto(),
List.of(dataDto),
getLanguage(),
mapToAddressDto()
mapToAddressDto(),
getInAppDeliveryCode()
);
}

Expand All @@ -59,7 +62,8 @@ protected TestCertificateCreateDto mapToCreateDto(TestCertificateDataDto dataDto
mapToPersonDto(),
List.of(dataDto),
getLanguage(),
mapToAddressDto()
mapToAddressDto(),
getInAppDeliveryCode()
);
}

Expand All @@ -68,7 +72,8 @@ protected RecoveryCertificateCreateDto mapToCreateDto(RecoveryCertificateDataDto
mapToPersonDto(),
List.of(dataDto),
getLanguage(),
mapToAddressDto()
mapToAddressDto(),
getInAppDeliveryCode()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ public RecoveryCertificateCreateDto(
CovidCertificatePersonDto personData,
List<RecoveryCertificateDataDto> recoveryInfo,
String language,
CovidCertificateAddressDto address
CovidCertificateAddressDto address,
String inAppDeliveryCode
) {
super(personData, language, address);
super(personData, language, address, inAppDeliveryCode);
this.recoveryInfo = recoveryInfo;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ public TestCertificateCreateDto(
CovidCertificatePersonDto personData,
List<TestCertificateDataDto> testInfo,
String language,
CovidCertificateAddressDto address
CovidCertificateAddressDto address,
String inAppDeliveryCode
) {
super(personData, language, address);
super(personData, language, address, inAppDeliveryCode);
this.testInfo = testInfo;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ public VaccinationCertificateCreateDto(
CovidCertificatePersonDto personData,
List<VaccinationCertificateDataDto> vaccinationInfo,
String language,
CovidCertificateAddressDto address
CovidCertificateAddressDto address,
String inAppDeliveryCode
) {
super(personData, language, address);
super(personData, language, address, inAppDeliveryCode);
this.vaccinationInfo = vaccinationInfo;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ public class VaccinationCertificateDataDto {
public void validate() {
if (numberOfDoses == null ||
numberOfDoses < 1 ||
numberOfDoses > 9 ||
totalNumberOfDoses == null ||
totalNumberOfDoses > 9 ||
numberOfDoses > totalNumberOfDoses) {
throw new CreateCertificateException(INVALID_DOSES);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ch.admin.bag.covidcertificate.client.inapp_delivery;

import ch.admin.bag.covidcertificate.api.exception.CreateCertificateException;
import ch.admin.bag.covidcertificate.client.inapp_delivery.domain.InAppDeliveryRequestDto;

public interface InAppDeliveryClient {
/**
* Sends an InApp delivery request to the app backend. If the request fails a CreateCertificateException is thrown.
*
* @param requestDto - data to be sent to the app.
*/
void deliverToApp(InAppDeliveryRequestDto requestDto) throws CreateCertificateException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ch.admin.bag.covidcertificate.client.inapp_delivery.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter
@ToString
@AllArgsConstructor
public class InAppDeliveryRequestDto {
/**
* Code of the App the certificate should be sent to. Must be 9 characters, alphanumeric and upper case.
*/
String code;
/**
* Payload of the QRCode. Starts with 'HC1:'
*/
String hcert;
/**
* Base64 encoded String of the PDF.
*/
String pdf;
}
Loading

0 comments on commit fbd011c

Please sign in to comment.