Skip to content
Snippets Groups Projects
Unverified Commit d9bf515b authored by Matthias Urhahn's avatar Matthias Urhahn Committed by GitHub
Browse files

Disable log-upload in `device` (prod) builds again (DEV) #2580


* Disable log-upload in `device` (prod) builds again ಠ_ಠ

* Typo

Co-authored-by: default avatarharambasicluka <64483219+harambasicluka@users.noreply.github.com>
Co-authored-by: default avatarRalf Gehrer <ralfgehrer@users.noreply.github.com>
parent 3bcda686
No related branches found
No related tags found
No related merge requests found
Showing
with 136 additions and 13 deletions
...@@ -7,6 +7,7 @@ import de.rki.coronawarnapp.appconfig.ConfigData ...@@ -7,6 +7,7 @@ import de.rki.coronawarnapp.appconfig.ConfigData
import de.rki.coronawarnapp.datadonation.safetynet.DeviceAttestation import de.rki.coronawarnapp.datadonation.safetynet.DeviceAttestation
import de.rki.coronawarnapp.server.protocols.internal.ppdd.ElsOtp import de.rki.coronawarnapp.server.protocols.internal.ppdd.ElsOtp
import de.rki.coronawarnapp.server.protocols.internal.ppdd.ElsOtpRequestAndroid import de.rki.coronawarnapp.server.protocols.internal.ppdd.ElsOtpRequestAndroid
import de.rki.coronawarnapp.util.CWADebug
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import org.joda.time.Instant import org.joda.time.Instant
import timber.log.Timber import timber.log.Timber
...@@ -26,6 +27,11 @@ class LogUploadAuthorizer @Inject constructor( ...@@ -26,6 +27,11 @@ class LogUploadAuthorizer @Inject constructor(
suspend fun getAuthorizedOTP(otp: UUID = UUID.randomUUID()): LogUploadOtp { suspend fun getAuthorizedOTP(otp: UUID = UUID.randomUUID()): LogUploadOtp {
Timber.tag(TAG).d("getAuthorizedOTP() trying to authorize %s", otp) Timber.tag(TAG).d("getAuthorizedOTP() trying to authorize %s", otp)
// TODO ¯\_(ツ)_/¯
if (!CWADebug.isDeviceForTestersBuild) {
throw UnsupportedOperationException()
}
val elsOtp = ElsOtp.ELSOneTimePassword.newBuilder().apply { val elsOtp = ElsOtp.ELSOneTimePassword.newBuilder().apply {
setOtp(otp.toString()) setOtp(otp.toString())
}.build() }.build()
......
...@@ -6,6 +6,12 @@ import de.rki.coronawarnapp.BuildConfig ...@@ -6,6 +6,12 @@ import de.rki.coronawarnapp.BuildConfig
@Suppress("MayBeConstant") @Suppress("MayBeConstant")
object BuildConfigWrap { object BuildConfigWrap {
val DEBUG: Boolean = BuildConfig.DEBUG
val FLAVOR: String = BuildConfig.FLAVOR
val BUILD_TYPE: String = BuildConfig.BUILD_TYPE
val GIT_COMMIT_SHORT_HASH: String = BuildConfig.GIT_COMMIT_SHORT_HASH
val ENVIRONMENT_JSONDATA = BuildConfig.ENVIRONMENT_JSONDATA val ENVIRONMENT_JSONDATA = BuildConfig.ENVIRONMENT_JSONDATA
val ENVIRONMENT_TYPE_DEFAULT = BuildConfig.ENVIRONMENT_TYPE_DEFAULT val ENVIRONMENT_TYPE_DEFAULT = BuildConfig.ENVIRONMENT_TYPE_DEFAULT
......
...@@ -57,7 +57,7 @@ class InformationFragment : Fragment(R.layout.fragment_information), AutoInject ...@@ -57,7 +57,7 @@ class InformationFragment : Fragment(R.layout.fragment_information), AutoInject
setButtonOnClickListener() setButtonOnClickListener()
setAccessibilityDelegate() setAccessibilityDelegate()
// TODO Hidden until further clarification regarding release schedule is available // TODO ¯\_(ツ)_/¯
binding.informationDebuglog.rootLayout.isGone = !CWADebug.isDeviceForTestersBuild binding.informationDebuglog.rootLayout.isGone = !CWADebug.isDeviceForTestersBuild
} }
......
...@@ -4,14 +4,17 @@ import android.annotation.SuppressLint ...@@ -4,14 +4,17 @@ import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.os.Build import android.os.Build
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import de.rki.coronawarnapp.BuildConfig
import de.rki.coronawarnapp.bugreporting.debuglog.DebugLogger import de.rki.coronawarnapp.bugreporting.debuglog.DebugLogger
import de.rki.coronawarnapp.environment.BuildConfigWrap
import de.rki.coronawarnapp.util.debug.UncaughtExceptionLogger import de.rki.coronawarnapp.util.debug.UncaughtExceptionLogger
import de.rki.coronawarnapp.util.di.ApplicationComponent import de.rki.coronawarnapp.util.di.ApplicationComponent
import timber.log.Timber import timber.log.Timber
object CWADebug { object CWADebug {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
var debugLoggerFactory: (Application) -> DebugLogger = { DebugLogger(context = it) }
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
lateinit var debugLogger: DebugLogger lateinit var debugLogger: DebugLogger
...@@ -24,15 +27,19 @@ object CWADebug { ...@@ -24,15 +27,19 @@ object CWADebug {
setupExceptionHandler() setupExceptionHandler()
debugLogger = DebugLogger(context = application).also { debugLogger = debugLoggerFactory(application).also {
it.init() // TODO Disabled until all parties are satisfied, search for ¯\_(ツ)_/¯
if (isDeviceForTestersBuild) it.init()
} }
logDeviceInfos() logDeviceInfos()
} }
fun initAfterInjection(component: ApplicationComponent) { fun initAfterInjection(component: ApplicationComponent) {
debugLogger.setInjectionIsReady(component) // TODO ¯\_(ツ)_/¯
if (isDeviceForTestersBuild) {
debugLogger.setInjectionIsReady(component)
}
} }
val isLogging: Boolean val isLogging: Boolean
...@@ -42,12 +49,13 @@ object CWADebug { ...@@ -42,12 +49,13 @@ object CWADebug {
} }
val isDebugBuildOrMode: Boolean val isDebugBuildOrMode: Boolean
get() = BuildConfig.DEBUG || buildFlavor == BuildFlavor.DEVICE_FOR_TESTERS get() = BuildConfigWrap.DEBUG || buildFlavor == BuildFlavor.DEVICE_FOR_TESTERS
val buildFlavor: BuildFlavor val buildFlavor: BuildFlavor
get() = BuildFlavor.values().single { it.rawValue == BuildConfig.FLAVOR } get() = BuildFlavor.values().single { it.rawValue == BuildConfigWrap.FLAVOR }
val isDeviceForTestersBuild: Boolean = buildFlavor == BuildFlavor.DEVICE_FOR_TESTERS val isDeviceForTestersBuild: Boolean
get() = buildFlavor == BuildFlavor.DEVICE_FOR_TESTERS
enum class BuildFlavor(val rawValue: String) { enum class BuildFlavor(val rawValue: String) {
DEVICE("device"), DEVICE("device"),
...@@ -64,8 +72,8 @@ object CWADebug { ...@@ -64,8 +72,8 @@ object CWADebug {
} }
fun logDeviceInfos() { fun logDeviceInfos() {
Timber.i("CWA version: %s (%s)", BuildConfig.VERSION_CODE, BuildConfig.GIT_COMMIT_SHORT_HASH) Timber.i("CWA version: %s (%s)", BuildConfigWrap.VERSION_CODE, BuildConfigWrap.GIT_COMMIT_SHORT_HASH)
Timber.i("CWA flavor: %s (%s)", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE) Timber.i("CWA flavor: %s (%s)", BuildConfigWrap.FLAVOR, BuildConfigWrap.BUILD_TYPE)
Timber.i("Build.FINGERPRINT: %s", Build.FINGERPRINT) Timber.i("Build.FINGERPRINT: %s", Build.FINGERPRINT)
} }
......
...@@ -13,9 +13,13 @@ class UncaughtExceptionLogger( ...@@ -13,9 +13,13 @@ class UncaughtExceptionLogger(
override fun uncaughtException(thread: Thread, error: Throwable) { override fun uncaughtException(thread: Thread, error: Throwable) {
Timber.tag(thread.name).e(error, "Uncaught exception!") Timber.tag(thread.name).e(error, "Uncaught exception!")
if (CWADebug.isLogging) { try {
// Make sure this crash is written before killing the app. if (CWADebug.isLogging) {
Thread.sleep(1500) // Make sure this crash is written before killing the app.
Thread.sleep(1500)
}
} catch (e: Exception) {
Timber.w("Couldn't delay exception for debug logger.")
} }
wrappedHandler?.uncaughtException(thread, error) wrappedHandler?.uncaughtException(thread, error)
} }
......
...@@ -6,6 +6,8 @@ import de.rki.coronawarnapp.appconfig.LogUploadConfig ...@@ -6,6 +6,8 @@ import de.rki.coronawarnapp.appconfig.LogUploadConfig
import de.rki.coronawarnapp.appconfig.SafetyNetRequirements import de.rki.coronawarnapp.appconfig.SafetyNetRequirements
import de.rki.coronawarnapp.datadonation.safetynet.DeviceAttestation import de.rki.coronawarnapp.datadonation.safetynet.DeviceAttestation
import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpacAndroid import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpacAndroid
import de.rki.coronawarnapp.util.CWADebug
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.Runs import io.mockk.Runs
...@@ -13,6 +15,7 @@ import io.mockk.coEvery ...@@ -13,6 +15,7 @@ import io.mockk.coEvery
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.just import io.mockk.just
import io.mockk.mockkObject
import io.mockk.slot import io.mockk.slot
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.runBlockingTest
...@@ -46,6 +49,9 @@ class LogUploadAuthorizerTest : BaseIOTest() { ...@@ -46,6 +49,9 @@ class LogUploadAuthorizerTest : BaseIOTest() {
fun setup() { fun setup() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
mockkObject(CWADebug)
every { CWADebug.isDeviceForTestersBuild } returns true
every { configData.logUpload } returns logUploadConfig every { configData.logUpload } returns logUploadConfig
every { logUploadConfig.safetyNetRequirements } returns safetyNetRequirements every { logUploadConfig.safetyNetRequirements } returns safetyNetRequirements
...@@ -82,4 +88,16 @@ class LogUploadAuthorizerTest : BaseIOTest() { ...@@ -82,4 +88,16 @@ class LogUploadAuthorizerTest : BaseIOTest() {
attestationRequestSlot.captured.configData shouldBe configData attestationRequestSlot.captured.configData shouldBe configData
attestationRequestSlot.captured.checkDeviceTime shouldBe false attestationRequestSlot.captured.checkDeviceTime shouldBe false
} }
@Test
fun `upload is not possible on prod builds`() = runBlockingTest {
every { CWADebug.isDeviceForTestersBuild } returns false
val expectedOtp = UUID.fromString("15cff19f-af26-41bc-94f2-c1a65075e894")
val instance = createInstance()
shouldThrow<UnsupportedOperationException> {
instance.getAuthorizedOTP(otp = expectedOtp)
}
}
} }
...@@ -4,9 +4,12 @@ import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository ...@@ -4,9 +4,12 @@ import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
import de.rki.coronawarnapp.ui.Country import de.rki.coronawarnapp.ui.Country
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.verify import io.mockk.verify
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
...@@ -25,6 +28,7 @@ class InteroperabilityConfigurationFragmentViewModelTest { ...@@ -25,6 +28,7 @@ class InteroperabilityConfigurationFragmentViewModelTest {
fun setupFreshViewModel() { fun setupFreshViewModel() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
coEvery { interoperabilityRepository.refreshCountries() } just Runs
every { interoperabilityRepository.countryList } returns flowOf(Country.values().toList()) every { interoperabilityRepository.countryList } returns flowOf(Country.values().toList())
} }
......
package de.rki.coronawarnapp.util
import android.app.Application
import de.rki.coronawarnapp.bugreporting.debuglog.DebugLogger
import de.rki.coronawarnapp.environment.BuildConfigWrap
import de.rki.coronawarnapp.util.di.ApplicationComponent
import io.kotest.matchers.shouldBe
import io.mockk.Called
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
import io.mockk.verifySequence
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import testhelpers.BaseTest
import java.io.File
class CWADebugTest : BaseTest() {
@MockK lateinit var application: Application
@MockK lateinit var appComponent: ApplicationComponent
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { application.cacheDir } returns File("cache")
mockkObject(BuildConfigWrap)
every { BuildConfigWrap.FLAVOR } returns "device"
}
@Test
fun `flavor check`() {
CWADebug.isDeviceForTestersBuild shouldBe false
every { BuildConfigWrap.FLAVOR } returns "deviceForTesters"
CWADebug.isDeviceForTestersBuild shouldBe true
CWADebug.buildFlavor shouldBe CWADebug.BuildFlavor.DEVICE_FOR_TESTERS
every { BuildConfigWrap.FLAVOR } returns "device"
CWADebug.buildFlavor shouldBe CWADebug.BuildFlavor.DEVICE
CWADebug.isDeviceForTestersBuild shouldBe false
}
@Test
fun `logging is only initialized on tester builds`() {
val debugLogger: DebugLogger = mockk()
CWADebug.debugLoggerFactory = { debugLogger }
CWADebug.init(application)
CWADebug.initAfterInjection(appComponent)
verify { debugLogger wasNot Called }
}
@Test
fun `logging is initialized on deviceForTester builds`() {
every { BuildConfigWrap.FLAVOR } returns "deviceForTesters"
val debugLogger = mockk<DebugLogger>().apply {
every { init() } just Runs
every { setInjectionIsReady(appComponent) } just Runs
}
CWADebug.debugLoggerFactory = { debugLogger }
CWADebug.init(application)
CWADebug.initAfterInjection(appComponent)
verifySequence {
debugLogger.init()
debugLogger.setInjectionIsReady(appComponent)
}
}
}
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