diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt index 86e3e087d..2a327fc13 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAccountsApi.kt @@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.DeleteAccountReque import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyOtpRequestJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.HTTP import retrofit2.http.POST @@ -18,43 +19,43 @@ interface AuthenticatedAccountsApi { * Converts the currently active account to a key-connector account. */ @POST("/accounts/convert-to-key-connector") - suspend fun convertToKeyConnector(): Result + suspend fun convertToKeyConnector(): NetworkResult /** * Creates the keys for the current account. */ @POST("/accounts/keys") - suspend fun createAccountKeys(@Body body: CreateAccountKeysRequest): Result + suspend fun createAccountKeys(@Body body: CreateAccountKeysRequest): NetworkResult /** * Deletes the current account. */ @HTTP(method = "DELETE", path = "/accounts", hasBody = true) - suspend fun deleteAccount(@Body body: DeleteAccountRequestJson): Result + suspend fun deleteAccount(@Body body: DeleteAccountRequestJson): NetworkResult @POST("/accounts/request-otp") - suspend fun requestOtp(): Result + suspend fun requestOtp(): NetworkResult @POST("/accounts/verify-otp") suspend fun verifyOtp( @Body body: VerifyOtpRequestJson, - ): Result + ): NetworkResult /** * Resets the temporary password. */ @HTTP(method = "PUT", path = "/accounts/update-temp-password", hasBody = true) - suspend fun resetTempPassword(@Body body: ResetPasswordRequestJson): Result + suspend fun resetTempPassword(@Body body: ResetPasswordRequestJson): NetworkResult /** * Resets the password. */ @HTTP(method = "POST", path = "/accounts/password", hasBody = true) - suspend fun resetPassword(@Body body: ResetPasswordRequestJson): Result + suspend fun resetPassword(@Body body: ResetPasswordRequestJson): NetworkResult /** * Sets the password. */ @POST("/accounts/set-password") - suspend fun setPassword(@Body body: SetPasswordRequestJson): Result + suspend fun setPassword(@Body body: SetPasswordRequestJson): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAuthRequestsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAuthRequestsApi.kt index 52b711f3f..d4e076c5c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAuthRequestsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedAuthRequestsApi.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestUpdateRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestsResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header @@ -22,7 +23,7 @@ interface AuthenticatedAuthRequestsApi { suspend fun createAdminAuthRequest( @Header("Device-Identifier") deviceIdentifier: String, @Body body: AuthRequestRequestJson, - ): Result + ): NetworkResult /** * Updates an authentication request. @@ -31,13 +32,13 @@ interface AuthenticatedAuthRequestsApi { suspend fun updateAuthRequest( @Path("id") userId: String, @Body body: AuthRequestUpdateRequestJson, - ): Result + ): NetworkResult /** * Gets a list of auth requests for this device. */ @GET("/auth-requests") - suspend fun getAuthRequests(): Result + suspend fun getAuthRequests(): NetworkResult /** * Retrieves an existing authentication request by ID. @@ -45,5 +46,5 @@ interface AuthenticatedAuthRequestsApi { @GET("/auth-requests/{requestId}") suspend fun getAuthRequest( @Path("requestId") requestId: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedDevicesApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedDevicesApi.kt index 642464d00..56fb2b62d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedDevicesApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedDevicesApi.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import androidx.annotation.Keep import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.PUT import retrofit2.http.Path @@ -16,5 +17,5 @@ interface AuthenticatedDevicesApi { suspend fun updateTrustedDeviceKeys( @Path(value = "appId") appId: String, @Body request: TrustedDeviceKeysRequestJson, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedKeyConnectorApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedKeyConnectorApi.kt index f296d7696..c06809e3e 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedKeyConnectorApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedKeyConnectorApi.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import androidx.annotation.Keep import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorMasterKeyRequestJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.POST import retrofit2.http.Url @@ -15,5 +16,5 @@ interface AuthenticatedKeyConnectorApi { suspend fun storeMasterKeyToKeyConnector( @Url url: String, @Body body: KeyConnectorMasterKeyRequestJson, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedOrganizationApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedOrganizationApi.kt index 0fd01787c..23b13f082 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedOrganizationApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/AuthenticatedOrganizationApi.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationAutoEnrollStatusResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationKeysResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationResetPasswordEnrollRequestJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.PUT @@ -20,7 +21,7 @@ interface AuthenticatedOrganizationApi { @Path("orgId") organizationId: String, @Path("userId") userId: String, @Body body: OrganizationResetPasswordEnrollRequestJson, - ): Result + ): NetworkResult /** * Checks whether this organization auto enrolls users in password reset. @@ -28,7 +29,7 @@ interface AuthenticatedOrganizationApi { @GET("/organizations/{identifier}/auto-enroll-status") suspend fun getOrganizationAutoEnrollResponse( @Path("identifier") organizationIdentifier: String, - ): Result + ): NetworkResult /** * Gets the public and private keys for this organization. @@ -36,5 +37,5 @@ interface AuthenticatedOrganizationApi { @GET("/organizations/{id}/keys") suspend fun getOrganizationKeys( @Path("id") organizationId: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/HaveIBeenPwnedApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/HaveIBeenPwnedApi.kt index 27d8d89b1..b67ddb2d4 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/HaveIBeenPwnedApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/HaveIBeenPwnedApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import okhttp3.ResponseBody import retrofit2.http.GET import retrofit2.http.Path @@ -14,5 +15,5 @@ interface HaveIBeenPwnedApi { suspend fun fetchBreachedPasswords( @Path("hashPrefix") hashPrefix: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAccountsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAccountsApi.kt index 505586e98..3015d4f87 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAccountsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAccountsApi.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorKeyRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_KEY_AUTHORIZATION import retrofit2.http.Body import retrofit2.http.Header @@ -15,16 +16,16 @@ interface UnauthenticatedAccountsApi { @POST("/accounts/password-hint") suspend fun passwordHintRequest( @Body body: PasswordHintRequestJson, - ): Result + ): NetworkResult @POST("/two-factor/send-email-login") suspend fun resendVerificationCodeEmail( @Body body: ResendEmailRequestJson, - ): Result + ): NetworkResult @POST("/accounts/set-key-connector-key") suspend fun setKeyConnectorKey( @Body body: KeyConnectorKeyRequestJson, @Header(HEADER_KEY_AUTHORIZATION) bearerToken: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAuthRequestsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAuthRequestsApi.kt index 36530e05f..eb61ca878 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAuthRequestsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedAuthRequestsApi.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestsResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Header @@ -21,7 +22,7 @@ interface UnauthenticatedAuthRequestsApi { suspend fun createAuthRequest( @Header("Device-Identifier") deviceIdentifier: String, @Body body: AuthRequestRequestJson, - ): Result + ): NetworkResult /** * Queries for updates to a given auth request. @@ -30,5 +31,5 @@ interface UnauthenticatedAuthRequestsApi { suspend fun getAuthRequestUpdate( @Path("requestId") requestId: String, @Query("code") accessCode: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedDevicesApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedDevicesApi.kt index 3190f6248..ad00ab928 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedDevicesApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedDevicesApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.GET import retrofit2.http.Header @@ -11,5 +12,5 @@ interface UnauthenticatedDevicesApi { suspend fun getIsKnownDevice( @Header(value = "X-Request-Email") emailAddress: String, @Header(value = "X-Device-Identifier") deviceId: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedIdentityApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedIdentityApi.kt index 343a86f6a..1be39c3fe 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedIdentityApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedIdentityApi.kt @@ -10,6 +10,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJso import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenRequestJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import kotlinx.serialization.json.JsonPrimitive import retrofit2.Call import retrofit2.http.Body @@ -46,12 +47,12 @@ interface UnauthenticatedIdentityApi { @Field(value = "twoFactorProvider") twoFactorMethod: String?, @Field(value = "twoFactorRemember") twoFactorRemember: String?, @Field(value = "authRequest") authRequestId: String?, - ): Result + ): NetworkResult @GET("/sso/prevalidate") suspend fun prevalidateSso( @Query("domainHint") organizationIdentifier: String, - ): Result + ): NetworkResult /** * This call needs to be synchronous so we need it to return a [Call] directly. The identity @@ -66,23 +67,25 @@ interface UnauthenticatedIdentityApi { ): Call @POST("/accounts/prelogin") - suspend fun preLogin(@Body body: PreLoginRequestJson): Result + suspend fun preLogin(@Body body: PreLoginRequestJson): NetworkResult @POST("/accounts/register") - suspend fun register(@Body body: RegisterRequestJson): Result + suspend fun register( + @Body body: RegisterRequestJson, + ): NetworkResult @POST("/accounts/register/finish") suspend fun registerFinish( @Body body: RegisterFinishRequestJson, - ): Result + ): NetworkResult @POST("/accounts/register/send-verification-email") suspend fun sendVerificationEmail( @Body body: SendVerificationEmailRequestJson, - ): Result + ): NetworkResult @POST("/accounts/register/verification-email-clicked") suspend fun verifyEmailToken( @Body body: VerifyEmailTokenRequestJson, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedKeyConnectorApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedKeyConnectorApi.kt index ecf803ccd..2d35a79ee 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedKeyConnectorApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedKeyConnectorApi.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api import androidx.annotation.Keep import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorMasterKeyRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorMasterKeyResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_KEY_AUTHORIZATION import retrofit2.http.Body import retrofit2.http.GET @@ -20,11 +21,11 @@ interface UnauthenticatedKeyConnectorApi { @Url url: String, @Header(HEADER_KEY_AUTHORIZATION) bearerToken: String, @Body body: KeyConnectorMasterKeyRequestJson, - ): Result + ): NetworkResult @GET suspend fun getMasterKeyFromKeyConnector( @Url url: String, @Header(HEADER_KEY_AUTHORIZATION) bearerToken: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedOrganizationApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedOrganizationApi.kt index ec26cb922..d9764fdd7 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedOrganizationApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/api/UnauthenticatedOrganizationApi.kt @@ -4,6 +4,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomain import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomainSsoDetailsResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.Body import retrofit2.http.POST @@ -17,7 +18,7 @@ interface UnauthenticatedOrganizationApi { @POST("/organizations/domain/sso/details") suspend fun getClaimedDomainOrganizationDetails( @Body body: OrganizationDomainSsoDetailsRequestJson, - ): Result + ): NetworkResult /** * Checks for the verfied organization domains of an email for SSO purposes. @@ -25,5 +26,5 @@ interface UnauthenticatedOrganizationApi { @POST("/organizations/domain/sso/verified") suspend fun getVerifiedOrganizationDomainsByEmail( @Body body: VerifiedOrganizationDomainSsoDetailsRequest, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt index 4904198fa..6e411d776 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AccountsServiceImpl.kt @@ -19,6 +19,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyOtpRequestJs import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_VALUE_BEARER_PREFIX import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import kotlinx.serialization.json.Json /** @@ -37,18 +38,22 @@ class AccountsServiceImpl( * Converts the currently active account to a key-connector account. */ override suspend fun convertToKeyConnector(): Result = - authenticatedAccountsApi.convertToKeyConnector() + authenticatedAccountsApi + .convertToKeyConnector() + .toResult() override suspend fun createAccountKeys( publicKey: String, encryptedPrivateKey: String, ): Result = - authenticatedAccountsApi.createAccountKeys( - body = CreateAccountKeysRequest( - publicKey = publicKey, - encryptedPrivateKey = encryptedPrivateKey, - ), - ) + authenticatedAccountsApi + .createAccountKeys( + body = CreateAccountKeysRequest( + publicKey = publicKey, + encryptedPrivateKey = encryptedPrivateKey, + ), + ) + .toResult() override suspend fun deleteAccount( masterPasswordHash: String?, @@ -61,9 +66,8 @@ class AccountsServiceImpl( oneTimePassword = oneTimePassword, ), ) - .map { - DeleteAccountResponseJson.Success - } + .toResult() + .map { DeleteAccountResponseJson.Success } .recoverCatching { throwable -> throwable .toBitwardenError() @@ -75,20 +79,25 @@ class AccountsServiceImpl( } override suspend fun requestOneTimePasscode(): Result = - authenticatedAccountsApi.requestOtp() + authenticatedAccountsApi + .requestOtp() + .toResult() override suspend fun verifyOneTimePasscode(passcode: String): Result = - authenticatedAccountsApi.verifyOtp( - VerifyOtpRequestJson( - oneTimePasscode = passcode, - ), - ) + authenticatedAccountsApi + .verifyOtp( + VerifyOtpRequestJson( + oneTimePasscode = passcode, + ), + ) + .toResult() override suspend fun requestPasswordHint( email: String, ): Result = unauthenticatedAccountsApi .passwordHintRequest(PasswordHintRequestJson(email)) + .toResult() .map { PasswordHintResponseJson.Success } .recoverCatching { throwable -> throwable @@ -101,54 +110,70 @@ class AccountsServiceImpl( } override suspend fun resendVerificationCodeEmail(body: ResendEmailRequestJson): Result = - unauthenticatedAccountsApi.resendVerificationCodeEmail(body = body) + unauthenticatedAccountsApi + .resendVerificationCodeEmail(body = body) + .toResult() - override suspend fun resetPassword(body: ResetPasswordRequestJson): Result { - return if (body.currentPasswordHash == null) { - authenticatedAccountsApi.resetTempPassword(body = body) + override suspend fun resetPassword(body: ResetPasswordRequestJson): Result = + if (body.currentPasswordHash == null) { + authenticatedAccountsApi + .resetTempPassword(body = body) + .toResult() } else { - authenticatedAccountsApi.resetPassword(body = body) + authenticatedAccountsApi + .resetPassword(body = body) + .toResult() } - } override suspend fun setKeyConnectorKey( accessToken: String, body: KeyConnectorKeyRequestJson, - ): Result = unauthenticatedAccountsApi.setKeyConnectorKey( - body = body, - bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", - ) + ): Result = + unauthenticatedAccountsApi + .setKeyConnectorKey( + body = body, + bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", + ) + .toResult() override suspend fun setPassword( body: SetPasswordRequestJson, - ): Result = authenticatedAccountsApi.setPassword(body) + ): Result = authenticatedAccountsApi + .setPassword(body) + .toResult() override suspend fun getMasterKeyFromKeyConnector( url: String, accessToken: String, ): Result = - unauthenticatedKeyConnectorApi.getMasterKeyFromKeyConnector( - url = "$url/user-keys", - bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", - ) + unauthenticatedKeyConnectorApi + .getMasterKeyFromKeyConnector( + url = "$url/user-keys", + bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", + ) + .toResult() override suspend fun storeMasterKeyToKeyConnector( url: String, masterKey: String, ): Result = - authenticatedKeyConnectorApi.storeMasterKeyToKeyConnector( - url = "$url/user-keys", - body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey), - ) + authenticatedKeyConnectorApi + .storeMasterKeyToKeyConnector( + url = "$url/user-keys", + body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey), + ) + .toResult() override suspend fun storeMasterKeyToKeyConnector( url: String, accessToken: String, masterKey: String, ): Result = - unauthenticatedKeyConnectorApi.storeMasterKeyToKeyConnector( - url = "$url/user-keys", - bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", - body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey), - ) + unauthenticatedKeyConnectorApi + .storeMasterKeyToKeyConnector( + url = "$url/user-keys", + bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken", + body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey), + ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AuthRequestsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AuthRequestsServiceImpl.kt index a6c4f5782..e9ccbc963 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AuthRequestsServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/AuthRequestsServiceImpl.kt @@ -3,17 +3,22 @@ package com.x8bit.bitwarden.data.auth.datasource.network.service import com.x8bit.bitwarden.data.auth.datasource.network.api.AuthenticatedAuthRequestsApi import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestUpdateRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestsResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult class AuthRequestsServiceImpl( private val authenticatedAuthRequestsApi: AuthenticatedAuthRequestsApi, ) : AuthRequestsService { override suspend fun getAuthRequests(): Result = - authenticatedAuthRequestsApi.getAuthRequests() + authenticatedAuthRequestsApi + .getAuthRequests() + .toResult() override suspend fun getAuthRequest( requestId: String, ): Result = - authenticatedAuthRequestsApi.getAuthRequest(requestId = requestId) + authenticatedAuthRequestsApi + .getAuthRequest(requestId = requestId) + .toResult() override suspend fun updateAuthRequest( requestId: String, @@ -22,13 +27,15 @@ class AuthRequestsServiceImpl( deviceId: String, isApproved: Boolean, ): Result = - authenticatedAuthRequestsApi.updateAuthRequest( - userId = requestId, - body = AuthRequestUpdateRequestJson( - key = key, - masterPasswordHash = masterPasswordHash, - deviceId = deviceId, - isApproved = isApproved, - ), - ) + authenticatedAuthRequestsApi + .updateAuthRequest( + userId = requestId, + body = AuthRequestUpdateRequestJson( + key = key, + masterPasswordHash = masterPasswordHash, + deviceId = deviceId, + isApproved = isApproved, + ), + ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/DevicesServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/DevicesServiceImpl.kt index d9efc6336..05f55a291 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/DevicesServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/DevicesServiceImpl.kt @@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.api.UnauthenticatedDevic import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysResponseJson import com.x8bit.bitwarden.data.platform.datasource.network.util.base64UrlEncode +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult class DevicesServiceImpl( private val authenticatedDevicesApi: AuthenticatedDevicesApi, @@ -13,22 +14,26 @@ class DevicesServiceImpl( override suspend fun getIsKnownDevice( emailAddress: String, deviceId: String, - ): Result = unauthenticatedDevicesApi.getIsKnownDevice( - emailAddress = emailAddress.base64UrlEncode(), - deviceId = deviceId, - ) + ): Result = unauthenticatedDevicesApi + .getIsKnownDevice( + emailAddress = emailAddress.base64UrlEncode(), + deviceId = deviceId, + ) + .toResult() override suspend fun trustDevice( appId: String, encryptedUserKey: String, encryptedDevicePublicKey: String, encryptedDevicePrivateKey: String, - ): Result = authenticatedDevicesApi.updateTrustedDeviceKeys( - appId = appId, - request = TrustedDeviceKeysRequestJson( - encryptedUserKey = encryptedUserKey, - encryptedDevicePublicKey = encryptedDevicePublicKey, - encryptedDevicePrivateKey = encryptedDevicePrivateKey, - ), - ) + ): Result = authenticatedDevicesApi + .updateTrustedDeviceKeys( + appId = appId, + request = TrustedDeviceKeysRequestJson( + encryptedUserKey = encryptedUserKey, + encryptedDevicePublicKey = encryptedDevicePublicKey, + encryptedDevicePrivateKey = encryptedDevicePrivateKey, + ), + ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/HaveIBeenPwnedServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/HaveIBeenPwnedServiceImpl.kt index 44d744541..cabd28383 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/HaveIBeenPwnedServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/HaveIBeenPwnedServiceImpl.kt @@ -1,6 +1,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.service import com.x8bit.bitwarden.data.auth.datasource.network.api.HaveIBeenPwnedApi +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import java.security.MessageDigest class HaveIBeenPwnedServiceImpl(private val api: HaveIBeenPwnedApi) : HaveIBeenPwnedService { @@ -17,6 +18,7 @@ class HaveIBeenPwnedServiceImpl(private val api: HaveIBeenPwnedApi) : HaveIBeenP return api .fetchBreachedPasswords(hashPrefix = hashPrefix) + .toResult() .mapCatching { responseBody -> responseBody.string() // First split the response by newline: each hashed password is on a new line. diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt index 7a32b598a..cb2a8e4f9 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt @@ -16,8 +16,9 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenRe import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenResponseJson import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.base64UrlEncode -import com.x8bit.bitwarden.data.platform.datasource.network.util.executeForResult +import com.x8bit.bitwarden.data.platform.datasource.network.util.executeForNetworkResult import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.platform.util.DeviceModelProvider import kotlinx.serialization.json.Json @@ -28,12 +29,15 @@ class IdentityServiceImpl( ) : IdentityService { override suspend fun preLogin(email: String): Result = - unauthenticatedIdentityApi.preLogin(PreLoginRequestJson(email = email)) + unauthenticatedIdentityApi + .preLogin(PreLoginRequestJson(email = email)) + .toResult() @Suppress("MagicNumber") override suspend fun register(body: RegisterRequestJson): Result = unauthenticatedIdentityApi .register(body) + .toResult() .recoverCatching { throwable -> val bitwardenError = throwable.toBitwardenError() bitwardenError @@ -75,6 +79,7 @@ class IdentityServiceImpl( captchaResponse = captchaToken, authRequestId = authModel.authRequestId, ) + .toResult() .recoverCatching { throwable -> val bitwardenError = throwable.toBitwardenError() bitwardenError.parseErrorBodyOrNull( @@ -95,6 +100,7 @@ class IdentityServiceImpl( .prevalidateSso( organizationIdentifier = organizationIdentifier, ) + .toResult() override fun refreshTokenSynchronously( refreshToken: String, @@ -104,7 +110,8 @@ class IdentityServiceImpl( grantType = "refresh_token", refreshToken = refreshToken, ) - .executeForResult() + .executeForNetworkResult() + .toResult() @Suppress("MagicNumber") override suspend fun registerFinish( @@ -112,6 +119,7 @@ class IdentityServiceImpl( ): Result = unauthenticatedIdentityApi .registerFinish(body) + .toResult() .recoverCatching { throwable -> val bitwardenError = throwable.toBitwardenError() bitwardenError @@ -127,6 +135,7 @@ class IdentityServiceImpl( ): Result { return unauthenticatedIdentityApi .sendVerificationEmail(body = body) + .toResult() .map { it?.content } } @@ -136,9 +145,8 @@ class IdentityServiceImpl( .verifyEmailToken( body = body, ) - .map { - VerifyEmailTokenResponseJson.Valid - } + .toResult() + .map { VerifyEmailTokenResponseJson.Valid } .recoverCatching { throwable -> val bitwardenError = throwable.toBitwardenError() bitwardenError diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/NewAuthRequestServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/NewAuthRequestServiceImpl.kt index 14cfb2b2c..0b0c9e51f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/NewAuthRequestServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/NewAuthRequestServiceImpl.kt @@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.api.UnauthenticatedAuthR import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestsResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.platform.util.asFailure /** @@ -24,17 +25,19 @@ class NewAuthRequestServiceImpl( ): Result = when (authRequestType) { AuthRequestTypeJson.LOGIN_WITH_DEVICE -> { - unauthenticatedAuthRequestsApi.createAuthRequest( - deviceIdentifier = deviceId, - body = AuthRequestRequestJson( - email = email, - publicKey = publicKey, - deviceId = deviceId, - accessCode = accessCode, - fingerprint = fingerprint, - type = authRequestType, - ), - ) + unauthenticatedAuthRequestsApi + .createAuthRequest( + deviceIdentifier = deviceId, + body = AuthRequestRequestJson( + email = email, + publicKey = publicKey, + deviceId = deviceId, + accessCode = accessCode, + fingerprint = fingerprint, + type = authRequestType, + ), + ) + .toResult() } AuthRequestTypeJson.UNLOCK -> { @@ -43,17 +46,19 @@ class NewAuthRequestServiceImpl( } AuthRequestTypeJson.ADMIN_APPROVAL -> { - authenticatedAuthRequestsApi.createAdminAuthRequest( - deviceIdentifier = deviceId, - body = AuthRequestRequestJson( - email = email, - publicKey = publicKey, - deviceId = deviceId, - accessCode = accessCode, - fingerprint = fingerprint, - type = authRequestType, - ), - ) + authenticatedAuthRequestsApi + .createAdminAuthRequest( + deviceIdentifier = deviceId, + body = AuthRequestRequestJson( + email = email, + publicKey = publicKey, + deviceId = deviceId, + accessCode = accessCode, + fingerprint = fingerprint, + type = authRequestType, + ), + ) + .toResult() } } @@ -63,11 +68,15 @@ class NewAuthRequestServiceImpl( isSso: Boolean, ): Result = if (isSso) { - authenticatedAuthRequestsApi.getAuthRequest(requestId) + authenticatedAuthRequestsApi + .getAuthRequest(requestId = requestId) + .toResult() } else { - unauthenticatedAuthRequestsApi.getAuthRequestUpdate( - requestId = requestId, - accessCode = accessCode, - ) + unauthenticatedAuthRequestsApi + .getAuthRequestUpdate( + requestId = requestId, + accessCode = accessCode, + ) + .toResult() } } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/OrganizationServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/OrganizationServiceImpl.kt index f4d857da9..c01a18840 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/OrganizationServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/OrganizationServiceImpl.kt @@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationKeysRe import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationResetPasswordEnrollRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult /** * Default implementation of [OrganizationService]. @@ -31,6 +32,7 @@ class OrganizationServiceImpl( resetPasswordKey = resetPasswordKey, ), ) + .toResult() override suspend fun getOrganizationDomainSsoDetails( email: String, @@ -40,6 +42,7 @@ class OrganizationServiceImpl( email = email, ), ) + .toResult() override suspend fun getOrganizationAutoEnrollStatus( organizationIdentifier: String, @@ -47,6 +50,7 @@ class OrganizationServiceImpl( .getOrganizationAutoEnrollResponse( organizationIdentifier = organizationIdentifier, ) + .toResult() override suspend fun getOrganizationKeys( organizationId: String, @@ -54,6 +58,7 @@ class OrganizationServiceImpl( .getOrganizationKeys( organizationId = organizationId, ) + .toResult() override suspend fun getVerifiedOrganizationDomainSsoDetails( email: String, @@ -63,4 +68,5 @@ class OrganizationServiceImpl( email = email, ), ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/api/DigitalAssetLinkApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/api/DigitalAssetLinkApi.kt index 594b5b236..dcf7b55fb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/api/DigitalAssetLinkApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/api/DigitalAssetLinkApi.kt @@ -1,6 +1,7 @@ package com.x8bit.bitwarden.data.autofill.fido2.datasource.network.api import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.GET import retrofit2.http.Url @@ -15,5 +16,5 @@ interface DigitalAssetLinkApi { @GET suspend fun getDigitalAssetLinks( @Url url: String, - ): Result> + ): NetworkResult> } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/service/DigitalAssetLinkServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/service/DigitalAssetLinkServiceImpl.kt index 4a48c5871..6ff84088b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/service/DigitalAssetLinkServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/autofill/fido2/datasource/network/service/DigitalAssetLinkServiceImpl.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.autofill.fido2.datasource.network.service import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.api.DigitalAssetLinkApi import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult /** * Primary implementation of [DigitalAssetLinkService]. @@ -18,4 +19,5 @@ class DigitalAssetLinkServiceImpl( .getDigitalAssetLinks( url = "$scheme$relyingParty/.well-known/assetlinks.json", ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/ConfigApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/ConfigApi.kt index 7b26a56df..8a381b330 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/ConfigApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/ConfigApi.kt @@ -1,6 +1,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.api import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.http.GET /** @@ -9,5 +10,5 @@ import retrofit2.http.GET interface ConfigApi { @GET("config") - suspend fun getConfig(): Result + suspend fun getConfig(): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/EventApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/EventApi.kt index 6b5072a33..6ff713ae4 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/EventApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/EventApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson import retrofit2.http.Body import retrofit2.http.POST @@ -9,5 +10,7 @@ import retrofit2.http.POST */ interface EventApi { @POST("/collect") - suspend fun collectOrganizationEvents(@Body events: List): Result + suspend fun collectOrganizationEvents( + @Body events: List, + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/PushApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/PushApi.kt index b6567163c..ab5216ec6 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/PushApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/api/PushApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest import retrofit2.http.Body import retrofit2.http.PUT @@ -13,5 +14,5 @@ interface PushApi { suspend fun putDeviceToken( @Path("appId") appId: String, @Body body: PushTokenRequest, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCall.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCall.kt similarity index 57% rename from app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCall.kt rename to app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCall.kt index 1555e42a3..8385f0c83 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCall.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCall.kt @@ -1,7 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.core -import com.x8bit.bitwarden.data.platform.util.asFailure -import com.x8bit.bitwarden.data.platform.util.asSuccess +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import okhttp3.Request import okio.IOException import okio.Timeout @@ -18,33 +17,36 @@ import java.lang.reflect.Type private const val NO_CONTENT_RESPONSE_CODE: Int = 204 /** - * A [Call] for wrapping a network request into a [Result]. + * A [Call] for wrapping a network request into a [NetworkResult]. */ @Suppress("TooManyFunctions") -class ResultCall( +class NetworkResultCall( private val backingCall: Call, private val successType: Type, -) : Call> { +) : Call> { override fun cancel(): Unit = backingCall.cancel() - override fun clone(): Call> = ResultCall(backingCall, successType) + override fun clone(): Call> = NetworkResultCall(backingCall, successType) - override fun enqueue(callback: Callback>): Unit = backingCall.enqueue( + override fun enqueue(callback: Callback>): Unit = backingCall.enqueue( object : Callback { override fun onResponse(call: Call, response: Response) { - callback.onResponse(this@ResultCall, Response.success(response.toResult())) + callback.onResponse( + this@NetworkResultCall, + Response.success(response.toNetworkResult()), + ) } override fun onFailure(call: Call, t: Throwable) { - callback.onResponse(this@ResultCall, Response.success(t.toFailure())) + callback.onResponse(this@NetworkResultCall, Response.success(t.toFailure())) } }, ) @Suppress("TooGenericExceptionCaught") - override fun execute(): Response> = + override fun execute(): Response> = try { - Response.success(backingCall.execute().toResult()) + Response.success(backingCall.execute().toNetworkResult()) } catch (ioException: IOException) { Response.success(ioException.toFailure()) } catch (runtimeException: RuntimeException) { @@ -60,20 +62,18 @@ class ResultCall( override fun timeout(): Timeout = backingCall.timeout() /** - * Synchronously send the request and return its response as a [Result]. + * Synchronously send the request and return its response as a [NetworkResult]. */ - fun executeForResult(): Result = requireNotNull(execute().body()) + fun executeForResult(): NetworkResult = requireNotNull(execute().body()) - private fun Throwable.toFailure(): Result = - this - .also { - // We rebuild the URL without query params, we do not want to log those - val url = backingCall.request().url.toUrl().run { "$protocol://$authority$path" } - Timber.w(it, "Network Error: $url") - } - .asFailure() + private fun Throwable.toFailure(): NetworkResult { + // We rebuild the URL without query params, we do not want to log those + val url = backingCall.request().url.toUrl().run { "$protocol://$authority$path" } + Timber.w(this, "Network Error: $url") + return NetworkResult.Failure(this) + } - private fun Response.toResult(): Result = + private fun Response.toNetworkResult(): NetworkResult = if (!this.isSuccessful) { HttpException(this).toFailure() } else { @@ -81,11 +81,11 @@ class ResultCall( @Suppress("UNCHECKED_CAST") when { // We got a nonnull T as the body, just return it. - body != null -> body.asSuccess() + body != null -> NetworkResult.Success(body) // We expected the body to be null since the successType is Unit, just return Unit. - successType == Unit::class.java -> (Unit as T).asSuccess() + successType == Unit::class.java -> NetworkResult.Success(Unit as T) // We allow null for 204's, just return null. - this.code() == NO_CONTENT_RESPONSE_CODE -> (null as T).asSuccess() + this.code() == NO_CONTENT_RESPONSE_CODE -> NetworkResult.Success(null as T) // All other null bodies result in an error. else -> IllegalStateException("Unexpected null body!").toFailure() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapter.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapter.kt new file mode 100644 index 000000000..4a07b7fea --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapter.kt @@ -0,0 +1,17 @@ +package com.x8bit.bitwarden.data.platform.datasource.network.core + +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult +import retrofit2.Call +import retrofit2.CallAdapter +import java.lang.reflect.Type + +/** + * A [CallAdapter] for wrapping network requests into [NetworkResult]. + */ +class NetworkResultCallAdapter( + private val successType: Type, +) : CallAdapter>> { + + override fun responseType(): Type = successType + override fun adapt(call: Call): Call> = NetworkResultCall(call, successType) +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterFactory.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterFactory.kt similarity index 68% rename from app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterFactory.kt rename to app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterFactory.kt index 4b808aa42..000986661 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterFactory.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterFactory.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.core +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.Call import retrofit2.CallAdapter import retrofit2.Retrofit @@ -7,9 +8,9 @@ import java.lang.reflect.ParameterizedType import java.lang.reflect.Type /** - * A [CallAdapter.Factory] for wrapping network requests into [kotlin.Result]. + * A [CallAdapter.Factory] for wrapping network requests into [NetworkResult]. */ -class ResultCallAdapterFactory : CallAdapter.Factory() { +class NetworkResultCallAdapterFactory : CallAdapter.Factory() { override fun get( returnType: Type, annotations: Array, @@ -18,13 +19,13 @@ class ResultCallAdapterFactory : CallAdapter.Factory() { check(returnType is ParameterizedType) { "$returnType must be parameterized" } val containerType = getParameterUpperBound(0, returnType) - if (getRawType(containerType) != Result::class.java) return null + if (getRawType(containerType) != NetworkResult::class.java) return null check(containerType is ParameterizedType) { "$containerType must be parameterized" } val requestType = getParameterUpperBound(0, containerType) return if (getRawType(returnType) == Call::class.java) { - ResultCallAdapter(successType = requestType) + NetworkResultCallAdapter(successType = requestType) } else { null } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapter.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapter.kt deleted file mode 100644 index 88e758d18..000000000 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapter.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.x8bit.bitwarden.data.platform.datasource.network.core - -import retrofit2.Call -import retrofit2.CallAdapter -import java.lang.reflect.Type - -/** - * A [CallAdapter] for wrapping network requests into [kotlin.Result]. - */ -class ResultCallAdapter( - private val successType: Type, -) : CallAdapter>> { - - override fun responseType(): Type = successType - override fun adapt(call: Call): Call> = ResultCall(call, successType) -} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/model/NetworkResult.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/model/NetworkResult.kt new file mode 100644 index 000000000..e96408a46 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/model/NetworkResult.kt @@ -0,0 +1,18 @@ +package com.x8bit.bitwarden.data.platform.datasource.network.model + +/** + * A wrapper class for a network result for type [T]. If the network request is successful, the + * response will be a [Success] containing the data. If the network request is a failure, the + * response will be a [Failure] containing the [Throwable]. + */ +sealed class NetworkResult { + /** + * A successful network result with the relevant [T] data. + */ + data class Success(val value: T) : NetworkResult() + + /** + * A failed network result with the relevant [throwable] error. + */ + data class Failure(val throwable: Throwable) : NetworkResult() +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsImpl.kt index e681f484c..7ee544457 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsImpl.kt @@ -1,7 +1,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.retrofit import com.x8bit.bitwarden.data.platform.datasource.network.authenticator.RefreshAuthenticator -import com.x8bit.bitwarden.data.platform.datasource.network.core.ResultCallAdapterFactory +import com.x8bit.bitwarden.data.platform.datasource.network.core.NetworkResultCallAdapterFactory import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptor import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors @@ -105,7 +105,7 @@ class RetrofitsImpl( private val baseRetrofitBuilder: Retrofit.Builder by lazy { Retrofit.Builder() .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) - .addCallAdapterFactory(ResultCallAdapterFactory()) + .addCallAdapterFactory(NetworkResultCallAdapterFactory()) .client(baseOkHttpClient) } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/ConfigServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/ConfigServiceImpl.kt index f90b01c6c..947a2ca7f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/ConfigServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/ConfigServiceImpl.kt @@ -2,7 +2,8 @@ package com.x8bit.bitwarden.data.platform.datasource.network.service import com.x8bit.bitwarden.data.platform.datasource.network.api.ConfigApi import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult class ConfigServiceImpl(private val configApi: ConfigApi) : ConfigService { - override suspend fun getConfig(): Result = configApi.getConfig() + override suspend fun getConfig(): Result = configApi.getConfig().toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/EventServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/EventServiceImpl.kt index 65a459509..77e13a453 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/EventServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/EventServiceImpl.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.service import com.x8bit.bitwarden.data.platform.datasource.network.api.EventApi import com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult /** * The default implementation of the [EventService]. @@ -11,5 +12,5 @@ class EventServiceImpl( ) : EventService { override suspend fun sendOrganizationEvents( events: List, - ): Result = eventApi.collectOrganizationEvents(events = events) + ): Result = eventApi.collectOrganizationEvents(events = events).toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/PushServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/PushServiceImpl.kt index 9916029c6..e83b01a3a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/PushServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/service/PushServiceImpl.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.platform.datasource.network.service import com.x8bit.bitwarden.data.platform.datasource.network.api.PushApi import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult class PushServiceImpl( private val pushApi: PushApi, @@ -15,4 +16,5 @@ class PushServiceImpl( appId = appId, body = body, ) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensions.kt index d7a061f3d..b5c4e69cb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensions.kt @@ -1,21 +1,22 @@ package com.x8bit.bitwarden.data.platform.datasource.network.util -import com.x8bit.bitwarden.data.platform.datasource.network.core.ResultCall +import com.x8bit.bitwarden.data.platform.datasource.network.core.NetworkResultCall +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import retrofit2.Call /** - * Synchronously executes the [Call] and returns the [Result]. + * Synchronously executes the [Call] and returns the [NetworkResult]. */ -inline fun Call.executeForResult(): Result = +inline fun Call.executeForNetworkResult(): NetworkResult = this - .toResultCall() + .toNetworkResultCall() .executeForResult() /** - * Wraps the existing [Call] in a [ResultCall]. + * Wraps the existing [Call] in a [NetworkResultCall]. */ -inline fun Call.toResultCall(): ResultCall = - ResultCall( +inline fun Call.toNetworkResultCall(): NetworkResultCall = + NetworkResultCall( backingCall = this, successType = T::class.java, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensions.kt new file mode 100644 index 000000000..7f4e983bb --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensions.kt @@ -0,0 +1,14 @@ +package com.x8bit.bitwarden.data.platform.datasource.network.util + +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult +import com.x8bit.bitwarden.data.platform.util.asFailure +import com.x8bit.bitwarden.data.platform.util.asSuccess + +/** + * Converts the [NetworkResult] to a [Result]. + */ +fun NetworkResult.toResult(): Result = + when (this) { + is NetworkResult.Failure -> this.throwable.asFailure() + is NetworkResult.Success -> this.value.asSuccess() + } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/AzureApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/AzureApi.kt index 42adf069a..ab9a21d21 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/AzureApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/AzureApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import okhttp3.RequestBody import retrofit2.http.Body import retrofit2.http.Header @@ -21,5 +22,5 @@ interface AzureApi { @Header("x-ms-date") date: String, @Header("x-ms-version") version: String?, @Body body: RequestBody, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/CiphersApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/CiphersApi.kt index 84c6c35cd..47f39f3bc 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/CiphersApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/CiphersApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonRequest import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonResponse import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest @@ -26,7 +27,7 @@ interface CiphersApi { * Create a cipher. */ @POST("ciphers") - suspend fun createCipher(@Body body: CipherJsonRequest): Result + suspend fun createCipher(@Body body: CipherJsonRequest): NetworkResult /** * Create a cipher that belongs to an organization. @@ -34,7 +35,7 @@ interface CiphersApi { @POST("ciphers/create") suspend fun createCipherInOrganization( @Body body: CreateCipherInOrganizationJsonRequest, - ): Result + ): NetworkResult /** * Associates an attachment with a cipher. @@ -43,7 +44,7 @@ interface CiphersApi { suspend fun createAttachment( @Path("cipherId") cipherId: String, @Body body: AttachmentJsonRequest, - ): Result + ): NetworkResult /** * Uploads the attachment associated with a cipher. @@ -53,7 +54,7 @@ interface CiphersApi { @Path("cipherId") cipherId: String, @Path("attachmentId") attachmentId: String, @Body body: MultipartBody, - ): Result + ): NetworkResult /** * Updates a cipher. @@ -62,7 +63,7 @@ interface CiphersApi { suspend fun updateCipher( @Path("cipherId") cipherId: String, @Body body: CipherJsonRequest, - ): Result + ): NetworkResult /** * Shares a cipher. @@ -71,7 +72,7 @@ interface CiphersApi { suspend fun shareCipher( @Path("cipherId") cipherId: String, @Body body: ShareCipherJsonRequest, - ): Result + ): NetworkResult /** * Shares an attachment. @@ -82,7 +83,7 @@ interface CiphersApi { @Path("attachmentId") attachmentId: String, @Query("organizationId") organizationId: String?, @Body body: MultipartBody, - ): Result + ): NetworkResult /** * Updates a cipher's collections. @@ -91,7 +92,7 @@ interface CiphersApi { suspend fun updateCipherCollections( @Path("cipherId") cipherId: String, @Body body: UpdateCipherCollectionsJsonRequest, - ): Result + ): NetworkResult /** * Hard deletes a cipher. @@ -99,7 +100,7 @@ interface CiphersApi { @DELETE("ciphers/{cipherId}") suspend fun hardDeleteCipher( @Path("cipherId") cipherId: String, - ): Result + ): NetworkResult /** * Soft deletes a cipher. @@ -107,7 +108,7 @@ interface CiphersApi { @PUT("ciphers/{cipherId}/delete") suspend fun softDeleteCipher( @Path("cipherId") cipherId: String, - ): Result + ): NetworkResult /** * Deletes an attachment from a cipher. @@ -116,7 +117,7 @@ interface CiphersApi { suspend fun deleteCipherAttachment( @Path("cipherId") cipherId: String, @Path("attachmentId") attachmentId: String, - ): Result + ): NetworkResult /** * Restores a cipher. @@ -124,7 +125,7 @@ interface CiphersApi { @PUT("ciphers/{cipherId}/restore") suspend fun restoreCipher( @Path("cipherId") cipherId: String, - ): Result + ): NetworkResult /** * Gets a cipher. @@ -132,7 +133,7 @@ interface CiphersApi { @GET("ciphers/{cipherId}") suspend fun getCipher( @Path("cipherId") cipherId: String, - ): Result + ): NetworkResult /** * Gets a cipher attachment. @@ -141,11 +142,11 @@ interface CiphersApi { suspend fun getCipherAttachment( @Path("cipherId") cipherId: String, @Path("attachmentId") attachmentId: String, - ): Result + ): NetworkResult /** * Indicates if the active user has unassigned ciphers. */ @GET("ciphers/has-unassigned-ciphers") - suspend fun hasUnassignedCiphers(): Result + suspend fun hasUnassignedCiphers(): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/DownloadApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/DownloadApi.kt index ae7bd4471..8a1b41f0c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/DownloadApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/DownloadApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import okhttp3.ResponseBody import retrofit2.http.GET import retrofit2.http.Streaming @@ -16,5 +17,5 @@ interface DownloadApi { @Streaming suspend fun getDataStream( @Url url: String, - ): Result + ): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/FoldersApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/FoldersApi.kt index 92097ade2..e301f1c58 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/FoldersApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/FoldersApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.vault.datasource.network.model.FolderJsonRequest import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson import retrofit2.http.Body @@ -18,7 +19,7 @@ interface FoldersApi { * Create a folder. */ @POST("folders") - suspend fun createFolder(@Body body: FolderJsonRequest): Result + suspend fun createFolder(@Body body: FolderJsonRequest): NetworkResult /** * Gets a folder. @@ -26,7 +27,7 @@ interface FoldersApi { @GET("folders/{folderId}") suspend fun getFolder( @Path("folderId") folderId: String, - ): Result + ): NetworkResult /** * Updates a folder. @@ -35,11 +36,11 @@ interface FoldersApi { suspend fun updateFolder( @Path("folderId") folderId: String, @Body body: FolderJsonRequest, - ): Result + ): NetworkResult /** * Deletes a folder. */ @DELETE("folders/{folderId}") - suspend fun deleteFolder(@Path("folderId") folderId: String): Result + suspend fun deleteFolder(@Path("folderId") folderId: String): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SendsApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SendsApi.kt index 102ff6a5e..fc5fe2cee 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SendsApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SendsApi.kt @@ -1,6 +1,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api import androidx.annotation.Keep +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateFileSendResponseJson import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson @@ -22,13 +23,15 @@ interface SendsApi { * Create a text send. */ @POST("sends") - suspend fun createTextSend(@Body body: SendJsonRequest): Result + suspend fun createTextSend(@Body body: SendJsonRequest): NetworkResult /** * Create a file send. */ @POST("sends/file/v2") - suspend fun createFileSend(@Body body: SendJsonRequest): Result + suspend fun createFileSend( + @Body body: SendJsonRequest, + ): NetworkResult /** * Updates a send. @@ -37,7 +40,7 @@ interface SendsApi { suspend fun updateSend( @Path("sendId") sendId: String, @Body body: SendJsonRequest, - ): Result + ): NetworkResult /** * Uploads the file associated with a send. @@ -47,23 +50,25 @@ interface SendsApi { @Path("sendId") sendId: String, @Path("fileId") fileId: String, @Body body: MultipartBody, - ): Result + ): NetworkResult /** * Deletes a send. */ @DELETE("sends/{sendId}") - suspend fun deleteSend(@Path("sendId") sendId: String): Result + suspend fun deleteSend(@Path("sendId") sendId: String): NetworkResult /** * Deletes a send. */ @PUT("sends/{sendId}/remove-password") - suspend fun removeSendPassword(@Path("sendId") sendId: String): Result + suspend fun removeSendPassword( + @Path("sendId") sendId: String, + ): NetworkResult /** * Gets a send. */ @GET("sends/{sendId}") - suspend fun getSend(@Path("sendId") sendId: String): Result + suspend fun getSend(@Path("sendId") sendId: String): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SyncApi.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SyncApi.kt index 1f1c7ece7..dcc2a3c72 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SyncApi.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/api/SyncApi.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.api +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson import retrofit2.http.GET @@ -13,8 +14,8 @@ interface SyncApi { * @return A [SyncResponseJson] containing the vault response model. */ @GET("sync") - suspend fun sync(): Result + suspend fun sync(): NetworkResult @GET("/accounts/revision-date") - suspend fun getAccountRevisionDateMillis(): Result + suspend fun getAccountRevisionDateMillis(): NetworkResult } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt index 7610fa77e..b4a61c39e 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceImpl.kt @@ -4,6 +4,7 @@ import androidx.core.net.toUri import com.bitwarden.vault.Attachment import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.platform.util.asFailure import com.x8bit.bitwarden.data.vault.datasource.network.api.AzureApi import com.x8bit.bitwarden.data.vault.datasource.network.api.CiphersApi @@ -34,20 +35,26 @@ class CiphersServiceImpl( private val clock: Clock, ) : CiphersService { override suspend fun createCipher(body: CipherJsonRequest): Result = - ciphersApi.createCipher(body = body) + ciphersApi + .createCipher(body = body) + .toResult() override suspend fun createCipherInOrganization( body: CreateCipherInOrganizationJsonRequest, - ): Result = ciphersApi.createCipherInOrganization(body = body) + ): Result = ciphersApi + .createCipherInOrganization(body = body) + .toResult() override suspend fun createAttachment( cipherId: String, body: AttachmentJsonRequest, ): Result = - ciphersApi.createAttachment( - cipherId = cipherId, - body = body, - ) + ciphersApi + .createAttachment( + cipherId = cipherId, + body = body, + ) + .toResult() override suspend fun uploadAttachment( attachmentJsonResponse: AttachmentJsonResponse, @@ -82,6 +89,7 @@ class CiphersServiceImpl( ) } } + .toResult() .map { cipher } } @@ -94,6 +102,7 @@ class CiphersServiceImpl( cipherId = cipherId, body = body, ) + .toResult() .map { UpdateCipherResponseJson.Success(cipher = it) } .recoverCatching { throwable -> throwable @@ -115,77 +124,97 @@ class CiphersServiceImpl( ?: return IllegalStateException("Attachment must have ID").asFailure() val attachmentKey = attachment.key ?: return IllegalStateException("Attachment must have Key").asFailure() - return ciphersApi.shareAttachment( - cipherId = cipherId, - attachmentId = attachmentId, - organizationId = organizationId, - body = this - .createMultipartBodyBuilder( - encryptedFile = encryptedFile, - filename = attachment.fileName, - ) - .addPart( - part = MultipartBody.Part.createFormData( - name = "key", - value = attachmentKey, - ), - ) - .build(), - ) + return ciphersApi + .shareAttachment( + cipherId = cipherId, + attachmentId = attachmentId, + organizationId = organizationId, + body = this + .createMultipartBodyBuilder( + encryptedFile = encryptedFile, + filename = attachment.fileName, + ) + .addPart( + part = MultipartBody.Part.createFormData( + name = "key", + value = attachmentKey, + ), + ) + .build(), + ) + .toResult() } override suspend fun shareCipher( cipherId: String, body: ShareCipherJsonRequest, ): Result = - ciphersApi.shareCipher( - cipherId = cipherId, - body = body, - ) + ciphersApi + .shareCipher( + cipherId = cipherId, + body = body, + ) + .toResult() override suspend fun updateCipherCollections( cipherId: String, body: UpdateCipherCollectionsJsonRequest, ): Result = - ciphersApi.updateCipherCollections( - cipherId = cipherId, - body = body, - ) + ciphersApi + .updateCipherCollections( + cipherId = cipherId, + body = body, + ) + .toResult() override suspend fun hardDeleteCipher(cipherId: String): Result = - ciphersApi.hardDeleteCipher(cipherId = cipherId) + ciphersApi + .hardDeleteCipher(cipherId = cipherId) + .toResult() override suspend fun softDeleteCipher(cipherId: String): Result = - ciphersApi.softDeleteCipher(cipherId = cipherId) + ciphersApi + .softDeleteCipher(cipherId = cipherId) + .toResult() override suspend fun deleteCipherAttachment( cipherId: String, attachmentId: String, ): Result = - ciphersApi.deleteCipherAttachment( - cipherId = cipherId, - attachmentId = attachmentId, - ) + ciphersApi + .deleteCipherAttachment( + cipherId = cipherId, + attachmentId = attachmentId, + ) + .toResult() override suspend fun restoreCipher(cipherId: String): Result = - ciphersApi.restoreCipher(cipherId = cipherId) + ciphersApi + .restoreCipher(cipherId = cipherId) + .toResult() override suspend fun getCipher( cipherId: String, ): Result = - ciphersApi.getCipher(cipherId = cipherId) + ciphersApi + .getCipher(cipherId = cipherId) + .toResult() override suspend fun getCipherAttachment( cipherId: String, attachmentId: String, ): Result = - ciphersApi.getCipherAttachment( - cipherId = cipherId, - attachmentId = attachmentId, - ) + ciphersApi + .getCipherAttachment( + cipherId = cipherId, + attachmentId = attachmentId, + ) + .toResult() override suspend fun hasUnassignedCiphers(): Result = - ciphersApi.hasUnassignedCiphers() + ciphersApi + .hasUnassignedCiphers() + .toResult() private fun createMultipartBodyBuilder( encryptedFile: File, diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/DownloadServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/DownloadServiceImpl.kt index 50e915362..cea6da4d6 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/DownloadServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/DownloadServiceImpl.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.vault.datasource.network.api.DownloadApi import okhttp3.ResponseBody @@ -12,5 +13,7 @@ class DownloadServiceImpl( override suspend fun getDataStream( url: String, ): Result = - downloadApi.getDataStream(url = url) + downloadApi + .getDataStream(url = url) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt index 572e87500..c1d7090fc 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/FolderServiceImpl.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.vault.datasource.network.api.FoldersApi import com.x8bit.bitwarden.data.vault.datasource.network.model.FolderJsonRequest import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson @@ -13,7 +14,9 @@ class FolderServiceImpl( private val json: Json, ) : FolderService { override suspend fun createFolder(body: FolderJsonRequest): Result = - foldersApi.createFolder(body = body) + foldersApi + .createFolder(body = body) + .toResult() override suspend fun updateFolder( folderId: String, @@ -24,6 +27,7 @@ class FolderServiceImpl( folderId = folderId, body = body, ) + .toResult() .map { UpdateFolderResponseJson.Success(folder = it) } .recoverCatching { throwable -> throwable @@ -36,10 +40,13 @@ class FolderServiceImpl( } override suspend fun deleteFolder(folderId: String): Result = - foldersApi.deleteFolder(folderId = folderId) + foldersApi + .deleteFolder(folderId = folderId) + .toResult() override suspend fun getFolder( folderId: String, ): Result = foldersApi .getFolder(folderId = folderId) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt index d8104447d..63647394c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SendsServiceImpl.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service import androidx.core.net.toUri import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.vault.datasource.network.api.AzureApi import com.x8bit.bitwarden.data.vault.datasource.network.api.SendsApi import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateFileSendResponse @@ -34,7 +35,9 @@ class SendsServiceImpl( override suspend fun createTextSend( body: SendJsonRequest, ): Result = - sendsApi.createTextSend(body = body) + sendsApi + .createTextSend(body = body) + .toResult() .map { CreateSendJsonResponse.Success(send = it) } .recoverCatching { throwable -> throwable.toBitwardenError() @@ -48,7 +51,9 @@ class SendsServiceImpl( override suspend fun createFileSend( body: SendJsonRequest, ): Result = - sendsApi.createFileSend(body = body) + sendsApi + .createFileSend(body = body) + .toResult() .map { CreateFileSendResponse.Success(it) } .recoverCatching { throwable -> throwable.toBitwardenError() @@ -68,6 +73,7 @@ class SendsServiceImpl( sendId = sendId, body = body, ) + .toResult() .map { UpdateSendResponseJson.Success(send = it) } .recoverCatching { throwable -> throwable @@ -118,16 +124,20 @@ class SendsServiceImpl( ) } } + .toResult() .onFailure { sendsApi.deleteSend(send.id) } .map { send } } override suspend fun deleteSend(sendId: String): Result = - sendsApi.deleteSend(sendId = sendId) + sendsApi + .deleteSend(sendId = sendId) + .toResult() override suspend fun removeSendPassword(sendId: String): Result = sendsApi .removeSendPassword(sendId = sendId) + .toResult() .map { UpdateSendResponseJson.Success(send = it) } .recoverCatching { throwable -> throwable @@ -142,5 +152,7 @@ class SendsServiceImpl( override suspend fun getSend( sendId: String, ): Result = - sendsApi.getSend(sendId = sendId) + sendsApi + .getSend(sendId = sendId) + .toResult() } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SyncServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SyncServiceImpl.kt index 57e478dd7..bfa8a0f3c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SyncServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/datasource/network/service/SyncServiceImpl.kt @@ -1,13 +1,18 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service +import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult import com.x8bit.bitwarden.data.vault.datasource.network.api.SyncApi import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson class SyncServiceImpl( private val syncApi: SyncApi, ) : SyncService { - override suspend fun sync(): Result = syncApi.sync() + override suspend fun sync(): Result = syncApi + .sync() + .toResult() override suspend fun getAccountRevisionDateMillis(): Result = - syncApi.getAccountRevisionDateMillis() + syncApi + .getAccountRevisionDateMillis() + .toResult() } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/BaseServiceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/base/BaseServiceTest.kt index 57bcf0e95..5a8e37a44 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/base/BaseServiceTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/base/BaseServiceTest.kt @@ -1,6 +1,6 @@ package com.x8bit.bitwarden.data.platform.base -import com.x8bit.bitwarden.data.platform.datasource.network.core.ResultCallAdapterFactory +import com.x8bit.bitwarden.data.platform.datasource.network.core.NetworkResultCallAdapterFactory import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule import okhttp3.HttpUrl import okhttp3.MediaType.Companion.toMediaType @@ -24,7 +24,7 @@ abstract class BaseServiceTest { protected val retrofit: Retrofit = Retrofit.Builder() .baseUrl(url.toString()) - .addCallAdapterFactory(ResultCallAdapterFactory()) + .addCallAdapterFactory(NetworkResultCallAdapterFactory()) .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) .build() diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterTest.kt similarity index 78% rename from app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterTest.kt rename to app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterTest.kt index e6688270e..a172e377e 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/ResultCallAdapterTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/core/NetworkResultCallAdapterTest.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.core +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import kotlinx.coroutines.runBlocking import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer @@ -10,14 +11,14 @@ import retrofit2.Retrofit import retrofit2.create import retrofit2.http.GET -class ResultCallAdapterTest { +class NetworkResultCallAdapterTest { private val server: MockWebServer = MockWebServer().apply { start() } private val testService: FakeService = Retrofit.Builder() .baseUrl(server.url("/").toString()) // add the adapter being tested - .addCallAdapterFactory(ResultCallAdapterFactory()) + .addCallAdapterFactory(NetworkResultCallAdapterFactory()) .build() .create() @@ -30,14 +31,14 @@ class ResultCallAdapterTest { fun `when server returns error response code result should be failure`() = runBlocking { server.enqueue(MockResponse().setResponseCode(500)) val result = testService.requestWithUnitData() - assertTrue(result.isFailure) + assertTrue(result is NetworkResult.Failure) } @Test fun `when server returns successful response result should be success`() = runBlocking { server.enqueue(MockResponse()) val result = testService.requestWithUnitData() - assertTrue(result.isSuccess) + assertTrue(result is NetworkResult.Success) } } @@ -46,5 +47,5 @@ class ResultCallAdapterTest { */ private interface FakeService { @GET("/fake") - suspend fun requestWithUnitData(): Result + suspend fun requestWithUnitData(): NetworkResult } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsTest.kt index 99e02a9ba..fe9cbb4b0 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/retrofit/RetrofitsTest.kt @@ -4,6 +4,7 @@ import com.x8bit.bitwarden.data.platform.datasource.network.authenticator.Refres import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.AuthTokenInterceptor import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.HeadersInterceptor +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import io.mockk.every import io.mockk.mockk import io.mockk.slot @@ -39,7 +40,7 @@ class RetrofitsTest { } } private val headersInterceptors = mockk { - mockIntercept { isheadersInterceptorCalled = true } + mockIntercept { isHeadersInterceptorCalled = true } } private val refreshAuthenticator = mockk { mockAuthenticate { isRefreshAuthenticatorCalled = true } @@ -57,7 +58,7 @@ class RetrofitsTest { private var isAuthInterceptorCalled = false private var isApiInterceptorCalled = false - private var isheadersInterceptorCalled = false + private var isHeadersInterceptorCalled = false private var isIdentityInterceptorCalled = false private var isEventsInterceptorCalled = false private var isRefreshAuthenticatorCalled = false @@ -158,7 +159,7 @@ class RetrofitsTest { assertTrue(isAuthInterceptorCalled) assertTrue(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertFalse(isIdentityInterceptorCalled) assertFalse(isEventsInterceptorCalled) } @@ -176,7 +177,7 @@ class RetrofitsTest { assertTrue(isAuthInterceptorCalled) assertFalse(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertFalse(isIdentityInterceptorCalled) assertTrue(isEventsInterceptorCalled) } @@ -194,7 +195,7 @@ class RetrofitsTest { assertFalse(isAuthInterceptorCalled) assertTrue(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertFalse(isIdentityInterceptorCalled) assertFalse(isEventsInterceptorCalled) } @@ -212,7 +213,7 @@ class RetrofitsTest { assertFalse(isAuthInterceptorCalled) assertFalse(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertTrue(isIdentityInterceptorCalled) assertFalse(isEventsInterceptorCalled) } @@ -231,7 +232,7 @@ class RetrofitsTest { assertTrue(isAuthInterceptorCalled) assertFalse(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertFalse(isIdentityInterceptorCalled) assertFalse(isEventsInterceptorCalled) } @@ -250,7 +251,7 @@ class RetrofitsTest { assertFalse(isAuthInterceptorCalled) assertFalse(isApiInterceptorCalled) - assertTrue(isheadersInterceptorCalled) + assertTrue(isHeadersInterceptorCalled) assertFalse(isIdentityInterceptorCalled) assertFalse(isEventsInterceptorCalled) } @@ -264,7 +265,7 @@ class RetrofitsTest { interface TestApi { @GET("/test") - suspend fun test(): Result + suspend fun test(): NetworkResult } /** diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensionsTest.kt index 393c0fd8c..64640abd1 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensionsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/CallExtensionsTest.kt @@ -1,6 +1,6 @@ package com.x8bit.bitwarden.data.platform.datasource.network.util -import com.x8bit.bitwarden.data.platform.util.asSuccess +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult import io.mockk.every import io.mockk.mockk import okhttp3.HttpUrl @@ -17,53 +17,53 @@ import java.net.URL class CallExtensionsTest { @Test - fun `executeForResult returns failure when execute throws IOException`() { + fun `executeForNetworkResult returns failure when execute throws IOException`() { val request = createMockkRequest() val call = mockk> { every { request() } returns request every { execute() } throws IOException("Fail") } - val result = call.executeForResult() + val result = call.executeForNetworkResult() - assertTrue(result.isFailure) + assertTrue(result is NetworkResult.Failure) } @Test - fun `executeForResult returns failure when execute throws RuntimeException`() { + fun `executeForNetworkResult returns failure when execute throws RuntimeException`() { val request = createMockkRequest() val call = mockk> { every { request() } returns request every { execute() } throws RuntimeException("Fail") } - val result = call.executeForResult() + val result = call.executeForNetworkResult() - assertTrue(result.isFailure) + assertTrue(result is NetworkResult.Failure) } @Test - fun `executeForResult returns failure when response is failure`() { + fun `executeForNetworkResult returns failure when response is failure`() { val request = createMockkRequest() val call = mockk> { every { request() } returns request every { execute() } returns Response.error(400, "".toResponseBody()) } - val result = call.executeForResult() + val result = call.executeForNetworkResult() - assertTrue(result.isFailure) + assertTrue(result is NetworkResult.Failure) } @Test - fun `executeForResult returns success when response is failure`() { + fun `executeForNetworkResult returns success when response is failure`() { val call = mockk> { every { execute() } returns Response.success(Unit) } - val result = call.executeForResult() + val result = call.executeForNetworkResult() - assertEquals(Unit.asSuccess(), result) + assertEquals(NetworkResult.Success(Unit), result) } private fun createMockkRequest(): Request { diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensionsTest.kt new file mode 100644 index 000000000..e21e45406 --- /dev/null +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/network/util/NetworkResultExtensionsTest.kt @@ -0,0 +1,29 @@ +package com.x8bit.bitwarden.data.platform.datasource.network.util + +import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult +import com.x8bit.bitwarden.data.platform.util.asFailure +import com.x8bit.bitwarden.data.platform.util.asSuccess +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class NetworkResultExtensionsTest { + @Test + fun `NetworkResult toResult with success should return successful result`() { + val value = "test" + val original = NetworkResult.Success(value) + + val result = original.toResult() + + assertEquals(value.asSuccess(), result) + } + + @Test + fun `NetworkResult toResult with failure should return failure result`() { + val exception = Exception("Failed") + val original = NetworkResult.Failure(exception) + + val result = original.toResult() + + assertEquals(exception.asFailure(), result) + } +} diff --git a/app/src/test/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceTest.kt index 50c6b07a4..d8036ce44 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/vault/datasource/network/service/CiphersServiceTest.kt @@ -311,7 +311,7 @@ class CiphersServiceTest : BaseServiceTest() { ) assertEquals( createMockAttachment(number = 1), - result.testGetOrThrow(), + result.getOrThrow(), ) } @@ -336,25 +336,6 @@ private fun setupMockUri( return mockUri } -/** - * A helper method to attempt validate that the the value is being boxed and causing test to - * inconsistently fail. - * - * This was modified from the code found here: - * * https://github.com/mockk/mockk/issues/485#issuecomment-1973170516 - */ -@Suppress("INVISIBLE_REFERENCE", "UNCHECKED_CAST") -private fun Result.testGetOrThrow(): T = - when (val unboxed: Any? = value) { - is Result.Failure -> throw unboxed.exception - !is Result<*> -> unboxed as T - else -> { - // This means the result is boxed, we could make this recursive to address the issue. - println("Unboxed value = $unboxed") - unboxed as T - } - } - private const val CREATE_ATTACHMENT_SUCCESS_JSON = """ { "attachmentId":"mockAttachmentId-1",