From 2ea4497a0a64813ce0a29336305e73ea647e1a25 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Wed, 5 Apr 2023 11:42:15 +0300 Subject: [PATCH 1/9] Simplified error handling. Refactored code.| #2241 --- .../email/api/retrofit/ApiClientRepository.kt | 51 ++++++++++--------- .../retrofit/RetrofitApiServiceInterface.kt | 2 - .../api/retrofit/base/BaseApiRepository.kt | 20 +++----- .../api/ClientConfigurationResponse.kt | 6 +-- .../response/api/EkmPrivateKeysResponse.kt | 14 ++--- .../response/api/FesServerResponse.kt | 7 ++- .../response/api/MessageReplyTokenResponse.kt | 7 ++- .../response/api/MessageUploadResponse.kt | 7 ++- .../response/api/PostHelpFeedbackResponse.kt | 27 ++++------ .../retrofit/response/attester/PubResponse.kt | 12 ++--- .../response/attester/SubmitPubKeyResponse.kt | 9 ++-- .../attester/WelcomeMessageResponse.kt | 15 ++---- .../api/retrofit/response/base/ApiError.kt | 11 ++-- .../api/retrofit/response/base/ApiResponse.kt | 6 ++- .../oauth2/MicrosoftOAuth2TokenResponse.kt | 7 ++- .../flowcrypt/email/extensions/ResultExt.kt | 2 +- .../jetpack/viewmodel/ComposeMsgViewModel.kt | 2 +- .../jetpack/viewmodel/PrivateKeysViewModel.kt | 7 ++- .../jetpack/viewmodel/RecipientsViewModel.kt | 2 +- .../email/util/exception/ApiException.kt | 2 +- 20 files changed, 93 insertions(+), 123 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt index b264670780..2c0fda92c9 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt @@ -71,7 +71,10 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult(context = context) { + getResult( + context = context, + expectedResultClass = ClientConfigurationResponse::class.java + ) { retrofitApiService.fesGetClientConfiguration( authorization = "Bearer $idToken", baseFesUrlPath = baseFesUrlPath, @@ -195,7 +198,10 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult { + getResult( + context = context, + expectedResultClass = WelcomeMessageResponse::class.java + ) { retrofitApiService.attesterPostWelcomeMessage( authorization = "Bearer $idToken", body = model @@ -224,7 +230,10 @@ object ApiClientRepository : BaseApiRepository { ) } val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult { + getResult( + context = context, + expectedResultClass = SubmitPubKeyResponse::class.java + ) { retrofitApiService.attesterSubmitPrimaryEmailPubKey( authorization = "Bearer $idToken", email = email, @@ -252,7 +261,10 @@ object ApiClientRepository : BaseApiRepository { ) } val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult { + getResult( + context = context, + expectedResultClass = SubmitPubKeyResponse::class.java + ) { retrofitApiService.attesterSubmitPubKeyWithConditionalEmailVerification( email, pubKey @@ -275,22 +287,6 @@ object ApiClientRepository : BaseApiRepository { clientConfiguration: ClientConfiguration? = null ): Result = withContext(Dispatchers.IO) { - val resultWrapperFun = fun(result: Result): Result { - return when (result.status) { - Result.Status.SUCCESS -> Result.success(data = PubResponse(null, result.data)) - - Result.Status.ERROR -> Result.error(data = PubResponse(null, null)) - - Result.Status.EXCEPTION -> Result.exception( - throwable = result.exception ?: Exception(context.getString(R.string.unknown_error)) - ) - - Result.Status.LOADING -> Result.loading() - - Result.Status.NONE -> Result.none() - } - } - if (email.isValidEmail()) { val wkdResult = getResult { val pgpPublicKeyRingCollection = WkdClient.lookupEmail(context, email) @@ -308,7 +304,7 @@ object ApiClientRepository : BaseApiRepository { } if (wkdResult.status == Result.Status.SUCCESS && wkdResult.data?.isNotEmpty() == true) { - return@withContext resultWrapperFun(wkdResult) + return@withContext Result.success(data = PubResponse(pubkey = wkdResult.data)) } if (clientConfiguration?.canLookupThisRecipientOnAttester(email) == false) { @@ -319,8 +315,17 @@ object ApiClientRepository : BaseApiRepository { ) val retrofitApiService = ApiHelper.createRetrofitApiService(context) - val result = getResult { retrofitApiService.attesterGetPubKey(email) } - return@withContext resultWrapperFun(result) + return@withContext getResult( + context = context, + expectedResultClass = PubResponse::class.java + ) { + val response = retrofitApiService.attesterGetPubKey(email) + if (response.isSuccessful) { + Response.success(PubResponse(pubkey = response.body())) + } else { + Response.error(response.errorBody() ?: byteArrayOf().toResponseBody(), response.raw()) + } + } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt index 2925988f5b..e7d6c0e3fd 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt @@ -65,8 +65,6 @@ interface RetrofitApiServiceInterface { /** * This method create a [Call] object for the API "https://flowcrypt.com/attester/pub" - * - * @return [<] */ @GET("pub/{keyIdOrEmailOrFingerprint}") suspend fun attesterGetPubKey(@Path("keyIdOrEmailOrFingerprint") keyIdOrEmailOrFingerprint: String): Response diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt index 140115c1ad..ab0dde1c6b 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt @@ -36,18 +36,12 @@ interface BaseApiRepository { if (response.isSuccessful) { val body = response.body() if (body != null) { - if (body is ApiResponse) { - return if (body.apiError != null) { - Result.error(data = body, requestCode = requestCode) - } else { - Result.success(data = body, requestCode = requestCode) - } - } else { - Result.success(data = body, requestCode = requestCode) - } + Result.success(data = body, requestCode = requestCode) } else { Result.exception( - throwable = ApiException(ApiError(response.code(), response.message())), + throwable = ApiException( + ApiError(code = response.code(), message = response.message()) + ), requestCode = requestCode ) } @@ -55,7 +49,9 @@ interface BaseApiRepository { val errorBody = response.errorBody() if (errorBody == null) { return Result.exception( - throwable = ApiException(ApiError(response.code(), "errorBody == null")), + throwable = ApiException( + ApiError(code = response.code(), message = "errorBody == null") + ), requestCode = requestCode ) } else { @@ -73,7 +69,7 @@ interface BaseApiRepository { return Result.error(data = apiResponseWithError, requestCode = requestCode) } else { Result.exception( - throwable = ApiException(ApiError(response.code(), String(buffer))), + throwable = ApiException(ApiError(code = response.code(), message = String(buffer))), requestCode = requestCode ) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt index ae29939c08..b7c90cebdf 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt @@ -5,7 +5,6 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.flowcrypt.email.api.retrofit.response.model.ClientConfiguration import com.google.gson.annotations.Expose @@ -17,8 +16,9 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class ClientConfigurationResponse constructor( - @SerializedName("error") - @Expose override val apiError: ApiError? = null, + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @SerializedName("clientConfiguration", alternate = ["domain_org_rules"]) @Expose val clientConfiguration: ClientConfiguration? ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt index 1314ebed2b..314e7e66ee 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt @@ -5,7 +5,6 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.flowcrypt.email.api.retrofit.response.model.Key import com.flowcrypt.email.security.model.PgpKeyDetails @@ -17,14 +16,9 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class EkmPrivateKeysResponse constructor( - @Expose val code: Int? = null, - @Expose val message: String? = null, + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @Expose val privateKeys: List? = null, val pgpKeyDetailsList: List? = null -) : ApiResponse { - - override val apiError: ApiError? - get() = if (code != null) { - ApiError(code = code, msg = message) - } else null -} +) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt index 9151b42b9f..26a4eaf75b 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt @@ -5,10 +5,8 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** @@ -16,8 +14,9 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class FesServerResponse constructor( - @SerializedName("error") - @Expose override val apiError: ApiError? = null, + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @Expose val vendor: String? = null, @Expose val service: String? = null, @Expose val orgId: String? = null, diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt index a657696527..f7008c0d44 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt @@ -5,10 +5,8 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** @@ -16,7 +14,8 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class MessageReplyTokenResponse( - @SerializedName("error") - @Expose override val apiError: ApiError? = null, + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @Expose val replyToken: String? = null ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt index 0bb21eff5a..91ad3708d4 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt @@ -5,10 +5,8 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** @@ -16,7 +14,8 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class MessageUploadResponse( - @SerializedName("error") - @Expose override val apiError: ApiError? = null, + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @Expose val url: String? = null ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt index cd81fbca44..b30ef4e3ca 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt @@ -9,24 +9,10 @@ import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize /** - * The simple POJO object, which contains information about a post feedback result. - * - * - * This class describes the next response: - * - * - *
- * `POST
- * response(200): {
- * "sent" (True, False)  # True if message was sent successfully
- * "text" ('str'>)  # User friendly success or error text
- * }
-` *
-
* - * * @author Denys Bondarenko */ @Parcelize @@ -34,4 +20,13 @@ data class PostHelpFeedbackResponse constructor( @SerializedName("error") @Expose override val apiError: ApiError? = null, @SerializedName("sent") @Expose val isSent: Boolean? = null, @Expose val text: String? = null -) : ApiResponse +) : ApiResponse { + @IgnoredOnParcel + override val code: Int? = null + + @IgnoredOnParcel + override val message: String? = null + + @IgnoredOnParcel + override val details: String? = null +} diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt index 3253941fe0..0ed6cba1d5 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt @@ -5,21 +5,17 @@ package com.flowcrypt.email.api.retrofit.response.attester -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** - * Response from the API - * "https://flowcrypt.com/attester/pub/{id or email}" - * * @author Denys Bondarenko */ @Parcelize data class PubResponse constructor( - @SerializedName("error") - @Expose override val apiError: ApiError? = null, - @Expose val pubkey: String? + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, + @Expose val pubkey: String? = null ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt index 884951de02..a8846a2cfe 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt @@ -5,19 +5,16 @@ package com.flowcrypt.email.api.retrofit.response.attester -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** - * This class describes a response from the https://flowcrypt.com/attester/pub API. - * * @author Denys Bondarenko */ @Parcelize data class SubmitPubKeyResponse constructor( - @SerializedName("error") @Expose override val - apiError: ApiError? = null + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt index 1d315ce9ba..256193c674 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt @@ -5,25 +5,16 @@ package com.flowcrypt.email.api.retrofit.response.attester -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose -import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** - * This class describes a response from the https://flowcrypt.com/attester/test/welcome API. - * - * - * `POST /test/welcome - * response(200): { - * "sent" (True, False) # successfuly sent email - * [voluntary] "error" ('str'>) # error detail, if not saved - * }` - * * @author Denys Bondarenko */ @Parcelize data class WelcomeMessageResponse constructor( - @SerializedName("error") @Expose override val apiError: ApiError? + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiError.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiError.kt index 34adf473b7..c2264b31a8 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiError.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiError.kt @@ -11,15 +11,12 @@ import com.google.gson.annotations.SerializedName import kotlinx.parcelize.Parcelize /** - * This POJO object describes a base error from the API. - * - * @author Denys Bondarenko +* @author Denys Bondarenko */ @Parcelize data class ApiError constructor( @Expose val code: Int? = null, - @SerializedName("message") @Expose val msg: String? = null, - @Expose val internal: String? = null, - @Expose val stack: String? = null, - @Expose val type: String? = null + @Expose val message: String? = null, + @SerializedName("details", alternate = ["internal"]) + @Expose val details: String? = null, ) : Parcelable diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt index e5a4e10314..3dae6da304 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt @@ -8,10 +8,12 @@ package com.flowcrypt.email.api.retrofit.response.base import android.os.Parcelable /** - * An interface for identification API response - * * @author Denys Bondarenko */ interface ApiResponse : Parcelable { + val code: Int? + val message: String? + val details: String? val apiError: ApiError? + get() = code?.let { ApiError(code = it, message = message, details = details) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt index 15b3ccfeb2..8b8fd3d336 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt @@ -16,6 +16,9 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class MicrosoftOAuth2TokenResponse constructor( + @Expose override val code: Int? = null, + @Expose override val message: String? = null, + @Expose override val details: String? = null, @SerializedName("access_token") @Expose val accessToken: String? = null, @SerializedName("token_type") @Expose val tokenType: String? = null, @SerializedName("expires_in") @Expose val expiresIn: Long? = null, @@ -33,8 +36,8 @@ data class MicrosoftOAuth2TokenResponse constructor( get() = if (error != null) { ApiError( code = errorCodes?.firstOrNull(), - msg = error + "\n" + errorDescription, - internal = error + message = error + "\n" + errorDescription, + details = error ) } else null diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt index 825e9a479c..eee8653291 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt @@ -33,7 +33,7 @@ val Result.exceptionMsg: String if (stringBuilder.isEmpty()) { val apiResponse = data as? ApiResponse apiResponse?.apiError?.let { apiError -> - stringBuilder.append(apiError.msg) + stringBuilder.append(apiError.message) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt index fcb1ee77f8..6252e0d4e3 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt @@ -364,7 +364,7 @@ class ComposeMsgViewModel(isCandidateToEncrypt: Boolean, application: Applicatio throw ApiException( response.data?.apiError ?: ApiError( code = -1, - msg = "Unknown API error" + message = "Unknown API error" ) ) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index f662db49df..5dc67dc00f 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -576,12 +576,11 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat val body = submitPubKeyResult.data when { isSilent -> { - body != null && (body.apiError == null || body.apiError.code !in 400..499) + body?.apiError == null || + (body.apiError?.code != null && body.apiError?.code !in 400..499) } - body?.apiError != null -> { - throw IllegalStateException(ApiException(body.apiError)) - } + body?.apiError != null -> throw IllegalStateException(ApiException(body.apiError)) else -> body != null } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt index b76923afb5..f544c5909c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt @@ -324,7 +324,7 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati Result.Status.ERROR -> { throw ApiException( response.data?.apiError - ?: ApiError(code = -1, msg = "Unknown API error") + ?: ApiError(code = -1, message = "Unknown API error") ) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/util/exception/ApiException.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/util/exception/ApiException.kt index f97451f71c..f3542f4471 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/util/exception/ApiException.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/util/exception/ApiException.kt @@ -15,4 +15,4 @@ import java.io.IOException * @author Denys Bondarenko */ class ApiException(val apiError: ApiError?) : - IOException("API error: code = " + apiError?.code + ", message = " + apiError?.msg) + IOException("API error: code = " + apiError?.code + ", message = " + apiError?.message) From 6a299ca165edf4db228274e3d5a0993adea6731c Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Wed, 5 Apr 2023 18:26:57 +0300 Subject: [PATCH 2/9] Simplified error handling. Refactored code. Step 2.| #2241 --- .../email/api/retrofit/ApiClientRepository.kt | 78 +++++++------------ .../api/retrofit/base/BaseApiRepository.kt | 22 ++---- .../api/ClientConfigurationResponse.kt | 3 - .../response/api/EkmPrivateKeysResponse.kt | 3 - .../response/api/FesServerResponse.kt | 3 - .../response/api/MessageReplyTokenResponse.kt | 3 - .../response/api/MessageUploadResponse.kt | 7 +- .../response/api/PostHelpFeedbackResponse.kt | 14 +--- .../retrofit/response/attester/PubResponse.kt | 7 +- .../response/attester/SubmitPubKeyResponse.kt | 6 +- .../attester/WelcomeMessageResponse.kt | 6 +- .../api/retrofit/response/base/ApiResponse.kt | 8 +- .../api/retrofit/response/base/Result.kt | 7 +- .../oauth2/MicrosoftOAuth2TokenResponse.kt | 5 +- .../flowcrypt/email/extensions/ResultExt.kt | 6 +- .../viewmodel/CheckPrivateKeysViewModel.kt | 2 +- .../jetpack/viewmodel/ComposeMsgViewModel.kt | 2 +- .../jetpack/viewmodel/PrivateKeysViewModel.kt | 12 +-- .../jetpack/viewmodel/RecipientsViewModel.kt | 3 +- .../RefreshPrivateKeysFromEkmViewModel.kt | 2 +- .../dialog/SendFeedbackDialogFragment.kt | 2 +- 21 files changed, 60 insertions(+), 141 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt index 2c0fda92c9..ac56e7e61e 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt @@ -71,10 +71,7 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = ClientConfigurationResponse::class.java - ) { + getResult(context = context) { retrofitApiService.fesGetClientConfiguration( authorization = "Bearer $idToken", baseFesUrlPath = baseFesUrlPath, @@ -97,10 +94,7 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = MessageReplyTokenResponse::class.java - ) { + getResult(context = context) { retrofitApiService.fesGetReplyTokenForPasswordProtectedMsg( authorization = "Bearer $idToken", baseFesUrlPath = baseFesUrlPath @@ -126,10 +120,7 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = MessageUploadResponse::class.java - ) { + getResult(context = context) { val details = GsonBuilder().create().toJson(messageUploadRequest) .toRequestBody(Constants.MIME_TYPE_JSON.toMediaTypeOrNull()) @@ -178,10 +169,11 @@ object ApiClientRepository : BaseApiRepository { .client(okHttpClient) .build() val retrofitApiService = retrofit.create(RetrofitApiServiceInterface::class.java) - return@withContext getResult( - context = context, - expectedResultClass = FesServerResponse::class.java - ) { retrofitApiService.fesCheckIfServerIsAvailable(domain) } + return@withContext getResult(context = context) { + retrofitApiService.fesCheckIfServerIsAvailable( + domain = domain + ) + } } } @@ -198,10 +190,7 @@ object ApiClientRepository : BaseApiRepository { ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = WelcomeMessageResponse::class.java - ) { + getResult(context = context) { retrofitApiService.attesterPostWelcomeMessage( authorization = "Bearer $idToken", body = model @@ -230,10 +219,7 @@ object ApiClientRepository : BaseApiRepository { ) } val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = SubmitPubKeyResponse::class.java - ) { + getResult(context = context) { retrofitApiService.attesterSubmitPrimaryEmailPubKey( authorization = "Bearer $idToken", email = email, @@ -261,13 +247,10 @@ object ApiClientRepository : BaseApiRepository { ) } val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = SubmitPubKeyResponse::class.java - ) { + getResult(context = context) { retrofitApiService.attesterSubmitPubKeyWithConditionalEmailVerification( - email, - pubKey + email = email, + pubKey = pubKey ) } } @@ -308,18 +291,15 @@ object ApiClientRepository : BaseApiRepository { } if (clientConfiguration?.canLookupThisRecipientOnAttester(email) == false) { - return@withContext Result.success(data = PubResponse(null, null)) + return@withContext Result.success(data = PubResponse()) } } else return@withContext Result.exception( throwable = IllegalStateException(context.getString(R.string.error_email_is_not_valid)) ) val retrofitApiService = ApiHelper.createRetrofitApiService(context) - return@withContext getResult( - context = context, - expectedResultClass = PubResponse::class.java - ) { - val response = retrofitApiService.attesterGetPubKey(email) + return@withContext getResult(context = context) { + val response = retrofitApiService.attesterGetPubKey(keyIdOrEmailOrFingerprint = email) if (response.isSuccessful) { Response.success(PubResponse(pubkey = response.body())) } else { @@ -341,10 +321,7 @@ object ApiClientRepository : BaseApiRepository { codeVerifier: String ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = MicrosoftOAuth2TokenResponse::class.java - ) { + getResult(context = context) { retrofitApiService.oAuthGetMicrosoftOAuth2Token( code = authorizeCode, scope = scopes, @@ -362,7 +339,7 @@ object ApiClientRepository : BaseApiRepository { withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) getResult { - retrofitApiService.oAuthGetOpenIdConfiguration(url) + retrofitApiService.oAuthGetOpenIdConfiguration(url = url) } } } @@ -383,10 +360,12 @@ object ApiClientRepository : BaseApiRepository { withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) val url = if (ekmUrl.endsWith("/")) ekmUrl else "$ekmUrl/" - getResult( - context = context, - expectedResultClass = EkmPrivateKeysResponse::class.java - ) { retrofitApiService.ekmGetPrivateKeys("${url}v1/keys/private", "Bearer $idToken") } + getResult(context = context) { + retrofitApiService.ekmGetPrivateKeys( + ekmUrl = "${url}v1/keys/private", + authorization = "Bearer $idToken" + ) + } } } @@ -402,10 +381,11 @@ object ApiClientRepository : BaseApiRepository { postHelpFeedbackModel: PostHelpFeedbackModel ): Result = withContext(Dispatchers.IO) { val retrofitApiService = ApiHelper.createRetrofitApiService(context) - getResult( - context = context, - expectedResultClass = PostHelpFeedbackResponse::class.java - ) { retrofitApiService.backendPostHelpFeedback(postHelpFeedbackModel) } + getResult(context = context) { + retrofitApiService.backendPostHelpFeedback( + body = postHelpFeedbackModel + ) + } } } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt index ab0dde1c6b..219602bf58 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/base/BaseApiRepository.kt @@ -8,7 +8,6 @@ package com.flowcrypt.email.api.retrofit.base import android.content.Context import com.flowcrypt.email.api.retrofit.ApiHelper import com.flowcrypt.email.api.retrofit.response.base.ApiError -import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.util.exception.ApiException import kotlinx.coroutines.Dispatchers @@ -28,7 +27,6 @@ interface BaseApiRepository { suspend fun getResult( requestCode: Long = 0L, context: Context? = null, - expectedResultClass: Class? = null, call: suspend () -> Response ): Result { return try { @@ -56,17 +54,13 @@ interface BaseApiRepository { ) } else { val buffer = errorBody.bytes() - val apiResponseWithError = parseError( + val apiError = parseApiError( context, - expectedResultClass, buffer.toResponseBody(errorBody.contentType()) ) - if (apiResponseWithError != null - && apiResponseWithError is ApiResponse - && apiResponseWithError.apiError != null - ) { - return Result.error(data = apiResponseWithError, requestCode = requestCode) + if (apiError != null) { + return Result.error(apiError = apiError, requestCode = requestCode) } else { Result.exception( throwable = ApiException(ApiError(code = response.code(), message = String(buffer))), @@ -81,18 +75,16 @@ interface BaseApiRepository { } } - private suspend fun parseError( + private suspend fun parseApiError( context: Context?, - exceptedClass: Class?, responseBody: ResponseBody - ): T? = + ): ApiError? = withContext(Dispatchers.IO) { context ?: return@withContext null - exceptedClass ?: return@withContext null try { - val errorConverter: Converter = + val errorConverter: Converter = ApiHelper.getInstance(context).retrofit.responseBodyConverter( - exceptedClass, + ApiError::class.java, arrayOfNulls(0) ) return@withContext errorConverter.convert(responseBody) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt index b7c90cebdf..6b31d05243 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/ClientConfigurationResponse.kt @@ -16,9 +16,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class ClientConfigurationResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, @SerializedName("clientConfiguration", alternate = ["domain_org_rules"]) @Expose val clientConfiguration: ClientConfiguration? ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt index 314e7e66ee..768cb601a4 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/EkmPrivateKeysResponse.kt @@ -16,9 +16,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class EkmPrivateKeysResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, @Expose val privateKeys: List? = null, val pgpKeyDetailsList: List? = null ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt index 26a4eaf75b..fe0a5a489f 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/FesServerResponse.kt @@ -14,9 +14,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class FesServerResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, @Expose val vendor: String? = null, @Expose val service: String? = null, @Expose val orgId: String? = null, diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt index f7008c0d44..f1276760de 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageReplyTokenResponse.kt @@ -14,8 +14,5 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class MessageReplyTokenResponse( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, @Expose val replyToken: String? = null ) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt index 91ad3708d4..ad2d2e7c28 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/MessageUploadResponse.kt @@ -13,9 +13,4 @@ import kotlinx.parcelize.Parcelize * @author Denys Bondarenko */ @Parcelize -data class MessageUploadResponse( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, - @Expose val url: String? = null -) : ApiResponse +data class MessageUploadResponse(@Expose val url: String? = null) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt index b30ef4e3ca..4cc25de84d 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/api/PostHelpFeedbackResponse.kt @@ -5,11 +5,9 @@ package com.flowcrypt.email.api.retrofit.response.api -import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.google.gson.annotations.Expose import com.google.gson.annotations.SerializedName -import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize /** @@ -17,16 +15,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class PostHelpFeedbackResponse constructor( - @SerializedName("error") @Expose override val apiError: ApiError? = null, @SerializedName("sent") @Expose val isSent: Boolean? = null, @Expose val text: String? = null -) : ApiResponse { - @IgnoredOnParcel - override val code: Int? = null - - @IgnoredOnParcel - override val message: String? = null - - @IgnoredOnParcel - override val details: String? = null -} +) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt index 0ed6cba1d5..a434d27217 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/PubResponse.kt @@ -13,9 +13,4 @@ import kotlinx.parcelize.Parcelize * @author Denys Bondarenko */ @Parcelize -data class PubResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, - @Expose val pubkey: String? = null -) : ApiResponse +data class PubResponse constructor(@Expose val pubkey: String? = null) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt index a8846a2cfe..5ce5c69d5d 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt @@ -13,8 +13,4 @@ import kotlinx.parcelize.Parcelize * @author Denys Bondarenko */ @Parcelize -data class SubmitPubKeyResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, -) : ApiResponse +data class SubmitPubKeyResponse constructor(@Expose val notUsed: Boolean? = null) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt index 256193c674..a32094fbef 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/WelcomeMessageResponse.kt @@ -13,8 +13,4 @@ import kotlinx.parcelize.Parcelize * @author Denys Bondarenko */ @Parcelize -data class WelcomeMessageResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, -) : ApiResponse +data class WelcomeMessageResponse constructor(@Expose val notUsed: Boolean? = null) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt index 3dae6da304..e69eb5e676 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/ApiResponse.kt @@ -10,10 +10,4 @@ import android.os.Parcelable /** * @author Denys Bondarenko */ -interface ApiResponse : Parcelable { - val code: Int? - val message: String? - val details: String? - val apiError: ApiError? - get() = code?.let { ApiError(code = it, message = message, details = details) } -} +interface ApiResponse : Parcelable diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/Result.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/Result.kt index 35968705b5..a8fb046d7c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/Result.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/base/Result.kt @@ -16,6 +16,7 @@ import java.io.Serializable data class Result( val status: Status, val data: T? = null, + val apiError: ApiError? = null, val exception: Throwable? = null, val requestCode: Long = 0, val resultCode: Int = 0, @@ -55,10 +56,10 @@ data class Result( ) } - fun error(data: T? = null, requestCode: Long = 0): Result { + fun error(apiError: ApiError, requestCode: Long = 0): Result { return Result( status = Status.ERROR, - data = data, + apiError = apiError, requestCode = requestCode ) } @@ -79,7 +80,7 @@ data class Result( fun throwExceptionIfNotSuccess(result: Result) { when (result.status) { Status.EXCEPTION -> result.exception?.let { throw it } - Status.ERROR -> result.data?.apiError?.let { throw ApiException(it) } + Status.ERROR -> result.apiError?.let { throw ApiException(it) } else -> { //do nothing } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt index 8b8fd3d336..254fe155c8 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/oauth2/MicrosoftOAuth2TokenResponse.kt @@ -16,9 +16,6 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class MicrosoftOAuth2TokenResponse constructor( - @Expose override val code: Int? = null, - @Expose override val message: String? = null, - @Expose override val details: String? = null, @SerializedName("access_token") @Expose val accessToken: String? = null, @SerializedName("token_type") @Expose val tokenType: String? = null, @SerializedName("expires_in") @Expose val expiresIn: Long? = null, @@ -32,7 +29,7 @@ data class MicrosoftOAuth2TokenResponse constructor( @SerializedName("trace_id") @Expose val traceId: String? = null, @SerializedName("correlation_id") @Expose val correlationId: String? = null ) : ApiResponse { - override val apiError: ApiError? + val apiError: ApiError? get() = if (error != null) { ApiError( code = errorCodes?.firstOrNull(), diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt index eee8653291..0f35a2fc90 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/ResultExt.kt @@ -5,7 +5,6 @@ package com.flowcrypt.email.extensions -import com.flowcrypt.email.api.retrofit.response.base.ApiResponse import com.flowcrypt.email.api.retrofit.response.base.Result /** @@ -31,10 +30,7 @@ val Result.exceptionMsg: String } if (stringBuilder.isEmpty()) { - val apiResponse = data as? ApiResponse - apiResponse?.apiError?.let { apiError -> - stringBuilder.append(apiError.message) - } + apiError?.let { stringBuilder.append(it.message) } } return stringBuilder.toString().ifEmpty { "Unknown error" } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CheckPrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CheckPrivateKeysViewModel.kt index 12bf33eef8..78d7000352 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CheckPrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CheckPrivateKeysViewModel.kt @@ -34,7 +34,7 @@ class CheckPrivateKeysViewModel(application: Application) : BaseAndroidViewModel viewModelScope.launch { checkPrvKeysLiveData.value = Result.loading() if (passphrase.isEmpty) { - checkPrvKeysLiveData.value = Result.error(emptyList()) + checkPrvKeysLiveData.value = Result.success(emptyList()) return@launch } checkPrvKeysLiveData.value = controlledRunnerForChecking.cancelPreviousThenRun { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt index 6252e0d4e3..e94b629325 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ComposeMsgViewModel.kt @@ -362,7 +362,7 @@ class ComposeMsgViewModel(isCandidateToEncrypt: Boolean, application: Applicatio Result.Status.ERROR -> { throw ApiException( - response.data?.apiError ?: ApiError( + response.apiError ?: ApiError( code = -1, message = "Unknown API error" ) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index 5dc67dc00f..aeb348c5a2 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -576,11 +576,13 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat val body = submitPubKeyResult.data when { isSilent -> { - body?.apiError == null || - (body.apiError?.code != null && body.apiError?.code !in 400..499) + submitPubKeyResult.apiError == null || + (submitPubKeyResult.apiError.code != null && submitPubKeyResult.apiError.code !in 400..499) } - body?.apiError != null -> throw IllegalStateException(ApiException(body.apiError)) + submitPubKeyResult.apiError != null -> { + throw IllegalStateException(ApiException(submitPubKeyResult.apiError)) + } else -> body != null } @@ -595,7 +597,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat } Result.Status.ERROR -> { - submitPubKeyResult.data?.apiError?.let { apiError -> throw ApiException(apiError) } + submitPubKeyResult.apiError?.let { apiError -> throw ApiException(apiError) } ?: throw IllegalStateException("Unknown API error") } @@ -627,7 +629,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat ) when (testWelcomeResult.status) { Result.Status.SUCCESS -> { - testWelcomeResult.data?.apiError == null + testWelcomeResult.apiError == null } else -> { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt index f544c5909c..082c89f43c 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RecipientsViewModel.kt @@ -323,8 +323,7 @@ class RecipientsViewModel(application: Application) : AccountViewModel(applicati Result.Status.ERROR -> { throw ApiException( - response.data?.apiError - ?: ApiError(code = -1, message = "Unknown API error") + response.apiError ?: ApiError(code = -1, message = "Unknown API error") ) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RefreshPrivateKeysFromEkmViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RefreshPrivateKeysFromEkmViewModel.kt index cce49cc70f..6e348008b0 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RefreshPrivateKeysFromEkmViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/RefreshPrivateKeysFromEkmViewModel.kt @@ -87,7 +87,7 @@ class RefreshPrivateKeysFromEkmViewModel(application: Application) : AccountView ) } - Result.Status.ERROR -> Result.exception(ApiException(ekmPrivateResult.data?.apiError)) + Result.Status.ERROR -> Result.exception(ApiException(ekmPrivateResult.apiError)) else -> throw IllegalStateException( "Unsupported status = ${ekmPrivateResult.status} at this step" diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/dialog/SendFeedbackDialogFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/dialog/SendFeedbackDialogFragment.kt index 96127cddaa..38998360fd 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/dialog/SendFeedbackDialogFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/dialog/SendFeedbackDialogFragment.kt @@ -92,7 +92,7 @@ class SendFeedbackDialogFragment : BaseDialogFragment() { binding?.pBLoading?.gone() binding?.btRetry?.visible() - val exception = it.exception ?: ApiException(it.data?.apiError) + val exception = it.exception ?: ApiException(it.apiError) val errorMsg = if (exception.message.isNullOrEmpty()) { exception.javaClass.simpleName } else exception.message From 07e4dae3b0a3a580e803f321056fbe6d421d4221 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Wed, 5 Apr 2023 18:35:04 +0300 Subject: [PATCH 3/9] Fixed tests.| #2241 --- .../email/ui/FesDuringSetupCommonFlowTest.kt | 15 ++++++-------- .../ui/FesDuringSetupConsumerFlowTest.kt | 11 +++++----- .../ui/FesDuringSetupEnterpriseFlowTest.kt | 5 ++--- .../email/ui/MainSignInFragmentFlowTest.kt | 20 ++++++++++--------- .../email/ui/RefreshKeysFromEkmFlowTest.kt | 10 ++++------ .../ui/SendFeedbackHasAccountFlowTest.kt | 4 ++-- ...testerForImportedKeyDuringSetupFlowTest.kt | 2 +- ...DuringRefreshingClientConfigurationTest.kt | 1 - ...FragmentEnterpriseTestUseFesUrlFlowTest.kt | 3 +-- 9 files changed, 32 insertions(+), 39 deletions(-) diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupCommonFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupCommonFlowTest.kt index 72f202c988..ebe0a01178 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupCommonFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupCommonFlowTest.kt @@ -54,14 +54,12 @@ class FesDuringSetupCommonFlowTest : BaseFesDuringSetupFlowTest() { override fun handleCheckIfFesIsAvailableAtCustomerFesUrl(gson: Gson): MockResponse { return when (testNameRule.methodName) { "testFesFailedApiError" -> { - MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + MockResponse().setResponseCode(HttpURLConnection.HTTP_FORBIDDEN) .setBody( gson.toJson( - FesServerResponse( - ApiError( - code = HttpURLConnection.HTTP_FORBIDDEN, - msg = ERROR_TEXT - ) + ApiError( + code = HttpURLConnection.HTTP_FORBIDDEN, + message = ERROR_TEXT ) ) ) @@ -112,7 +110,7 @@ class FesDuringSetupCommonFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_NOT_ACCEPTABLE, - msg = "" + message = "" ) ).message!! ) @@ -128,7 +126,7 @@ class FesDuringSetupCommonFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_CONFLICT, - msg = "" + message = "" ) ).message!! ) @@ -166,7 +164,6 @@ class FesDuringSetupCommonFlowTest : BaseFesDuringSetupFlowTest() { private const val ERROR_TEXT = "ERROR_TEXT" private val FES_SUCCESS_RESPONSE = FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "enterprise-server", orgId = "localhost", diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupConsumerFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupConsumerFlowTest.kt index 1cd9fcbd26..5600c08c30 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupConsumerFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupConsumerFlowTest.kt @@ -149,7 +149,7 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_NOT_ACCEPTABLE, - msg = "" + message = "" ) ).message ) @@ -163,7 +163,7 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_BAD_REQUEST, - msg = "" + message = "" ) ).message ) @@ -177,7 +177,7 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_FORBIDDEN, - msg = "" + message = "" ) ).message ) @@ -191,7 +191,7 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_GONE, - msg = "" + message = "" ) ).message ) @@ -215,7 +215,7 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_NOT_FOUND, - msg = "" + message = "" ) ).message ) @@ -256,7 +256,6 @@ class FesDuringSetupConsumerFlowTest : BaseFesDuringSetupFlowTest() { ) private val FES_SUCCESS_RESPONSE = FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "enterprise-server", orgId = "localhost", diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt index eaf139089c..13139ec5c5 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt @@ -150,7 +150,7 @@ class FesDuringSetupEnterpriseFlowTest : BaseFesDuringSetupFlowTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_FORBIDDEN, - msg = "" + message = "" ) ).message ) @@ -167,7 +167,7 @@ class FesDuringSetupEnterpriseFlowTest : BaseFesDuringSetupFlowTest() { ApiException( ApiError( code = HttpURLConnection.HTTP_INTERNAL_ERROR, - msg = "" + message = "" ) ) ).exceptionMsg @@ -256,7 +256,6 @@ class FesDuringSetupEnterpriseFlowTest : BaseFesDuringSetupFlowTest() { ) private val FES_SUCCESS_RESPONSE = FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "enterprise-server", orgId = "localhost", diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MainSignInFragmentFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MainSignInFragmentFlowTest.kt index eb7d5ee0e3..1acbcd1238 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MainSignInFragmentFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MainSignInFragmentFlowTest.kt @@ -286,7 +286,7 @@ class MainSignInFragmentFlowTest : BaseSignTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_FORBIDDEN, - msg = "" + message = "" ) ).message!! ) @@ -315,7 +315,7 @@ class MainSignInFragmentFlowTest : BaseSignTest() { isDialogWithTextDisplayed( decorView, - ApiException(ApiError(code = HttpURLConnection.HTTP_NOT_FOUND, msg = "")).message!! + ApiException(ApiError(code = HttpURLConnection.HTTP_NOT_FOUND, message = "")).message!! ) } @@ -369,8 +369,15 @@ class MainSignInFragmentFlowTest : BaseSignTest() { private fun handleEkmAPI(request: RecordedRequest, gson: Gson): MockResponse? { if (request.path.equals("/ekm/error/v1/keys/private")) { - return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) - .setBody(gson.toJson(EKM_ERROR_RESPONSE)) + return MockResponse().setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST) + .setBody( + gson.toJson( + ApiError( + code = HttpURLConnection.HTTP_BAD_REQUEST, + message = EKM_ERROR + ) + ) + ) } if (request.path.equals("/ekm/empty/v1/keys/private")) { @@ -557,10 +564,6 @@ class MainSignInFragmentFlowTest : BaseSignTest() { ) private const val EKM_ERROR = "some error" - private val EKM_ERROR_RESPONSE = EkmPrivateKeysResponse( - code = HttpURLConnection.HTTP_BAD_REQUEST, - message = EKM_ERROR - ) private val EKM_FES_RESPONSE = EkmPrivateKeysResponse( privateKeys = listOf( @@ -571,7 +574,6 @@ class MainSignInFragmentFlowTest : BaseSignTest() { ) private val FES_SUCCESS_RESPONSE = FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "enterprise-server", orgId = "localhost", diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt index 7cd1cd7a34..796eed8c48 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt @@ -18,6 +18,7 @@ import androidx.test.filters.MediumTest import com.flowcrypt.email.R import com.flowcrypt.email.TestConstants import com.flowcrypt.email.api.retrofit.response.api.EkmPrivateKeysResponse +import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.model.Key import com.flowcrypt.email.database.entity.KeyEntity import com.flowcrypt.email.extensions.org.pgpainless.util.asString @@ -84,7 +85,7 @@ class RefreshKeysFromEkmFlowTest : BaseRefreshKeysFromEkmFlowTest() { "testUpdatePrvKeyFromEkmShowApiError" -> MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) - .setBody(gson.toJson(EKM_ERROR_RESPONSE)) + .setBody(gson.toJson(EKM_API_ERROR)) else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) } @@ -164,7 +165,7 @@ class RefreshKeysFromEkmFlowTest : BaseRefreshKeysFromEkmFlowTest() { isDialogWithTextDisplayed(decorView, getResString(R.string.refreshing_keys_from_ekm_failed)) val stringBuilder = StringBuilder() - val exception = ApiException(EKM_ERROR_RESPONSE.apiError) + val exception = ApiException(EKM_API_ERROR) stringBuilder.append(exception.javaClass.simpleName) stringBuilder.append(":") stringBuilder.append(exception.message) @@ -191,10 +192,7 @@ class RefreshKeysFromEkmFlowTest : BaseRefreshKeysFromEkmFlowTest() { "pgp/expired_extended@flowcrypt.test_prv_default.asc" ) private const val EKM_ERROR = "some error" - private val EKM_ERROR_RESPONSE = EkmPrivateKeysResponse( - code = 400, - message = EKM_ERROR - ) + private val EKM_API_ERROR = ApiError(code = 400, message = EKM_ERROR) private val EKM_RESPONSE_SUCCESS = EkmPrivateKeysResponse( privateKeys = listOf( Key( diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SendFeedbackHasAccountFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SendFeedbackHasAccountFlowTest.kt index f1902a8d41..a58958c1ed 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SendFeedbackHasAccountFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SendFeedbackHasAccountFlowTest.kt @@ -145,7 +145,7 @@ class SendFeedbackHasAccountFlowTest : BaseFeedbackFragmentTest() { "testHandleApiErrorWhenSendingFeedback" -> { MockResponse() .setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST) - .setBody(gson.toJson(PostHelpFeedbackResponse(apiError = API_ERROR))) + .setBody(gson.toJson(API_ERROR)) } "testSendingFeedbackSuccess" -> { @@ -161,7 +161,7 @@ class SendFeedbackHasAccountFlowTest : BaseFeedbackFragmentTest() { companion object { private val API_ERROR = ApiError( code = HttpURLConnection.HTTP_BAD_REQUEST, - msg = "Wrong request received" + message = "Wrong request received" ) } } diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SubmitPublicKeyToAttesterForImportedKeyDuringSetupFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SubmitPublicKeyToAttesterForImportedKeyDuringSetupFlowTest.kt index 38ce8ebbd8..2c0cc92227 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SubmitPublicKeyToAttesterForImportedKeyDuringSetupFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/SubmitPublicKeyToAttesterForImportedKeyDuringSetupFlowTest.kt @@ -137,7 +137,7 @@ class SubmitPublicKeyToAttesterForImportedKeyDuringSetupFlowTest : BaseSignTest( private fun checkAttesterErrorIsDisplayed() { isDialogWithTextDisplayed( decorView = decorView, - message = requireNotNull(ApiException(ApiError(code = 404, msg = "")).message) + message = requireNotNull(ApiException(ApiError(code = 404, message = "")).message) ) } diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/UseFesAfterSetupDuringRefreshingClientConfigurationTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/UseFesAfterSetupDuringRefreshingClientConfigurationTest.kt index 21b67ef9af..98e670b4c5 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/UseFesAfterSetupDuringRefreshingClientConfigurationTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/UseFesAfterSetupDuringRefreshingClientConfigurationTest.kt @@ -60,7 +60,6 @@ class UseFesAfterSetupDuringRefreshingClientConfigurationTest : BaseTest() { return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK).setBody( gson.toJson( FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "enterprise-server", orgId = "localhost", diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/fes/login/MainSignInFragmentEnterpriseTestUseFesUrlFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/fes/login/MainSignInFragmentEnterpriseTestUseFesUrlFlowTest.kt index 2f191c2498..5920945703 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/fes/login/MainSignInFragmentEnterpriseTestUseFesUrlFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/fes/login/MainSignInFragmentEnterpriseTestUseFesUrlFlowTest.kt @@ -97,7 +97,7 @@ class MainSignInFragmentEnterpriseTestUseFesUrlFlowTest : BaseSignTest() { "ApiException:" + ApiException( ApiError( code = HttpURLConnection.HTTP_UNAUTHORIZED, - msg = "" + message = "" ) ).message!! ) @@ -113,7 +113,6 @@ class MainSignInFragmentEnterpriseTestUseFesUrlFlowTest : BaseSignTest() { private const val EMAIL_ENTERPRISE_USER = "enterprise_user@flowcrypt.test" private val FES_SUCCESS_RESPONSE = FesServerResponse( - apiError = null, vendor = "FlowCrypt", service = "external-service", orgId = "localhost", From 9e4d46c1f5fc13f1c2bb0fd83487c634dbc33ad5 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Thu, 6 Apr 2023 11:54:20 +0300 Subject: [PATCH 4/9] Fixed tests. Step 2.| #2241 --- .../com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt index 796eed8c48..97324fd0a2 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/RefreshKeysFromEkmFlowTest.kt @@ -84,7 +84,7 @@ class RefreshKeysFromEkmFlowTest : BaseRefreshKeysFromEkmFlowTest() { .setBody(gson.toJson(EKM_RESPONSE_SUCCESS)) "testUpdatePrvKeyFromEkmShowApiError" -> - MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + MockResponse().setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST) .setBody(gson.toJson(EKM_API_ERROR)) else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) @@ -192,7 +192,8 @@ class RefreshKeysFromEkmFlowTest : BaseRefreshKeysFromEkmFlowTest() { "pgp/expired_extended@flowcrypt.test_prv_default.asc" ) private const val EKM_ERROR = "some error" - private val EKM_API_ERROR = ApiError(code = 400, message = EKM_ERROR) + private val EKM_API_ERROR = + ApiError(code = HttpURLConnection.HTTP_BAD_REQUEST, message = EKM_ERROR) private val EKM_RESPONSE_SUCCESS = EkmPrivateKeysResponse( privateKeys = listOf( Key( From c15eb7fc495eeec9f9be1735ce49d4c186b8c7b4 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Thu, 6 Apr 2023 15:42:11 +0300 Subject: [PATCH 5/9] Added changes to ApiClientRepository.| #2241 --- .../email/api/retrofit/ApiClientRepository.kt | 20 +++++++++++++++++-- .../retrofit/RetrofitApiServiceInterface.kt | 14 ++++++++++--- .../response/attester/SubmitPubKeyResponse.kt | 2 +- .../jetpack/viewmodel/PrivateKeysViewModel.kt | 3 +-- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt index ac56e7e61e..d1c3101057 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/ApiClientRepository.kt @@ -220,11 +220,18 @@ object ApiClientRepository : BaseApiRepository { } val retrofitApiService = ApiHelper.createRetrofitApiService(context) getResult(context = context) { - retrofitApiService.attesterSubmitPrimaryEmailPubKey( + val response = retrofitApiService.attesterSubmitPrimaryEmailPubKey( authorization = "Bearer $idToken", email = email, pubKey = pubKey ) + //we have to handle a response manually due to different behavior. More details here + //https://github.com/FlowCrypt/flowcrypt-android/issues/2241#issuecomment-1497787161 + if (response.isSuccessful) { + Response.success(SubmitPubKeyResponse(isSent = true)) + } else { + Response.error(response.errorBody() ?: byteArrayOf().toResponseBody(), response.raw()) + } } } @@ -248,10 +255,17 @@ object ApiClientRepository : BaseApiRepository { } val retrofitApiService = ApiHelper.createRetrofitApiService(context) getResult(context = context) { - retrofitApiService.attesterSubmitPubKeyWithConditionalEmailVerification( + val response = retrofitApiService.attesterSubmitPubKeyWithConditionalEmailVerification( email = email, pubKey = pubKey ) + //we have to handle a response manually due to different behavior. More details here + //https://github.com/FlowCrypt/flowcrypt-android/issues/2241#issuecomment-1497787161 + if (response.isSuccessful) { + Response.success(SubmitPubKeyResponse(isSent = true)) + } else { + Response.error(response.errorBody() ?: byteArrayOf().toResponseBody(), response.raw()) + } } } } @@ -300,6 +314,8 @@ object ApiClientRepository : BaseApiRepository { val retrofitApiService = ApiHelper.createRetrofitApiService(context) return@withContext getResult(context = context) { val response = retrofitApiService.attesterGetPubKey(keyIdOrEmailOrFingerprint = email) + //we have to handle a response manually due to different behavior. More details here + //https://github.com/FlowCrypt/flowcrypt-android/issues/2241#issuecomment-1497787161 if (response.isSuccessful) { Response.success(PubResponse(pubkey = response.body())) } else { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt index e7d6c0e3fd..371d48e062 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/RetrofitApiServiceInterface.kt @@ -15,8 +15,8 @@ import com.flowcrypt.email.api.retrofit.response.api.FesServerResponse import com.flowcrypt.email.api.retrofit.response.api.MessageReplyTokenResponse import com.flowcrypt.email.api.retrofit.response.api.MessageUploadResponse import com.flowcrypt.email.api.retrofit.response.api.PostHelpFeedbackResponse -import com.flowcrypt.email.api.retrofit.response.attester.SubmitPubKeyResponse import com.flowcrypt.email.api.retrofit.response.attester.WelcomeMessageResponse +import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.oauth2.MicrosoftOAuth2TokenResponse import com.google.gson.JsonObject import okhttp3.MultipartBody @@ -65,6 +65,10 @@ interface RetrofitApiServiceInterface { /** * This method create a [Call] object for the API "https://flowcrypt.com/attester/pub" + * + * @return a pub key as a string if success result or JSON as [ApiError]. + * But here we have an exception + * (https://github.com/FlowCrypt/flowcrypt-android/issues/2241#issuecomment-1497787161) */ @GET("pub/{keyIdOrEmailOrFingerprint}") suspend fun attesterGetPubKey(@Path("keyIdOrEmailOrFingerprint") keyIdOrEmailOrFingerprint: String): Response @@ -123,24 +127,28 @@ interface RetrofitApiServiceInterface { * Set or replace public key with idToken as an auth mechanism * Used during setup * Can only be used for primary email because idToken does not contain info about aliases + * + * @return a string if success result or JSON as [ApiError] */ @POST("pub/{email}") suspend fun attesterSubmitPrimaryEmailPubKey( @Header("Authorization") authorization: String, @Path("email") email: String, @Body pubKey: String, - ): Response + ): Response /** * Request to replace public key that will be verified by clicking email * Used when user manually chooses to replace key * Can also be used for aliases + * + * @return a string if success result or JSON as [ApiError] */ @POST("pub/{email}") suspend fun attesterSubmitPubKeyWithConditionalEmailVerification( @Path("email") email: String, @Body pubKey: String - ): Response + ): Response @FormUrlEncoded @POST(OAuth2Helper.MICROSOFT_OAUTH2_TOKEN_URL) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt index 5ce5c69d5d..3c9ed255f3 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/attester/SubmitPubKeyResponse.kt @@ -13,4 +13,4 @@ import kotlinx.parcelize.Parcelize * @author Denys Bondarenko */ @Parcelize -data class SubmitPubKeyResponse constructor(@Expose val notUsed: Boolean? = null) : ApiResponse +data class SubmitPubKeyResponse constructor(@Expose val isSent: Boolean? = null) : ApiResponse diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index aeb348c5a2..f6d766e89e 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -573,7 +573,6 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat when (submitPubKeyResult.status) { Result.Status.SUCCESS -> { - val body = submitPubKeyResult.data when { isSilent -> { submitPubKeyResult.apiError == null || @@ -584,7 +583,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat throw IllegalStateException(ApiException(submitPubKeyResult.apiError)) } - else -> body != null + else -> submitPubKeyResult.data?.isSent == true } } From ac5affcd382853cea84799bbfe1f26458baa41e5 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Thu, 6 Apr 2023 15:54:06 +0300 Subject: [PATCH 6/9] Refactored code.| #2241 --- .../email/jetpack/viewmodel/PrivateKeysViewModel.kt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index f6d766e89e..e1dffc2789 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -621,20 +621,13 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat withContext(Dispatchers.IO) { return@withContext try { val model = WelcomeMessageModel(accountEntity.email, keyDetails.publicKey) - val testWelcomeResult = ApiClientRepository.Attester.postWelcomeMessage( + val result = ApiClientRepository.Attester.postWelcomeMessage( context = getApplication(), idToken = idToken, model = model ) - when (testWelcomeResult.status) { - Result.Status.SUCCESS -> { - testWelcomeResult.apiError == null - } - else -> { - false - } - } + result.status == Result.Status.SUCCESS } catch (e: Exception) { e.printStackTrace() false From 3d4baf9cbfb75680640642007b75ed16116335b3 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Thu, 6 Apr 2023 16:40:12 +0300 Subject: [PATCH 7/9] Updated tests.| #2241 --- .../email/ui/MessageDetailsPassphraseInRamFlowTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MessageDetailsPassphraseInRamFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MessageDetailsPassphraseInRamFlowTest.kt index 820a840242..3730a412e0 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MessageDetailsPassphraseInRamFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/MessageDetailsPassphraseInRamFlowTest.kt @@ -153,6 +153,7 @@ class MessageDetailsPassphraseInRamFlowTest : BaseMessageDetailsFlowTest() { } @Test + @FlakyTest fun testNeedPassphraseSingleFingerprint() { val decryptedInfo = TestGeneralUtil.getObjectFromJson( jsonPathInAssets = "messages/info/encrypted_msg_info_text.json", @@ -176,6 +177,9 @@ class MessageDetailsPassphraseInRamFlowTest : BaseMessageDetailsFlowTest() { R.plurals.please_provide_passphrase_for_following_keys, 1 ) + + Thread.sleep(2000) + onView(withId(R.id.tVStatusMessage)) .check(matches(withText(tVStatusMessageText))) From 8f4c2b6edcca2a7aca22d11d883e81b67d828da6 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Thu, 6 Apr 2023 18:13:21 +0300 Subject: [PATCH 8/9] Updated tests.| #2241 --- .../ui/DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest.kt index acc2d1e375..570b0c4472 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest.kt @@ -164,6 +164,8 @@ class DraftsGmailAPITestCorrectCreatingAndUpdatingFlowTest : BaseDraftsGmailAPIF //open the first draft and modify it onView(withId(R.id.recyclerViewMsgs)) .perform(actionOnItemAtPosition(1, click())) + //wait for the message details + Thread.sleep(2000) onView(withId(R.id.imageButtonEditDraft)) .check(matches(isDisplayed())) .perform(click()) From 29955e20680e5490b5dbeae58d54c49877bac798 Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Fri, 7 Apr 2023 08:43:01 +0300 Subject: [PATCH 9/9] Refactored code.| #2241 --- .../flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index e1dffc2789..ba3e8d0793 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -575,8 +575,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat Result.Status.SUCCESS -> { when { isSilent -> { - submitPubKeyResult.apiError == null || - (submitPubKeyResult.apiError.code != null && submitPubKeyResult.apiError.code !in 400..499) + submitPubKeyResult.apiError?.code?.let { it !in 400..499 } ?: true } submitPubKeyResult.apiError != null -> {