mirror of
https://github.com/bitwarden/android.git
synced 2026-05-10 05:49:44 -05:00
Compare commits
1 Commits
crowdin-pu
...
remove-ret
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
727cf0e585 |
@@ -285,8 +285,6 @@ dependencies {
|
||||
implementation(libs.kotlinx.serialization)
|
||||
implementation(platform(libs.square.okhttp.bom))
|
||||
implementation(libs.square.okhttp)
|
||||
implementation(platform(libs.square.retrofit.bom))
|
||||
implementation(libs.square.retrofit)
|
||||
implementation(libs.timber)
|
||||
|
||||
// For now we are restricted to running Compose tests for debug builds only
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.bitwarden.network.model.ArchiveCipherResponseJson
|
||||
import com.bitwarden.network.model.AttachmentJsonResponse
|
||||
import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherResponseJson
|
||||
import com.bitwarden.network.model.GetCipherResponse
|
||||
import com.bitwarden.network.model.ShareCipherJsonRequest
|
||||
import com.bitwarden.network.model.UnarchiveCipherResponseJson
|
||||
import com.bitwarden.network.model.UpdateCipherCollectionsJsonRequest
|
||||
@@ -48,7 +49,6 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import retrofit2.HttpException
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
|
||||
@@ -763,6 +763,7 @@ class CipherManagerImpl(
|
||||
* are met. If the resource cannot be found cloud-side, and it was updated, delete it from disk
|
||||
* for now.
|
||||
*/
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private suspend fun syncCipherIfNecessary(syncCipherUpsertData: SyncCipherUpsertData) {
|
||||
val userId = syncCipherUpsertData.userId
|
||||
val cipherId = syncCipherUpsertData.cipherId
|
||||
@@ -817,15 +818,22 @@ class CipherManagerImpl(
|
||||
ciphersService
|
||||
.getCipher(cipherId = cipherId)
|
||||
.fold(
|
||||
onSuccess = { vaultDiskSource.saveCipher(userId = userId, cipher = it) },
|
||||
onFailure = {
|
||||
// Delete any updates if it's missing from the server
|
||||
val httpException = it as? HttpException
|
||||
@Suppress("MagicNumber")
|
||||
if (httpException?.code() == 404 && isUpdate) {
|
||||
vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId)
|
||||
onSuccess = { response ->
|
||||
when (response) {
|
||||
is GetCipherResponse.NotFound -> {
|
||||
if (isUpdate) {
|
||||
vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId)
|
||||
}
|
||||
}
|
||||
|
||||
is GetCipherResponse.Success -> {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = response.cipher)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
// no-op
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.bitwarden.core.data.util.flatMap
|
||||
import com.bitwarden.data.manager.file.FileManager
|
||||
import com.bitwarden.network.model.CreateFileSendResponse
|
||||
import com.bitwarden.network.model.CreateSendJsonResponse
|
||||
import com.bitwarden.network.model.GetSendResponse
|
||||
import com.bitwarden.network.model.UpdateSendResponseJson
|
||||
import com.bitwarden.network.service.SendsService
|
||||
import com.bitwarden.send.Send
|
||||
@@ -32,7 +33,6 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import retrofit2.HttpException
|
||||
|
||||
/**
|
||||
* The default implementation of the [SendManager].
|
||||
@@ -291,15 +291,22 @@ class SendManagerImpl(
|
||||
sendsService
|
||||
.getSend(sendId = sendId)
|
||||
.fold(
|
||||
onSuccess = { vaultDiskSource.saveSend(userId = userId, send = it) },
|
||||
onFailure = {
|
||||
// Delete any updates if it's missing from the server
|
||||
val httpException = it as? HttpException
|
||||
@Suppress("MagicNumber")
|
||||
if (httpException?.code() == 404 && isUpdate) {
|
||||
vaultDiskSource.deleteSend(userId = userId, sendId = sendId)
|
||||
onSuccess = { response ->
|
||||
when (response) {
|
||||
is GetSendResponse.NotFound -> {
|
||||
if (isUpdate) {
|
||||
vaultDiskSource.deleteSend(userId = userId, sendId = sendId)
|
||||
}
|
||||
}
|
||||
|
||||
is GetSendResponse.Success -> {
|
||||
vaultDiskSource.saveSend(userId = userId, send = response.send)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
// no-op
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.bitwarden.network.model.ArchiveCipherResponseJson
|
||||
import com.bitwarden.network.model.AttachmentJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherResponseJson
|
||||
import com.bitwarden.network.model.GetCipherResponse
|
||||
import com.bitwarden.network.model.ShareCipherJsonRequest
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.UnarchiveCipherResponseJson
|
||||
@@ -80,7 +81,6 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import retrofit2.HttpException
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
@@ -2610,6 +2610,7 @@ class CipherManagerTest {
|
||||
revisionDate = clock.instant().minus(5, ChronoUnit.MINUTES),
|
||||
)
|
||||
val updatedCipher = mockk<SyncResponseJson.Cipher>()
|
||||
val updatedCipherResponse = GetCipherResponse.Success(cipher = updatedCipher)
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
coEvery {
|
||||
@@ -2620,7 +2621,7 @@ class CipherManagerTest {
|
||||
} returns MutableStateFlow(listOf(collection))
|
||||
coEvery {
|
||||
ciphersService.getCipher(cipherId = cipherId)
|
||||
} returns updatedCipher.asSuccess()
|
||||
} returns updatedCipherResponse.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher)
|
||||
} just runs
|
||||
@@ -2655,6 +2656,7 @@ class CipherManagerTest {
|
||||
revisionDate = clock.instant().minus(5, ChronoUnit.MINUTES),
|
||||
)
|
||||
val updatedCipher = mockk<SyncResponseJson.Cipher>()
|
||||
val updatedCipherResponse = GetCipherResponse.Success(cipher = updatedCipher)
|
||||
val collection = createMockCollection(number = number)
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
@@ -2663,7 +2665,7 @@ class CipherManagerTest {
|
||||
vaultDiskSource.getCollectionsFlow(userId = userId)
|
||||
} returns MutableStateFlow(listOf(collection))
|
||||
|
||||
coEvery { ciphersService.getCipher(cipherId) } returns updatedCipher.asSuccess()
|
||||
coEvery { ciphersService.getCipher(cipherId) } returns updatedCipherResponse.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher)
|
||||
} just runs
|
||||
@@ -2761,10 +2763,9 @@ class CipherManagerTest {
|
||||
coEvery {
|
||||
vaultDiskSource.getCipher(userId = userId, cipherId = cipherId)
|
||||
} returns createMockCipher(number = number)
|
||||
val response: HttpException = mockk {
|
||||
every { code() } returns 404
|
||||
}
|
||||
coEvery { ciphersService.getCipher(cipherId = cipherId) } returns response.asFailure()
|
||||
val response = GetCipherResponse.NotFound(throwable = Throwable("Fail"))
|
||||
|
||||
coEvery { ciphersService.getCipher(cipherId = cipherId) } returns response.asSuccess()
|
||||
coEvery { vaultDiskSource.deleteCipher(userId = userId, cipherId = cipherId) } just runs
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
|
||||
@@ -2794,10 +2795,8 @@ class CipherManagerTest {
|
||||
val cipherId = "mockId-1"
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
val response: HttpException = mockk {
|
||||
every { code() } returns 404
|
||||
}
|
||||
coEvery { ciphersService.getCipher(cipherId = cipherId) } returns response.asFailure()
|
||||
val response = GetCipherResponse.NotFound(throwable = Throwable("Fail"))
|
||||
coEvery { ciphersService.getCipher(cipherId = cipherId) } returns response.asSuccess()
|
||||
coEvery { vaultDiskSource.getCipher(userId = userId, cipherId = cipherId) } returns null
|
||||
|
||||
mutableSyncCipherUpsertFlow.tryEmit(
|
||||
@@ -2828,6 +2827,7 @@ class CipherManagerTest {
|
||||
val userId = MOCK_USER_STATE.activeUserId
|
||||
val cipherId = "mockId-$number"
|
||||
val updatedCipher = mockk<SyncResponseJson.Cipher>()
|
||||
val updatedCipherResponse = GetCipherResponse.Success(cipher = updatedCipher)
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
coEvery {
|
||||
@@ -2835,7 +2835,7 @@ class CipherManagerTest {
|
||||
} returns null
|
||||
coEvery {
|
||||
ciphersService.getCipher(cipherId = cipherId)
|
||||
} returns updatedCipher.asSuccess()
|
||||
} returns updatedCipherResponse.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher)
|
||||
} just runs
|
||||
@@ -2869,12 +2869,13 @@ class CipherManagerTest {
|
||||
every { revisionDate } returns clock.instant().minus(5, ChronoUnit.MINUTES)
|
||||
}
|
||||
val updatedCipher = mockk<SyncResponseJson.Cipher>()
|
||||
val updatedCipherResponse = GetCipherResponse.Success(cipher = updatedCipher)
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
coEvery {
|
||||
vaultDiskSource.getCipher(userId = userId, cipherId = cipherId)
|
||||
} returns originalCipher
|
||||
coEvery { ciphersService.getCipher(cipherId) } returns updatedCipher.asSuccess()
|
||||
coEvery { ciphersService.getCipher(cipherId) } returns updatedCipherResponse.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.saveCipher(userId = userId, cipher = updatedCipher)
|
||||
} just runs
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.bitwarden.data.manager.file.FileManager
|
||||
import com.bitwarden.network.exception.CookieRedirectException
|
||||
import com.bitwarden.network.model.CreateFileSendResponse
|
||||
import com.bitwarden.network.model.CreateSendJsonResponse
|
||||
import com.bitwarden.network.model.GetSendResponse
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.UpdateSendResponseJson
|
||||
@@ -53,7 +54,6 @@ import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import retrofit2.HttpException
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
@@ -186,10 +186,11 @@ class SendManagerTest {
|
||||
revisionDate = FIXED_CLOCK.instant(),
|
||||
)
|
||||
val updatedSend = createMockSend(number = number)
|
||||
val updatedSendResponse = GetSendResponse.Success(send = updatedSend)
|
||||
coEvery {
|
||||
vaultDiskSource.getSendsFlow(userId = userId)
|
||||
} returns MutableStateFlow(listOf(send))
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns updatedSend.asSuccess()
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns updatedSendResponse.asSuccess()
|
||||
coEvery { vaultDiskSource.saveSend(userId = userId, send = updatedSend) } just runs
|
||||
|
||||
mutableSyncSendUpsertFlow.tryEmit(
|
||||
@@ -216,10 +217,8 @@ class SendManagerTest {
|
||||
val sendId = "mockId-$number"
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
val response: HttpException = mockk {
|
||||
every { code() } returns 404
|
||||
}
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns response.asFailure()
|
||||
val response = GetSendResponse.NotFound(throwable = Throwable("Fail"))
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns response.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.deleteSend(userId = userId, sendId = sendId)
|
||||
} just runs
|
||||
@@ -255,10 +254,8 @@ class SendManagerTest {
|
||||
val sendId = "mockId-1"
|
||||
|
||||
fakeAuthDiskSource.userState = MOCK_USER_STATE
|
||||
val response: HttpException = mockk {
|
||||
every { code() } returns 404
|
||||
}
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns response.asFailure()
|
||||
val response = GetSendResponse.NotFound(throwable = Throwable("Fail"))
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns response.asSuccess()
|
||||
coEvery {
|
||||
vaultDiskSource.getSendsFlow(userId = userId)
|
||||
} returns MutableStateFlow(emptyList())
|
||||
@@ -293,7 +290,10 @@ class SendManagerTest {
|
||||
vaultDiskSource.getSendsFlow(userId = userId)
|
||||
} returns MutableStateFlow(emptyList())
|
||||
val send = mockk<SyncResponseJson.Send>()
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns send.asSuccess()
|
||||
val updatedSendResponse = GetSendResponse.Success(send = send)
|
||||
coEvery {
|
||||
sendsService.getSend(sendId = sendId)
|
||||
} returns updatedSendResponse.asSuccess()
|
||||
coEvery { vaultDiskSource.saveSend(userId = userId, send = send) } just runs
|
||||
|
||||
mutableSyncSendUpsertFlow.tryEmit(
|
||||
@@ -329,7 +329,10 @@ class SendManagerTest {
|
||||
} returns MutableStateFlow(listOf(sendView))
|
||||
|
||||
val send = mockk<SyncResponseJson.Send>()
|
||||
coEvery { sendsService.getSend(sendId = sendId) } returns send.asSuccess()
|
||||
val updatedSendResponse = GetSendResponse.Success(send = send)
|
||||
coEvery {
|
||||
sendsService.getSend(sendId = sendId)
|
||||
} returns updatedSendResponse.asSuccess()
|
||||
coEvery { vaultDiskSource.saveSend(userId = userId, send = send) } just runs
|
||||
|
||||
mutableSyncSendUpsertFlow.tryEmit(
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.bitwarden.network.model
|
||||
|
||||
/**
|
||||
* Models response body from fetching a Cipher.
|
||||
*/
|
||||
sealed class GetCipherResponse {
|
||||
/**
|
||||
* Models response of a successful Get Cipher request.
|
||||
*/
|
||||
data class Success(
|
||||
val cipher: SyncResponseJson.Cipher,
|
||||
) : GetCipherResponse()
|
||||
|
||||
/**
|
||||
* Models the response of an unfindable Get Cipher request.
|
||||
*/
|
||||
data class NotFound(
|
||||
val throwable: Throwable,
|
||||
) : GetCipherResponse()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.bitwarden.network.model
|
||||
|
||||
/**
|
||||
* Models response body from fetching a Send.
|
||||
*/
|
||||
sealed class GetSendResponse {
|
||||
/**
|
||||
* Models response of a successful Get Send request.
|
||||
*/
|
||||
data class Success(
|
||||
val send: SyncResponseJson.Send,
|
||||
) : GetSendResponse()
|
||||
|
||||
/**
|
||||
* Models the response of an unfindable Get Send request.
|
||||
*/
|
||||
data class NotFound(
|
||||
val throwable: Throwable,
|
||||
) : GetSendResponse()
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.bitwarden.network.model.CipherJsonRequest
|
||||
import com.bitwarden.network.model.CipherMiniResponseJson
|
||||
import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherResponseJson
|
||||
import com.bitwarden.network.model.GetCipherResponse
|
||||
import com.bitwarden.network.model.ImportCiphersJsonRequest
|
||||
import com.bitwarden.network.model.ImportCiphersResponseJson
|
||||
import com.bitwarden.network.model.ShareCipherJsonRequest
|
||||
@@ -128,7 +129,7 @@ interface CiphersService {
|
||||
/**
|
||||
* Attempt to retrieve a cipher.
|
||||
*/
|
||||
suspend fun getCipher(cipherId: String): Result<SyncResponseJson.Cipher>
|
||||
suspend fun getCipher(cipherId: String): Result<GetCipherResponse>
|
||||
|
||||
/**
|
||||
* Attempt to retrieve a cipher's attachment data.
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.bitwarden.network.model.CipherMiniResponseJson
|
||||
import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherResponseJson
|
||||
import com.bitwarden.network.model.FileUploadType
|
||||
import com.bitwarden.network.model.GetCipherResponse
|
||||
import com.bitwarden.network.model.ImportCiphersJsonRequest
|
||||
import com.bitwarden.network.model.ImportCiphersResponseJson
|
||||
import com.bitwarden.network.model.ShareCipherJsonRequest
|
||||
@@ -22,6 +23,7 @@ import com.bitwarden.network.model.UpdateCipherCollectionsJsonRequest
|
||||
import com.bitwarden.network.model.UpdateCipherResponseJson
|
||||
import com.bitwarden.network.model.toBitwardenError
|
||||
import com.bitwarden.network.util.NetworkErrorCode
|
||||
import com.bitwarden.network.util.isErrorCode
|
||||
import com.bitwarden.network.util.parseErrorBodyOrNull
|
||||
import com.bitwarden.network.util.toResult
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -269,10 +271,19 @@ internal class CiphersServiceImpl(
|
||||
|
||||
override suspend fun getCipher(
|
||||
cipherId: String,
|
||||
): Result<SyncResponseJson.Cipher> =
|
||||
): Result<GetCipherResponse> =
|
||||
ciphersApi
|
||||
.getCipher(cipherId = cipherId)
|
||||
.toResult()
|
||||
.map { GetCipherResponse.Success(cipher = it) }
|
||||
.recoverCatching { throwable ->
|
||||
val bitwardenError = throwable.toBitwardenError()
|
||||
if (bitwardenError.isErrorCode(code = NetworkErrorCode.NOT_FOUND)) {
|
||||
GetCipherResponse.NotFound(throwable = throwable)
|
||||
} else {
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getCipherAttachment(
|
||||
cipherId: String,
|
||||
|
||||
@@ -121,6 +121,7 @@ internal class IdentityServiceImpl(
|
||||
}
|
||||
|
||||
NetworkErrorCode.BAD_REQUEST,
|
||||
NetworkErrorCode.NOT_FOUND,
|
||||
NetworkErrorCode.TOO_MANY_REQUESTS,
|
||||
null,
|
||||
-> throw throwable
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bitwarden.network.service
|
||||
import com.bitwarden.network.model.CreateFileSendResponse
|
||||
import com.bitwarden.network.model.CreateFileSendResponseJson
|
||||
import com.bitwarden.network.model.CreateSendJsonResponse
|
||||
import com.bitwarden.network.model.GetSendResponse
|
||||
import com.bitwarden.network.model.SendJsonRequest
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.UpdateSendResponseJson
|
||||
@@ -43,7 +44,7 @@ interface SendsService {
|
||||
): Result<UpdateSendResponseJson>
|
||||
|
||||
/**
|
||||
* Attempt to delete a send.
|
||||
* Attempt to delete a Send.
|
||||
*/
|
||||
suspend fun deleteSend(
|
||||
sendId: String,
|
||||
@@ -57,7 +58,7 @@ interface SendsService {
|
||||
): Result<UpdateSendResponseJson>
|
||||
|
||||
/**
|
||||
* Attempt to retrieve a send.
|
||||
* Attempt to retrieve a Send.
|
||||
*/
|
||||
suspend fun getSend(sendId: String): Result<SyncResponseJson.Send>
|
||||
suspend fun getSend(sendId: String): Result<GetSendResponse>
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ import com.bitwarden.network.model.CreateFileSendResponse
|
||||
import com.bitwarden.network.model.CreateFileSendResponseJson
|
||||
import com.bitwarden.network.model.CreateSendJsonResponse
|
||||
import com.bitwarden.network.model.FileUploadType
|
||||
import com.bitwarden.network.model.GetSendResponse
|
||||
import com.bitwarden.network.model.SendJsonRequest
|
||||
import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.network.model.UpdateSendResponseJson
|
||||
import com.bitwarden.network.model.toBitwardenError
|
||||
import com.bitwarden.network.util.NetworkErrorCode
|
||||
import com.bitwarden.network.util.isErrorCode
|
||||
import com.bitwarden.network.util.parseErrorBodyOrNull
|
||||
import com.bitwarden.network.util.toResult
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -152,8 +154,17 @@ internal class SendsServiceImpl(
|
||||
|
||||
override suspend fun getSend(
|
||||
sendId: String,
|
||||
): Result<SyncResponseJson.Send> =
|
||||
): Result<GetSendResponse> =
|
||||
sendsApi
|
||||
.getSend(sendId = sendId)
|
||||
.toResult()
|
||||
.map { GetSendResponse.Success(send = it) }
|
||||
.recoverCatching { throwable ->
|
||||
val bitwardenError = throwable.toBitwardenError()
|
||||
if (bitwardenError.isErrorCode(code = NetworkErrorCode.NOT_FOUND)) {
|
||||
GetSendResponse.NotFound(throwable = throwable)
|
||||
} else {
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,13 @@ internal fun BitwardenError.getNetworkErrorCodeOrNull(): NetworkErrorCode? =
|
||||
NetworkErrorCode.entries.firstOrNull { httpError.code == it.code }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `true` if the underlying error is from the [code] provided.
|
||||
*/
|
||||
internal fun BitwardenError.isErrorCode(
|
||||
code: NetworkErrorCode,
|
||||
): Boolean = (this as? BitwardenError.Http)?.let { code.code == this.code } == true
|
||||
|
||||
/**
|
||||
* Attempt to parse the error body to serializable type [T].
|
||||
*
|
||||
|
||||
@@ -9,5 +9,6 @@ internal enum class NetworkErrorCode(
|
||||
BAD_REQUEST(code = 400),
|
||||
UNAUTHORIZED(code = 401),
|
||||
FORBIDDEN(code = 403),
|
||||
NOT_FOUND(code = 404),
|
||||
TOO_MANY_REQUESTS(code = 429),
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.bitwarden.network.model.BulkShareCiphersJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherInOrganizationJsonRequest
|
||||
import com.bitwarden.network.model.CreateCipherResponseJson
|
||||
import com.bitwarden.network.model.FileUploadType
|
||||
import com.bitwarden.network.model.GetCipherResponse
|
||||
import com.bitwarden.network.model.ImportCiphersJsonRequest
|
||||
import com.bitwarden.network.model.ImportCiphersResponseJson
|
||||
import com.bitwarden.network.model.ShareCipherJsonRequest
|
||||
@@ -35,6 +36,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertInstanceOf
|
||||
import retrofit2.create
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
@@ -440,15 +442,22 @@ class CiphersServiceTest : BaseServiceTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCipher should return the correct response`() = runTest {
|
||||
fun `getCipher with success should return the correct response`() = runTest {
|
||||
server.enqueue(MockResponse().setBody(CREATE_RESTORE_UPDATE_CIPHER_SUCCESS_JSON))
|
||||
val result = ciphersService.getCipher(cipherId = "mockId-1")
|
||||
assertEquals(
|
||||
createMockCipher(number = 1),
|
||||
GetCipherResponse.Success(cipher = createMockCipher(number = 1)),
|
||||
result.getOrThrow(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getSend with 404 should return the NotFound response`() = runTest {
|
||||
server.enqueue(MockResponse().setResponseCode(404))
|
||||
val result = ciphersService.getCipher("mockId-1")
|
||||
assertInstanceOf<GetCipherResponse.NotFound>(result.getOrThrow())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getCipherAttachment should return the correct response`() = runTest {
|
||||
server.enqueue(MockResponse().setBody(GET_CIPHER_ATTACHMENT_SUCCESS_JSON))
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.bitwarden.network.api.SendsApi
|
||||
import com.bitwarden.network.base.BaseServiceTest
|
||||
import com.bitwarden.network.model.CreateFileSendResponse
|
||||
import com.bitwarden.network.model.CreateSendJsonResponse
|
||||
import com.bitwarden.network.model.GetSendResponse
|
||||
import com.bitwarden.network.model.SendTypeJson
|
||||
import com.bitwarden.network.model.UpdateSendResponseJson
|
||||
import com.bitwarden.network.model.createMockFileSendResponseJson
|
||||
@@ -21,6 +22,7 @@ import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertInstanceOf
|
||||
import retrofit2.create
|
||||
import java.io.File
|
||||
import java.time.Clock
|
||||
@@ -180,11 +182,18 @@ class SendsServiceTest : BaseServiceTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getSend should return the correct response`() = runTest {
|
||||
fun `getSend with success should return the success response`() = runTest {
|
||||
val response = createMockSend(number = 1)
|
||||
server.enqueue(MockResponse().setBody(CREATE_UPDATE_SEND_SUCCESS_JSON))
|
||||
val result = sendsService.getSend("mockId-1")
|
||||
assertEquals(response, result.getOrThrow())
|
||||
assertEquals(GetSendResponse.Success(send = response), result.getOrThrow())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getSend with 404 should return the NotFound response`() = runTest {
|
||||
server.enqueue(MockResponse().setResponseCode(404))
|
||||
val result = sendsService.getSend("mockId-1")
|
||||
assertInstanceOf<GetSendResponse.NotFound>(result.getOrThrow())
|
||||
}
|
||||
|
||||
private fun setupMockUri(
|
||||
|
||||
Reference in New Issue
Block a user