mirror of
https://github.com/bitwarden/android.git
synced 2024-11-21 17:05:44 +03:00
PM-14805: Use network result in all Retrofit API requests (#4286)
This commit is contained in:
parent
a8416b073e
commit
f33296b44f
52 changed files with 524 additions and 323 deletions
|
@ -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.ResetPasswordRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson
|
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.auth.datasource.network.model.VerifyOtpRequestJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.HTTP
|
import retrofit2.http.HTTP
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
@ -18,43 +19,43 @@ interface AuthenticatedAccountsApi {
|
||||||
* Converts the currently active account to a key-connector account.
|
* Converts the currently active account to a key-connector account.
|
||||||
*/
|
*/
|
||||||
@POST("/accounts/convert-to-key-connector")
|
@POST("/accounts/convert-to-key-connector")
|
||||||
suspend fun convertToKeyConnector(): Result<Unit>
|
suspend fun convertToKeyConnector(): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the keys for the current account.
|
* Creates the keys for the current account.
|
||||||
*/
|
*/
|
||||||
@POST("/accounts/keys")
|
@POST("/accounts/keys")
|
||||||
suspend fun createAccountKeys(@Body body: CreateAccountKeysRequest): Result<Unit>
|
suspend fun createAccountKeys(@Body body: CreateAccountKeysRequest): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the current account.
|
* Deletes the current account.
|
||||||
*/
|
*/
|
||||||
@HTTP(method = "DELETE", path = "/accounts", hasBody = true)
|
@HTTP(method = "DELETE", path = "/accounts", hasBody = true)
|
||||||
suspend fun deleteAccount(@Body body: DeleteAccountRequestJson): Result<Unit>
|
suspend fun deleteAccount(@Body body: DeleteAccountRequestJson): NetworkResult<Unit>
|
||||||
|
|
||||||
@POST("/accounts/request-otp")
|
@POST("/accounts/request-otp")
|
||||||
suspend fun requestOtp(): Result<Unit>
|
suspend fun requestOtp(): NetworkResult<Unit>
|
||||||
|
|
||||||
@POST("/accounts/verify-otp")
|
@POST("/accounts/verify-otp")
|
||||||
suspend fun verifyOtp(
|
suspend fun verifyOtp(
|
||||||
@Body body: VerifyOtpRequestJson,
|
@Body body: VerifyOtpRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the temporary password.
|
* Resets the temporary password.
|
||||||
*/
|
*/
|
||||||
@HTTP(method = "PUT", path = "/accounts/update-temp-password", hasBody = true)
|
@HTTP(method = "PUT", path = "/accounts/update-temp-password", hasBody = true)
|
||||||
suspend fun resetTempPassword(@Body body: ResetPasswordRequestJson): Result<Unit>
|
suspend fun resetTempPassword(@Body body: ResetPasswordRequestJson): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the password.
|
* Resets the password.
|
||||||
*/
|
*/
|
||||||
@HTTP(method = "POST", path = "/accounts/password", hasBody = true)
|
@HTTP(method = "POST", path = "/accounts/password", hasBody = true)
|
||||||
suspend fun resetPassword(@Body body: ResetPasswordRequestJson): Result<Unit>
|
suspend fun resetPassword(@Body body: ResetPasswordRequestJson): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the password.
|
* Sets the password.
|
||||||
*/
|
*/
|
||||||
@POST("/accounts/set-password")
|
@POST("/accounts/set-password")
|
||||||
suspend fun setPassword(@Body body: SetPasswordRequestJson): Result<Unit>
|
suspend fun setPassword(@Body body: SetPasswordRequestJson): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.AuthRequestRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestUpdateRequestJson
|
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.auth.datasource.network.model.AuthRequestsResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
@ -22,7 +23,7 @@ interface AuthenticatedAuthRequestsApi {
|
||||||
suspend fun createAdminAuthRequest(
|
suspend fun createAdminAuthRequest(
|
||||||
@Header("Device-Identifier") deviceIdentifier: String,
|
@Header("Device-Identifier") deviceIdentifier: String,
|
||||||
@Body body: AuthRequestRequestJson,
|
@Body body: AuthRequestRequestJson,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest>
|
): NetworkResult<AuthRequestsResponseJson.AuthRequest>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an authentication request.
|
* Updates an authentication request.
|
||||||
|
@ -31,13 +32,13 @@ interface AuthenticatedAuthRequestsApi {
|
||||||
suspend fun updateAuthRequest(
|
suspend fun updateAuthRequest(
|
||||||
@Path("id") userId: String,
|
@Path("id") userId: String,
|
||||||
@Body body: AuthRequestUpdateRequestJson,
|
@Body body: AuthRequestUpdateRequestJson,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest>
|
): NetworkResult<AuthRequestsResponseJson.AuthRequest>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of auth requests for this device.
|
* Gets a list of auth requests for this device.
|
||||||
*/
|
*/
|
||||||
@GET("/auth-requests")
|
@GET("/auth-requests")
|
||||||
suspend fun getAuthRequests(): Result<AuthRequestsResponseJson>
|
suspend fun getAuthRequests(): NetworkResult<AuthRequestsResponseJson>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves an existing authentication request by ID.
|
* Retrieves an existing authentication request by ID.
|
||||||
|
@ -45,5 +46,5 @@ interface AuthenticatedAuthRequestsApi {
|
||||||
@GET("/auth-requests/{requestId}")
|
@GET("/auth-requests/{requestId}")
|
||||||
suspend fun getAuthRequest(
|
suspend fun getAuthRequest(
|
||||||
@Path("requestId") requestId: String,
|
@Path("requestId") requestId: String,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest>
|
): NetworkResult<AuthRequestsResponseJson.AuthRequest>
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysRequestJson
|
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.auth.datasource.network.model.TrustedDeviceKeysResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.PUT
|
import retrofit2.http.PUT
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
|
@ -16,5 +17,5 @@ interface AuthenticatedDevicesApi {
|
||||||
suspend fun updateTrustedDeviceKeys(
|
suspend fun updateTrustedDeviceKeys(
|
||||||
@Path(value = "appId") appId: String,
|
@Path(value = "appId") appId: String,
|
||||||
@Body request: TrustedDeviceKeysRequestJson,
|
@Body request: TrustedDeviceKeysRequestJson,
|
||||||
): Result<TrustedDeviceKeysResponseJson>
|
): NetworkResult<TrustedDeviceKeysResponseJson>
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorMasterKeyRequestJson
|
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.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Url
|
import retrofit2.http.Url
|
||||||
|
@ -15,5 +16,5 @@ interface AuthenticatedKeyConnectorApi {
|
||||||
suspend fun storeMasterKeyToKeyConnector(
|
suspend fun storeMasterKeyToKeyConnector(
|
||||||
@Url url: String,
|
@Url url: String,
|
||||||
@Body body: KeyConnectorMasterKeyRequestJson,
|
@Body body: KeyConnectorMasterKeyRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.OrganizationAutoEnrollStatusResponseJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationKeysResponseJson
|
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.auth.datasource.network.model.OrganizationResetPasswordEnrollRequestJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.PUT
|
import retrofit2.http.PUT
|
||||||
|
@ -20,7 +21,7 @@ interface AuthenticatedOrganizationApi {
|
||||||
@Path("orgId") organizationId: String,
|
@Path("orgId") organizationId: String,
|
||||||
@Path("userId") userId: String,
|
@Path("userId") userId: String,
|
||||||
@Body body: OrganizationResetPasswordEnrollRequestJson,
|
@Body body: OrganizationResetPasswordEnrollRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether this organization auto enrolls users in password reset.
|
* Checks whether this organization auto enrolls users in password reset.
|
||||||
|
@ -28,7 +29,7 @@ interface AuthenticatedOrganizationApi {
|
||||||
@GET("/organizations/{identifier}/auto-enroll-status")
|
@GET("/organizations/{identifier}/auto-enroll-status")
|
||||||
suspend fun getOrganizationAutoEnrollResponse(
|
suspend fun getOrganizationAutoEnrollResponse(
|
||||||
@Path("identifier") organizationIdentifier: String,
|
@Path("identifier") organizationIdentifier: String,
|
||||||
): Result<OrganizationAutoEnrollStatusResponseJson>
|
): NetworkResult<OrganizationAutoEnrollStatusResponseJson>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the public and private keys for this organization.
|
* Gets the public and private keys for this organization.
|
||||||
|
@ -36,5 +37,5 @@ interface AuthenticatedOrganizationApi {
|
||||||
@GET("/organizations/{id}/keys")
|
@GET("/organizations/{id}/keys")
|
||||||
suspend fun getOrganizationKeys(
|
suspend fun getOrganizationKeys(
|
||||||
@Path("id") organizationId: String,
|
@Path("id") organizationId: String,
|
||||||
): Result<OrganizationKeysResponseJson>
|
): NetworkResult<OrganizationKeysResponseJson>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.auth.datasource.network.api
|
package com.x8bit.bitwarden.data.auth.datasource.network.api
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
|
@ -14,5 +15,5 @@ interface HaveIBeenPwnedApi {
|
||||||
suspend fun fetchBreachedPasswords(
|
suspend fun fetchBreachedPasswords(
|
||||||
@Path("hashPrefix")
|
@Path("hashPrefix")
|
||||||
hashPrefix: String,
|
hashPrefix: String,
|
||||||
): Result<ResponseBody>
|
): NetworkResult<ResponseBody>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.KeyConnectorKeyRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.PasswordHintRequestJson
|
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.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 com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_KEY_AUTHORIZATION
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
@ -15,16 +16,16 @@ interface UnauthenticatedAccountsApi {
|
||||||
@POST("/accounts/password-hint")
|
@POST("/accounts/password-hint")
|
||||||
suspend fun passwordHintRequest(
|
suspend fun passwordHintRequest(
|
||||||
@Body body: PasswordHintRequestJson,
|
@Body body: PasswordHintRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
@POST("/two-factor/send-email-login")
|
@POST("/two-factor/send-email-login")
|
||||||
suspend fun resendVerificationCodeEmail(
|
suspend fun resendVerificationCodeEmail(
|
||||||
@Body body: ResendEmailRequestJson,
|
@Body body: ResendEmailRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
@POST("/accounts/set-key-connector-key")
|
@POST("/accounts/set-key-connector-key")
|
||||||
suspend fun setKeyConnectorKey(
|
suspend fun setKeyConnectorKey(
|
||||||
@Body body: KeyConnectorKeyRequestJson,
|
@Body body: KeyConnectorKeyRequestJson,
|
||||||
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.AuthRequestRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestsResponseJson
|
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.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
@ -21,7 +22,7 @@ interface UnauthenticatedAuthRequestsApi {
|
||||||
suspend fun createAuthRequest(
|
suspend fun createAuthRequest(
|
||||||
@Header("Device-Identifier") deviceIdentifier: String,
|
@Header("Device-Identifier") deviceIdentifier: String,
|
||||||
@Body body: AuthRequestRequestJson,
|
@Body body: AuthRequestRequestJson,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest>
|
): NetworkResult<AuthRequestsResponseJson.AuthRequest>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries for updates to a given auth request.
|
* Queries for updates to a given auth request.
|
||||||
|
@ -30,5 +31,5 @@ interface UnauthenticatedAuthRequestsApi {
|
||||||
suspend fun getAuthRequestUpdate(
|
suspend fun getAuthRequestUpdate(
|
||||||
@Path("requestId") requestId: String,
|
@Path("requestId") requestId: String,
|
||||||
@Query("code") accessCode: String,
|
@Query("code") accessCode: String,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest>
|
): NetworkResult<AuthRequestsResponseJson.AuthRequest>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.auth.datasource.network.api
|
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.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
|
||||||
|
@ -11,5 +12,5 @@ interface UnauthenticatedDevicesApi {
|
||||||
suspend fun getIsKnownDevice(
|
suspend fun getIsKnownDevice(
|
||||||
@Header(value = "X-Request-Email") emailAddress: String,
|
@Header(value = "X-Request-Email") emailAddress: String,
|
||||||
@Header(value = "X-Device-Identifier") deviceId: String,
|
@Header(value = "X-Device-Identifier") deviceId: String,
|
||||||
): Result<Boolean>
|
): NetworkResult<Boolean>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.RegisterResponseJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailRequestJson
|
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.auth.datasource.network.model.VerifyEmailTokenRequestJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import kotlinx.serialization.json.JsonPrimitive
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
@ -46,12 +47,12 @@ interface UnauthenticatedIdentityApi {
|
||||||
@Field(value = "twoFactorProvider") twoFactorMethod: String?,
|
@Field(value = "twoFactorProvider") twoFactorMethod: String?,
|
||||||
@Field(value = "twoFactorRemember") twoFactorRemember: String?,
|
@Field(value = "twoFactorRemember") twoFactorRemember: String?,
|
||||||
@Field(value = "authRequest") authRequestId: String?,
|
@Field(value = "authRequest") authRequestId: String?,
|
||||||
): Result<GetTokenResponseJson.Success>
|
): NetworkResult<GetTokenResponseJson.Success>
|
||||||
|
|
||||||
@GET("/sso/prevalidate")
|
@GET("/sso/prevalidate")
|
||||||
suspend fun prevalidateSso(
|
suspend fun prevalidateSso(
|
||||||
@Query("domainHint") organizationIdentifier: String,
|
@Query("domainHint") organizationIdentifier: String,
|
||||||
): Result<PrevalidateSsoResponseJson>
|
): NetworkResult<PrevalidateSsoResponseJson>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This call needs to be synchronous so we need it to return a [Call] directly. The identity
|
* This call needs to be synchronous so we need it to return a [Call] directly. The identity
|
||||||
|
@ -66,23 +67,25 @@ interface UnauthenticatedIdentityApi {
|
||||||
): Call<RefreshTokenResponseJson>
|
): Call<RefreshTokenResponseJson>
|
||||||
|
|
||||||
@POST("/accounts/prelogin")
|
@POST("/accounts/prelogin")
|
||||||
suspend fun preLogin(@Body body: PreLoginRequestJson): Result<PreLoginResponseJson>
|
suspend fun preLogin(@Body body: PreLoginRequestJson): NetworkResult<PreLoginResponseJson>
|
||||||
|
|
||||||
@POST("/accounts/register")
|
@POST("/accounts/register")
|
||||||
suspend fun register(@Body body: RegisterRequestJson): Result<RegisterResponseJson.Success>
|
suspend fun register(
|
||||||
|
@Body body: RegisterRequestJson,
|
||||||
|
): NetworkResult<RegisterResponseJson.Success>
|
||||||
|
|
||||||
@POST("/accounts/register/finish")
|
@POST("/accounts/register/finish")
|
||||||
suspend fun registerFinish(
|
suspend fun registerFinish(
|
||||||
@Body body: RegisterFinishRequestJson,
|
@Body body: RegisterFinishRequestJson,
|
||||||
): Result<RegisterResponseJson.Success>
|
): NetworkResult<RegisterResponseJson.Success>
|
||||||
|
|
||||||
@POST("/accounts/register/send-verification-email")
|
@POST("/accounts/register/send-verification-email")
|
||||||
suspend fun sendVerificationEmail(
|
suspend fun sendVerificationEmail(
|
||||||
@Body body: SendVerificationEmailRequestJson,
|
@Body body: SendVerificationEmailRequestJson,
|
||||||
): Result<JsonPrimitive?>
|
): NetworkResult<JsonPrimitive?>
|
||||||
|
|
||||||
@POST("/accounts/register/verification-email-clicked")
|
@POST("/accounts/register/verification-email-clicked")
|
||||||
suspend fun verifyEmailToken(
|
suspend fun verifyEmailToken(
|
||||||
@Body body: VerifyEmailTokenRequestJson,
|
@Body body: VerifyEmailTokenRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.KeyConnectorMasterKeyRequestJson
|
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.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 com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_KEY_AUTHORIZATION
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
@ -20,11 +21,11 @@ interface UnauthenticatedKeyConnectorApi {
|
||||||
@Url url: String,
|
@Url url: String,
|
||||||
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
||||||
@Body body: KeyConnectorMasterKeyRequestJson,
|
@Body body: KeyConnectorMasterKeyRequestJson,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
suspend fun getMasterKeyFromKeyConnector(
|
suspend fun getMasterKeyFromKeyConnector(
|
||||||
@Url url: String,
|
@Url url: String,
|
||||||
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
@Header(HEADER_KEY_AUTHORIZATION) bearerToken: String,
|
||||||
): Result<KeyConnectorMasterKeyResponseJson>
|
): NetworkResult<KeyConnectorMasterKeyResponseJson>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.OrganizationDomainSsoDetailsResponseJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest
|
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.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ interface UnauthenticatedOrganizationApi {
|
||||||
@POST("/organizations/domain/sso/details")
|
@POST("/organizations/domain/sso/details")
|
||||||
suspend fun getClaimedDomainOrganizationDetails(
|
suspend fun getClaimedDomainOrganizationDetails(
|
||||||
@Body body: OrganizationDomainSsoDetailsRequestJson,
|
@Body body: OrganizationDomainSsoDetailsRequestJson,
|
||||||
): Result<OrganizationDomainSsoDetailsResponseJson>
|
): NetworkResult<OrganizationDomainSsoDetailsResponseJson>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for the verfied organization domains of an email for SSO purposes.
|
* Checks for the verfied organization domains of an email for SSO purposes.
|
||||||
|
@ -25,5 +26,5 @@ interface UnauthenticatedOrganizationApi {
|
||||||
@POST("/organizations/domain/sso/verified")
|
@POST("/organizations/domain/sso/verified")
|
||||||
suspend fun getVerifiedOrganizationDomainsByEmail(
|
suspend fun getVerifiedOrganizationDomainsByEmail(
|
||||||
@Body body: VerifiedOrganizationDomainSsoDetailsRequest,
|
@Body body: VerifiedOrganizationDomainSsoDetailsRequest,
|
||||||
): Result<VerifiedOrganizationDomainSsoDetailsResponse>
|
): NetworkResult<VerifiedOrganizationDomainSsoDetailsResponse>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.model.toBitwardenError
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.util.HEADER_VALUE_BEARER_PREFIX
|
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.parseErrorBodyOrNull
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,18 +38,22 @@ class AccountsServiceImpl(
|
||||||
* Converts the currently active account to a key-connector account.
|
* Converts the currently active account to a key-connector account.
|
||||||
*/
|
*/
|
||||||
override suspend fun convertToKeyConnector(): Result<Unit> =
|
override suspend fun convertToKeyConnector(): Result<Unit> =
|
||||||
authenticatedAccountsApi.convertToKeyConnector()
|
authenticatedAccountsApi
|
||||||
|
.convertToKeyConnector()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun createAccountKeys(
|
override suspend fun createAccountKeys(
|
||||||
publicKey: String,
|
publicKey: String,
|
||||||
encryptedPrivateKey: String,
|
encryptedPrivateKey: String,
|
||||||
): Result<Unit> =
|
): Result<Unit> =
|
||||||
authenticatedAccountsApi.createAccountKeys(
|
authenticatedAccountsApi
|
||||||
body = CreateAccountKeysRequest(
|
.createAccountKeys(
|
||||||
publicKey = publicKey,
|
body = CreateAccountKeysRequest(
|
||||||
encryptedPrivateKey = encryptedPrivateKey,
|
publicKey = publicKey,
|
||||||
),
|
encryptedPrivateKey = encryptedPrivateKey,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun deleteAccount(
|
override suspend fun deleteAccount(
|
||||||
masterPasswordHash: String?,
|
masterPasswordHash: String?,
|
||||||
|
@ -61,9 +66,8 @@ class AccountsServiceImpl(
|
||||||
oneTimePassword = oneTimePassword,
|
oneTimePassword = oneTimePassword,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map {
|
.toResult()
|
||||||
DeleteAccountResponseJson.Success
|
.map { DeleteAccountResponseJson.Success }
|
||||||
}
|
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
.toBitwardenError()
|
.toBitwardenError()
|
||||||
|
@ -75,20 +79,25 @@ class AccountsServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun requestOneTimePasscode(): Result<Unit> =
|
override suspend fun requestOneTimePasscode(): Result<Unit> =
|
||||||
authenticatedAccountsApi.requestOtp()
|
authenticatedAccountsApi
|
||||||
|
.requestOtp()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun verifyOneTimePasscode(passcode: String): Result<Unit> =
|
override suspend fun verifyOneTimePasscode(passcode: String): Result<Unit> =
|
||||||
authenticatedAccountsApi.verifyOtp(
|
authenticatedAccountsApi
|
||||||
VerifyOtpRequestJson(
|
.verifyOtp(
|
||||||
oneTimePasscode = passcode,
|
VerifyOtpRequestJson(
|
||||||
),
|
oneTimePasscode = passcode,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun requestPasswordHint(
|
override suspend fun requestPasswordHint(
|
||||||
email: String,
|
email: String,
|
||||||
): Result<PasswordHintResponseJson> =
|
): Result<PasswordHintResponseJson> =
|
||||||
unauthenticatedAccountsApi
|
unauthenticatedAccountsApi
|
||||||
.passwordHintRequest(PasswordHintRequestJson(email))
|
.passwordHintRequest(PasswordHintRequestJson(email))
|
||||||
|
.toResult()
|
||||||
.map { PasswordHintResponseJson.Success }
|
.map { PasswordHintResponseJson.Success }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
|
@ -101,54 +110,70 @@ class AccountsServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun resendVerificationCodeEmail(body: ResendEmailRequestJson): Result<Unit> =
|
override suspend fun resendVerificationCodeEmail(body: ResendEmailRequestJson): Result<Unit> =
|
||||||
unauthenticatedAccountsApi.resendVerificationCodeEmail(body = body)
|
unauthenticatedAccountsApi
|
||||||
|
.resendVerificationCodeEmail(body = body)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun resetPassword(body: ResetPasswordRequestJson): Result<Unit> {
|
override suspend fun resetPassword(body: ResetPasswordRequestJson): Result<Unit> =
|
||||||
return if (body.currentPasswordHash == null) {
|
if (body.currentPasswordHash == null) {
|
||||||
authenticatedAccountsApi.resetTempPassword(body = body)
|
authenticatedAccountsApi
|
||||||
|
.resetTempPassword(body = body)
|
||||||
|
.toResult()
|
||||||
} else {
|
} else {
|
||||||
authenticatedAccountsApi.resetPassword(body = body)
|
authenticatedAccountsApi
|
||||||
|
.resetPassword(body = body)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun setKeyConnectorKey(
|
override suspend fun setKeyConnectorKey(
|
||||||
accessToken: String,
|
accessToken: String,
|
||||||
body: KeyConnectorKeyRequestJson,
|
body: KeyConnectorKeyRequestJson,
|
||||||
): Result<Unit> = unauthenticatedAccountsApi.setKeyConnectorKey(
|
): Result<Unit> =
|
||||||
body = body,
|
unauthenticatedAccountsApi
|
||||||
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
.setKeyConnectorKey(
|
||||||
)
|
body = body,
|
||||||
|
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun setPassword(
|
override suspend fun setPassword(
|
||||||
body: SetPasswordRequestJson,
|
body: SetPasswordRequestJson,
|
||||||
): Result<Unit> = authenticatedAccountsApi.setPassword(body)
|
): Result<Unit> = authenticatedAccountsApi
|
||||||
|
.setPassword(body)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getMasterKeyFromKeyConnector(
|
override suspend fun getMasterKeyFromKeyConnector(
|
||||||
url: String,
|
url: String,
|
||||||
accessToken: String,
|
accessToken: String,
|
||||||
): Result<KeyConnectorMasterKeyResponseJson> =
|
): Result<KeyConnectorMasterKeyResponseJson> =
|
||||||
unauthenticatedKeyConnectorApi.getMasterKeyFromKeyConnector(
|
unauthenticatedKeyConnectorApi
|
||||||
url = "$url/user-keys",
|
.getMasterKeyFromKeyConnector(
|
||||||
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
url = "$url/user-keys",
|
||||||
)
|
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun storeMasterKeyToKeyConnector(
|
override suspend fun storeMasterKeyToKeyConnector(
|
||||||
url: String,
|
url: String,
|
||||||
masterKey: String,
|
masterKey: String,
|
||||||
): Result<Unit> =
|
): Result<Unit> =
|
||||||
authenticatedKeyConnectorApi.storeMasterKeyToKeyConnector(
|
authenticatedKeyConnectorApi
|
||||||
url = "$url/user-keys",
|
.storeMasterKeyToKeyConnector(
|
||||||
body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey),
|
url = "$url/user-keys",
|
||||||
)
|
body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun storeMasterKeyToKeyConnector(
|
override suspend fun storeMasterKeyToKeyConnector(
|
||||||
url: String,
|
url: String,
|
||||||
accessToken: String,
|
accessToken: String,
|
||||||
masterKey: String,
|
masterKey: String,
|
||||||
): Result<Unit> =
|
): Result<Unit> =
|
||||||
unauthenticatedKeyConnectorApi.storeMasterKeyToKeyConnector(
|
unauthenticatedKeyConnectorApi
|
||||||
url = "$url/user-keys",
|
.storeMasterKeyToKeyConnector(
|
||||||
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
url = "$url/user-keys",
|
||||||
body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey),
|
bearerToken = "$HEADER_VALUE_BEARER_PREFIX$accessToken",
|
||||||
)
|
body = KeyConnectorMasterKeyRequestJson(masterKey = masterKey),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.api.AuthenticatedAuthRequestsApi
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestUpdateRequestJson
|
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.auth.datasource.network.model.AuthRequestsResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
|
|
||||||
class AuthRequestsServiceImpl(
|
class AuthRequestsServiceImpl(
|
||||||
private val authenticatedAuthRequestsApi: AuthenticatedAuthRequestsApi,
|
private val authenticatedAuthRequestsApi: AuthenticatedAuthRequestsApi,
|
||||||
) : AuthRequestsService {
|
) : AuthRequestsService {
|
||||||
override suspend fun getAuthRequests(): Result<AuthRequestsResponseJson> =
|
override suspend fun getAuthRequests(): Result<AuthRequestsResponseJson> =
|
||||||
authenticatedAuthRequestsApi.getAuthRequests()
|
authenticatedAuthRequestsApi
|
||||||
|
.getAuthRequests()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getAuthRequest(
|
override suspend fun getAuthRequest(
|
||||||
requestId: String,
|
requestId: String,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest> =
|
): Result<AuthRequestsResponseJson.AuthRequest> =
|
||||||
authenticatedAuthRequestsApi.getAuthRequest(requestId = requestId)
|
authenticatedAuthRequestsApi
|
||||||
|
.getAuthRequest(requestId = requestId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun updateAuthRequest(
|
override suspend fun updateAuthRequest(
|
||||||
requestId: String,
|
requestId: String,
|
||||||
|
@ -22,13 +27,15 @@ class AuthRequestsServiceImpl(
|
||||||
deviceId: String,
|
deviceId: String,
|
||||||
isApproved: Boolean,
|
isApproved: Boolean,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest> =
|
): Result<AuthRequestsResponseJson.AuthRequest> =
|
||||||
authenticatedAuthRequestsApi.updateAuthRequest(
|
authenticatedAuthRequestsApi
|
||||||
userId = requestId,
|
.updateAuthRequest(
|
||||||
body = AuthRequestUpdateRequestJson(
|
userId = requestId,
|
||||||
key = key,
|
body = AuthRequestUpdateRequestJson(
|
||||||
masterPasswordHash = masterPasswordHash,
|
key = key,
|
||||||
deviceId = deviceId,
|
masterPasswordHash = masterPasswordHash,
|
||||||
isApproved = isApproved,
|
deviceId = deviceId,
|
||||||
),
|
isApproved = isApproved,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.TrustedDeviceKeysRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceKeysResponseJson
|
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.base64UrlEncode
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
|
|
||||||
class DevicesServiceImpl(
|
class DevicesServiceImpl(
|
||||||
private val authenticatedDevicesApi: AuthenticatedDevicesApi,
|
private val authenticatedDevicesApi: AuthenticatedDevicesApi,
|
||||||
|
@ -13,22 +14,26 @@ class DevicesServiceImpl(
|
||||||
override suspend fun getIsKnownDevice(
|
override suspend fun getIsKnownDevice(
|
||||||
emailAddress: String,
|
emailAddress: String,
|
||||||
deviceId: String,
|
deviceId: String,
|
||||||
): Result<Boolean> = unauthenticatedDevicesApi.getIsKnownDevice(
|
): Result<Boolean> = unauthenticatedDevicesApi
|
||||||
emailAddress = emailAddress.base64UrlEncode(),
|
.getIsKnownDevice(
|
||||||
deviceId = deviceId,
|
emailAddress = emailAddress.base64UrlEncode(),
|
||||||
)
|
deviceId = deviceId,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun trustDevice(
|
override suspend fun trustDevice(
|
||||||
appId: String,
|
appId: String,
|
||||||
encryptedUserKey: String,
|
encryptedUserKey: String,
|
||||||
encryptedDevicePublicKey: String,
|
encryptedDevicePublicKey: String,
|
||||||
encryptedDevicePrivateKey: String,
|
encryptedDevicePrivateKey: String,
|
||||||
): Result<TrustedDeviceKeysResponseJson> = authenticatedDevicesApi.updateTrustedDeviceKeys(
|
): Result<TrustedDeviceKeysResponseJson> = authenticatedDevicesApi
|
||||||
appId = appId,
|
.updateTrustedDeviceKeys(
|
||||||
request = TrustedDeviceKeysRequestJson(
|
appId = appId,
|
||||||
encryptedUserKey = encryptedUserKey,
|
request = TrustedDeviceKeysRequestJson(
|
||||||
encryptedDevicePublicKey = encryptedDevicePublicKey,
|
encryptedUserKey = encryptedUserKey,
|
||||||
encryptedDevicePrivateKey = encryptedDevicePrivateKey,
|
encryptedDevicePublicKey = encryptedDevicePublicKey,
|
||||||
),
|
encryptedDevicePrivateKey = encryptedDevicePrivateKey,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.data.auth.datasource.network.service
|
package com.x8bit.bitwarden.data.auth.datasource.network.service
|
||||||
|
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.api.HaveIBeenPwnedApi
|
import com.x8bit.bitwarden.data.auth.datasource.network.api.HaveIBeenPwnedApi
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
class HaveIBeenPwnedServiceImpl(private val api: HaveIBeenPwnedApi) : HaveIBeenPwnedService {
|
class HaveIBeenPwnedServiceImpl(private val api: HaveIBeenPwnedApi) : HaveIBeenPwnedService {
|
||||||
|
@ -17,6 +18,7 @@ class HaveIBeenPwnedServiceImpl(private val api: HaveIBeenPwnedApi) : HaveIBeenP
|
||||||
|
|
||||||
return api
|
return api
|
||||||
.fetchBreachedPasswords(hashPrefix = hashPrefix)
|
.fetchBreachedPasswords(hashPrefix = hashPrefix)
|
||||||
|
.toResult()
|
||||||
.mapCatching { responseBody ->
|
.mapCatching { responseBody ->
|
||||||
responseBody.string()
|
responseBody.string()
|
||||||
// First split the response by newline: each hashed password is on a new line.
|
// First split the response by newline: each hashed password is on a new line.
|
||||||
|
|
|
@ -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.auth.datasource.network.model.VerifyEmailTokenResponseJson
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
|
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.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.parseErrorBodyOrNull
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
import com.x8bit.bitwarden.data.platform.util.DeviceModelProvider
|
import com.x8bit.bitwarden.data.platform.util.DeviceModelProvider
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
@ -28,12 +29,15 @@ class IdentityServiceImpl(
|
||||||
) : IdentityService {
|
) : IdentityService {
|
||||||
|
|
||||||
override suspend fun preLogin(email: String): Result<PreLoginResponseJson> =
|
override suspend fun preLogin(email: String): Result<PreLoginResponseJson> =
|
||||||
unauthenticatedIdentityApi.preLogin(PreLoginRequestJson(email = email))
|
unauthenticatedIdentityApi
|
||||||
|
.preLogin(PreLoginRequestJson(email = email))
|
||||||
|
.toResult()
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
override suspend fun register(body: RegisterRequestJson): Result<RegisterResponseJson> =
|
override suspend fun register(body: RegisterRequestJson): Result<RegisterResponseJson> =
|
||||||
unauthenticatedIdentityApi
|
unauthenticatedIdentityApi
|
||||||
.register(body)
|
.register(body)
|
||||||
|
.toResult()
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
val bitwardenError = throwable.toBitwardenError()
|
val bitwardenError = throwable.toBitwardenError()
|
||||||
bitwardenError
|
bitwardenError
|
||||||
|
@ -75,6 +79,7 @@ class IdentityServiceImpl(
|
||||||
captchaResponse = captchaToken,
|
captchaResponse = captchaToken,
|
||||||
authRequestId = authModel.authRequestId,
|
authRequestId = authModel.authRequestId,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
val bitwardenError = throwable.toBitwardenError()
|
val bitwardenError = throwable.toBitwardenError()
|
||||||
bitwardenError.parseErrorBodyOrNull<GetTokenResponseJson.CaptchaRequired>(
|
bitwardenError.parseErrorBodyOrNull<GetTokenResponseJson.CaptchaRequired>(
|
||||||
|
@ -95,6 +100,7 @@ class IdentityServiceImpl(
|
||||||
.prevalidateSso(
|
.prevalidateSso(
|
||||||
organizationIdentifier = organizationIdentifier,
|
organizationIdentifier = organizationIdentifier,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override fun refreshTokenSynchronously(
|
override fun refreshTokenSynchronously(
|
||||||
refreshToken: String,
|
refreshToken: String,
|
||||||
|
@ -104,7 +110,8 @@ class IdentityServiceImpl(
|
||||||
grantType = "refresh_token",
|
grantType = "refresh_token",
|
||||||
refreshToken = refreshToken,
|
refreshToken = refreshToken,
|
||||||
)
|
)
|
||||||
.executeForResult()
|
.executeForNetworkResult()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
override suspend fun registerFinish(
|
override suspend fun registerFinish(
|
||||||
|
@ -112,6 +119,7 @@ class IdentityServiceImpl(
|
||||||
): Result<RegisterResponseJson> =
|
): Result<RegisterResponseJson> =
|
||||||
unauthenticatedIdentityApi
|
unauthenticatedIdentityApi
|
||||||
.registerFinish(body)
|
.registerFinish(body)
|
||||||
|
.toResult()
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
val bitwardenError = throwable.toBitwardenError()
|
val bitwardenError = throwable.toBitwardenError()
|
||||||
bitwardenError
|
bitwardenError
|
||||||
|
@ -127,6 +135,7 @@ class IdentityServiceImpl(
|
||||||
): Result<String?> {
|
): Result<String?> {
|
||||||
return unauthenticatedIdentityApi
|
return unauthenticatedIdentityApi
|
||||||
.sendVerificationEmail(body = body)
|
.sendVerificationEmail(body = body)
|
||||||
|
.toResult()
|
||||||
.map { it?.content }
|
.map { it?.content }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,9 +145,8 @@ class IdentityServiceImpl(
|
||||||
.verifyEmailToken(
|
.verifyEmailToken(
|
||||||
body = body,
|
body = body,
|
||||||
)
|
)
|
||||||
.map {
|
.toResult()
|
||||||
VerifyEmailTokenResponseJson.Valid
|
.map { VerifyEmailTokenResponseJson.Valid }
|
||||||
}
|
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
val bitwardenError = throwable.toBitwardenError()
|
val bitwardenError = throwable.toBitwardenError()
|
||||||
bitwardenError
|
bitwardenError
|
||||||
|
|
|
@ -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.AuthRequestRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.AuthRequestTypeJson
|
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.auth.datasource.network.model.AuthRequestsResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
import com.x8bit.bitwarden.data.platform.util.asFailure
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,17 +25,19 @@ class NewAuthRequestServiceImpl(
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest> =
|
): Result<AuthRequestsResponseJson.AuthRequest> =
|
||||||
when (authRequestType) {
|
when (authRequestType) {
|
||||||
AuthRequestTypeJson.LOGIN_WITH_DEVICE -> {
|
AuthRequestTypeJson.LOGIN_WITH_DEVICE -> {
|
||||||
unauthenticatedAuthRequestsApi.createAuthRequest(
|
unauthenticatedAuthRequestsApi
|
||||||
deviceIdentifier = deviceId,
|
.createAuthRequest(
|
||||||
body = AuthRequestRequestJson(
|
deviceIdentifier = deviceId,
|
||||||
email = email,
|
body = AuthRequestRequestJson(
|
||||||
publicKey = publicKey,
|
email = email,
|
||||||
deviceId = deviceId,
|
publicKey = publicKey,
|
||||||
accessCode = accessCode,
|
deviceId = deviceId,
|
||||||
fingerprint = fingerprint,
|
accessCode = accessCode,
|
||||||
type = authRequestType,
|
fingerprint = fingerprint,
|
||||||
),
|
type = authRequestType,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthRequestTypeJson.UNLOCK -> {
|
AuthRequestTypeJson.UNLOCK -> {
|
||||||
|
@ -43,17 +46,19 @@ class NewAuthRequestServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthRequestTypeJson.ADMIN_APPROVAL -> {
|
AuthRequestTypeJson.ADMIN_APPROVAL -> {
|
||||||
authenticatedAuthRequestsApi.createAdminAuthRequest(
|
authenticatedAuthRequestsApi
|
||||||
deviceIdentifier = deviceId,
|
.createAdminAuthRequest(
|
||||||
body = AuthRequestRequestJson(
|
deviceIdentifier = deviceId,
|
||||||
email = email,
|
body = AuthRequestRequestJson(
|
||||||
publicKey = publicKey,
|
email = email,
|
||||||
deviceId = deviceId,
|
publicKey = publicKey,
|
||||||
accessCode = accessCode,
|
deviceId = deviceId,
|
||||||
fingerprint = fingerprint,
|
accessCode = accessCode,
|
||||||
type = authRequestType,
|
fingerprint = fingerprint,
|
||||||
),
|
type = authRequestType,
|
||||||
)
|
),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +68,15 @@ class NewAuthRequestServiceImpl(
|
||||||
isSso: Boolean,
|
isSso: Boolean,
|
||||||
): Result<AuthRequestsResponseJson.AuthRequest> =
|
): Result<AuthRequestsResponseJson.AuthRequest> =
|
||||||
if (isSso) {
|
if (isSso) {
|
||||||
authenticatedAuthRequestsApi.getAuthRequest(requestId)
|
authenticatedAuthRequestsApi
|
||||||
|
.getAuthRequest(requestId = requestId)
|
||||||
|
.toResult()
|
||||||
} else {
|
} else {
|
||||||
unauthenticatedAuthRequestsApi.getAuthRequestUpdate(
|
unauthenticatedAuthRequestsApi
|
||||||
requestId = requestId,
|
.getAuthRequestUpdate(
|
||||||
accessCode = accessCode,
|
requestId = requestId,
|
||||||
)
|
accessCode = accessCode,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.OrganizationResetPasswordEnrollRequestJson
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest
|
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.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of [OrganizationService].
|
* Default implementation of [OrganizationService].
|
||||||
|
@ -31,6 +32,7 @@ class OrganizationServiceImpl(
|
||||||
resetPasswordKey = resetPasswordKey,
|
resetPasswordKey = resetPasswordKey,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getOrganizationDomainSsoDetails(
|
override suspend fun getOrganizationDomainSsoDetails(
|
||||||
email: String,
|
email: String,
|
||||||
|
@ -40,6 +42,7 @@ class OrganizationServiceImpl(
|
||||||
email = email,
|
email = email,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getOrganizationAutoEnrollStatus(
|
override suspend fun getOrganizationAutoEnrollStatus(
|
||||||
organizationIdentifier: String,
|
organizationIdentifier: String,
|
||||||
|
@ -47,6 +50,7 @@ class OrganizationServiceImpl(
|
||||||
.getOrganizationAutoEnrollResponse(
|
.getOrganizationAutoEnrollResponse(
|
||||||
organizationIdentifier = organizationIdentifier,
|
organizationIdentifier = organizationIdentifier,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getOrganizationKeys(
|
override suspend fun getOrganizationKeys(
|
||||||
organizationId: String,
|
organizationId: String,
|
||||||
|
@ -54,6 +58,7 @@ class OrganizationServiceImpl(
|
||||||
.getOrganizationKeys(
|
.getOrganizationKeys(
|
||||||
organizationId = organizationId,
|
organizationId = organizationId,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getVerifiedOrganizationDomainSsoDetails(
|
override suspend fun getVerifiedOrganizationDomainSsoDetails(
|
||||||
email: String,
|
email: String,
|
||||||
|
@ -63,4 +68,5 @@ class OrganizationServiceImpl(
|
||||||
email = email,
|
email = email,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.data.autofill.fido2.datasource.network.api
|
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.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Url
|
import retrofit2.http.Url
|
||||||
|
|
||||||
|
@ -15,5 +16,5 @@ interface DigitalAssetLinkApi {
|
||||||
@GET
|
@GET
|
||||||
suspend fun getDigitalAssetLinks(
|
suspend fun getDigitalAssetLinks(
|
||||||
@Url url: String,
|
@Url url: String,
|
||||||
): Result<List<DigitalAssetLinkResponseJson>>
|
): NetworkResult<List<DigitalAssetLinkResponseJson>>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.api.DigitalAssetLinkApi
|
||||||
import com.x8bit.bitwarden.data.autofill.fido2.datasource.network.model.DigitalAssetLinkResponseJson
|
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].
|
* Primary implementation of [DigitalAssetLinkService].
|
||||||
|
@ -18,4 +19,5 @@ class DigitalAssetLinkServiceImpl(
|
||||||
.getDigitalAssetLinks(
|
.getDigitalAssetLinks(
|
||||||
url = "$scheme$relyingParty/.well-known/assetlinks.json",
|
url = "$scheme$relyingParty/.well-known/assetlinks.json",
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.api
|
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.ConfigResponseJson
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,5 +10,5 @@ import retrofit2.http.GET
|
||||||
interface ConfigApi {
|
interface ConfigApi {
|
||||||
|
|
||||||
@GET("config")
|
@GET("config")
|
||||||
suspend fun getConfig(): Result<ConfigResponseJson>
|
suspend fun getConfig(): NetworkResult<ConfigResponseJson>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.api
|
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 com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
@ -9,5 +10,7 @@ import retrofit2.http.POST
|
||||||
*/
|
*/
|
||||||
interface EventApi {
|
interface EventApi {
|
||||||
@POST("/collect")
|
@POST("/collect")
|
||||||
suspend fun collectOrganizationEvents(@Body events: List<OrganizationEventJson>): Result<Unit>
|
suspend fun collectOrganizationEvents(
|
||||||
|
@Body events: List<OrganizationEventJson>,
|
||||||
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.api
|
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 com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.PUT
|
import retrofit2.http.PUT
|
||||||
|
@ -13,5 +14,5 @@ interface PushApi {
|
||||||
suspend fun putDeviceToken(
|
suspend fun putDeviceToken(
|
||||||
@Path("appId") appId: String,
|
@Path("appId") appId: String,
|
||||||
@Body body: PushTokenRequest,
|
@Body body: PushTokenRequest,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
||||||
|
|
||||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import com.x8bit.bitwarden.data.platform.util.asSuccess
|
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okio.IOException
|
import okio.IOException
|
||||||
import okio.Timeout
|
import okio.Timeout
|
||||||
|
@ -18,33 +17,36 @@ import java.lang.reflect.Type
|
||||||
private const val NO_CONTENT_RESPONSE_CODE: Int = 204
|
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")
|
@Suppress("TooManyFunctions")
|
||||||
class ResultCall<T>(
|
class NetworkResultCall<T>(
|
||||||
private val backingCall: Call<T>,
|
private val backingCall: Call<T>,
|
||||||
private val successType: Type,
|
private val successType: Type,
|
||||||
) : Call<Result<T>> {
|
) : Call<NetworkResult<T>> {
|
||||||
override fun cancel(): Unit = backingCall.cancel()
|
override fun cancel(): Unit = backingCall.cancel()
|
||||||
|
|
||||||
override fun clone(): Call<Result<T>> = ResultCall(backingCall, successType)
|
override fun clone(): Call<NetworkResult<T>> = NetworkResultCall(backingCall, successType)
|
||||||
|
|
||||||
override fun enqueue(callback: Callback<Result<T>>): Unit = backingCall.enqueue(
|
override fun enqueue(callback: Callback<NetworkResult<T>>): Unit = backingCall.enqueue(
|
||||||
object : Callback<T> {
|
object : Callback<T> {
|
||||||
override fun onResponse(call: Call<T>, response: Response<T>) {
|
override fun onResponse(call: Call<T>, response: Response<T>) {
|
||||||
callback.onResponse(this@ResultCall, Response.success(response.toResult()))
|
callback.onResponse(
|
||||||
|
this@NetworkResultCall,
|
||||||
|
Response.success(response.toNetworkResult()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<T>, t: Throwable) {
|
override fun onFailure(call: Call<T>, t: Throwable) {
|
||||||
callback.onResponse(this@ResultCall, Response.success(t.toFailure()))
|
callback.onResponse(this@NetworkResultCall, Response.success(t.toFailure()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@Suppress("TooGenericExceptionCaught")
|
@Suppress("TooGenericExceptionCaught")
|
||||||
override fun execute(): Response<Result<T>> =
|
override fun execute(): Response<NetworkResult<T>> =
|
||||||
try {
|
try {
|
||||||
Response.success(backingCall.execute().toResult())
|
Response.success(backingCall.execute().toNetworkResult())
|
||||||
} catch (ioException: IOException) {
|
} catch (ioException: IOException) {
|
||||||
Response.success(ioException.toFailure())
|
Response.success(ioException.toFailure())
|
||||||
} catch (runtimeException: RuntimeException) {
|
} catch (runtimeException: RuntimeException) {
|
||||||
|
@ -60,20 +62,18 @@ class ResultCall<T>(
|
||||||
override fun timeout(): Timeout = backingCall.timeout()
|
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<T> = requireNotNull(execute().body())
|
fun executeForResult(): NetworkResult<T> = requireNotNull(execute().body())
|
||||||
|
|
||||||
private fun Throwable.toFailure(): Result<T> =
|
private fun Throwable.toFailure(): NetworkResult<T> {
|
||||||
this
|
// We rebuild the URL without query params, we do not want to log those
|
||||||
.also {
|
val url = backingCall.request().url.toUrl().run { "$protocol://$authority$path" }
|
||||||
// We rebuild the URL without query params, we do not want to log those
|
Timber.w(this, "Network Error: $url")
|
||||||
val url = backingCall.request().url.toUrl().run { "$protocol://$authority$path" }
|
return NetworkResult.Failure(this)
|
||||||
Timber.w(it, "Network Error: $url")
|
}
|
||||||
}
|
|
||||||
.asFailure()
|
|
||||||
|
|
||||||
private fun Response<T>.toResult(): Result<T> =
|
private fun Response<T>.toNetworkResult(): NetworkResult<T> =
|
||||||
if (!this.isSuccessful) {
|
if (!this.isSuccessful) {
|
||||||
HttpException(this).toFailure()
|
HttpException(this).toFailure()
|
||||||
} else {
|
} else {
|
||||||
|
@ -81,11 +81,11 @@ class ResultCall<T>(
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
when {
|
when {
|
||||||
// We got a nonnull T as the body, just return it.
|
// 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.
|
// 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.
|
// 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.
|
// All other null bodies result in an error.
|
||||||
else -> IllegalStateException("Unexpected null body!").toFailure()
|
else -> IllegalStateException("Unexpected null body!").toFailure()
|
||||||
}
|
}
|
|
@ -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<T>(
|
||||||
|
private val successType: Type,
|
||||||
|
) : CallAdapter<T, Call<NetworkResult<T>>> {
|
||||||
|
|
||||||
|
override fun responseType(): Type = successType
|
||||||
|
override fun adapt(call: Call<T>): Call<NetworkResult<T>> = NetworkResultCall(call, successType)
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.CallAdapter
|
import retrofit2.CallAdapter
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
|
@ -7,9 +8,9 @@ import java.lang.reflect.ParameterizedType
|
||||||
import java.lang.reflect.Type
|
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(
|
override fun get(
|
||||||
returnType: Type,
|
returnType: Type,
|
||||||
annotations: Array<out Annotation>,
|
annotations: Array<out Annotation>,
|
||||||
|
@ -18,13 +19,13 @@ class ResultCallAdapterFactory : CallAdapter.Factory() {
|
||||||
check(returnType is ParameterizedType) { "$returnType must be parameterized" }
|
check(returnType is ParameterizedType) { "$returnType must be parameterized" }
|
||||||
val containerType = getParameterUpperBound(0, returnType)
|
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" }
|
check(containerType is ParameterizedType) { "$containerType must be parameterized" }
|
||||||
|
|
||||||
val requestType = getParameterUpperBound(0, containerType)
|
val requestType = getParameterUpperBound(0, containerType)
|
||||||
|
|
||||||
return if (getRawType(returnType) == Call::class.java) {
|
return if (getRawType(returnType) == Call::class.java) {
|
||||||
ResultCallAdapter<Any>(successType = requestType)
|
NetworkResultCallAdapter<Any>(successType = requestType)
|
||||||
} else {
|
} else {
|
||||||
null
|
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<T>(
|
|
||||||
private val successType: Type,
|
|
||||||
) : CallAdapter<T, Call<Result<T>>> {
|
|
||||||
|
|
||||||
override fun responseType(): Type = successType
|
|
||||||
override fun adapt(call: Call<T>): Call<Result<T>> = ResultCall(call, successType)
|
|
||||||
}
|
|
|
@ -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<out T> {
|
||||||
|
/**
|
||||||
|
* A successful network result with the relevant [T] data.
|
||||||
|
*/
|
||||||
|
data class Success<T>(val value: T) : NetworkResult<T>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A failed network result with the relevant [throwable] error.
|
||||||
|
*/
|
||||||
|
data class Failure(val throwable: Throwable) : NetworkResult<Nothing>()
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.retrofit
|
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.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.AuthTokenInterceptor
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptor
|
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptor
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors
|
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors
|
||||||
|
@ -105,7 +105,7 @@ class RetrofitsImpl(
|
||||||
private val baseRetrofitBuilder: Retrofit.Builder by lazy {
|
private val baseRetrofitBuilder: Retrofit.Builder by lazy {
|
||||||
Retrofit.Builder()
|
Retrofit.Builder()
|
||||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||||
.addCallAdapterFactory(ResultCallAdapterFactory())
|
.addCallAdapterFactory(NetworkResultCallAdapterFactory())
|
||||||
.client(baseOkHttpClient)
|
.client(baseOkHttpClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.api.ConfigApi
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
|
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 {
|
class ConfigServiceImpl(private val configApi: ConfigApi) : ConfigService {
|
||||||
override suspend fun getConfig(): Result<ConfigResponseJson> = configApi.getConfig()
|
override suspend fun getConfig(): Result<ConfigResponseJson> = configApi.getConfig().toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.api.EventApi
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.OrganizationEventJson
|
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].
|
* The default implementation of the [EventService].
|
||||||
|
@ -11,5 +12,5 @@ class EventServiceImpl(
|
||||||
) : EventService {
|
) : EventService {
|
||||||
override suspend fun sendOrganizationEvents(
|
override suspend fun sendOrganizationEvents(
|
||||||
events: List<OrganizationEventJson>,
|
events: List<OrganizationEventJson>,
|
||||||
): Result<Unit> = eventApi.collectOrganizationEvents(events = events)
|
): Result<Unit> = eventApi.collectOrganizationEvents(events = events).toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.api.PushApi
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
|
|
||||||
class PushServiceImpl(
|
class PushServiceImpl(
|
||||||
private val pushApi: PushApi,
|
private val pushApi: PushApi,
|
||||||
|
@ -15,4 +16,5 @@ class PushServiceImpl(
|
||||||
appId = appId,
|
appId = appId,
|
||||||
body = body,
|
body = body,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.util
|
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
|
import retrofit2.Call
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronously executes the [Call] and returns the [Result].
|
* Synchronously executes the [Call] and returns the [NetworkResult].
|
||||||
*/
|
*/
|
||||||
inline fun <reified T : Any> Call<T>.executeForResult(): Result<T> =
|
inline fun <reified T : Any> Call<T>.executeForNetworkResult(): NetworkResult<T> =
|
||||||
this
|
this
|
||||||
.toResultCall()
|
.toNetworkResultCall()
|
||||||
.executeForResult()
|
.executeForResult()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps the existing [Call] in a [ResultCall].
|
* Wraps the existing [Call] in a [NetworkResultCall].
|
||||||
*/
|
*/
|
||||||
inline fun <reified T : Any> Call<T>.toResultCall(): ResultCall<T> =
|
inline fun <reified T : Any> Call<T>.toNetworkResultCall(): NetworkResultCall<T> =
|
||||||
ResultCall(
|
NetworkResultCall(
|
||||||
backingCall = this,
|
backingCall = this,
|
||||||
successType = T::class.java,
|
successType = T::class.java,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 <T> NetworkResult<T>.toResult(): Result<T> =
|
||||||
|
when (this) {
|
||||||
|
is NetworkResult.Failure -> this.throwable.asFailure()
|
||||||
|
is NetworkResult.Success -> this.value.asSuccess()
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
@ -21,5 +22,5 @@ interface AzureApi {
|
||||||
@Header("x-ms-date") date: String,
|
@Header("x-ms-date") date: String,
|
||||||
@Header("x-ms-version") version: String?,
|
@Header("x-ms-version") version: String?,
|
||||||
@Body body: RequestBody,
|
@Body body: RequestBody,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
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.AttachmentJsonRequest
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonResponse
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonResponse
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
|
||||||
|
@ -26,7 +27,7 @@ interface CiphersApi {
|
||||||
* Create a cipher.
|
* Create a cipher.
|
||||||
*/
|
*/
|
||||||
@POST("ciphers")
|
@POST("ciphers")
|
||||||
suspend fun createCipher(@Body body: CipherJsonRequest): Result<SyncResponseJson.Cipher>
|
suspend fun createCipher(@Body body: CipherJsonRequest): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a cipher that belongs to an organization.
|
* Create a cipher that belongs to an organization.
|
||||||
|
@ -34,7 +35,7 @@ interface CiphersApi {
|
||||||
@POST("ciphers/create")
|
@POST("ciphers/create")
|
||||||
suspend fun createCipherInOrganization(
|
suspend fun createCipherInOrganization(
|
||||||
@Body body: CreateCipherInOrganizationJsonRequest,
|
@Body body: CreateCipherInOrganizationJsonRequest,
|
||||||
): Result<SyncResponseJson.Cipher>
|
): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates an attachment with a cipher.
|
* Associates an attachment with a cipher.
|
||||||
|
@ -43,7 +44,7 @@ interface CiphersApi {
|
||||||
suspend fun createAttachment(
|
suspend fun createAttachment(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Body body: AttachmentJsonRequest,
|
@Body body: AttachmentJsonRequest,
|
||||||
): Result<AttachmentJsonResponse>
|
): NetworkResult<AttachmentJsonResponse>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads the attachment associated with a cipher.
|
* Uploads the attachment associated with a cipher.
|
||||||
|
@ -53,7 +54,7 @@ interface CiphersApi {
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Path("attachmentId") attachmentId: String,
|
@Path("attachmentId") attachmentId: String,
|
||||||
@Body body: MultipartBody,
|
@Body body: MultipartBody,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a cipher.
|
* Updates a cipher.
|
||||||
|
@ -62,7 +63,7 @@ interface CiphersApi {
|
||||||
suspend fun updateCipher(
|
suspend fun updateCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Body body: CipherJsonRequest,
|
@Body body: CipherJsonRequest,
|
||||||
): Result<SyncResponseJson.Cipher>
|
): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shares a cipher.
|
* Shares a cipher.
|
||||||
|
@ -71,7 +72,7 @@ interface CiphersApi {
|
||||||
suspend fun shareCipher(
|
suspend fun shareCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Body body: ShareCipherJsonRequest,
|
@Body body: ShareCipherJsonRequest,
|
||||||
): Result<SyncResponseJson.Cipher>
|
): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shares an attachment.
|
* Shares an attachment.
|
||||||
|
@ -82,7 +83,7 @@ interface CiphersApi {
|
||||||
@Path("attachmentId") attachmentId: String,
|
@Path("attachmentId") attachmentId: String,
|
||||||
@Query("organizationId") organizationId: String?,
|
@Query("organizationId") organizationId: String?,
|
||||||
@Body body: MultipartBody,
|
@Body body: MultipartBody,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a cipher's collections.
|
* Updates a cipher's collections.
|
||||||
|
@ -91,7 +92,7 @@ interface CiphersApi {
|
||||||
suspend fun updateCipherCollections(
|
suspend fun updateCipherCollections(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Body body: UpdateCipherCollectionsJsonRequest,
|
@Body body: UpdateCipherCollectionsJsonRequest,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hard deletes a cipher.
|
* Hard deletes a cipher.
|
||||||
|
@ -99,7 +100,7 @@ interface CiphersApi {
|
||||||
@DELETE("ciphers/{cipherId}")
|
@DELETE("ciphers/{cipherId}")
|
||||||
suspend fun hardDeleteCipher(
|
suspend fun hardDeleteCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Soft deletes a cipher.
|
* Soft deletes a cipher.
|
||||||
|
@ -107,7 +108,7 @@ interface CiphersApi {
|
||||||
@PUT("ciphers/{cipherId}/delete")
|
@PUT("ciphers/{cipherId}/delete")
|
||||||
suspend fun softDeleteCipher(
|
suspend fun softDeleteCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes an attachment from a cipher.
|
* Deletes an attachment from a cipher.
|
||||||
|
@ -116,7 +117,7 @@ interface CiphersApi {
|
||||||
suspend fun deleteCipherAttachment(
|
suspend fun deleteCipherAttachment(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Path("attachmentId") attachmentId: String,
|
@Path("attachmentId") attachmentId: String,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restores a cipher.
|
* Restores a cipher.
|
||||||
|
@ -124,7 +125,7 @@ interface CiphersApi {
|
||||||
@PUT("ciphers/{cipherId}/restore")
|
@PUT("ciphers/{cipherId}/restore")
|
||||||
suspend fun restoreCipher(
|
suspend fun restoreCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
): Result<SyncResponseJson.Cipher>
|
): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a cipher.
|
* Gets a cipher.
|
||||||
|
@ -132,7 +133,7 @@ interface CiphersApi {
|
||||||
@GET("ciphers/{cipherId}")
|
@GET("ciphers/{cipherId}")
|
||||||
suspend fun getCipher(
|
suspend fun getCipher(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
): Result<SyncResponseJson.Cipher>
|
): NetworkResult<SyncResponseJson.Cipher>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a cipher attachment.
|
* Gets a cipher attachment.
|
||||||
|
@ -141,11 +142,11 @@ interface CiphersApi {
|
||||||
suspend fun getCipherAttachment(
|
suspend fun getCipherAttachment(
|
||||||
@Path("cipherId") cipherId: String,
|
@Path("cipherId") cipherId: String,
|
||||||
@Path("attachmentId") attachmentId: String,
|
@Path("attachmentId") attachmentId: String,
|
||||||
): Result<SyncResponseJson.Cipher.Attachment>
|
): NetworkResult<SyncResponseJson.Cipher.Attachment>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the active user has unassigned ciphers.
|
* Indicates if the active user has unassigned ciphers.
|
||||||
*/
|
*/
|
||||||
@GET("ciphers/has-unassigned-ciphers")
|
@GET("ciphers/has-unassigned-ciphers")
|
||||||
suspend fun hasUnassignedCiphers(): Result<Boolean>
|
suspend fun hasUnassignedCiphers(): NetworkResult<Boolean>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Streaming
|
import retrofit2.http.Streaming
|
||||||
|
@ -16,5 +17,5 @@ interface DownloadApi {
|
||||||
@Streaming
|
@Streaming
|
||||||
suspend fun getDataStream(
|
suspend fun getDataStream(
|
||||||
@Url url: String,
|
@Url url: String,
|
||||||
): Result<ResponseBody>
|
): NetworkResult<ResponseBody>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
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.FolderJsonRequest
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
|
@ -18,7 +19,7 @@ interface FoldersApi {
|
||||||
* Create a folder.
|
* Create a folder.
|
||||||
*/
|
*/
|
||||||
@POST("folders")
|
@POST("folders")
|
||||||
suspend fun createFolder(@Body body: FolderJsonRequest): Result<SyncResponseJson.Folder>
|
suspend fun createFolder(@Body body: FolderJsonRequest): NetworkResult<SyncResponseJson.Folder>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a folder.
|
* Gets a folder.
|
||||||
|
@ -26,7 +27,7 @@ interface FoldersApi {
|
||||||
@GET("folders/{folderId}")
|
@GET("folders/{folderId}")
|
||||||
suspend fun getFolder(
|
suspend fun getFolder(
|
||||||
@Path("folderId") folderId: String,
|
@Path("folderId") folderId: String,
|
||||||
): Result<SyncResponseJson.Folder>
|
): NetworkResult<SyncResponseJson.Folder>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a folder.
|
* Updates a folder.
|
||||||
|
@ -35,11 +36,11 @@ interface FoldersApi {
|
||||||
suspend fun updateFolder(
|
suspend fun updateFolder(
|
||||||
@Path("folderId") folderId: String,
|
@Path("folderId") folderId: String,
|
||||||
@Body body: FolderJsonRequest,
|
@Body body: FolderJsonRequest,
|
||||||
): Result<SyncResponseJson.Folder>
|
): NetworkResult<SyncResponseJson.Folder>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a folder.
|
* Deletes a folder.
|
||||||
*/
|
*/
|
||||||
@DELETE("folders/{folderId}")
|
@DELETE("folders/{folderId}")
|
||||||
suspend fun deleteFolder(@Path("folderId") folderId: String): Result<Unit>
|
suspend fun deleteFolder(@Path("folderId") folderId: String): NetworkResult<Unit>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
||||||
|
|
||||||
import androidx.annotation.Keep
|
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.CreateFileSendResponseJson
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SendJsonRequest
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
|
@ -22,13 +23,15 @@ interface SendsApi {
|
||||||
* Create a text send.
|
* Create a text send.
|
||||||
*/
|
*/
|
||||||
@POST("sends")
|
@POST("sends")
|
||||||
suspend fun createTextSend(@Body body: SendJsonRequest): Result<SyncResponseJson.Send>
|
suspend fun createTextSend(@Body body: SendJsonRequest): NetworkResult<SyncResponseJson.Send>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a file send.
|
* Create a file send.
|
||||||
*/
|
*/
|
||||||
@POST("sends/file/v2")
|
@POST("sends/file/v2")
|
||||||
suspend fun createFileSend(@Body body: SendJsonRequest): Result<CreateFileSendResponseJson>
|
suspend fun createFileSend(
|
||||||
|
@Body body: SendJsonRequest,
|
||||||
|
): NetworkResult<CreateFileSendResponseJson>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a send.
|
* Updates a send.
|
||||||
|
@ -37,7 +40,7 @@ interface SendsApi {
|
||||||
suspend fun updateSend(
|
suspend fun updateSend(
|
||||||
@Path("sendId") sendId: String,
|
@Path("sendId") sendId: String,
|
||||||
@Body body: SendJsonRequest,
|
@Body body: SendJsonRequest,
|
||||||
): Result<SyncResponseJson.Send>
|
): NetworkResult<SyncResponseJson.Send>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads the file associated with a send.
|
* Uploads the file associated with a send.
|
||||||
|
@ -47,23 +50,25 @@ interface SendsApi {
|
||||||
@Path("sendId") sendId: String,
|
@Path("sendId") sendId: String,
|
||||||
@Path("fileId") fileId: String,
|
@Path("fileId") fileId: String,
|
||||||
@Body body: MultipartBody,
|
@Body body: MultipartBody,
|
||||||
): Result<Unit>
|
): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a send.
|
* Deletes a send.
|
||||||
*/
|
*/
|
||||||
@DELETE("sends/{sendId}")
|
@DELETE("sends/{sendId}")
|
||||||
suspend fun deleteSend(@Path("sendId") sendId: String): Result<Unit>
|
suspend fun deleteSend(@Path("sendId") sendId: String): NetworkResult<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a send.
|
* Deletes a send.
|
||||||
*/
|
*/
|
||||||
@PUT("sends/{sendId}/remove-password")
|
@PUT("sends/{sendId}/remove-password")
|
||||||
suspend fun removeSendPassword(@Path("sendId") sendId: String): Result<SyncResponseJson.Send>
|
suspend fun removeSendPassword(
|
||||||
|
@Path("sendId") sendId: String,
|
||||||
|
): NetworkResult<SyncResponseJson.Send>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a send.
|
* Gets a send.
|
||||||
*/
|
*/
|
||||||
@GET("sends/{sendId}")
|
@GET("sends/{sendId}")
|
||||||
suspend fun getSend(@Path("sendId") sendId: String): Result<SyncResponseJson.Send>
|
suspend fun getSend(@Path("sendId") sendId: String): NetworkResult<SyncResponseJson.Send>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.api
|
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 com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
|
||||||
|
@ -13,8 +14,8 @@ interface SyncApi {
|
||||||
* @return A [SyncResponseJson] containing the vault response model.
|
* @return A [SyncResponseJson] containing the vault response model.
|
||||||
*/
|
*/
|
||||||
@GET("sync")
|
@GET("sync")
|
||||||
suspend fun sync(): Result<SyncResponseJson>
|
suspend fun sync(): NetworkResult<SyncResponseJson>
|
||||||
|
|
||||||
@GET("/accounts/revision-date")
|
@GET("/accounts/revision-date")
|
||||||
suspend fun getAccountRevisionDateMillis(): Result<Long>
|
suspend fun getAccountRevisionDateMillis(): NetworkResult<Long>
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import androidx.core.net.toUri
|
||||||
import com.bitwarden.vault.Attachment
|
import com.bitwarden.vault.Attachment
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
|
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.parseErrorBodyOrNull
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.util.toResult
|
||||||
import com.x8bit.bitwarden.data.platform.util.asFailure
|
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.AzureApi
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.api.CiphersApi
|
import com.x8bit.bitwarden.data.vault.datasource.network.api.CiphersApi
|
||||||
|
@ -34,20 +35,26 @@ class CiphersServiceImpl(
|
||||||
private val clock: Clock,
|
private val clock: Clock,
|
||||||
) : CiphersService {
|
) : CiphersService {
|
||||||
override suspend fun createCipher(body: CipherJsonRequest): Result<SyncResponseJson.Cipher> =
|
override suspend fun createCipher(body: CipherJsonRequest): Result<SyncResponseJson.Cipher> =
|
||||||
ciphersApi.createCipher(body = body)
|
ciphersApi
|
||||||
|
.createCipher(body = body)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun createCipherInOrganization(
|
override suspend fun createCipherInOrganization(
|
||||||
body: CreateCipherInOrganizationJsonRequest,
|
body: CreateCipherInOrganizationJsonRequest,
|
||||||
): Result<SyncResponseJson.Cipher> = ciphersApi.createCipherInOrganization(body = body)
|
): Result<SyncResponseJson.Cipher> = ciphersApi
|
||||||
|
.createCipherInOrganization(body = body)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun createAttachment(
|
override suspend fun createAttachment(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
body: AttachmentJsonRequest,
|
body: AttachmentJsonRequest,
|
||||||
): Result<AttachmentJsonResponse> =
|
): Result<AttachmentJsonResponse> =
|
||||||
ciphersApi.createAttachment(
|
ciphersApi
|
||||||
cipherId = cipherId,
|
.createAttachment(
|
||||||
body = body,
|
cipherId = cipherId,
|
||||||
)
|
body = body,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun uploadAttachment(
|
override suspend fun uploadAttachment(
|
||||||
attachmentJsonResponse: AttachmentJsonResponse,
|
attachmentJsonResponse: AttachmentJsonResponse,
|
||||||
|
@ -82,6 +89,7 @@ class CiphersServiceImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.toResult()
|
||||||
.map { cipher }
|
.map { cipher }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +102,7 @@ class CiphersServiceImpl(
|
||||||
cipherId = cipherId,
|
cipherId = cipherId,
|
||||||
body = body,
|
body = body,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
.map { UpdateCipherResponseJson.Success(cipher = it) }
|
.map { UpdateCipherResponseJson.Success(cipher = it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
|
@ -115,77 +124,97 @@ class CiphersServiceImpl(
|
||||||
?: return IllegalStateException("Attachment must have ID").asFailure()
|
?: return IllegalStateException("Attachment must have ID").asFailure()
|
||||||
val attachmentKey = attachment.key
|
val attachmentKey = attachment.key
|
||||||
?: return IllegalStateException("Attachment must have Key").asFailure()
|
?: return IllegalStateException("Attachment must have Key").asFailure()
|
||||||
return ciphersApi.shareAttachment(
|
return ciphersApi
|
||||||
cipherId = cipherId,
|
.shareAttachment(
|
||||||
attachmentId = attachmentId,
|
cipherId = cipherId,
|
||||||
organizationId = organizationId,
|
attachmentId = attachmentId,
|
||||||
body = this
|
organizationId = organizationId,
|
||||||
.createMultipartBodyBuilder(
|
body = this
|
||||||
encryptedFile = encryptedFile,
|
.createMultipartBodyBuilder(
|
||||||
filename = attachment.fileName,
|
encryptedFile = encryptedFile,
|
||||||
)
|
filename = attachment.fileName,
|
||||||
.addPart(
|
)
|
||||||
part = MultipartBody.Part.createFormData(
|
.addPart(
|
||||||
name = "key",
|
part = MultipartBody.Part.createFormData(
|
||||||
value = attachmentKey,
|
name = "key",
|
||||||
),
|
value = attachmentKey,
|
||||||
)
|
),
|
||||||
.build(),
|
)
|
||||||
)
|
.build(),
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun shareCipher(
|
override suspend fun shareCipher(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
body: ShareCipherJsonRequest,
|
body: ShareCipherJsonRequest,
|
||||||
): Result<SyncResponseJson.Cipher> =
|
): Result<SyncResponseJson.Cipher> =
|
||||||
ciphersApi.shareCipher(
|
ciphersApi
|
||||||
cipherId = cipherId,
|
.shareCipher(
|
||||||
body = body,
|
cipherId = cipherId,
|
||||||
)
|
body = body,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun updateCipherCollections(
|
override suspend fun updateCipherCollections(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
body: UpdateCipherCollectionsJsonRequest,
|
body: UpdateCipherCollectionsJsonRequest,
|
||||||
): Result<Unit> =
|
): Result<Unit> =
|
||||||
ciphersApi.updateCipherCollections(
|
ciphersApi
|
||||||
cipherId = cipherId,
|
.updateCipherCollections(
|
||||||
body = body,
|
cipherId = cipherId,
|
||||||
)
|
body = body,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun hardDeleteCipher(cipherId: String): Result<Unit> =
|
override suspend fun hardDeleteCipher(cipherId: String): Result<Unit> =
|
||||||
ciphersApi.hardDeleteCipher(cipherId = cipherId)
|
ciphersApi
|
||||||
|
.hardDeleteCipher(cipherId = cipherId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun softDeleteCipher(cipherId: String): Result<Unit> =
|
override suspend fun softDeleteCipher(cipherId: String): Result<Unit> =
|
||||||
ciphersApi.softDeleteCipher(cipherId = cipherId)
|
ciphersApi
|
||||||
|
.softDeleteCipher(cipherId = cipherId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun deleteCipherAttachment(
|
override suspend fun deleteCipherAttachment(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
attachmentId: String,
|
attachmentId: String,
|
||||||
): Result<Unit> =
|
): Result<Unit> =
|
||||||
ciphersApi.deleteCipherAttachment(
|
ciphersApi
|
||||||
cipherId = cipherId,
|
.deleteCipherAttachment(
|
||||||
attachmentId = attachmentId,
|
cipherId = cipherId,
|
||||||
)
|
attachmentId = attachmentId,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun restoreCipher(cipherId: String): Result<SyncResponseJson.Cipher> =
|
override suspend fun restoreCipher(cipherId: String): Result<SyncResponseJson.Cipher> =
|
||||||
ciphersApi.restoreCipher(cipherId = cipherId)
|
ciphersApi
|
||||||
|
.restoreCipher(cipherId = cipherId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getCipher(
|
override suspend fun getCipher(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
): Result<SyncResponseJson.Cipher> =
|
): Result<SyncResponseJson.Cipher> =
|
||||||
ciphersApi.getCipher(cipherId = cipherId)
|
ciphersApi
|
||||||
|
.getCipher(cipherId = cipherId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getCipherAttachment(
|
override suspend fun getCipherAttachment(
|
||||||
cipherId: String,
|
cipherId: String,
|
||||||
attachmentId: String,
|
attachmentId: String,
|
||||||
): Result<SyncResponseJson.Cipher.Attachment> =
|
): Result<SyncResponseJson.Cipher.Attachment> =
|
||||||
ciphersApi.getCipherAttachment(
|
ciphersApi
|
||||||
cipherId = cipherId,
|
.getCipherAttachment(
|
||||||
attachmentId = attachmentId,
|
cipherId = cipherId,
|
||||||
)
|
attachmentId = attachmentId,
|
||||||
|
)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun hasUnassignedCiphers(): Result<Boolean> =
|
override suspend fun hasUnassignedCiphers(): Result<Boolean> =
|
||||||
ciphersApi.hasUnassignedCiphers()
|
ciphersApi
|
||||||
|
.hasUnassignedCiphers()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
private fun createMultipartBodyBuilder(
|
private fun createMultipartBodyBuilder(
|
||||||
encryptedFile: File,
|
encryptedFile: File,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.service
|
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 com.x8bit.bitwarden.data.vault.datasource.network.api.DownloadApi
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
|
||||||
|
@ -12,5 +13,7 @@ class DownloadServiceImpl(
|
||||||
override suspend fun getDataStream(
|
override suspend fun getDataStream(
|
||||||
url: String,
|
url: String,
|
||||||
): Result<ResponseBody> =
|
): Result<ResponseBody> =
|
||||||
downloadApi.getDataStream(url = url)
|
downloadApi
|
||||||
|
.getDataStream(url = url)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.model.toBitwardenError
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.util.parseErrorBodyOrNull
|
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.api.FoldersApi
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.FolderJsonRequest
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.FolderJsonRequest
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
|
@ -13,7 +14,9 @@ class FolderServiceImpl(
|
||||||
private val json: Json,
|
private val json: Json,
|
||||||
) : FolderService {
|
) : FolderService {
|
||||||
override suspend fun createFolder(body: FolderJsonRequest): Result<SyncResponseJson.Folder> =
|
override suspend fun createFolder(body: FolderJsonRequest): Result<SyncResponseJson.Folder> =
|
||||||
foldersApi.createFolder(body = body)
|
foldersApi
|
||||||
|
.createFolder(body = body)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun updateFolder(
|
override suspend fun updateFolder(
|
||||||
folderId: String,
|
folderId: String,
|
||||||
|
@ -24,6 +27,7 @@ class FolderServiceImpl(
|
||||||
folderId = folderId,
|
folderId = folderId,
|
||||||
body = body,
|
body = body,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
.map { UpdateFolderResponseJson.Success(folder = it) }
|
.map { UpdateFolderResponseJson.Success(folder = it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
|
@ -36,10 +40,13 @@ class FolderServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteFolder(folderId: String): Result<Unit> =
|
override suspend fun deleteFolder(folderId: String): Result<Unit> =
|
||||||
foldersApi.deleteFolder(folderId = folderId)
|
foldersApi
|
||||||
|
.deleteFolder(folderId = folderId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getFolder(
|
override suspend fun getFolder(
|
||||||
folderId: String,
|
folderId: String,
|
||||||
): Result<SyncResponseJson.Folder> = foldersApi
|
): Result<SyncResponseJson.Folder> = foldersApi
|
||||||
.getFolder(folderId = folderId)
|
.getFolder(folderId = folderId)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.vault.datasource.network.service
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.toBitwardenError
|
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.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.AzureApi
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.api.SendsApi
|
import com.x8bit.bitwarden.data.vault.datasource.network.api.SendsApi
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateFileSendResponse
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.CreateFileSendResponse
|
||||||
|
@ -34,7 +35,9 @@ class SendsServiceImpl(
|
||||||
override suspend fun createTextSend(
|
override suspend fun createTextSend(
|
||||||
body: SendJsonRequest,
|
body: SendJsonRequest,
|
||||||
): Result<CreateSendJsonResponse> =
|
): Result<CreateSendJsonResponse> =
|
||||||
sendsApi.createTextSend(body = body)
|
sendsApi
|
||||||
|
.createTextSend(body = body)
|
||||||
|
.toResult()
|
||||||
.map { CreateSendJsonResponse.Success(send = it) }
|
.map { CreateSendJsonResponse.Success(send = it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable.toBitwardenError()
|
throwable.toBitwardenError()
|
||||||
|
@ -48,7 +51,9 @@ class SendsServiceImpl(
|
||||||
override suspend fun createFileSend(
|
override suspend fun createFileSend(
|
||||||
body: SendJsonRequest,
|
body: SendJsonRequest,
|
||||||
): Result<CreateFileSendResponse> =
|
): Result<CreateFileSendResponse> =
|
||||||
sendsApi.createFileSend(body = body)
|
sendsApi
|
||||||
|
.createFileSend(body = body)
|
||||||
|
.toResult()
|
||||||
.map { CreateFileSendResponse.Success(it) }
|
.map { CreateFileSendResponse.Success(it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable.toBitwardenError()
|
throwable.toBitwardenError()
|
||||||
|
@ -68,6 +73,7 @@ class SendsServiceImpl(
|
||||||
sendId = sendId,
|
sendId = sendId,
|
||||||
body = body,
|
body = body,
|
||||||
)
|
)
|
||||||
|
.toResult()
|
||||||
.map { UpdateSendResponseJson.Success(send = it) }
|
.map { UpdateSendResponseJson.Success(send = it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
|
@ -118,16 +124,20 @@ class SendsServiceImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.toResult()
|
||||||
.onFailure { sendsApi.deleteSend(send.id) }
|
.onFailure { sendsApi.deleteSend(send.id) }
|
||||||
.map { send }
|
.map { send }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteSend(sendId: String): Result<Unit> =
|
override suspend fun deleteSend(sendId: String): Result<Unit> =
|
||||||
sendsApi.deleteSend(sendId = sendId)
|
sendsApi
|
||||||
|
.deleteSend(sendId = sendId)
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun removeSendPassword(sendId: String): Result<UpdateSendResponseJson> =
|
override suspend fun removeSendPassword(sendId: String): Result<UpdateSendResponseJson> =
|
||||||
sendsApi
|
sendsApi
|
||||||
.removeSendPassword(sendId = sendId)
|
.removeSendPassword(sendId = sendId)
|
||||||
|
.toResult()
|
||||||
.map { UpdateSendResponseJson.Success(send = it) }
|
.map { UpdateSendResponseJson.Success(send = it) }
|
||||||
.recoverCatching { throwable ->
|
.recoverCatching { throwable ->
|
||||||
throwable
|
throwable
|
||||||
|
@ -142,5 +152,7 @@ class SendsServiceImpl(
|
||||||
override suspend fun getSend(
|
override suspend fun getSend(
|
||||||
sendId: String,
|
sendId: String,
|
||||||
): Result<SyncResponseJson.Send> =
|
): Result<SyncResponseJson.Send> =
|
||||||
sendsApi.getSend(sendId = sendId)
|
sendsApi
|
||||||
|
.getSend(sendId = sendId)
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
package com.x8bit.bitwarden.data.vault.datasource.network.service
|
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.api.SyncApi
|
||||||
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
|
||||||
|
|
||||||
class SyncServiceImpl(
|
class SyncServiceImpl(
|
||||||
private val syncApi: SyncApi,
|
private val syncApi: SyncApi,
|
||||||
) : SyncService {
|
) : SyncService {
|
||||||
override suspend fun sync(): Result<SyncResponseJson> = syncApi.sync()
|
override suspend fun sync(): Result<SyncResponseJson> = syncApi
|
||||||
|
.sync()
|
||||||
|
.toResult()
|
||||||
|
|
||||||
override suspend fun getAccountRevisionDateMillis(): Result<Long> =
|
override suspend fun getAccountRevisionDateMillis(): Result<Long> =
|
||||||
syncApi.getAccountRevisionDateMillis()
|
syncApi
|
||||||
|
.getAccountRevisionDateMillis()
|
||||||
|
.toResult()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.base
|
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 com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
@ -24,7 +24,7 @@ abstract class BaseServiceTest {
|
||||||
|
|
||||||
protected val retrofit: Retrofit = Retrofit.Builder()
|
protected val retrofit: Retrofit = Retrofit.Builder()
|
||||||
.baseUrl(url.toString())
|
.baseUrl(url.toString())
|
||||||
.addCallAdapterFactory(ResultCallAdapterFactory())
|
.addCallAdapterFactory(NetworkResultCallAdapterFactory())
|
||||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
package com.x8bit.bitwarden.data.platform.datasource.network.core
|
||||||
|
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.mockwebserver.MockResponse
|
import okhttp3.mockwebserver.MockResponse
|
||||||
import okhttp3.mockwebserver.MockWebServer
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
|
@ -10,14 +11,14 @@ import retrofit2.Retrofit
|
||||||
import retrofit2.create
|
import retrofit2.create
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
|
||||||
class ResultCallAdapterTest {
|
class NetworkResultCallAdapterTest {
|
||||||
|
|
||||||
private val server: MockWebServer = MockWebServer().apply { start() }
|
private val server: MockWebServer = MockWebServer().apply { start() }
|
||||||
private val testService: FakeService =
|
private val testService: FakeService =
|
||||||
Retrofit.Builder()
|
Retrofit.Builder()
|
||||||
.baseUrl(server.url("/").toString())
|
.baseUrl(server.url("/").toString())
|
||||||
// add the adapter being tested
|
// add the adapter being tested
|
||||||
.addCallAdapterFactory(ResultCallAdapterFactory())
|
.addCallAdapterFactory(NetworkResultCallAdapterFactory())
|
||||||
.build()
|
.build()
|
||||||
.create()
|
.create()
|
||||||
|
|
||||||
|
@ -30,14 +31,14 @@ class ResultCallAdapterTest {
|
||||||
fun `when server returns error response code result should be failure`() = runBlocking {
|
fun `when server returns error response code result should be failure`() = runBlocking {
|
||||||
server.enqueue(MockResponse().setResponseCode(500))
|
server.enqueue(MockResponse().setResponseCode(500))
|
||||||
val result = testService.requestWithUnitData()
|
val result = testService.requestWithUnitData()
|
||||||
assertTrue(result.isFailure)
|
assertTrue(result is NetworkResult.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when server returns successful response result should be success`() = runBlocking {
|
fun `when server returns successful response result should be success`() = runBlocking {
|
||||||
server.enqueue(MockResponse())
|
server.enqueue(MockResponse())
|
||||||
val result = testService.requestWithUnitData()
|
val result = testService.requestWithUnitData()
|
||||||
assertTrue(result.isSuccess)
|
assertTrue(result is NetworkResult.Success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,5 +47,5 @@ class ResultCallAdapterTest {
|
||||||
*/
|
*/
|
||||||
private interface FakeService {
|
private interface FakeService {
|
||||||
@GET("/fake")
|
@GET("/fake")
|
||||||
suspend fun requestWithUnitData(): Result<Unit>
|
suspend fun requestWithUnitData(): NetworkResult<Unit>
|
||||||
}
|
}
|
|
@ -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.AuthTokenInterceptor
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.interceptor.BaseUrlInterceptors
|
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.interceptor.HeadersInterceptor
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.NetworkResult
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.slot
|
import io.mockk.slot
|
||||||
|
@ -39,7 +40,7 @@ class RetrofitsTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private val headersInterceptors = mockk<HeadersInterceptor> {
|
private val headersInterceptors = mockk<HeadersInterceptor> {
|
||||||
mockIntercept { isheadersInterceptorCalled = true }
|
mockIntercept { isHeadersInterceptorCalled = true }
|
||||||
}
|
}
|
||||||
private val refreshAuthenticator = mockk<RefreshAuthenticator> {
|
private val refreshAuthenticator = mockk<RefreshAuthenticator> {
|
||||||
mockAuthenticate { isRefreshAuthenticatorCalled = true }
|
mockAuthenticate { isRefreshAuthenticatorCalled = true }
|
||||||
|
@ -57,7 +58,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
private var isAuthInterceptorCalled = false
|
private var isAuthInterceptorCalled = false
|
||||||
private var isApiInterceptorCalled = false
|
private var isApiInterceptorCalled = false
|
||||||
private var isheadersInterceptorCalled = false
|
private var isHeadersInterceptorCalled = false
|
||||||
private var isIdentityInterceptorCalled = false
|
private var isIdentityInterceptorCalled = false
|
||||||
private var isEventsInterceptorCalled = false
|
private var isEventsInterceptorCalled = false
|
||||||
private var isRefreshAuthenticatorCalled = false
|
private var isRefreshAuthenticatorCalled = false
|
||||||
|
@ -158,7 +159,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertTrue(isAuthInterceptorCalled)
|
assertTrue(isAuthInterceptorCalled)
|
||||||
assertTrue(isApiInterceptorCalled)
|
assertTrue(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertFalse(isIdentityInterceptorCalled)
|
assertFalse(isIdentityInterceptorCalled)
|
||||||
assertFalse(isEventsInterceptorCalled)
|
assertFalse(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -176,7 +177,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertTrue(isAuthInterceptorCalled)
|
assertTrue(isAuthInterceptorCalled)
|
||||||
assertFalse(isApiInterceptorCalled)
|
assertFalse(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertFalse(isIdentityInterceptorCalled)
|
assertFalse(isIdentityInterceptorCalled)
|
||||||
assertTrue(isEventsInterceptorCalled)
|
assertTrue(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -194,7 +195,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertFalse(isAuthInterceptorCalled)
|
assertFalse(isAuthInterceptorCalled)
|
||||||
assertTrue(isApiInterceptorCalled)
|
assertTrue(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertFalse(isIdentityInterceptorCalled)
|
assertFalse(isIdentityInterceptorCalled)
|
||||||
assertFalse(isEventsInterceptorCalled)
|
assertFalse(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +213,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertFalse(isAuthInterceptorCalled)
|
assertFalse(isAuthInterceptorCalled)
|
||||||
assertFalse(isApiInterceptorCalled)
|
assertFalse(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertTrue(isIdentityInterceptorCalled)
|
assertTrue(isIdentityInterceptorCalled)
|
||||||
assertFalse(isEventsInterceptorCalled)
|
assertFalse(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -231,7 +232,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertTrue(isAuthInterceptorCalled)
|
assertTrue(isAuthInterceptorCalled)
|
||||||
assertFalse(isApiInterceptorCalled)
|
assertFalse(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertFalse(isIdentityInterceptorCalled)
|
assertFalse(isIdentityInterceptorCalled)
|
||||||
assertFalse(isEventsInterceptorCalled)
|
assertFalse(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -250,7 +251,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
assertFalse(isAuthInterceptorCalled)
|
assertFalse(isAuthInterceptorCalled)
|
||||||
assertFalse(isApiInterceptorCalled)
|
assertFalse(isApiInterceptorCalled)
|
||||||
assertTrue(isheadersInterceptorCalled)
|
assertTrue(isHeadersInterceptorCalled)
|
||||||
assertFalse(isIdentityInterceptorCalled)
|
assertFalse(isIdentityInterceptorCalled)
|
||||||
assertFalse(isEventsInterceptorCalled)
|
assertFalse(isEventsInterceptorCalled)
|
||||||
}
|
}
|
||||||
|
@ -264,7 +265,7 @@ class RetrofitsTest {
|
||||||
|
|
||||||
interface TestApi {
|
interface TestApi {
|
||||||
@GET("/test")
|
@GET("/test")
|
||||||
suspend fun test(): Result<JsonObject>
|
suspend fun test(): NetworkResult<JsonObject>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.x8bit.bitwarden.data.platform.datasource.network.util
|
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.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
@ -17,53 +17,53 @@ import java.net.URL
|
||||||
class CallExtensionsTest {
|
class CallExtensionsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when execute throws IOException`() {
|
fun `executeForNetworkResult returns failure when execute throws IOException`() {
|
||||||
val request = createMockkRequest()
|
val request = createMockkRequest()
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
every { request() } returns request
|
every { request() } returns request
|
||||||
every { execute() } throws IOException("Fail")
|
every { execute() } throws IOException("Fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = call.executeForResult()
|
val result = call.executeForNetworkResult()
|
||||||
|
|
||||||
assertTrue(result.isFailure)
|
assertTrue(result is NetworkResult.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when execute throws RuntimeException`() {
|
fun `executeForNetworkResult returns failure when execute throws RuntimeException`() {
|
||||||
val request = createMockkRequest()
|
val request = createMockkRequest()
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
every { request() } returns request
|
every { request() } returns request
|
||||||
every { execute() } throws RuntimeException("Fail")
|
every { execute() } throws RuntimeException("Fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = call.executeForResult()
|
val result = call.executeForNetworkResult()
|
||||||
|
|
||||||
assertTrue(result.isFailure)
|
assertTrue(result is NetworkResult.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns failure when response is failure`() {
|
fun `executeForNetworkResult returns failure when response is failure`() {
|
||||||
val request = createMockkRequest()
|
val request = createMockkRequest()
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
every { request() } returns request
|
every { request() } returns request
|
||||||
every { execute() } returns Response.error(400, "".toResponseBody())
|
every { execute() } returns Response.error(400, "".toResponseBody())
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = call.executeForResult()
|
val result = call.executeForNetworkResult()
|
||||||
|
|
||||||
assertTrue(result.isFailure)
|
assertTrue(result is NetworkResult.Failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `executeForResult returns success when response is failure`() {
|
fun `executeForNetworkResult returns success when response is failure`() {
|
||||||
val call = mockk<Call<Unit>> {
|
val call = mockk<Call<Unit>> {
|
||||||
every { execute() } returns Response.success(Unit)
|
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 {
|
private fun createMockkRequest(): Request {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -311,7 +311,7 @@ class CiphersServiceTest : BaseServiceTest() {
|
||||||
)
|
)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
createMockAttachment(number = 1),
|
createMockAttachment(number = 1),
|
||||||
result.testGetOrThrow(),
|
result.getOrThrow(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,25 +336,6 @@ private fun setupMockUri(
|
||||||
return mockUri
|
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 <T> Result<T>.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 = """
|
private const val CREATE_ATTACHMENT_SUCCESS_JSON = """
|
||||||
{
|
{
|
||||||
"attachmentId":"mockAttachmentId-1",
|
"attachmentId":"mockAttachmentId-1",
|
||||||
|
|
Loading…
Reference in a new issue