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

Commit

Permalink
Map blocked state from DccWalletInfo and remove code that is now obso…
Browse files Browse the repository at this point in the history
…lete (EXPOSUREAPP-12420, EXPOSUREAPP-12308) (#5004)

* Map blocked state from DccWalletInfo and remove code that is now obsolete

* Adjusted certificatesRevokedByInvalidationRules

* Made CertificatesRevokedByInvalidationRules optional

* Fix badges

Co-authored-by: Mohamed Metwalli <mohamed.metwalli@sap.com>
Co-authored-by: BerndMitter <Berndus@gmx.de>
  • Loading branch information
3 people authored Mar 30, 2022
1 parent 303525b commit 1badc0f
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,9 @@ class DccWalletInfoDatabaseTest : BaseTestInstrumentation() {
identifier = "booster_rule_identifier"
)

private val certificatesRevokedByInvalidationRules = CertificatesRevokedByInvalidationRules(
certificateRef = listOf(
CertificateRef(barcodeData = "HC1:7..."),
CertificateRef(barcodeData = "HC1:8...")
)
private val certificatesRevokedByInvalidationRules = listOf(
CertificatesRevokedByInvalidationRules(certificateRef = CertificateRef(barcodeData = "HC1:7...")),
CertificatesRevokedByInvalidationRules(certificateRef = CertificateRef(barcodeData = "HC1:8..."))
)

private val dccWalletInfo = DccWalletInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ data class DccWalletInfo(
val certificateReissuance: CertificateReissuance? = null,

@JsonProperty("certificatesRevokedByInvalidationRules")
val certificatesRevokedByInvalidationRules: CertificatesRevokedByInvalidationRules? = null
val certificatesRevokedByInvalidationRules: List<CertificatesRevokedByInvalidationRules>? = null

) {
@get:JsonIgnore
Expand Down Expand Up @@ -270,5 +270,5 @@ data class ReissuanceDivision(

data class CertificatesRevokedByInvalidationRules(
@JsonProperty("certificateRef")
val certificateRef: List<CertificateRef>
val certificateRef: CertificateRef
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ class DccWalletInfoRepository @Inject constructor(
scope = appScope + dispatcherProvider.IO
)

val blockedCertificateQrCodeHashes: Flow<Set<String>> = personWallets
.map { it.toBlockedCertificateQrCodeHashes() }
.shareLatest(
tag = TAG,
scope = appScope + dispatcherProvider.IO
)

suspend fun save(
personIdentifier: CertificatePersonIdentifier,
dccWalletInfo: DccWalletInfo
Expand All @@ -60,6 +67,15 @@ class DccWalletInfoRepository @Inject constructor(
dccWalletInfoDao.deleteAll()
}

private fun Set<PersonWalletInfo>.toBlockedCertificateQrCodeHashes() = mapNotNull { walletInfo ->
walletInfo
.dccWalletInfo
?.certificatesRevokedByInvalidationRules
?.map { it.certificateRef.qrCodeHash() }
}
.flatten()
.toSet()

companion object {
private val TAG = tag<DccWalletInfoRepository>()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import de.rki.coronawarnapp.covidcertificate.common.certificate.DccData
import de.rki.coronawarnapp.covidcertificate.expiration.DccExpirationChecker
import de.rki.coronawarnapp.covidcertificate.signature.core.DscRepository
import de.rki.coronawarnapp.covidcertificate.signature.core.DscSignatureValidator
import de.rki.coronawarnapp.covidcertificate.validation.core.BlocklistValidator
import de.rki.coronawarnapp.util.TimeStamper
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
Expand All @@ -20,24 +19,19 @@ class DccStateChecker @Inject constructor(
private val appConfigProvider: AppConfigProvider,
private val dscRepository: DscRepository,
private val dscSignatureValidator: DscSignatureValidator,
private val blocklistValidator: BlocklistValidator,
private val expirationChecker: DccExpirationChecker,
) {

suspend fun checkState(
dccData: DccData<*>
dccData: DccData<*>,
qrCodeHash: String,
blockedCertificateQrCodeHashes: Set<String>
): Flow<CwaCovidCertificate.State> = combine(
appConfigProvider.currentConfig,
dscRepository.dscData
) { appConfig, dscData ->

try {
blocklistValidator.validate(
dccData = dccData,
blocklist = appConfig.covidCertificateParameters.blockListParameters
)
} catch (e: Exception) {
Timber.tag(TAG).w("Certificate is in the blocklist %s", e.message)
if (qrCodeHash in blockedCertificateQrCodeHashes) {
return@combine CwaCovidCertificate.State.Blocked
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.rki.coronawarnapp.covidcertificate.recovery.core

import de.rki.coronawarnapp.bugreporting.reportProblem
import de.rki.coronawarnapp.ccl.dccwalletinfo.storage.DccWalletInfoRepository
import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate
import de.rki.coronawarnapp.covidcertificate.common.certificate.DccQrCodeExtractor
import de.rki.coronawarnapp.covidcertificate.common.exception.InvalidHealthCertificateException
Expand Down Expand Up @@ -45,7 +46,8 @@ class RecoveryCertificateRepository @Inject constructor(
private val storage: RecoveryCertificateStorage,
private val dccStateChecker: DccStateChecker,
private val timeStamper: TimeStamper,
dscRepository: DscRepository
dscRepository: DscRepository,
private val dccWalletInfoRepository: DccWalletInfoRepository
) {

private val internalData: HotDataFlow<Map<RecoveryCertificateContainerId, RecoveryCertificateContainer>> =
Expand Down Expand Up @@ -81,12 +83,19 @@ class RecoveryCertificateRepository @Inject constructor(

val freshCertificates: Flow<Set<RecoveryCertificateWrapper>> = combine(
internalData.data,
dscRepository.dscData
) { certMap, _ ->
dscRepository.dscData,
dccWalletInfoRepository.blockedCertificateQrCodeHashes
) { certMap, _, blockedCertificateQrCodeHashes ->
certMap.values
.filter { it.isNotRecycled }
.map { container ->
val state = dccStateChecker.checkState(container.certificateData).first()

val state = dccStateChecker.checkState(
container.certificateData,
container.qrCodeHash,
blockedCertificateQrCodeHashes
).first()

RecoveryCertificateWrapper(
valueSets = valueSetsRepository.latestVaccinationValueSets.first(),
container = container,
Expand Down Expand Up @@ -196,7 +205,12 @@ class RecoveryCertificateRepository @Inject constructor(
return@updateBlocking this
}

val currentState = dccStateChecker.checkState(toUpdate.certificateData).first()
val currentState =
dccStateChecker.checkState(
toUpdate.certificateData,
toUpdate.qrCodeHash,
dccWalletInfoRepository.blockedCertificateQrCodeHashes.first()
).first()

if (currentState == toUpdate.data.lastSeenStateChange) {
Timber.tag(TAG).w("State equals last acknowledged state.")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.rki.coronawarnapp.covidcertificate.test.core

import de.rki.coronawarnapp.bugreporting.reportProblem
import de.rki.coronawarnapp.ccl.dccwalletinfo.storage.DccWalletInfoRepository
import de.rki.coronawarnapp.coronatest.type.BaseCoronaTest
import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate
import de.rki.coronawarnapp.covidcertificate.common.certificate.DccQrCodeExtractor
Expand All @@ -18,18 +19,19 @@ import de.rki.coronawarnapp.covidcertificate.test.core.storage.types.PCRCertific
import de.rki.coronawarnapp.covidcertificate.test.core.storage.types.RACertificateData
import de.rki.coronawarnapp.covidcertificate.test.core.storage.types.RetrievedTestCertificate
import de.rki.coronawarnapp.covidcertificate.valueset.ValueSetsRepository
import de.rki.coronawarnapp.util.HashExtensions.toSHA256
import de.rki.coronawarnapp.util.TimeStamper
import de.rki.coronawarnapp.util.coroutine.AppScope
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.encryption.rsa.RSAKeyPairGenerator
import de.rki.coronawarnapp.util.flow.HotDataFlow
import de.rki.coronawarnapp.util.flow.combine
import de.rki.coronawarnapp.util.flow.shareLatest
import de.rki.coronawarnapp.util.mutate
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
Expand All @@ -56,7 +58,8 @@ class TestCertificateRepository @Inject constructor(
valueSetsRepository: ValueSetsRepository,
private val rsaKeyPairGenerator: RSAKeyPairGenerator,
private val dccStateChecker: DccStateChecker,
dscRepository: DscRepository
dscRepository: DscRepository,
private val dccWalletInfoRepository: DccWalletInfoRepository
) {

private val internalData: HotDataFlow<Map<TestCertificateContainerId, TestCertificateContainer>> = HotDataFlow(
Expand All @@ -79,15 +82,19 @@ class TestCertificateRepository @Inject constructor(
val certificates: Flow<Set<TestCertificateWrapper>> = combine(
internalData.data,
valueSetsRepository.latestTestCertificateValueSets,
dscRepository.dscData
) { certMap, valueSets, _ ->
dscRepository.dscData,
dccWalletInfoRepository.blockedCertificateQrCodeHashes
) { certMap, valueSets, _, blockedCertificateQrCodeHashes ->
certMap.values
.filter { it.isNotRecycled }
.map { container ->
val state = when {
container.isCertificateRetrievalPending -> CwaCovidCertificate.State.Invalid()
else -> container.testCertificateQRCode?.data?.let {
dccStateChecker.checkState(it).first()
else -> container.testCertificateQRCode?.let {
dccStateChecker.checkState(
it.data, it.qrCode.toSHA256(),
blockedCertificateQrCodeHashes
).first()
} ?: CwaCovidCertificate.State.Invalid()
}

Expand Down Expand Up @@ -431,7 +438,11 @@ class TestCertificateRepository @Inject constructor(
return@updateBlocking this
}

val currentState = dccStateChecker.checkState(current.testCertificateQRCode!!.data).first()
val currentState = dccStateChecker.checkState(
current.testCertificateQRCode!!.data,
current.qrCodeHash,
dccWalletInfoRepository.blockedCertificateQrCodeHashes.first()
).first()

if (currentState !is CwaCovidCertificate.State.Invalid) {
Timber.tag(TAG).w("%s is still valid ", containerId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.rki.coronawarnapp.covidcertificate.vaccination.core.repository

import de.rki.coronawarnapp.bugreporting.reportProblem
import de.rki.coronawarnapp.ccl.dccwalletinfo.storage.DccWalletInfoRepository
import de.rki.coronawarnapp.covidcertificate.common.certificate.CwaCovidCertificate
import de.rki.coronawarnapp.covidcertificate.common.certificate.DccQrCodeExtractor
import de.rki.coronawarnapp.covidcertificate.common.exception.InvalidHealthCertificateException.ErrorCode.ALREADY_REGISTERED
Expand Down Expand Up @@ -39,6 +40,7 @@ import javax.inject.Inject
import javax.inject.Singleton

@Singleton
@Suppress("LongParameterList")
class VaccinationCertificateRepository @Inject constructor(
dispatcherProvider: DispatcherProvider,
valueSetsRepository: ValueSetsRepository,
Expand All @@ -48,7 +50,8 @@ class VaccinationCertificateRepository @Inject constructor(
private val dccStateChecker: DccStateChecker,
private val vaccinationMigration: VaccinationMigration,
@AppScope private val appScope: CoroutineScope,
dscRepository: DscRepository
dscRepository: DscRepository,
private val dccWalletInfoRepository: DccWalletInfoRepository
) {

private val internalData: HotDataFlow<Map<VaccinationCertificateContainerId, VaccinationCertificateContainer>> =
Expand All @@ -72,12 +75,19 @@ class VaccinationCertificateRepository @Inject constructor(
val freshCertificates: Flow<Set<VaccinationCertificateWrapper>> = combine(
internalData.data,
valueSetsRepository.latestVaccinationValueSets,
dscRepository.dscData
) { certMap, valueSets, _ ->
dscRepository.dscData,
dccWalletInfoRepository.blockedCertificateQrCodeHashes
) { certMap, valueSets, _, blockedCertificateQrCodeHashes ->
certMap.values
.filter { it.isNotRecycled }
.map { container ->
val state = dccStateChecker.checkState(container.certificateData).first()

val state = dccStateChecker.checkState(
container.certificateData,
container.qrCodeHash,
blockedCertificateQrCodeHashes
).first()

VaccinationCertificateWrapper(
valueSets = valueSets,
container = container,
Expand Down Expand Up @@ -197,7 +207,11 @@ class VaccinationCertificateRepository @Inject constructor(
return@updateBlocking this
}

val currentState = dccStateChecker.checkState(toUpdate.certificateData).first()
val currentState = dccStateChecker.checkState(
toUpdate.certificateData,
toUpdate.qrCodeHash,
dccWalletInfoRepository.blockedCertificateQrCodeHashes.first()
).first()

if (currentState == toUpdate.data.lastSeenStateChange) {
Timber.tag(TAG).w("State equals last acknowledged state.")
Expand Down

This file was deleted.

Loading

0 comments on commit 1badc0f

Please sign in to comment.