diff --git a/Corona-Warn-App/config/detekt.yml b/Corona-Warn-App/config/detekt.yml index 9cad3798d18..16a273985e2 100644 --- a/Corona-Warn-App/config/detekt.yml +++ b/Corona-Warn-App/config/detekt.yml @@ -66,7 +66,7 @@ complexity: active: true threshold: 15 ignoreSingleWhenExpression: false - ignoreSimpleWhenEntries: false + ignoreSimpleWhenEntries: true ignoreNestingFunctions: false nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull] LabeledExpression: @@ -514,7 +514,15 @@ style: maxJumpCount: 1 MagicNumber: active: true - excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt'] + excludes: [ + '**/test/**', + '**/androidTest/**', + '**/*.Test.kt', + '**/*.Spec.kt', + '**/*.Spek.kt', + '**/CwaWebException.kt', + '**/HttpErrorParser.kt' + ] ignoreNumbers: ['-1', '0', '1', '2'] ignoreHashCodeFunction: true ignorePropertyDeclaration: false @@ -523,7 +531,7 @@ style: ignoreCompanionObjectPropertyDeclaration: true ignoreAnnotation: false ignoreNamedArgument: true - ignoreEnums: false + ignoreEnums: true ignoreRanges: false MandatoryBracesIfStatements: active: false diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt deleted file mode 100644 index 55b2acb7cde..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * Corona-Warn-App * - * * - * SAP SE and all other contributors / * - * copyright owners license this file to you under the Apache * - * License, Version 2.0 (the "License"); you may not use this * - * file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ******************************************************************************/ - -package de.rki.coronawarnapp.exception - -/** - * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder] - * - * @param message an Exception thrown inside the WebRequestBuilder - * @param cause the cause of the error - */ -class SubmissionTanInvalidException(message: String, cause: Throwable) : Exception(message, cause) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt deleted file mode 100644 index b2af0b017dc..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * Corona-Warn-App * - * * - * SAP SE and all other contributors / * - * copyright owners license this file to you under the Apache * - * License, Version 2.0 (the "License"); you may not use this * - * file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ******************************************************************************/ - -package de.rki.coronawarnapp.exception - -/** - * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder] - * - * @param message an Exception thrown inside the WebRequestBuilder - * @param cause the cause of the error - */ -class TestAlreadyPairedException(message: String, cause: Throwable) : Exception(message, cause) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt deleted file mode 100644 index 77619440763..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * Corona-Warn-App * - * * - * SAP SE and all other contributors / * - * copyright owners license this file to you under the Apache * - * License, Version 2.0 (the "License"); you may not use this * - * file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ******************************************************************************/ - -package de.rki.coronawarnapp.exception - -/** - * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder] - * - * @param message an Exception thrown inside the WebRequestBuilder - * @param cause the cause of the error - */ -class TestPairingInvalidException(message: String, cause: Throwable) : Exception(message, cause) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/WebRequestException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/WebRequestException.kt deleted file mode 100644 index bb9d4442e47..00000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/WebRequestException.kt +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * Corona-Warn-App * - * * - * SAP SE and all other contributors / * - * copyright owners license this file to you under the Apache * - * License, Version 2.0 (the "License"); you may not use this * - * file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ******************************************************************************/ - -package de.rki.coronawarnapp.exception - -/** - * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder] - * - * @param message an Exception thrown inside the WebRequestBuilder - * @param cause the cause of the error - */ -class WebRequestException(message: String, cause: Throwable) : Exception(message, cause) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt new file mode 100644 index 00000000000..fd628417f20 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt @@ -0,0 +1,44 @@ +package de.rki.coronawarnapp.exception.http + +import java.io.IOException + +open class CwaWebException(statusCode: Int) : IOException( + "error during web request, http status $statusCode" +) + +open class CwaServerError(val statusCode: Int) : CwaWebException(statusCode) { + init { + if (statusCode !in 500..599) + throw IllegalArgumentException("a server error has to have code 5xx") + } +} + +open class CwaClientError(val statusCode: Int) : CwaWebException(statusCode) { + init { + if (statusCode !in 400..499) + throw IllegalArgumentException("a client error has to have code 4xx") + } +} + +open class CwaSuccessResponseWithCodeMismatchNotSupportedError(val statusCode: Int) : CwaWebException(statusCode) +open class CwaInformationalNotSupportedError(val statusCode: Int) : CwaWebException(statusCode) +open class CwaRedirectNotSupportedError(val statusCode: Int) : CwaWebException(statusCode) + +class BadRequestException : CwaClientError(400) +class UnauthorizedException : CwaClientError(401) +class ForbiddenException : CwaClientError(403) +class NotFoundException : CwaClientError(404) +class ConflictException : CwaClientError(409) +class GoneException : CwaClientError(410) +class UnsupportedMediaTypeException : CwaClientError(415) +class TooManyRequestsException : CwaClientError(429) + +class InternalServerErrorException : CwaServerError(500) +class NotImplementedException : CwaServerError(501) +class BadGatewayException : CwaServerError(502) +class ServiceUnavailableException : CwaServerError(503) +class GatewayTimeoutException : CwaServerError(504) +class HTTPVersionNotSupported : CwaServerError(505) +class NetworkAuthenticationRequiredException : CwaServerError(511) +class NetworkReadTimeoutException : CwaServerError(598) +class NetworkConnectTimeoutException : CwaServerError(599) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt new file mode 100644 index 00000000000..66001700537 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt @@ -0,0 +1,64 @@ +package de.rki.coronawarnapp.http + +import de.rki.coronawarnapp.exception.http.BadGatewayException +import de.rki.coronawarnapp.exception.http.CwaWebException +import de.rki.coronawarnapp.exception.http.BadRequestException +import de.rki.coronawarnapp.exception.http.ConflictException +import de.rki.coronawarnapp.exception.http.CwaClientError +import de.rki.coronawarnapp.exception.http.CwaInformationalNotSupportedError +import de.rki.coronawarnapp.exception.http.CwaRedirectNotSupportedError +import de.rki.coronawarnapp.exception.http.CwaServerError +import de.rki.coronawarnapp.exception.http.CwaSuccessResponseWithCodeMismatchNotSupportedError +import de.rki.coronawarnapp.exception.http.ForbiddenException +import de.rki.coronawarnapp.exception.http.GatewayTimeoutException +import de.rki.coronawarnapp.exception.http.GoneException +import de.rki.coronawarnapp.exception.http.HTTPVersionNotSupported +import de.rki.coronawarnapp.exception.http.InternalServerErrorException +import de.rki.coronawarnapp.exception.http.NetworkAuthenticationRequiredException +import de.rki.coronawarnapp.exception.http.NetworkConnectTimeoutException +import de.rki.coronawarnapp.exception.http.NetworkReadTimeoutException +import de.rki.coronawarnapp.exception.http.NotFoundException +import de.rki.coronawarnapp.exception.http.NotImplementedException +import de.rki.coronawarnapp.exception.http.ServiceUnavailableException +import de.rki.coronawarnapp.exception.http.TooManyRequestsException +import de.rki.coronawarnapp.exception.http.UnauthorizedException +import de.rki.coronawarnapp.exception.http.UnsupportedMediaTypeException +import okhttp3.Interceptor +import okhttp3.Response + +class HttpErrorParser : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val response = chain.proceed(chain.request()) + return when (val code = response.code) { + 200 -> response + 201 -> response + 202 -> response + 204 -> response + 400 -> throw BadRequestException() + 401 -> throw UnauthorizedException() + 403 -> throw ForbiddenException() + 404 -> throw NotFoundException() + 409 -> throw ConflictException() + 410 -> throw GoneException() + 415 -> throw UnsupportedMediaTypeException() + 429 -> throw TooManyRequestsException() + 500 -> throw InternalServerErrorException() + 501 -> throw NotImplementedException() + 502 -> throw BadGatewayException() + 503 -> throw ServiceUnavailableException() + 504 -> throw GatewayTimeoutException() + 505 -> throw HTTPVersionNotSupported() + 511 -> throw NetworkAuthenticationRequiredException() + 598 -> throw NetworkReadTimeoutException() + 599 -> throw NetworkConnectTimeoutException() + else -> { + if (code in 100..199) throw CwaInformationalNotSupportedError(code) + if (code in 200..299) throw CwaSuccessResponseWithCodeMismatchNotSupportedError(code) + if (code in 300..399) throw CwaRedirectNotSupportedError(code) + if (code in 400..499) throw CwaClientError(code) + if (code in 500..599) throw CwaServerError(code) + throw CwaWebException(code) + } + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt index b17803daad1..90c2fd6fcfc 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt @@ -39,7 +39,8 @@ class ServiceFactory { if (BuildConfig.DEBUG) it.setLevel(HttpLoggingInterceptor.Level.BODY) }, OfflineCacheInterceptor(CoronaWarnApplication.getAppContext()), - RetryInterceptor() + RetryInterceptor(), + HttpErrorParser() ) /** diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt index e30de86ea56..fc4cc03daa3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt @@ -23,10 +23,7 @@ import KeyExportFormat import android.util.Log import de.rki.coronawarnapp.exception.DiagnosisKeyRetrievalException import de.rki.coronawarnapp.exception.DiagnosisKeySubmissionException -import de.rki.coronawarnapp.exception.SubmissionTanInvalidException import de.rki.coronawarnapp.http.WebRequestBuilder -import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants.SERVER_ERROR_CODE_403 -import retrofit2.HttpException /** * The Diagnosis Key Service is used to interact with the Server to submit and retrieve keys through @@ -50,21 +47,11 @@ object DiagnosisKeyService { * @param keysToReport - KeyList in the Server Format to submit to the Server */ suspend fun asyncSubmitKeys(authCode: String, keysToReport: List) { - try { - Log.d(TAG, "Diagnosis Keys will be submitted.") - WebRequestBuilder.asyncSubmitKeysToServer( - authCode, - false, - keysToReport - ) - } catch (e: HttpException) { - if (e.code() == SERVER_ERROR_CODE_403) { - throw SubmissionTanInvalidException( - "the test paring to the device is invalid", - e - ) - } - throw e - } + Log.d(TAG, "Diagnosis Keys will be submitted.") + WebRequestBuilder.asyncSubmitKeysToServer( + authCode, + false, + keysToReport + ) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt index fc3f3266758..6cdd39fee0d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt @@ -2,38 +2,24 @@ package de.rki.coronawarnapp.service.submission import de.rki.coronawarnapp.exception.NoGUIDOrTANSetException import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException -import de.rki.coronawarnapp.exception.TestAlreadyPairedException -import de.rki.coronawarnapp.exception.TestPairingInvalidException import de.rki.coronawarnapp.http.WebRequestBuilder import de.rki.coronawarnapp.service.submission.SubmissionConstants.QR_CODE_KEY_TYPE -import de.rki.coronawarnapp.service.submission.SubmissionConstants.SERVER_ERROR_CODE_400 import de.rki.coronawarnapp.service.submission.SubmissionConstants.TELE_TAN_KEY_TYPE import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction import de.rki.coronawarnapp.util.formatter.TestResult -import retrofit2.HttpException object SubmissionService { suspend fun asyncRegisterDevice() { - try { - val testGUID = LocalData.testGUID() - val testTAN = LocalData.teletan() - - when { - testGUID != null -> asyncRegisterDeviceViaGUID(testGUID) - testTAN != null -> asyncRegisterDeviceViaTAN(testTAN) - else -> throw NoGUIDOrTANSetException() - } - LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis()) - } catch (err: HttpException) { - if (err.code() == SERVER_ERROR_CODE_400) { - throw TestAlreadyPairedException( - "the test was already paired to a different device", - err - ) - } - throw err + val testGUID = LocalData.testGUID() + val testTAN = LocalData.teletan() + + when { + testGUID != null -> asyncRegisterDeviceViaGUID(testGUID) + testTAN != null -> asyncRegisterDeviceViaTAN(testTAN) + else -> throw NoGUIDOrTANSetException() } + LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis()) } private suspend fun asyncRegisterDeviceViaGUID(guid: String) { @@ -59,17 +45,7 @@ object SubmissionService { } suspend fun asyncRequestAuthCode(registrationToken: String): String { - try { - return WebRequestBuilder.asyncGetTan(registrationToken) - } catch (err: HttpException) { - if (err.code() == SERVER_ERROR_CODE_400) { - throw TestPairingInvalidException( - "the test paring to the device is invalid", - err - ) - } - throw err - } + return WebRequestBuilder.asyncGetTan(registrationToken) } suspend fun asyncSubmitExposureKeys() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt index 97d467a1fb5..0b3a2ccef22 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionQRCodeScanFragment.kt @@ -11,14 +11,16 @@ import com.journeyapps.barcodescanner.BarcodeResult import com.journeyapps.barcodescanner.DefaultDecoderFactory import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionQrCodeScanBinding -import de.rki.coronawarnapp.exception.TestAlreadyPairedException +import de.rki.coronawarnapp.exception.http.BadRequestException +import de.rki.coronawarnapp.exception.http.CwaClientError +import de.rki.coronawarnapp.exception.http.CwaServerError +import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.main.MainActivity import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.CameraPermissionHelper import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.observeEvent -import retrofit2.HttpException /** * A simple [BaseFragment] subclass. @@ -57,9 +59,9 @@ class SubmissionQRCodeScanFragment : BaseFragment() { _binding = null } - private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { + private fun buildErrorDialog(exception: CwaWebException): DialogHelper.DialogInstance { return when (exception) { - is TestAlreadyPairedException -> DialogHelper.DialogInstance( + is BadRequestException -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_test_paired_title, R.string.submission_error_dialog_web_test_paired_body, @@ -68,12 +70,24 @@ class SubmissionQRCodeScanFragment : BaseFragment() { true, ::navigateToDispatchScreen ) - is HttpException -> DialogHelper.DialogInstance( + is CwaServerError -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_generic_error_title, getString( R.string.submission_error_dialog_web_generic_network_error_body, - exception.code() + exception.statusCode + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + is CwaClientError -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.statusCode ), R.string.submission_error_dialog_web_generic_error_button_positive, null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt index 477722597f3..02872234709 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt @@ -8,15 +8,16 @@ import androidx.fragment.app.activityViewModels import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionPositiveOtherWarningBinding -import de.rki.coronawarnapp.exception.SubmissionTanInvalidException -import de.rki.coronawarnapp.exception.TestPairingInvalidException +import de.rki.coronawarnapp.exception.http.BadRequestException +import de.rki.coronawarnapp.exception.http.CwaClientError +import de.rki.coronawarnapp.exception.http.CwaServerError +import de.rki.coronawarnapp.exception.http.ForbiddenException import de.rki.coronawarnapp.nearby.InternalExposureNotificationPermissionHelper import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.observeEvent -import retrofit2.HttpException class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), InternalExposureNotificationPermissionHelper.Callback { @@ -71,7 +72,7 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { return when (exception) { - is TestPairingInvalidException -> DialogHelper.DialogInstance( + is BadRequestException -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_paring_invalid_title, R.string.submission_error_dialog_web_paring_invalid_body, @@ -80,7 +81,7 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), true, ::navigateToSubmissionResultFragment ) - is SubmissionTanInvalidException -> DialogHelper.DialogInstance( + is ForbiddenException -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_tan_invalid_title, R.string.submission_error_dialog_web_tan_invalid_body, @@ -89,12 +90,24 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(), true, ::navigateToSubmissionResultFragment ) - is HttpException -> DialogHelper.DialogInstance( + is CwaServerError -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_generic_error_title, getString( R.string.submission_error_dialog_web_generic_network_error_body, - exception.code() + exception.statusCode + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToSubmissionResultFragment + ) + is CwaClientError -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.statusCode ), R.string.submission_error_dialog_web_generic_error_button_positive, null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt index 56b4c46080f..62877109447 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt @@ -7,12 +7,14 @@ import android.view.ViewGroup import androidx.fragment.app.activityViewModels import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionTanBinding -import de.rki.coronawarnapp.exception.TestAlreadyPairedException +import de.rki.coronawarnapp.exception.http.BadRequestException +import de.rki.coronawarnapp.exception.http.CwaClientError +import de.rki.coronawarnapp.exception.http.CwaServerError +import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.observeEvent -import retrofit2.HttpException /** * Fragment for TAN entry @@ -41,9 +43,9 @@ class SubmissionTanFragment : BaseFragment() { _binding = null } - private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { + private fun buildErrorDialog(exception: CwaWebException): DialogHelper.DialogInstance { return when (exception) { - is TestAlreadyPairedException -> DialogHelper.DialogInstance( + is BadRequestException -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_test_paired_title, R.string.submission_error_dialog_web_test_paired_body, @@ -52,12 +54,24 @@ class SubmissionTanFragment : BaseFragment() { true, ::navigateToDispatchScreen ) - is HttpException -> DialogHelper.DialogInstance( + is CwaServerError -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_generic_error_title, getString( R.string.submission_error_dialog_web_generic_network_error_body, - exception.code() + exception.statusCode + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToDispatchScreen + ) + is CwaClientError -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.statusCode ), R.string.submission_error_dialog_web_generic_error_button_positive, null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt index c0b07dfed34..3037b5b61e0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt @@ -7,12 +7,14 @@ import android.view.ViewGroup import androidx.fragment.app.activityViewModels import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultBinding +import de.rki.coronawarnapp.exception.http.CwaClientError +import de.rki.coronawarnapp.exception.http.CwaServerError +import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.ui.BaseFragment import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.util.DialogHelper import de.rki.coronawarnapp.util.observeEvent -import retrofit2.HttpException /** * A simple [BaseFragment] subclass. @@ -44,14 +46,26 @@ class SubmissionTestResultFragment : BaseFragment() { private fun navigateToMainScreen() = doNavigate(SubmissionTestResultFragmentDirections.actionSubmissionResultFragmentToMainFragment()) - private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance { + private fun buildErrorDialog(exception: CwaWebException): DialogHelper.DialogInstance { return when (exception) { - is HttpException -> DialogHelper.DialogInstance( + is CwaServerError -> DialogHelper.DialogInstance( requireActivity(), R.string.submission_error_dialog_web_generic_error_title, getString( R.string.submission_error_dialog_web_generic_network_error_body, - exception.code() + exception.statusCode + ), + R.string.submission_error_dialog_web_generic_error_button_positive, + null, + true, + ::navigateToMainScreen + ) + is CwaClientError -> DialogHelper.DialogInstance( + requireActivity(), + R.string.submission_error_dialog_web_generic_error_title, + getString( + R.string.submission_error_dialog_web_generic_network_error_body, + exception.statusCode ), R.string.submission_error_dialog_web_generic_error_button_positive, null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt index 39431e54f09..60ab8b5cdc4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt @@ -4,6 +4,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import de.rki.coronawarnapp.exception.ExceptionCategory +import de.rki.coronawarnapp.exception.http.CwaWebException +import de.rki.coronawarnapp.exception.report import de.rki.coronawarnapp.service.submission.SubmissionService import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository @@ -18,24 +21,24 @@ class SubmissionViewModel : ViewModel() { private val _scanStatus = MutableLiveData(Event(ScanStatus.STARTED)) private val _registrationState = MutableLiveData(Event(ApiRequestState.IDLE)) - private val _registrationError = MutableLiveData>(null) + private val _registrationError = MutableLiveData>(null) private val _uiStateState = MutableLiveData(ApiRequestState.IDLE) - private val _uiStateError = MutableLiveData>(null) + private val _uiStateError = MutableLiveData>(null) private val _submissionState = MutableLiveData(Event(ApiRequestState.IDLE)) - private val _submissionError = MutableLiveData>(null) + private val _submissionError = MutableLiveData>(null) val scanStatus: LiveData> = _scanStatus val registrationState: LiveData> = _registrationState - val registrationError: LiveData> = _registrationError + val registrationError: LiveData> = _registrationError val uiStateState: LiveData = _uiStateState - val uiStateError: LiveData> = _uiStateError + val uiStateError: LiveData> = _uiStateError val submissionState: LiveData> = _submissionState - val submissionError: LiveData> = _submissionError + val submissionError: LiveData> = _submissionError val deviceRegistered get() = LocalData.registrationToken() != null @@ -89,16 +92,18 @@ class SubmissionViewModel : ViewModel() { private fun executeRequestWithState( apiRequest: suspend () -> Unit, state: MutableLiveData, - exceptionLiveData: MutableLiveData>? = null + exceptionLiveData: MutableLiveData>? = null ) { state.value = ApiRequestState.STARTED viewModelScope.launch { try { apiRequest() state.value = ApiRequestState.SUCCESS - } catch (err: Exception) { + } catch (err: CwaWebException) { exceptionLiveData?.value = Event(err) state.value = ApiRequestState.FAILED + } catch (err: Exception) { + err.report(ExceptionCategory.INTERNAL) } } } @@ -106,16 +111,18 @@ class SubmissionViewModel : ViewModel() { private fun executeRequestWithStateForEvent( apiRequest: suspend () -> Unit, state: MutableLiveData>, - exceptionLiveData: MutableLiveData>? = null + exceptionLiveData: MutableLiveData>? = null ) { state.value = Event(ApiRequestState.STARTED) viewModelScope.launch { try { apiRequest() state.value = Event(ApiRequestState.SUCCESS) - } catch (err: Exception) { + } catch (err: CwaWebException) { exceptionLiveData?.value = Event(err) state.value = Event(ApiRequestState.FAILED) + } catch (err: Exception) { + err.report(ExceptionCategory.INTERNAL) } } }