Skip to content
Snippets Groups Projects
Unverified Commit 062d6fff authored by Lukas Lechner's avatar Lukas Lechner Committed by GitHub
Browse files

Censor private information in log files (EXPOSUREAPP-6516) (#3013)


* Create TraceLocationCensor.kt and add tests

* Create CheckInsCensor.kt and add tests

* Inject new censors

* Censor Trace Location Type

* Create RACoronaTestCensor.kt and RatQrCodeCensor.kt and add tests

* Move censors to sub packages

* Extend RatQrCodeCensor.kt

* Censor RAT profile data

* Address PR feedback: Improve performance

* Address PR feedback

* Censor identifier for corona tests

* Remove useless censor

* Make sure that censoring still works even if the data to censor is deleted

* Censor TraceLocationInputData

* Fix issue in TraceLocationCensor.kt

Co-authored-by: default avatarharambasicluka <64483219+harambasicluka@users.noreply.github.com>
parent b8595e52
No related branches found
No related tags found
No related merge requests found
Showing
with 497 additions and 28 deletions
...@@ -5,12 +5,17 @@ import dagger.Provides ...@@ -5,12 +5,17 @@ import dagger.Provides
import dagger.Reusable import dagger.Reusable
import dagger.multibindings.IntoSet import dagger.multibindings.IntoSet
import de.rki.coronawarnapp.bugreporting.censors.BugCensor import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.DiaryEncounterCensor import de.rki.coronawarnapp.bugreporting.censors.contactdiary.DiaryEncounterCensor
import de.rki.coronawarnapp.bugreporting.censors.DiaryLocationCensor import de.rki.coronawarnapp.bugreporting.censors.contactdiary.DiaryLocationCensor
import de.rki.coronawarnapp.bugreporting.censors.DiaryPersonCensor import de.rki.coronawarnapp.bugreporting.censors.contactdiary.DiaryPersonCensor
import de.rki.coronawarnapp.bugreporting.censors.DiaryVisitCensor import de.rki.coronawarnapp.bugreporting.censors.contactdiary.DiaryVisitCensor
import de.rki.coronawarnapp.bugreporting.censors.QRCodeCensor import de.rki.coronawarnapp.bugreporting.censors.presencetracing.CheckInsCensor
import de.rki.coronawarnapp.bugreporting.censors.RegistrationTokenCensor import de.rki.coronawarnapp.bugreporting.censors.presencetracing.TraceLocationCensor
import de.rki.coronawarnapp.bugreporting.censors.submission.CoronaTestCensor
import de.rki.coronawarnapp.bugreporting.censors.submission.PcrQrCodeCensor
import de.rki.coronawarnapp.bugreporting.censors.submission.RACoronaTestCensor
import de.rki.coronawarnapp.bugreporting.censors.submission.RatProfileCensor
import de.rki.coronawarnapp.bugreporting.censors.submission.RatQrCodeCensor
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebugLoggerScope import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebugLoggerScope
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
import de.rki.coronawarnapp.bugreporting.debuglog.upload.server.LogUploadApiV1 import de.rki.coronawarnapp.bugreporting.debuglog.upload.server.LogUploadApiV1
...@@ -71,11 +76,19 @@ class BugReportingSharedModule { ...@@ -71,11 +76,19 @@ class BugReportingSharedModule {
@Provides @Provides
@IntoSet @IntoSet
fun registrationTokenCensor(censor: RegistrationTokenCensor): BugCensor = censor fun registrationTokenCensor(censor: CoronaTestCensor): BugCensor = censor
@Provides @Provides
@IntoSet @IntoSet
fun qrCodeCensor(censor: QRCodeCensor): BugCensor = censor fun pcrQrCodeCensor(censor: PcrQrCodeCensor): BugCensor = censor
@Provides
@IntoSet
fun ratQrCodeCensor(censor: RatQrCodeCensor): BugCensor = censor
@Provides
@IntoSet
fun raCoronaTestCensor(censor: RACoronaTestCensor): BugCensor = censor
@Provides @Provides
@IntoSet @IntoSet
...@@ -92,4 +105,16 @@ class BugReportingSharedModule { ...@@ -92,4 +105,16 @@ class BugReportingSharedModule {
@Provides @Provides
@IntoSet @IntoSet
fun diaryVisitCensor(censor: DiaryVisitCensor): BugCensor = censor fun diaryVisitCensor(censor: DiaryVisitCensor): BugCensor = censor
@Provides
@IntoSet
fun checkInsCensor(censor: CheckInsCensor): BugCensor = censor
@Provides
@IntoSet
fun traceLocationsCensor(censor: TraceLocationCensor): BugCensor = censor
@Provides
@IntoSet
fun ratProfileCensor(censor: RatProfileCensor): BugCensor = censor
} }
...@@ -38,6 +38,34 @@ interface BugCensor { ...@@ -38,6 +38,34 @@ interface BugCensor {
return true return true
} }
fun withValidDescription(description: String?, action: (String) -> Unit): Boolean {
if (description.isNullOrBlank()) return false
if (description.length < 5) return false
action(description)
return true
}
fun withValidAddress(address: String?, action: (String) -> Unit): Boolean {
if (address.isNullOrBlank()) return false
if (address.length < 4) return false
action(address)
return true
}
fun withValidCity(city: String?, action: (String) -> Unit): Boolean {
if (city.isNullOrBlank()) return false
if (city.length < 3) return false
action(city)
return true
}
fun withValidZipCode(zipCode: String?, action: (String) -> Unit): Boolean {
if (zipCode.isNullOrBlank()) return false
if (zipCode.length < 5) return false
action(zipCode)
return true
}
fun LogLine.toNewLogLineIfDifferent(newMessage: String): LogLine? { fun LogLine.toNewLogLineIfDifferent(newMessage: String): LogLine? {
return if (newMessage != message) copy(message = newMessage) else null return if (newMessage != message) copy(message = newMessage) else null
} }
......
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.contactdiary
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidComment import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidComment
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
......
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.contactdiary
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidEmail import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidEmail
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName
......
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.contactdiary
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidEmail import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidEmail
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName
......
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.contactdiary
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
......
package de.rki.coronawarnapp.bugreporting.censors.presencetracing
import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidAddress
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidDescription
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
import de.rki.coronawarnapp.presencetracing.checkins.CheckInRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject
@Reusable
class CheckInsCensor @Inject constructor(
@DebuggerScope debugScope: CoroutineScope,
private val checkInRepository: CheckInRepository
) : BugCensor {
private val checkInsFlow by lazy {
checkInRepository.allCheckIns.stateIn(
scope = debugScope,
started = SharingStarted.Lazily,
initialValue = null
).filterNotNull()
}
override suspend fun checkLog(entry: LogLine): LogLine? {
val checkIns = checkInsFlow.first()
if (checkIns.isEmpty()) return null
val newLogMsg = checkIns.fold(entry.message) { initial, checkIn ->
var acc = initial
withValidDescription(checkIn.description) { description ->
acc = acc.replace(description, "CheckIn#${checkIn.id}/Description")
}
withValidAddress(checkIn.address) { address ->
acc = acc.replace(address, "CheckIn#${checkIn.id}/Address")
}
acc
}
return entry.toNewLogLineIfDifferent(newLogMsg)
}
}
package de.rki.coronawarnapp.bugreporting.censors.presencetracing
import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidAddress
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidDescription
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
import de.rki.coronawarnapp.presencetracing.locations.TraceLocationUserInput
import de.rki.coronawarnapp.presencetracing.storage.repo.TraceLocationRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject
/**
* Censors Trace Location Data
*
* The information about which data to censor comes from two places
* - traceLocationRepository, for traceLocations that are already stored
* - dataToCensor, which is set before a traceLocation is created; this is needed in cases when the app crashes between
* data input and storing
*/
@Reusable
class TraceLocationCensor @Inject constructor(
@DebuggerScope debugScope: CoroutineScope,
private val traceLocationRepository: TraceLocationRepository
) : BugCensor {
private val traceLocationsFlow by lazy {
traceLocationRepository.allTraceLocations.stateIn(
scope = debugScope,
started = SharingStarted.Lazily,
initialValue = null
).filterNotNull()
}
override suspend fun checkLog(entry: LogLine): LogLine? {
val traceLocations = traceLocationsFlow.first()
var newLogMsg = traceLocations.fold(entry.message) { initial, traceLocation ->
var acc = initial
acc = acc.replace(traceLocation.type.name, "TraceLocation#${traceLocation.id}/Type")
withValidDescription(traceLocation.description) { description ->
acc = acc.replace(description, "TraceLocation#${traceLocation.id}/Description")
}
withValidAddress(traceLocation.address) { address ->
acc = acc.replace(address, "TraceLocation#${traceLocation.id}/Address")
}
acc
}
val inputDataToCensor = dataToCensor
if (inputDataToCensor != null) {
newLogMsg = newLogMsg.replace(inputDataToCensor.type.name, "TraceLocationUserInput#Type")
withValidDescription(inputDataToCensor.description) {
newLogMsg = newLogMsg.replace(inputDataToCensor.description, "TraceLocationUserInput#Description")
}
withValidAddress(inputDataToCensor.address) {
newLogMsg = newLogMsg.replace(inputDataToCensor.address, "TraceLocationUserInput#Address")
}
}
return entry.toNewLogLineIfDifferent(newLogMsg)
}
companion object {
var dataToCensor: TraceLocationUserInput? = null
}
}
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.submission
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.coronatest.CoronaTestRepository import de.rki.coronawarnapp.coronatest.CoronaTestRepository
...@@ -9,17 +10,25 @@ import kotlinx.coroutines.flow.first ...@@ -9,17 +10,25 @@ import kotlinx.coroutines.flow.first
import javax.inject.Inject import javax.inject.Inject
@Reusable @Reusable
class RegistrationTokenCensor @Inject constructor( class CoronaTestCensor @Inject constructor(
private val coronaTestRepository: CoronaTestRepository, private val coronaTestRepository: CoronaTestRepository,
) : BugCensor { ) : BugCensor {
// Keep a history to have references even after the user deletes a test
private val tokenHistory = mutableSetOf<String>()
private val identifierHistory = mutableSetOf<String>()
override suspend fun checkLog(entry: LogLine): LogLine? { override suspend fun checkLog(entry: LogLine): LogLine? {
// The Registration Token is received after registration of PCR and RAT tests. It is required to poll the test result.
val tokens = coronaTestRepository.coronaTests.first().map { it.registrationToken } val tokens = coronaTestRepository.coronaTests.first().map { it.registrationToken }
tokenHistory.addAll(tokens)
if (tokens.isEmpty()) return null val identifiers = coronaTestRepository.coronaTests.first().map { it.identifier }
identifierHistory.addAll(identifiers)
var newMessage = entry.message var newMessage = entry.message
for (token in tokenHistory) {
for (token in tokens) {
if (!entry.message.contains(token)) continue if (!entry.message.contains(token)) continue
newMessage = if (CWADebug.isDeviceForTestersBuild) { newMessage = if (CWADebug.isDeviceForTestersBuild) {
...@@ -29,6 +38,12 @@ class RegistrationTokenCensor @Inject constructor( ...@@ -29,6 +38,12 @@ class RegistrationTokenCensor @Inject constructor(
} }
} }
identifierHistory
.filter { entry.message.contains(it) }
.forEach {
newMessage = newMessage.replace(it, "${it.take(11)}CoronaTest/Identifier")
}
return entry.toNewLogLineIfDifferent(newMessage) return entry.toNewLogLineIfDifferent(newMessage)
} }
......
package de.rki.coronawarnapp.bugreporting.censors package de.rki.coronawarnapp.bugreporting.censors.submission
import dagger.Reusable import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.util.CWADebug import de.rki.coronawarnapp.util.CWADebug
import javax.inject.Inject import javax.inject.Inject
@Reusable @Reusable
class QRCodeCensor @Inject constructor() : BugCensor { class PcrQrCodeCensor @Inject constructor() : BugCensor {
override suspend fun checkLog(entry: LogLine): LogLine? { override suspend fun checkLog(entry: LogLine): LogLine? {
......
package de.rki.coronawarnapp.bugreporting.censors.submission
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
import de.rki.coronawarnapp.coronatest.CoronaTestRepository
import de.rki.coronawarnapp.coronatest.type.rapidantigen.RACoronaTest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import org.joda.time.format.DateTimeFormat
import javax.inject.Inject
class RACoronaTestCensor @Inject constructor(
@DebuggerScope debugScope: CoroutineScope,
private val coronaTestRepository: CoronaTestRepository
) : BugCensor {
private val dayOfBirthFormatter = DateTimeFormat.forPattern("yyyy-MM-dd")
private val coronaTestFlow by lazy {
coronaTestRepository.coronaTests.stateIn(
scope = debugScope,
started = SharingStarted.Lazily,
initialValue = null
).filterNotNull()
}
override suspend fun checkLog(entry: LogLine): LogLine? {
val raCoronaTestFlow = coronaTestFlow.map { tests -> tests.filterIsInstance<RACoronaTest>() }.first()
val raCoronaTest = raCoronaTestFlow.firstOrNull() ?: return null
var newMessage = entry.message
with(raCoronaTest) {
withValidName(firstName) { firstName ->
newMessage = newMessage.replace(firstName, "RATest/FirstName")
}
withValidName(lastName) { lastName ->
newMessage = newMessage.replace(lastName, "RATest/LastName")
}
val dateOfBirthString = dateOfBirth?.toString(dayOfBirthFormatter) ?: return@with
newMessage = newMessage.replace(dateOfBirthString, "RATest/DateOfBirth")
}
return entry.toNewLogLineIfDifferent(newMessage)
}
}
package de.rki.coronawarnapp.bugreporting.censors.submission
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidAddress
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidCity
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidPhoneNumber
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidZipCode
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfile
import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings
import kotlinx.coroutines.flow.first
import org.joda.time.format.DateTimeFormat
import javax.inject.Inject
class RatProfileCensor @Inject constructor(
private val ratProfileSettings: RATProfileSettings
) : BugCensor {
private val dayOfBirthFormatter = DateTimeFormat.forPattern("yyyy-MM-dd")
private val ratProfileHistory = mutableSetOf<RATProfile>()
override suspend fun checkLog(entry: LogLine): LogLine? {
val ratProfile = ratProfileSettings.profile.flow.first()
// store the profile in a property so we still have a reference after it was deleted by the user
if (ratProfile != null) {
ratProfileHistory.add(ratProfile)
}
var newMessage = entry.message
ratProfileHistory.forEach { profile ->
with(profile) {
withValidName(firstName) { firstName ->
newMessage = newMessage.replace(firstName, "RAT-Profile/FirstName")
}
withValidName(lastName) { lastName ->
newMessage = newMessage.replace(lastName, "RAT-Profile/LastName")
}
val dateOfBirthString = birthDate?.toString(dayOfBirthFormatter)
if (dateOfBirthString != null) {
newMessage = newMessage.replace(dateOfBirthString, "RAT-Profile/DateOfBirth")
}
withValidAddress(street) { street ->
newMessage = newMessage.replace(street, "RAT-Profile/Street")
}
withValidCity(city) { city ->
newMessage = newMessage.replace(city, "RAT-Profile/City")
}
withValidZipCode(zipCode) { zipCode ->
newMessage = newMessage.replace(zipCode, "RAT-Profile/Zip-Code")
}
withValidPhoneNumber(phone) { phone ->
newMessage = newMessage.replace(phone, "RAT-Profile/Phone")
}
withValidPhoneNumber(email) { phone ->
newMessage = newMessage.replace(phone, "RAT-Profile/eMail")
}
}
}
return entry.toNewLogLineIfDifferent(newMessage)
}
}
package de.rki.coronawarnapp.bugreporting.censors.submission
import dagger.Reusable
import de.rki.coronawarnapp.bugreporting.censors.BugCensor
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.withValidName
import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
import de.rki.coronawarnapp.coronatest.qrcode.RapidAntigenHash
import de.rki.coronawarnapp.util.CWADebug
import org.joda.time.LocalDate
import org.joda.time.format.DateTimeFormat
import javax.inject.Inject
@Reusable
class RatQrCodeCensor @Inject constructor() : BugCensor {
private val dayOfBirthFormatter = DateTimeFormat.forPattern("yyyy-MM-dd")
override suspend fun checkLog(entry: LogLine): LogLine? {
val dataToCensor = dataToCensor ?: return null
var newMessage = entry.message
with(dataToCensor) {
newMessage = newMessage.replace(rawString, "RatQrCode/ScannedRawString")
newMessage = if (CWADebug.isDeviceForTestersBuild) {
newMessage.replace(hash, PLACEHOLDER + hash.takeLast(28))
} else {
newMessage.replace(hash, PLACEHOLDER + hash.takeLast(4))
}
withValidName(firstName) { firstName ->
newMessage = newMessage.replace(firstName, "RATest/FirstName")
}
withValidName(lastName) { lastName ->
newMessage = newMessage.replace(lastName, "RATest/LastName")
}
val dateOfBirthString = dateOfBirth?.toString(dayOfBirthFormatter) ?: return@with
newMessage = newMessage.replace(dateOfBirthString, "RATest/DateOfBirth")
}
return entry.toNewLogLineIfDifferent(newMessage)
}
companion object {
var dataToCensor: CensorData? = null
private const val PLACEHOLDER = "SHA256HASH-ENDING-WITH-"
}
data class CensorData(
val rawString: String,
val hash: RapidAntigenHash,
val firstName: String?,
val lastName: String?,
val dateOfBirth: LocalDate?
)
}
package de.rki.coronawarnapp.coronatest.qrcode package de.rki.coronawarnapp.coronatest.qrcode
import de.rki.coronawarnapp.bugreporting.censors.submission.PcrQrCodeCensor
import java.util.regex.Pattern import java.util.regex.Pattern
import javax.inject.Inject import javax.inject.Inject
...@@ -8,9 +9,9 @@ class PcrQrCodeExtractor @Inject constructor() : QrCodeExtractor<CoronaTestQRCod ...@@ -8,9 +9,9 @@ class PcrQrCodeExtractor @Inject constructor() : QrCodeExtractor<CoronaTestQRCod
override fun canHandle(rawString: String): Boolean = rawString.startsWith(prefix, ignoreCase = true) override fun canHandle(rawString: String): Boolean = rawString.startsWith(prefix, ignoreCase = true)
override fun extract(rawString: String): CoronaTestQRCode.PCR { override fun extract(rawString: String): CoronaTestQRCode.PCR {
return CoronaTestQRCode.PCR( val guid = extractGUID(rawString)
extractGUID(rawString) PcrQrCodeCensor.lastGUID = guid
) return CoronaTestQRCode.PCR(guid)
} }
private fun extractGUID(rawString: String): CoronaTestGUID { private fun extractGUID(rawString: String): CoronaTestGUID {
......
...@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.coronatest.qrcode ...@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.coronatest.qrcode
import com.google.common.io.BaseEncoding import com.google.common.io.BaseEncoding
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import de.rki.coronawarnapp.bugreporting.censors.submission.RatQrCodeCensor
import de.rki.coronawarnapp.util.HashExtensions.toSHA256 import de.rki.coronawarnapp.util.HashExtensions.toSHA256
import de.rki.coronawarnapp.util.hashing.isSha256Hash import de.rki.coronawarnapp.util.hashing.isSha256Hash
import de.rki.coronawarnapp.util.serialization.fromJson import de.rki.coronawarnapp.util.serialization.fromJson
...@@ -22,6 +23,14 @@ class RapidAntigenQrCodeExtractor @Inject constructor() : QrCodeExtractor<Corona ...@@ -22,6 +23,14 @@ class RapidAntigenQrCodeExtractor @Inject constructor() : QrCodeExtractor<Corona
Timber.v("extract(rawString=%s)", rawString) Timber.v("extract(rawString=%s)", rawString)
val payload = CleanPayload(extractData(rawString)) val payload = CleanPayload(extractData(rawString))
RatQrCodeCensor.dataToCensor = RatQrCodeCensor.CensorData(
rawString = rawString,
hash = payload.hash,
firstName = payload.firstName,
lastName = payload.lastName,
dateOfBirth = payload.dateOfBirth
)
payload.requireValidData() payload.requireValidData()
return CoronaTestQRCode.RapidAntigen( return CoronaTestQRCode.RapidAntigen(
......
...@@ -8,6 +8,7 @@ import dagger.assisted.Assisted ...@@ -8,6 +8,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import de.rki.coronawarnapp.R import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.bugreporting.censors.presencetracing.TraceLocationCensor
import de.rki.coronawarnapp.contactdiary.util.CWADateTimeFormatPatternFactory.shortDatePattern import de.rki.coronawarnapp.contactdiary.util.CWADateTimeFormatPatternFactory.shortDatePattern
import de.rki.coronawarnapp.presencetracing.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.presencetracing.checkins.qrcode.TraceLocation
import de.rki.coronawarnapp.presencetracing.locations.TraceLocationCreator import de.rki.coronawarnapp.presencetracing.locations.TraceLocationCreator
...@@ -68,6 +69,8 @@ class TraceLocationCreateViewModel @AssistedInject constructor( ...@@ -68,6 +69,8 @@ class TraceLocationCreateViewModel @AssistedInject constructor(
defaultCheckInLengthInMinutes = checkInLength.standardMinutes.toInt() defaultCheckInLengthInMinutes = checkInLength.standardMinutes.toInt()
) )
TraceLocationCensor.dataToCensor = userInput
launch { launch {
try { try {
val traceLocation = traceLocationCreator.createTraceLocation(userInput) val traceLocation = traceLocationCreator.createTraceLocation(userInput)
......
...@@ -4,7 +4,6 @@ import androidx.lifecycle.asLiveData ...@@ -4,7 +4,6 @@ import androidx.lifecycle.asLiveData
import com.google.android.gms.common.api.ApiException import com.google.android.gms.common.api.ApiException
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import de.rki.coronawarnapp.bugreporting.censors.QRCodeCensor
import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQrCodeValidator import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQrCodeValidator
import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException
import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider
...@@ -79,8 +78,6 @@ class SubmissionConsentViewModel @AssistedInject constructor( ...@@ -79,8 +78,6 @@ class SubmissionConsentViewModel @AssistedInject constructor(
private suspend fun validateAndRegister(qrCodeString: String) { private suspend fun validateAndRegister(qrCodeString: String) {
try { try {
val coronaTestQRCode = qrCodeValidator.validate(qrCodeString) val coronaTestQRCode = qrCodeValidator.validate(qrCodeString)
// TODO this needs to be adapted to work for different types
QRCodeCensor.lastGUID = coronaTestQRCode.registrationIdentifier
qrCodeValidationState.postValue(QrCodeRegistrationStateProcessor.ValidationState.SUCCESS) qrCodeValidationState.postValue(QrCodeRegistrationStateProcessor.ValidationState.SUCCESS)
val coronaTest = submissionRepository.testForType(coronaTestQRCode.type).first() val coronaTest = submissionRepository.testForType(coronaTestQRCode.type).first()
......
...@@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.submission.qrcode.scan ...@@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.submission.qrcode.scan
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import de.rki.coronawarnapp.bugreporting.censors.QRCodeCensor
import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQrCodeValidator import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQrCodeValidator
import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException import de.rki.coronawarnapp.coronatest.qrcode.InvalidQRCodeException
import de.rki.coronawarnapp.coronatest.type.CoronaTest import de.rki.coronawarnapp.coronatest.type.CoronaTest
...@@ -43,8 +42,6 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor( ...@@ -43,8 +42,6 @@ class SubmissionQRCodeScanViewModel @AssistedInject constructor(
suspend fun startQrCodeRegistration(rawResult: String, isConsentGiven: Boolean) { suspend fun startQrCodeRegistration(rawResult: String, isConsentGiven: Boolean) {
try { try {
val coronaTestQRCode = qrCodeValidator.validate(rawResult) val coronaTestQRCode = qrCodeValidator.validate(rawResult)
// TODO this needs to be adapted to work for different types
QRCodeCensor.lastGUID = coronaTestQRCode.registrationIdentifier
qrCodeValidationState.postValue(QrCodeRegistrationStateProcessor.ValidationState.SUCCESS) qrCodeValidationState.postValue(QrCodeRegistrationStateProcessor.ValidationState.SUCCESS)
val coronaTest = submissionRepository.testForType(coronaTestQRCode.type).first() val coronaTest = submissionRepository.testForType(coronaTestQRCode.type).first()
......
...@@ -54,6 +54,51 @@ class BugCensorTest : BaseTest() { ...@@ -54,6 +54,51 @@ class BugCensorTest : BaseTest() {
BugCensor.withValidComment("abc") {} shouldBe true BugCensor.withValidComment("abc") {} shouldBe true
} }
@Test
fun `description censoring validity`() {
BugCensor.withValidDescription(null) {} shouldBe false
BugCensor.withValidDescription(" ") {} shouldBe false
BugCensor.withValidDescription(" ") {} shouldBe false
BugCensor.withValidDescription("a") {} shouldBe false
BugCensor.withValidDescription("ab") {} shouldBe false
BugCensor.withValidDescription("abc") {} shouldBe false
BugCensor.withValidDescription("abcd") {} shouldBe false
BugCensor.withValidDescription("abcde") {} shouldBe true
}
@Test
fun `address censoring validity`() {
BugCensor.withValidAddress(null) {} shouldBe false
BugCensor.withValidAddress(" ") {} shouldBe false
BugCensor.withValidAddress(" ") {} shouldBe false
BugCensor.withValidAddress("a") {} shouldBe false
BugCensor.withValidAddress("ab") {} shouldBe false
BugCensor.withValidAddress("abc") {} shouldBe false
BugCensor.withValidAddress("abcd") {} shouldBe true
}
@Test
fun `city censoring validity`() {
BugCensor.withValidCity(null) {} shouldBe false
BugCensor.withValidCity(" ") {} shouldBe false
BugCensor.withValidCity(" ") {} shouldBe false
BugCensor.withValidCity("a") {} shouldBe false
BugCensor.withValidCity("ab") {} shouldBe false
BugCensor.withValidCity("abc") {} shouldBe true
}
@Test
fun `zip-code censoring validity`() {
BugCensor.withValidZipCode(null) {} shouldBe false
BugCensor.withValidZipCode(" ") {} shouldBe false
BugCensor.withValidZipCode(" ") {} shouldBe false
BugCensor.withValidZipCode("1") {} shouldBe false
BugCensor.withValidZipCode("12") {} shouldBe false
BugCensor.withValidZipCode("123") {} shouldBe false
BugCensor.withValidZipCode("1234") {} shouldBe false
BugCensor.withValidZipCode("12345") {} shouldBe true
}
@Test @Test
fun `loglines are only copied if the message is different`() { fun `loglines are only copied if the message is different`() {
val logLine = LogLine( val logLine = LogLine(
......
...@@ -6,6 +6,9 @@ import dagger.Provides ...@@ -6,6 +6,9 @@ import dagger.Provides
import de.rki.coronawarnapp.bugreporting.BugReportingSharedModule import de.rki.coronawarnapp.bugreporting.BugReportingSharedModule
import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository
import de.rki.coronawarnapp.coronatest.CoronaTestRepository import de.rki.coronawarnapp.coronatest.CoronaTestRepository
import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings
import de.rki.coronawarnapp.presencetracing.checkins.CheckInRepository
import de.rki.coronawarnapp.presencetracing.storage.repo.TraceLocationRepository
import de.rki.coronawarnapp.submission.SubmissionSettings import de.rki.coronawarnapp.submission.SubmissionSettings
import io.github.classgraph.ClassGraph import io.github.classgraph.ClassGraph
import io.kotest.matchers.collections.shouldContainAll import io.kotest.matchers.collections.shouldContainAll
...@@ -73,4 +76,16 @@ class MockProvider { ...@@ -73,4 +76,16 @@ class MockProvider {
@Singleton @Singleton
@Provides @Provides
fun coronaTestRepository(): CoronaTestRepository = mockk() fun coronaTestRepository(): CoronaTestRepository = mockk()
@Singleton
@Provides
fun checkInRepository(): CheckInRepository = mockk()
@Singleton
@Provides
fun traceLocationRepository(): TraceLocationRepository = mockk()
@Singleton
@Provides
fun ratProfileSettings(): RATProfileSettings = mockk()
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment