diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt index fe0d08c1c83191d1cf216edf70e56c92b78fe4d1..8ea9f61d764bd44df49652abd76dce8ee9e8ba1c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt @@ -3,8 +3,9 @@ package de.rki.coronawarnapp.bugreporting.censors.vaccination import dagger.Reusable import de.rki.coronawarnapp.bugreporting.censors.BugCensor import de.rki.coronawarnapp.bugreporting.censors.BugCensor.CensorContainer -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateData +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 import java.util.LinkedList import javax.inject.Inject @@ -35,7 +36,7 @@ class CertificateQrCodeCensor @Inject constructor() : BugCensor { newMessage = censorNameData(nameData, newMessage) - vaccinationDatas.forEach { data -> + payload.let { data -> newMessage = censorVaccinationData(data, newMessage) } } @@ -45,7 +46,7 @@ class CertificateQrCodeCensor @Inject constructor() : BugCensor { } private fun censorVaccinationData( - vaccinationData: VaccinationDGCV1.VaccinationData, + vaccinationData: VaccinationDccV1.VaccinationData, message: CensorContainer ): CensorContainer { var newMessage = message @@ -76,8 +77,8 @@ class CertificateQrCodeCensor @Inject constructor() : BugCensor { ) newMessage = newMessage.censor( - vaccinationData.countryOfVaccination, - "vaccinationData/countryOfVaccination" + vaccinationData.certificateCountry, + "vaccinationData/certificateCountry" ) newMessage = newMessage.censor( @@ -100,7 +101,7 @@ class CertificateQrCodeCensor @Inject constructor() : BugCensor { return newMessage } - private fun censorNameData(nameData: VaccinationDGCV1.NameData, message: CensorContainer): CensorContainer { + private fun censorNameData(nameData: Dcc.NameData, message: CensorContainer): CensorContainer { var newMessage = message nameData.familyName?.let { fName -> @@ -146,8 +147,8 @@ class CertificateQrCodeCensor @Inject constructor() : BugCensor { fun clearQRCodeStringToCensor() = synchronized(qrCodeStringsToCensor) { qrCodeStringsToCensor.clear() } - private val certsToCensor = LinkedList<VaccinationCertificateData>() - fun addCertificateToCensor(cert: VaccinationCertificateData) = synchronized(certsToCensor) { + private val certsToCensor = LinkedList<DccData<VaccinationDccV1>>() + fun addCertificateToCensor(cert: DccData<VaccinationDccV1>) = synchronized(certsToCensor) { certsToCensor.apply { if (contains(cert)) return@apply addFirst(cert) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifier.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CertificatePersonIdentifier.kt similarity index 61% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifier.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CertificatePersonIdentifier.kt index dcfd255a303c3aa5a0f5939cd72eede1ecbf909e..3148343d4e36ea6d868b1aef3547109cd29658ed 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifier.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CertificatePersonIdentifier.kt @@ -1,12 +1,8 @@ -package de.rki.coronawarnapp.covidcertificate.common +package de.rki.coronawarnapp.covidcertificate.common.certificate import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.VC_DOB_MISMATCH import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.VC_NAME_MISMATCH import de.rki.coronawarnapp.covidcertificate.exception.InvalidVaccinationCertificateException -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateDccV1 -import de.rki.coronawarnapp.covidcertificate.test.core.qrcode.TestCertificateQRCode -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateQRCode import de.rki.coronawarnapp.util.HashExtensions.toSHA256 import org.joda.time.LocalDate import timber.log.Timber @@ -50,23 +46,3 @@ data class CertificatePersonIdentifier( } } } - -val VaccinationDGCV1.personIdentifier: CertificatePersonIdentifier - get() = CertificatePersonIdentifier( - dateOfBirth = dateOfBirth, - lastNameStandardized = nameData.familyNameStandardized, - firstNameStandardized = nameData.givenNameStandardized - ) - -val VaccinationCertificateQRCode.personIdentifier: CertificatePersonIdentifier - get() = parsedData.certificate.personIdentifier - -val TestCertificateDccV1.personIdentifier: CertificatePersonIdentifier - get() = CertificatePersonIdentifier( - dateOfBirth = dateOfBirth, - lastNameStandardized = nameData.familyNameStandardized, - firstNameStandardized = nameData.givenNameStandardized - ) - -val TestCertificateQRCode.personIdentifier: CertificatePersonIdentifier - get() = testCertificateData.certificate.personIdentifier diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CwaCovidCertificate.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CwaCovidCertificate.kt new file mode 100644 index 0000000000000000000000000000000000000000..bd58201d2ebc0e8e4968d8dff2fa241679b874c0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/CwaCovidCertificate.kt @@ -0,0 +1,29 @@ +package de.rki.coronawarnapp.covidcertificate.common.certificate + +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString +import org.joda.time.Instant +import org.joda.time.LocalDate + +/** + * For use with the UI + */ +interface CwaCovidCertificate { + // Header + val issuer: String + val issuedAt: Instant + val expiresAt: Instant + + val qrCode: QrCodeString + + val firstName: String? + + val lastName: String + val fullName: String + val dateOfBirth: LocalDate + + val personIdentifier: CertificatePersonIdentifier + + val certificateIssuer: String + val certificateCountry: String + val certificateId: String +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt new file mode 100644 index 0000000000000000000000000000000000000000..8d8c4b030802099b01ee409d6f422c46f96b1c2c --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/Dcc.kt @@ -0,0 +1,50 @@ +package de.rki.coronawarnapp.covidcertificate.common.certificate + +import com.google.gson.annotations.SerializedName +import org.joda.time.LocalDate + +interface Dcc<PayloadType : Dcc.Payload> { + data class NameData( + @SerializedName("fn") internal val familyName: String?, + @SerializedName("fnt") internal val familyNameStandardized: String, + @SerializedName("gn") internal val givenName: String?, + @SerializedName("gnt") internal val givenNameStandardized: String?, + ) { + val firstName: String? + get() = if (givenName.isNullOrBlank()) givenNameStandardized else givenName + + val lastName: String + get() = if (familyName.isNullOrBlank()) familyNameStandardized else familyName + + val fullName: String + get() = when { + firstName.isNullOrBlank() -> lastName + else -> "$firstName $lastName" + } + } + + val version: String + val nameData: NameData + val dob: String + + val dateOfBirth: LocalDate + get() = LocalDate.parse(dob) + + val payloads: List<PayloadType> + val payload: PayloadType + get() = payloads.single() + + val personIdentifier: CertificatePersonIdentifier + get() = CertificatePersonIdentifier( + dateOfBirth = dateOfBirth, + lastNameStandardized = nameData.familyNameStandardized, + firstNameStandardized = nameData.givenNameStandardized + ) + + interface Payload { + val targetId: String + val certificateCountry: String + val certificateIssuer: String + val uniqueCertificateIdentifier: String + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccData.kt new file mode 100644 index 0000000000000000000000000000000000000000..89a2aac6b817b69cd06a50167364ef15651ba2f4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccData.kt @@ -0,0 +1,6 @@ +package de.rki.coronawarnapp.covidcertificate.common.certificate + +data class DccData<CertT : Dcc<*>>( + val header: DccHeader, + val certificate: CertT, +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccHeader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccHeader.kt new file mode 100644 index 0000000000000000000000000000000000000000..4964d707431c1bb29a0fb79e88e4b14d4383d19e --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/certificate/DccHeader.kt @@ -0,0 +1,9 @@ +package de.rki.coronawarnapp.covidcertificate.common.certificate + +import org.joda.time.Instant + +data class DccHeader( + val issuer: String, + val issuedAt: Instant, + val expiresAt: Instant, +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccCoseDecoder.kt similarity index 94% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccCoseDecoder.kt index 4662a3c8421543191e70f06128ac8c4571de993e..51773c92558ee0ef541cc8dc95ebe284dad85e8d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccCoseDecoder.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate +package de.rki.coronawarnapp.covidcertificate.common.decoder import com.upokecenter.cbor.CBORObject import de.rki.coronawarnapp.covidcertificate.cryptography.AesCryptography @@ -9,7 +9,7 @@ import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateE import timber.log.Timber import javax.inject.Inject -class HealthCertificateCOSEDecoder @Inject constructor( +class DccCoseDecoder @Inject constructor( private val aesEncryptor: AesCryptography ) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeaderParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccHeaderParser.kt similarity index 86% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeaderParser.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccHeaderParser.kt index 8878f55ad166a44a2be098a3895b98032046c901..2bac92a71c8847e5cd20d3d8cd572cbb315aa20e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeaderParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/DccHeaderParser.kt @@ -1,7 +1,8 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate +package de.rki.coronawarnapp.covidcertificate.common.decoder import com.upokecenter.cbor.CBORObject import dagger.Reusable +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccHeader import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_CBOR_DECODING_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_CWT_NO_EXP @@ -10,9 +11,9 @@ import org.joda.time.Instant import javax.inject.Inject @Reusable -class HealthCertificateHeaderParser @Inject constructor() { +class DccHeaderParser @Inject constructor() { - fun parse(map: CBORObject): CoseCertificateHeader = try { + fun parse(map: CBORObject): DccHeader = try { val issuer: String = map[keyIssuer]?.AsString() ?: throw InvalidHealthCertificateException(HC_CWT_NO_ISS) val issuedAt: Instant = map[keyIssuedAt]?.run { @@ -23,7 +24,7 @@ class HealthCertificateHeaderParser @Inject constructor() { Instant.ofEpochSecond(AsNumber().ToInt64Checked()) } ?: throw InvalidHealthCertificateException(HC_CWT_NO_EXP) - HealthCertificateHeader( + DccHeader( issuer = issuer, issuedAt = issuedAt, expiresAt = expiresAt, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/RawCOSEObject.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/RawCOSEObject.kt new file mode 100644 index 0000000000000000000000000000000000000000..233796803fd4c90fd7e02f5ef7d3af35d0d08395 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/decoder/RawCOSEObject.kt @@ -0,0 +1,3 @@ +package de.rki.coronawarnapp.covidcertificate.common.decoder + +typealias RawCOSEObject = ByteArray diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/DccQrCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/DccQrCode.kt new file mode 100644 index 0000000000000000000000000000000000000000..9d1527dd0afb14850f7abd32e41edfcdde9421af --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/DccQrCode.kt @@ -0,0 +1,16 @@ +package de.rki.coronawarnapp.covidcertificate.common.qrcode + +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData + +interface DccQrCode<DccT : Dcc<*>> { + val qrCode: QrCodeString + val data: DccData<DccT> + + val personIdentifier: CertificatePersonIdentifier + get() = data.certificate.personIdentifier + + val uniqueCertificateIdentifier: String + get() = data.certificate.payload.uniqueCertificateIdentifier +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/QrCodeString.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/QrCodeString.kt new file mode 100644 index 0000000000000000000000000000000000000000..9c8208fe1c4978bfc8f5f4e941228ca16d1ac329 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/common/qrcode/QrCodeString.kt @@ -0,0 +1,3 @@ +package de.rki.coronawarnapp.covidcertificate.common.qrcode + +typealias QrCodeString = String diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/TestCertificate.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/TestCertificate.kt index b03f5ab10ebf27469a7f873cdff8fbac09f25ba9..b4589236afa4541e4266755cd1a88cd6ab5022b6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/TestCertificate.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/TestCertificate.kt @@ -1,15 +1,9 @@ package de.rki.coronawarnapp.covidcertificate.test.core -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.QrCodeString +import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate import org.joda.time.Instant -import org.joda.time.LocalDate -interface TestCertificate { - val firstName: String? - val lastName: String - - val dateOfBirth: LocalDate +interface TestCertificate : CwaCovidCertificate { /** * Disease or agent targeted (required) @@ -30,16 +24,4 @@ interface TestCertificate { val sampleCollectedAt: Instant val testResultAt: Instant? val testCenter: String - - val certificateIssuer: String - val certificateCountry: String - val certificateId: String - - val personIdentifier: CertificatePersonIdentifier - - val issuer: String - val issuedAt: Instant - val expiresAt: Instant - - val qrCode: QrCodeString } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateData.kt deleted file mode 100644 index 862b61f0cccfd289520fceec03a2ceec608ba3f0..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateData.kt +++ /dev/null @@ -1,8 +0,0 @@ -package de.rki.coronawarnapp.covidcertificate.test.core.certificate - -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.CoseCertificateHeader - -data class TestCertificateData( - val header: CoseCertificateHeader, - val certificate: TestCertificateDccV1, -) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccParser.kt similarity index 86% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccParser.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccParser.kt index 61a4a1ac1b9a4e4cbc9f4c19233811706c845fab..96f3c7445372a4578aa126a8bbd4b19675b23426 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccParser.kt @@ -15,10 +15,10 @@ import timber.log.Timber import javax.inject.Inject @Reusable -class TestCertificateDccParser @Inject constructor( +class TestDccParser @Inject constructor( @BaseGson private val gson: Gson, ) { - fun parse(map: CBORObject): TestCertificateDccV1 = try { + fun parse(map: CBORObject): TestDccV1 = try { map[keyHCert]?.run { this[keyEuDgcV1]?.run { toCertificate() @@ -31,19 +31,19 @@ class TestCertificateDccParser @Inject constructor( } @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") - private fun TestCertificateDccV1.validate(): TestCertificateDccV1 { - if (testCertificateData.isNullOrEmpty()) { + private fun TestDccV1.validate(): TestDccV1 { + if (payloads.isNullOrEmpty()) { throw InvalidTestCertificateException(NO_TEST_ENTRY) } // check for non null (Gson does not enforce it) & force date parsing version!! nameData.familyNameStandardized!! dateOfBirth - testCertificateData.forEach { + payload.let { it.testResultAt it.sampleCollectedAt it.certificateIssuer!! - it.countryOfTest!! + it.certificateCountry!! it.targetId!! it.testCenter!! it.testResult!! @@ -54,7 +54,7 @@ class TestCertificateDccParser @Inject constructor( private fun CBORObject.toCertificate() = try { val json = ToJSONString() - gson.fromJson<TestCertificateDccV1>(json).validate() + gson.fromJson<TestDccV1>(json).validate() } catch (e: InvalidTestCertificateException) { throw e } catch (e: Throwable) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccV1.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt similarity index 63% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccV1.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt index 062878f47a7d70928fd447d32672fa7966f820f1..c105167986ab66c556716285921ab8978fddef9b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestCertificateDccV1.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/certificate/TestDccV1.kt @@ -1,25 +1,19 @@ package de.rki.coronawarnapp.covidcertificate.test.core.certificate import com.google.gson.annotations.SerializedName +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc import org.joda.time.Instant -import org.joda.time.LocalDate -data class TestCertificateDccV1( - @SerializedName("ver") val version: String, - @SerializedName("nam") val nameData: NameData, - @SerializedName("dob") val dob: String, - @SerializedName("t") val testCertificateData: List<TestCertificateData>, -) { - data class NameData( - @SerializedName("fn") val familyName: String?, - @SerializedName("fnt") val familyNameStandardized: String, - @SerializedName("gn") val givenName: String?, - @SerializedName("gnt") val givenNameStandardized: String?, - ) +data class TestDccV1( + @SerializedName("ver") override val version: String, + @SerializedName("nam") override val nameData: Dcc.NameData, + @SerializedName("dob") override val dob: String, + @SerializedName("t") override val payloads: List<TestCertificateData>, +) : Dcc<TestDccV1.TestCertificateData> { data class TestCertificateData( // Disease or agent targeted, e.g. "tg": "840539006" - @SerializedName("tg") val targetId: String, + @SerializedName("tg") override val targetId: String, // Type of Test (required) eg "LP217198-3" @SerializedName("tt") val testType: String, // Test Result (required) e. g. "tr": "260415000" @@ -35,12 +29,12 @@ data class TestCertificateDccV1( // Testing Center (required) "tc": "GGD Fryslân, L-Heliconweg", @SerializedName("tc") val testCenter: String, // Country of Test (required) - @SerializedName("co") val countryOfTest: String, + @SerializedName("co") override val certificateCountry: String, // Certificate Issuer, e.g. "is": "Ministry of Public Health, Welfare and Sport", - @SerializedName("is") val certificateIssuer: String, + @SerializedName("is") override val certificateIssuer: String, // Unique Certificate Identifier, e.g. "ci": "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ" - @SerializedName("ci") val uniqueCertificateIdentifier: String - ) { + @SerializedName("ci") override val uniqueCertificateIdentifier: String + ) : Dcc.Payload { val testResultAt: Instant? get() = dr?.let { Instant.parse(it) } @@ -48,7 +42,4 @@ data class TestCertificateDccV1( val sampleCollectedAt: Instant get() = Instant.parse(sc) } - - val dateOfBirth: LocalDate - get() = LocalDate.parse(dob) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCode.kt index 9dc25f420f8d04bc554f895c5fbfecd71fa00589..5e20630680c30cd7107d81348e6ece36cc82fcdd 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCode.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCode.kt @@ -1,8 +1,11 @@ package de.rki.coronawarnapp.covidcertificate.test.core.qrcode -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateData +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.qrcode.DccQrCode +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccV1 data class TestCertificateQRCode( - val qrCode: String, - val testCertificateData: TestCertificateData, -) + override val qrCode: QrCodeString, + override val data: DccData<TestDccV1>, +) : DccQrCode<TestDccV1> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractor.kt index cf8963cbd514e1ba0783549c213d9cea4b0279f7..51a8de2f1f8bc7087001278a0005b77fed23af5e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractor.kt @@ -2,6 +2,10 @@ package de.rki.coronawarnapp.covidcertificate.test.core.qrcode import com.upokecenter.cbor.CBORObject import dagger.Reusable +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccCoseDecoder +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccHeaderParser +import de.rki.coronawarnapp.covidcertificate.common.decoder.RawCOSEObject import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_BASE45_DECODING_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_BASE45_ENCODING_FAILED @@ -10,11 +14,8 @@ import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateE import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_ZLIB_COMPRESSION_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_ZLIB_DECOMPRESSION_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidTestCertificateException -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateData -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateDccParser -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateCOSEDecoder -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateHeaderParser -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.RawCOSEObject +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccParser +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccV1 import de.rki.coronawarnapp.util.compression.deflate import de.rki.coronawarnapp.util.compression.inflate import de.rki.coronawarnapp.util.encoding.Base45Decoder @@ -23,9 +24,9 @@ import javax.inject.Inject @Reusable class TestCertificateQRCodeExtractor @Inject constructor( - private val coseDecoder: HealthCertificateCOSEDecoder, - private val headerParser: HealthCertificateHeaderParser, - private val bodyParser: TestCertificateDccParser, + private val coseDecoder: DccCoseDecoder, + private val headerParser: DccHeaderParser, + private val bodyParser: TestDccParser, ) { /** @@ -37,7 +38,7 @@ class TestCertificateQRCodeExtractor @Inject constructor( ): TestCertificateQRCode { val rawCoseObject = rawCoseObjectEncrypted.decrypt(decryptionKey) return TestCertificateQRCode( - testCertificateData = rawCoseObject.decode(), + data = rawCoseObject.decode(), qrCode = rawCoseObject.encode() ) } @@ -46,7 +47,7 @@ class TestCertificateQRCodeExtractor @Inject constructor( * May throw an **[InvalidTestCertificateException]** */ fun extract(qrCode: String) = TestCertificateQRCode( - testCertificateData = qrCode.extract(), + data = qrCode.extract(), qrCode = qrCode ) @@ -62,7 +63,7 @@ class TestCertificateQRCodeExtractor @Inject constructor( throw InvalidTestCertificateException(HC_COSE_MESSAGE_INVALID) } - private fun String.extract(): TestCertificateData = + private fun String.extract(): DccData<TestDccV1> = removePrefix(PREFIX) .decodeBase45() .decompress() @@ -72,7 +73,7 @@ class TestCertificateQRCodeExtractor @Inject constructor( return PREFIX + compress().encodeBase45() } - private fun RawCOSEObject.decode(): TestCertificateData = try { + private fun RawCOSEObject.decode(): DccData<TestDccV1> = try { coseDecoder.decode(this).parse() } catch (e: InvalidHealthCertificateException) { throw InvalidTestCertificateException(e.errorCode) @@ -81,8 +82,8 @@ class TestCertificateQRCodeExtractor @Inject constructor( throw InvalidTestCertificateException(HC_COSE_MESSAGE_INVALID) } - private fun CBORObject.parse(): TestCertificateData = try { - TestCertificateData( + private fun CBORObject.parse(): DccData<TestDccV1> = try { + DccData( header = headerParser.parse(this), certificate = bodyParser.parse(this) ).also { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/storage/TestCertificateContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/storage/TestCertificateContainer.kt index e97c7b8767bbead57ab0a49609d33fe9eb925cf1..972fcc5db5ee6c333fb06819ec23d70eb719632c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/storage/TestCertificateContainer.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/test/core/storage/TestCertificateContainer.kt @@ -1,11 +1,11 @@ package de.rki.coronawarnapp.covidcertificate.test.core.storage -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier -import de.rki.coronawarnapp.covidcertificate.common.personIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString import de.rki.coronawarnapp.covidcertificate.test.core.TestCertificate -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateData +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccV1 import de.rki.coronawarnapp.covidcertificate.test.core.qrcode.TestCertificateQRCodeExtractor -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.QrCodeString import de.rki.coronawarnapp.covidcertificate.valueset.valuesets.TestCertificateValueSets import org.joda.time.Instant import org.joda.time.LocalDate @@ -18,8 +18,8 @@ data class TestCertificateContainer( ) : StoredTestCertificateData by data { @delegate:Transient - private val certificateData: TestCertificateData by lazy { - data.testCertificateQrCode!!.let { qrCodeExtractor.extract(it).testCertificateData } + private val certificateData: DccData<TestDccV1> by lazy { + data.testCertificateQrCode!!.let { qrCodeExtractor.extract(it).data } } val isPublicKeyRegistered: Boolean @@ -31,7 +31,7 @@ data class TestCertificateContainer( val certificateId: String? get() { if (isCertificateRetrievalPending) return null - return certificateData.certificate.testCertificateData.single().uniqueCertificateIdentifier + return certificateData.certificate.payload.uniqueCertificateIdentifier } fun toTestCertificate( @@ -42,16 +42,20 @@ data class TestCertificateContainer( val header = certificateData.header val certificate = certificateData.certificate - val testCertificate = certificate.testCertificateData.single() + val testCertificate = certificate.payload return object : TestCertificate { override val personIdentifier: CertificatePersonIdentifier get() = certificate.personIdentifier override val firstName: String? - get() = certificate.nameData.givenName + get() = certificate.nameData.firstName + override val lastName: String - get() = certificate.nameData.familyName ?: certificate.nameData.familyNameStandardized + get() = certificate.nameData.lastName + + override val fullName: String + get() = certificate.nameData.fullName override val dateOfBirth: LocalDate get() = certificate.dateOfBirth @@ -76,7 +80,7 @@ data class TestCertificateContainer( override val certificateIssuer: String get() = header.issuer override val certificateCountry: String - get() = Locale(userLocale.language, testCertificate.countryOfTest.uppercase()) + get() = Locale(userLocale.language, testCertificate.certificateCountry.uppercase()) .getDisplayCountry(userLocale) override val certificateId: String get() = testCertificate.uniqueCertificateIdentifier diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinatedPerson.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinatedPerson.kt index a5592ef6d6dc3326b94b358152778b8fb183828f..942fe20bd7096d0eb936facb7a8e867abfc99c8c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinatedPerson.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinatedPerson.kt @@ -1,6 +1,6 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier import de.rki.coronawarnapp.covidcertificate.vaccination.core.repository.storage.VaccinatedPersonData import de.rki.coronawarnapp.covidcertificate.valueset.valuesets.VaccinationValueSets import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDateUtc diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationCertificate.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationCertificate.kt index 9428b8f24277c61487681eade344f93c656a278a..21efe369b7c65a85c67f367f07f5a799308a7647 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationCertificate.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationCertificate.kt @@ -1,17 +1,10 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.QrCodeString -import org.joda.time.Instant +import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate import org.joda.time.LocalDate -interface VaccinationCertificate { - val firstName: String? - val lastName: String +interface VaccinationCertificate : CwaCovidCertificate { - val fullName: String - - val dateOfBirth: LocalDate val vaccinatedAt: LocalDate val vaccineTypeName: String @@ -20,16 +13,4 @@ interface VaccinationCertificate { val doseNumber: Int val totalSeriesOfDoses: Int - - val certificateIssuer: String - val certificateCountry: String - val certificateId: String - - val personIdentifier: CertificatePersonIdentifier - - val issuer: String - val issuedAt: Instant - val expiresAt: Instant - - val vaccinationQrCodeString: QrCodeString } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/CoseCertificateHeader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/CoseCertificateHeader.kt deleted file mode 100644 index 8b26288ecd9b01916062cfb94da86ed5bb6bc1fe..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/CoseCertificateHeader.kt +++ /dev/null @@ -1,9 +0,0 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate - -import org.joda.time.Instant - -interface CoseCertificateHeader { - val issuer: String - val issuedAt: Instant - val expiresAt: Instant -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeader.kt deleted file mode 100644 index ed7761cb5158b520e4bf782915d5290070286105..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/HealthCertificateHeader.kt +++ /dev/null @@ -1,9 +0,0 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate - -import org.joda.time.Instant - -data class HealthCertificateHeader( - override val issuer: String, - override val issuedAt: Instant, - override val expiresAt: Instant, -) : CoseCertificateHeader diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/RawCOSEObject.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/RawCOSEObject.kt deleted file mode 100644 index c3b69dfe1a6aebf05b081b6a6ce2c03ceb455c45..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/RawCOSEObject.kt +++ /dev/null @@ -1,3 +0,0 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate - -typealias RawCOSEObject = ByteArray diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt similarity index 59% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt index 29ed5027005f7fd4b88e0335fe6e0250b9dfd240..3583458aa0c5211d4524647a6c449e81b5bd6af6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1.kt @@ -1,24 +1,19 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate import com.google.gson.annotations.SerializedName +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc import org.joda.time.LocalDate -data class VaccinationDGCV1( - @SerializedName("ver") val version: String, - @SerializedName("nam") val nameData: NameData, - @SerializedName("dob") val dob: String, - @SerializedName("v") val vaccinationDatas: List<VaccinationData>, -) { - data class NameData( - @SerializedName("fn") val familyName: String?, - @SerializedName("fnt") val familyNameStandardized: String, - @SerializedName("gn") val givenName: String?, - @SerializedName("gnt") val givenNameStandardized: String?, - ) +data class VaccinationDccV1( + @SerializedName("ver") override val version: String, + @SerializedName("nam") override val nameData: Dcc.NameData, + @SerializedName("dob") override val dob: String, + @SerializedName("v") override val payloads: List<VaccinationData>, +) : Dcc<VaccinationDccV1.VaccinationData> { data class VaccinationData( // Disease or agent targeted, e.g. "tg": "840539006" - @SerializedName("tg") val targetId: String, + @SerializedName("tg") override val targetId: String, // Vaccine or prophylaxis, e.g. "vp": "1119349007" @SerializedName("vp") val vaccineId: String, // Vaccine medicinal product,e.g. "mp": "EU/1/20/1528", @@ -32,16 +27,13 @@ data class VaccinationDGCV1( // Date of Vaccination, e.g. "dt" : "2021-04-21" @SerializedName("dt") val dt: String, // Country of Vaccination, e.g. "co": "NL" - @SerializedName("co") val countryOfVaccination: String, + @SerializedName("co") override val certificateCountry: String, // Certificate Issuer, e.g. "is": "Ministry of Public Health, Welfare and Sport", - @SerializedName("is") val certificateIssuer: String, + @SerializedName("is") override val certificateIssuer: String, // Unique Certificate Identifier, e.g. "ci": "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ" - @SerializedName("ci") val uniqueCertificateIdentifier: String - ) { + @SerializedName("ci") override val uniqueCertificateIdentifier: String + ) : Dcc.Payload { val vaccinatedAt: LocalDate get() = LocalDate.parse(dt) } - - val dateOfBirth: LocalDate - get() = LocalDate.parse(dob) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1Parser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1Parser.kt similarity index 87% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1Parser.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1Parser.kt index e60e0f17092ab2b3a471cebb9276390b938f2641..7b4f9b0c2964d8a729e38e63f2b069931828e058 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDGCV1Parser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/certificate/VaccinationDccV1Parser.kt @@ -15,11 +15,11 @@ import de.rki.coronawarnapp.util.serialization.fromJson import javax.inject.Inject @Reusable -class VaccinationDGCV1Parser @Inject constructor( +class VaccinationDccV1Parser @Inject constructor( @BaseGson private val gson: Gson ) { - fun parse(map: CBORObject): VaccinationDGCV1 = try { + fun parse(map: CBORObject): VaccinationDccV1 = try { map[keyHCert]?.run { this[keyEuDgcV1]?.run { toCertificate() @@ -32,18 +32,18 @@ class VaccinationDGCV1Parser @Inject constructor( } @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") - private fun VaccinationDGCV1.validate(): VaccinationDGCV1 { - if (vaccinationDatas.isNullOrEmpty()) { + private fun VaccinationDccV1.validate(): VaccinationDccV1 { + if (payloads.isNullOrEmpty()) { throw InvalidVaccinationCertificateException(VC_NO_VACCINATION_ENTRY) } // check for non null (Gson does not enforce it) & force date parsing version!! nameData.familyNameStandardized.isNotBlank() dateOfBirth - vaccinationDatas.forEach { + payload.let { it.vaccinatedAt it.certificateIssuer.isNotBlank() - it.countryOfVaccination.isNotBlank() + it.certificateCountry.isNotBlank() it.marketAuthorizationHolderId.isNotBlank() it.medicalProductId.isNotBlank() it.targetId.isNotBlank() @@ -55,7 +55,7 @@ class VaccinationDGCV1Parser @Inject constructor( private fun CBORObject.toCertificate() = try { val json = ToJSONString() - gson.fromJson<VaccinationDGCV1>(json).validate() + gson.fromJson<VaccinationDccV1>(json).validate() } catch (e: InvalidVaccinationCertificateException) { throw e } catch (e: Throwable) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateData.kt deleted file mode 100644 index 5fcafc3822bbd7953f795040f116b18b84365a9b..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateData.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode - -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.CoseCertificateHeader -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 - -/** - * Represents the parsed data from the QR code - */ -data class VaccinationCertificateData( - val header: CoseCertificateHeader, - val certificate: VaccinationDGCV1, -) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateQRCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateQRCode.kt index c90117e5eb8fa6c2358e5020fadff5f0ec166866..ad88fb5911610916e6ad6a1c1b2abf2493c2c5bb 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateQRCode.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationCertificateQRCode.kt @@ -1,11 +1,11 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode -data class VaccinationCertificateQRCode( - val qrCodeString: QrCodeString, - val parsedData: VaccinationCertificateData, -) { - val uniqueCertificateIdentifier: String - get() = parsedData.certificate.vaccinationDatas.single().uniqueCertificateIdentifier -} +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.qrcode.DccQrCode +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 -typealias QrCodeString = String +data class VaccinationCertificateQRCode( + override val qrCode: QrCodeString, + override val data: DccData<VaccinationDccV1> +) : DccQrCode<VaccinationDccV1> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt index b467ddff11814510f3a8fa9cd7c3794e98b0b319..362c7f7a621ca4628383e5c97f0cf286b405cea3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt @@ -2,24 +2,26 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode import de.rki.coronawarnapp.bugreporting.censors.vaccination.CertificateQrCodeCensor import de.rki.coronawarnapp.coronatest.qrcode.QrCodeExtractor +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccCoseDecoder +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccHeaderParser +import de.rki.coronawarnapp.covidcertificate.common.decoder.RawCOSEObject import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_BASE45_DECODING_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_CBOR_DECODING_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.HC_ZLIB_DECOMPRESSION_FAILED import de.rki.coronawarnapp.covidcertificate.exception.InvalidVaccinationCertificateException -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateCOSEDecoder -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateHeaderParser -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.RawCOSEObject -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1Parser +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1Parser import de.rki.coronawarnapp.util.compression.inflate import de.rki.coronawarnapp.util.encoding.Base45Decoder import timber.log.Timber import javax.inject.Inject class VaccinationQRCodeExtractor @Inject constructor( - private val coseDecoder: HealthCertificateCOSEDecoder, - private val headerParser: HealthCertificateHeaderParser, - private val bodyParser: VaccinationDGCV1Parser, + private val coseDecoder: DccCoseDecoder, + private val headerParser: DccHeaderParser, + private val bodyParser: VaccinationDccV1Parser, ) : QrCodeExtractor<VaccinationCertificateQRCode> { override fun canHandle(rawString: String): Boolean = rawString.startsWith(PREFIX) @@ -34,8 +36,8 @@ class VaccinationQRCodeExtractor @Inject constructor( .parse() return VaccinationCertificateQRCode( - parsedData = parsedData, - qrCodeString = rawString, + qrCode = rawString, + data = parsedData, ) } @@ -53,11 +55,11 @@ class VaccinationQRCodeExtractor @Inject constructor( throw InvalidVaccinationCertificateException(HC_ZLIB_DECOMPRESSION_FAILED) } - fun RawCOSEObject.parse(): VaccinationCertificateData = try { + fun RawCOSEObject.parse(): DccData<VaccinationDccV1> = try { Timber.v("Parsing COSE for vaccination certificate.") val cbor = coseDecoder.decode(this) - VaccinationCertificateData( + DccData( header = headerParser.parse(cbor), certificate = bodyParser.parse(cbor) ).also { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/VaccinationRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/VaccinationRepository.kt index c8b7136e6ca65aa023603fbd8d25c693365a3b8b..187a85d33b612ccf70bd1bd64b16530b1c42bb89 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/VaccinationRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/VaccinationRepository.kt @@ -1,8 +1,7 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.repository import de.rki.coronawarnapp.bugreporting.reportProblem -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier -import de.rki.coronawarnapp.covidcertificate.common.personIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.VC_ALREADY_REGISTERED import de.rki.coronawarnapp.covidcertificate.exception.InvalidVaccinationCertificateException import de.rki.coronawarnapp.covidcertificate.vaccination.core.VaccinatedPerson diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinatedPersonData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinatedPersonData.kt index 516e8867f4648fbe1516696dbc65a3f771759974..ab4663c66ad5b6c44b4a7287ace60be7986d9eb6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinatedPersonData.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinatedPersonData.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.repository.storage import com.google.gson.annotations.SerializedName -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier data class VaccinatedPersonData( @SerializedName("vaccinationData") val vaccinations: Set<VaccinationContainer> = emptySet() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainer.kt index 1b8804fe1945961a92771f47172579576958b626..61aa1c59989870f4ec1c28cb53496093cf72040b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainer.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainer.kt @@ -2,13 +2,12 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.repository.storag import androidx.annotation.Keep import com.google.gson.annotations.SerializedName -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier -import de.rki.coronawarnapp.covidcertificate.common.personIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccHeader +import de.rki.coronawarnapp.covidcertificate.common.qrcode.QrCodeString import de.rki.coronawarnapp.covidcertificate.vaccination.core.VaccinationCertificate -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.CoseCertificateHeader -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.QrCodeString -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateData +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateQRCode import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationQRCodeExtractor import de.rki.coronawarnapp.covidcertificate.valueset.valuesets.VaccinationValueSets @@ -24,25 +23,25 @@ data class VaccinationContainer internal constructor( // Either set by [ContainerPostProcessor] or via [toVaccinationContainer] @Transient lateinit var qrCodeExtractor: VaccinationQRCodeExtractor - @Transient internal var preParsedData: VaccinationCertificateData? = null + @Transient internal var preParsedData: DccData<VaccinationDccV1>? = null // Otherwise GSON unsafes reflection to create this class, and sets the LAZY to null @Suppress("unused") constructor() : this("", Instant.EPOCH) @delegate:Transient - internal val certificateData: VaccinationCertificateData by lazy { - preParsedData ?: qrCodeExtractor.extract(vaccinationQrCode).parsedData + internal val certificateData: DccData<VaccinationDccV1> by lazy { + preParsedData ?: qrCodeExtractor.extract(vaccinationQrCode).data } - val header: CoseCertificateHeader + val header: DccHeader get() = certificateData.header - val certificate: VaccinationDGCV1 + val certificate: VaccinationDccV1 get() = certificateData.certificate - val vaccination: VaccinationDGCV1.VaccinationData - get() = certificate.vaccinationDatas.single() + val vaccination: VaccinationDccV1.VaccinationData + get() = certificate.payload val certificateId: String get() = vaccination.uniqueCertificateIdentifier @@ -58,20 +57,13 @@ data class VaccinationContainer internal constructor( get() = certificate.personIdentifier override val firstName: String? - get() = if (certificate.nameData.givenName.isNullOrBlank()) - certificate.nameData.givenNameStandardized - else certificate.nameData.givenName + get() = certificate.nameData.firstName override val lastName: String - get() = if (certificate.nameData.familyName.isNullOrBlank()) - certificate.nameData.familyNameStandardized - else certificate.nameData.familyName!! + get() = certificate.nameData.lastName override val fullName: String - get() = when { - firstName.isNullOrBlank() -> lastName - else -> "$firstName $lastName" - } + get() = certificate.nameData.fullName override val dateOfBirth: LocalDate get() = certificate.dateOfBirth @@ -97,7 +89,7 @@ data class VaccinationContainer internal constructor( override val certificateCountry: String get() = Locale( userLocale.language, - vaccination.countryOfVaccination.uppercase() + vaccination.certificateCountry.uppercase() ).getDisplayCountry(userLocale) override val certificateId: String @@ -110,7 +102,7 @@ data class VaccinationContainer internal constructor( override val expiresAt: Instant get() = header.expiresAt - override val vaccinationQrCodeString: QrCodeString + override val qrCode: QrCodeString get() = vaccinationQrCode } } @@ -119,9 +111,9 @@ fun VaccinationCertificateQRCode.toVaccinationContainer( scannedAt: Instant, qrCodeExtractor: VaccinationQRCodeExtractor, ) = VaccinationContainer( - vaccinationQrCode = this.qrCodeString, + vaccinationQrCode = this.qrCode, scannedAt = scannedAt, ).apply { this.qrCodeExtractor = qrCodeExtractor - preParsedData = parsedData + preParsedData = data } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsViewModel.kt index 863a6c7c995a75acccb7af1a9a757560763a149a..9cb494dd22f82ea6a76c3595dc0d393a2e0d289b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/details/VaccinationDetailsViewModel.kt @@ -60,8 +60,8 @@ class VaccinationDetailsViewModel @AssistedInject constructor( private fun generateQrCode(certificate: VaccinationCertificate?) = launch { try { mutableStateFlow.value = certificate?.let { - qrCodeText = it.vaccinationQrCodeString - qrCodeGenerator.createQrCode(it.vaccinationQrCodeString) + qrCodeText = it.qrCode + qrCodeGenerator.createQrCode(it.qrCode) } } catch (e: Exception) { Timber.d(e, "generateQrCode failed for vaccinationCertificate=%s", certificate) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/list/VaccinationListViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/list/VaccinationListViewModel.kt index 707490bbe27856c9b78f3a883c78525d1ef93f42..9dea2c3500fe560abdba6ef75945cd14967b6087 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/list/VaccinationListViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/covidcertificate/vaccination/ui/list/VaccinationListViewModel.kt @@ -56,7 +56,7 @@ class VaccinationListViewModel @AssistedInject constructor( // immediately ... emit(null) // ... and after the QR code was generated, it is emitted - emit(qrCodeGenerator.createQrCode(it.getMostRecentVaccinationCertificate.vaccinationQrCodeString)) + emit(qrCodeGenerator.createQrCode(it.getMostRecentVaccinationCertificate.qrCode)) } val uiState: LiveData<UiState> = combine(vaccinatedPersonFlow, vaccinationQrCodeFlow) { vaccinatedPerson, qrCode -> @@ -92,7 +92,7 @@ class VaccinationListViewModel @AssistedInject constructor( onQrCodeClick = { events.postValue( Event.NavigateToQrCodeFullScreen( - qrCode = vaccinatedPerson.getMostRecentVaccinationCertificate.vaccinationQrCodeString, + qrCode = vaccinatedPerson.getMostRecentVaccinationCertificate.qrCode, positionInList = 0 ) ) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt index 572a3d710e0cfab7100da833c0b893f766a42655..ed3ee7d48e3af793155877f19fa6e39e9b7bb831 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt @@ -1,7 +1,8 @@ package de.rki.coronawarnapp.bugreporting.censors.vaccination -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateData +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.mockk @@ -15,19 +16,19 @@ internal class CertificateQrCodeCensorTest { private val testRawString = "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3.ZH9M9ESIGUBA KWML/O6HXK 0D+4O5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3GG396B-43FZT-43:S0X37*ZV+FNI6HXY0ZSVILVQJF//05MVZJ5V.499TXY9KK9+OC+G9QJPNF67J6QW67KQY466PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIJSBHVA7UJQWT.+S+ND%%M%331BH.IA.C8KRDL4O54O4IGUJKJGI0JAXD15IAXMFU*GSHGHD63DAOC9JU0H11+*4.\$S6ZC0JBZAB-C3QHISKE MCAOI8%M3V96-PY\$N6XOWLIBPIAYU:*JIRHUF2XZQ4H9 XJ72WG1K36VF/9BL56%E8T1OEEG%5TW5A 6YO67N6UCE:WT6BT-UMM:ABJK2TMDN1:FW-%T+\$D78NDSC3%5F61NYS-P9LOE0%J/ZAY:N5L4H-H/LH:AO3FU JHG7K46IOIMT.RE%PHLA21JRI3HTC\$AH" - private val testCertificateData = VaccinationCertificateData( + private val testCertificateData = DccData( header = mockk(), - certificate = VaccinationDGCV1( + certificate = VaccinationDccV1( version = "1", - nameData = VaccinationDGCV1.NameData( + nameData = Dcc.NameData( familyName = "Kevin", familyNameStandardized = "KEVIN", givenName = "Bob", givenNameStandardized = "BOB" ), dob = "1969-11-16", - vaccinationDatas = listOf( - VaccinationDGCV1.VaccinationData( + payloads = listOf( + VaccinationDccV1.VaccinationData( targetId = "12345", vaccineId = "1214765", medicalProductId = "aaEd/easd", @@ -35,7 +36,7 @@ internal class CertificateQrCodeCensorTest { doseNumber = 2, totalSeriesOfDoses = 5, dt = "1969-04-20", - countryOfVaccination = "DE", + certificateCountry = "DE", certificateIssuer = "Herbert", uniqueCertificateIdentifier = "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ" ) @@ -77,7 +78,7 @@ internal class CertificateQrCodeCensorTest { "vaccinationCertificate/dateOfBirth, i have been vaccinated with: vaccinationData/targetId " + "vaccinationData/vaccineId vaccinationData/medicalProductId" + " vaccinationData/marketAuthorizationHolderId vaccinationData/vaccinatedAt" + - " vaccinationData/countryOfVaccination vaccinationData/certificateIssuer" + + " vaccinationData/certificateCountry vaccinationData/certificateIssuer" + " vaccinationData/uniqueCertificateIdentifier" } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifierTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifierTest.kt index 2b4da93088477abfdd84f0e59fed62f3be700786..f0b34bd137c7cd1357012aeeb38eb4877a7218cd 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifierTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/common/CertificatePersonIdentifierTest.kt @@ -1,5 +1,6 @@ package de.rki.coronawarnapp.covidcertificate.common +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.VC_DOB_MISMATCH import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException.ErrorCode.VC_NAME_MISMATCH import de.rki.coronawarnapp.covidcertificate.exception.InvalidVaccinationCertificateException diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/execution/TestCertificateProcessorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/execution/TestCertificateProcessorTest.kt index cada4eae052b53069cb6eb37d3bb76b59612e7f4..605e0e21c8a1a7792f4a8c4b1fa4cd8b757f3191 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/execution/TestCertificateProcessorTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/execution/TestCertificateProcessorTest.kt @@ -84,7 +84,7 @@ class TestCertificateProcessorTest : BaseTest() { coEvery { qrCodeExtractor.extract(any(), any()) } returns mockk<TestCertificateQRCode>().apply { every { qrCode } returns "qrCode" - every { testCertificateData } returns mockk() + every { data } returns mockk() } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/TestCertificateRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/TestCertificateRepositoryTest.kt index 3a4dd7cdef30fb5d9727f75f905893447150fdb8..75e7d3204b206d34ced87d863b56b867d7307535 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/TestCertificateRepositoryTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/TestCertificateRepositoryTest.kt @@ -63,7 +63,7 @@ class TestCertificateRepositoryTest : BaseTest() { coEvery { qrCodeExtractor.extract(any(), any()) } returns mockk<TestCertificateQRCode>().apply { every { qrCode } returns "qrCode" - every { testCertificateData } returns mockk() + every { data } returns mockk() } every { valueSetsRepository.latestTestCertificateValueSets } returns emptyFlow() } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateDccParserTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateDccParserTest.kt index 3603b4954f0f6f006d5186e58389aeb3ae221fee..f9f50f5c6da1cda8b97095a696dcd1055dc7515c 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateDccParserTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateDccParserTest.kt @@ -3,7 +3,7 @@ package de.rki.coronawarnapp.covidcertificate.test.core.qrcode import com.google.gson.Gson import com.upokecenter.cbor.CBORObject import de.rki.coronawarnapp.covidcertificate.test.TestData -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateDccParser +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccParser import io.kotest.matchers.shouldBe import okio.ByteString.Companion.decodeHex import org.joda.time.LocalDate @@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test class TestCertificateDccParserTest { - private val bodyParser = TestCertificateDccParser(Gson()) + private val bodyParser = TestDccParser(Gson()) @Test fun `happy path cose decryption with Ellen Cheng`() { @@ -28,9 +28,9 @@ class TestCertificateDccParserTest { dateOfBirth shouldBe LocalDate.parse("1998-02-26") version shouldBe "1.2.1" - with(testCertificateData[0]) { + with(payloads[0]) { uniqueCertificateIdentifier shouldBe "URN:UVCI:01:AT:71EE2559DE38C6BF7304FB65A1A451EC#3" - countryOfTest shouldBe "AT" + certificateCountry shouldBe "AT" certificateIssuer shouldBe "Ministry of Health, Austria" targetId shouldBe "840539006" sampleCollectedAt shouldBe org.joda.time.Instant.parse("2021-02-20T12:34:56+00:00") diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractorTest.kt index 8b67db97d8cfff3a79aac07179c8f67e705f4387..39226fcec68b6fdf0526183fc6aba5a6b1cf5a75 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractorTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/test/core/qrcode/TestCertificateQRCodeExtractorTest.kt @@ -1,14 +1,14 @@ package de.rki.coronawarnapp.covidcertificate.test.core.qrcode import com.google.gson.Gson +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccCoseDecoder +import de.rki.coronawarnapp.covidcertificate.common.decoder.DccHeaderParser import de.rki.coronawarnapp.covidcertificate.cryptography.AesCryptography import de.rki.coronawarnapp.covidcertificate.exception.InvalidHealthCertificateException import de.rki.coronawarnapp.covidcertificate.exception.InvalidTestCertificateException import de.rki.coronawarnapp.covidcertificate.test.TestData -import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestCertificateDccParser +import de.rki.coronawarnapp.covidcertificate.test.core.certificate.TestDccParser import de.rki.coronawarnapp.covidcertificate.vaccination.core.VaccinationQrCodeTestData -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateCOSEDecoder -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateHeaderParser import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import okio.ByteString.Companion.decodeBase64 @@ -18,21 +18,21 @@ import org.junit.jupiter.api.Test import testhelpers.BaseTest class TestCertificateQRCodeExtractorTest : BaseTest() { - private val coseDecoder = HealthCertificateCOSEDecoder(AesCryptography()) - private val headerParser = HealthCertificateHeaderParser() - private val bodyParser = TestCertificateDccParser(Gson()) + private val coseDecoder = DccCoseDecoder(AesCryptography()) + private val headerParser = DccHeaderParser() + private val bodyParser = TestDccParser(Gson()) private val extractor = TestCertificateQRCodeExtractor(coseDecoder, headerParser, bodyParser) @Test fun `happy path qr code`() { val qrCode = extractor.extract(TestData.qrCodeTestCertificate) - with(qrCode.testCertificateData.header) { + with(qrCode.data.header) { issuer shouldBe "AT" issuedAt shouldBe Instant.parse("2021-06-01T10:12:48.000Z") expiresAt shouldBe Instant.parse("2021-06-03T10:12:48.000Z") } - with(qrCode.testCertificateData.certificate) { + with(qrCode.data.certificate) { with(nameData) { familyName shouldBe "Musterfrau-Gößinger" familyNameStandardized shouldBe "MUSTERFRAU<GOESSINGER" @@ -43,9 +43,9 @@ class TestCertificateQRCodeExtractorTest : BaseTest() { dateOfBirth shouldBe LocalDate.parse("1998-02-26") version shouldBe "1.2.1" - with(testCertificateData[0]) { + with(payloads[0]) { uniqueCertificateIdentifier shouldBe "URN:UVCI:01:AT:71EE2559DE38C6BF7304FB65A1A451EC#3" - countryOfTest shouldBe "AT" + certificateCountry shouldBe "AT" certificateIssuer shouldBe "Ministry of Health, Austria" targetId shouldBe "840539006" sampleCollectedAt shouldBe Instant.parse("2021-02-20T12:34:56+00:00") @@ -63,12 +63,12 @@ class TestCertificateQRCodeExtractorTest : BaseTest() { val coseObject = coseWithEncryptedPayload.decodeBase64()!!.toByteArray() val dek = dek.decodeBase64()!!.toByteArray() val result = extractor.extract(dek, coseObject) - with(result.testCertificateData.certificate.nameData) { + with(result.data.certificate.nameData) { familyName shouldBe "Cheng" givenName shouldBe "Ellen" } val result2 = extractor.extract(result.qrCode) - with(result2.testCertificateData.certificate.nameData) { + with(result2.data.certificate.nameData) { familyName shouldBe "Cheng" givenName shouldBe "Ellen" } @@ -81,12 +81,12 @@ class TestCertificateQRCodeExtractorTest : BaseTest() { val coseObject = coseWithEncryptedPayload.decodeBase64()!!.toByteArray() val dek = dek.decodeBase64()!!.toByteArray() val result = extractor.extract(dek, coseObject) - with(result.testCertificateData.certificate.nameData) { + with(result.data.certificate.nameData) { familyName shouldBe "Calamandrei" givenName shouldBe "Brian" } val result2 = extractor.extract(result.qrCode) - with(result2.testCertificateData.certificate.nameData) { + with(result2.data.certificate.nameData) { familyName shouldBe "Calamandrei" givenName shouldBe "Brian" } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationTestData.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationTestData.kt index 7446be10c64eaadacc47f1afc89dfb23a6dcf1c9..079022777951abd1eedc80dfd9e383b08853b2f4 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationTestData.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/VaccinationTestData.kt @@ -1,8 +1,9 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.HealthCertificateHeader -import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDGCV1 -import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateData +import de.rki.coronawarnapp.covidcertificate.common.certificate.Dcc +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData +import de.rki.coronawarnapp.covidcertificate.common.certificate.DccHeader +import de.rki.coronawarnapp.covidcertificate.vaccination.core.certificate.VaccinationDccV1 import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationCertificateQRCode import de.rki.coronawarnapp.covidcertificate.vaccination.core.qrcode.VaccinationQRCodeExtractor import de.rki.coronawarnapp.covidcertificate.vaccination.core.repository.storage.VaccinatedPersonData @@ -19,17 +20,17 @@ class VaccinationTestData @Inject constructor( val personAVac1QRCodeString = "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3KXH9M9ESIGUBA KWML%6S5B9-+P70Q5VC9:BPCNYKMXEE1JAA/CXGG0JK1WL260X638J3-E3ND3DAJ-43TTTO3HK1H3QBCWNZ83UQJ:T0/8F7V0HKN:Q8.HBV+0SZ4GH00T9UKP0T9WC5PF6846A\$Q$76QW6%V98T5\$FQMI5DN9QZ5Y0Q\$UPE%5MZ5*T57ZA\$O7T6LEJOA+MZ55EII-EB1EKC422JBBD0D2K.EJJ14B2MP41WTRZPQEC5L64HX6IAS 8S8FT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKG8VG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT$.FTD852IWKP/HLIJL8JF8JF172IMAS EDAHMXFBFBQSKJE72KV\$FHJ%3O%6:XM+1QD+T2/VKKER3L3%1THL7MGY.1S:T:GLOX6OCE7+RWYL3.C-L27WNV0G::M74O%K7C50AAEI4" - val personAVac1Certificate = VaccinationDGCV1( + val personAVac1Certificate = VaccinationDccV1( version = "1.0.0", - nameData = VaccinationDGCV1.NameData( + nameData = Dcc.NameData( givenName = "Andreas", givenNameStandardized = "ANDREAS", familyName = "Astrá Eins", familyNameStandardized = "ASTRA<EINS", ), dob = "1966-11-11", - vaccinationDatas = listOf( - VaccinationDGCV1.VaccinationData( + payloads = listOf( + VaccinationDccV1.VaccinationData( targetId = "840539006", vaccineId = "1119305005", medicalProductId = "EU/1/21/1529", @@ -37,27 +38,27 @@ class VaccinationTestData @Inject constructor( doseNumber = 1, totalSeriesOfDoses = 2, dt = "2021-03-01", - countryOfVaccination = "DE", + certificateCountry = "DE", certificateIssuer = "Bundesministerium für Gesundheit - Test01", uniqueCertificateIdentifier = "01DE/00001/1119305005/7T1UG87G61Y7NRXIBQJDTYQ9#S", ) ) ) - val personAVac1CertificateHeader = HealthCertificateHeader( + val personAVac1CertificateHeader = DccHeader( issuer = "DE", issuedAt = Instant.parse("2021-05-11T09:25:00.000Z"), expiresAt = Instant.parse("2022-05-11T09:25:00.000Z"), ) - val personAVac1CertificateData = VaccinationCertificateData( + val personAVac1CertificateData = DccData( certificate = personAVac1Certificate, header = personAVac1CertificateHeader ) val personAVac1QRCode = VaccinationCertificateQRCode( - qrCodeString = personAVac1QRCodeString, - parsedData = personAVac1CertificateData, + qrCode = personAVac1QRCodeString, + data = personAVac1CertificateData, ) val personAVac1Container = VaccinationContainer( @@ -71,17 +72,17 @@ class VaccinationTestData @Inject constructor( val personAVac2QRCodeString = "6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3D H9M9ESIGUBA KWMLYX1HXK 0DV:D5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3ND3DAJ-43TTTMDF6S8:B73QN VNZ.0K6HYI3CNN96BPHNW*0I85V.499TXY9KK9%OC+G9QJPNF67J6QW67KQ9G66PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIPUBN9CIZI.EJJ14B2MP41IZRZPQEC5L64HX6IAS 8SAFT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKGGVG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT\$.FTD852IWKP/HLIJL8JF8JF172E2JA0K*WDQMPB8T3%KLUSR43M.F\$QBQDR\$VT7V01Y7J0BOZLH+D-QF6MO\$R3%XB+.4QI596GY\$SITJP5BS0DFROC.7B.2RTB*UNYSM$*00HIL+H" - val personAVac2Certificate = VaccinationDGCV1( + val personAVac2Certificate = VaccinationDccV1( version = "1.0.0", - nameData = VaccinationDGCV1.NameData( + nameData = Dcc.NameData( givenName = "Andreas", givenNameStandardized = "ANDREAS", familyName = "Astrá Eins", familyNameStandardized = "ASTRA<EINS", ), dob = "1966-11-11", - vaccinationDatas = listOf( - VaccinationDGCV1.VaccinationData( + payloads = listOf( + VaccinationDccV1.VaccinationData( targetId = "840539006", vaccineId = "1119305005", medicalProductId = "EU/1/21/1529", @@ -89,27 +90,27 @@ class VaccinationTestData @Inject constructor( doseNumber = 2, totalSeriesOfDoses = 2, dt = "2021-04-27", - countryOfVaccination = "DE", + certificateCountry = "DE", certificateIssuer = "Bundesministerium für Gesundheit - Test01", uniqueCertificateIdentifier = "01DE/00001/1119305005/6IPYBAIDWEWRWW73QEP92FQSN#S", ) ) ) - val personAVac2CertificateHeader = HealthCertificateHeader( + val personAVac2CertificateHeader = DccHeader( issuer = "DE", issuedAt = Instant.parse("2021-05-11T09:26:08.000Z"), expiresAt = Instant.parse("2022-05-11T09:26:08.000Z"), ) - val personAVac2CertificateData = VaccinationCertificateData( + val personAVac2CertificateData = DccData( certificate = personAVac2Certificate, header = personAVac2CertificateHeader ) val personAVac2QRCode = VaccinationCertificateQRCode( - qrCodeString = personAVac2QRCodeString, - parsedData = personAVac2CertificateData, + qrCode = personAVac2QRCodeString, + data = personAVac2CertificateData, ) val personAVac2Container = VaccinationContainer( @@ -127,17 +128,17 @@ class VaccinationTestData @Inject constructor( val personBVac1QRCodeString = "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3QVH9M9ESIGUBA KWML:SPHXK 0DMYF5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3ND3DAJ-43 QTCPFFIJRF3O8H43HX37DUF GFE VMJJYC3SM74E5V.499TXY9KK9+OC+G9QJPNF67J6QW67KQ2G66PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIPUBN9CIZI.EJJ14B2MP41AZRSEQEC5L64HX6IAS3DS2980IQ.DPUHLW\$GAHLW 70SO:GOLIROGO3T59YLQM14+OP\$I/XK\$M8CL6PZB*L8PK99Q9E\$BDZIF9J8-I\$GI0 J1ALL:F71APC9*KF6LF/NLR/FZ.COKEH-BB4OQ9OG4C5AO**HOELK2AZ7LBLEH-BHPLV5GK3DNKE\$JDVPLW1KD0KCZG.M1LUSB5BCQRJ\$DB5N9%V/GO4IHIBBJ-BI%NWRS%LR%\$KR46325NABFDDAFHD9PZP11COD5U*2KQXCA5W8HH/K51DQO8O0-SOSENFH9101U8$3" - val personBVac1Certificate = VaccinationDGCV1( + val personBVac1Certificate = VaccinationDccV1( version = "1.0.0", - nameData = VaccinationDGCV1.NameData( + nameData = Dcc.NameData( givenName = "Boris", givenNameStandardized = "BORIS", familyName = "Johnson Gültig", familyNameStandardized = "JOHNSON<GUELTIG", ), dob = "1966-11-11", - vaccinationDatas = listOf( - VaccinationDGCV1.VaccinationData( + payloads = listOf( + VaccinationDccV1.VaccinationData( targetId = "840539006", vaccineId = "1119305005", medicalProductId = "EU/1/20/1525", @@ -145,27 +146,27 @@ class VaccinationTestData @Inject constructor( doseNumber = 1, totalSeriesOfDoses = 1, dt = "2021-04-20", - countryOfVaccination = "DE", + certificateCountry = "DE", certificateIssuer = "Bundesministerium für Gesundheit - Test01", uniqueCertificateIdentifier = "01DE/00001/1119305005/3H24U2KVOTPCSINK7N64F2OB9#S", ) ) ) - val personBVac1CertificateHeader = HealthCertificateHeader( + val personBVac1CertificateHeader = DccHeader( issuer = "DE", issuedAt = Instant.parse("2021-05-11T09:23:03.000Z"), expiresAt = Instant.parse("2022-05-11T09:23:03.000Z"), ) - val personBVac1CertificateData = VaccinationCertificateData( + val personBVac1CertificateData = DccData( certificate = personBVac1Certificate, header = personBVac1CertificateHeader ) val personBVac1QRCode = VaccinationCertificateQRCode( - qrCodeString = personBVac1QRCodeString, - parsedData = personBVac1CertificateData, + qrCode = personBVac1QRCodeString, + data = personBVac1CertificateData, ) val personBVac1Container = VaccinationContainer( diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt index a740c1d223c2e6d91a01d311c59afa0d70732f2d..a6634d63ac6c477ebbdd7a3dffa50af50258bf5e 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt @@ -42,13 +42,13 @@ class VaccinationQRCodeExtractorTest : BaseTest() { fun `happy path extraction with data`() { val qrCode = extractor.extract(VaccinationQrCodeTestData.validVaccinationQrCode3) - with(qrCode.parsedData.header) { + with(qrCode.data.header) { issuer shouldBe "AT" issuedAt shouldBe Instant.ofEpochSecond(1620392021) expiresAt shouldBe Instant.ofEpochSecond(1620564821) } - with(qrCode.parsedData.certificate) { + with(qrCode.data.certificate) { with(nameData) { familyName shouldBe "Musterfrau-Gößinger" familyNameStandardized shouldBe "MUSTERFRAU<GOESSINGER" @@ -59,9 +59,9 @@ class VaccinationQRCodeExtractorTest : BaseTest() { dateOfBirth shouldBe LocalDate.parse("1998-02-26") version shouldBe "1.0.0" - with(vaccinationDatas[0]) { + with(payloads[0]) { uniqueCertificateIdentifier shouldBe "urn:uvci:01:AT:10807843F94AEE0EE5093FBC254BD813P" - countryOfVaccination shouldBe "AT" + certificateCountry shouldBe "AT" doseNumber shouldBe 1 dt shouldBe "2021-02-18" certificateIssuer shouldBe "BMSGPK Austria" diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainerTest.kt index 4498d70dca75cc2140b2babbd403b8d541c07778..7c9d5d97fbaabf88fb8e2f33441b956fa62a9746 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainerTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/covidcertificate/vaccination/core/repository/storage/VaccinationContainerTest.kt @@ -1,6 +1,6 @@ package de.rki.coronawarnapp.covidcertificate.vaccination.core.repository.storage -import de.rki.coronawarnapp.covidcertificate.common.CertificatePersonIdentifier +import de.rki.coronawarnapp.covidcertificate.common.certificate.CertificatePersonIdentifier import de.rki.coronawarnapp.covidcertificate.vaccination.core.DaggerVaccinationTestComponent import de.rki.coronawarnapp.covidcertificate.vaccination.core.VaccinationTestData import de.rki.coronawarnapp.covidcertificate.valueset.valuesets.DefaultValueSet