Skip to content

Commit 8548893

Browse files
Support translations for Cookie Acquisition error
1 parent 8fe23ad commit 8548893

17 files changed

Lines changed: 94 additions & 31 deletions

File tree

app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
8989
import com.x8bit.bitwarden.data.vault.datasource.disk.VaultDiskSource
9090
import com.x8bit.bitwarden.data.vault.manager.VaultLockManager
9191
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
92+
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
9293
import dagger.Module
9394
import dagger.Provides
9495
import dagger.hilt.InstallIn
@@ -439,10 +440,12 @@ object PlatformManagerModule {
439440
@Provides
440441
@Singleton
441442
fun provideNetworkCookieManager(
443+
resourceManager: ResourceManager,
442444
configDiskSource: ConfigDiskSource,
443445
cookieDiskSource: CookieDiskSource,
444446
cookieAcquisitionRequestManager: CookieAcquisitionRequestManager,
445447
): NetworkCookieManager = NetworkCookieManagerImpl(
448+
resourceManager = resourceManager,
446449
configDiskSource = configDiskSource,
447450
cookieDiskSource = cookieDiskSource,
448451
cookieAcquisitionRequestManager = cookieAcquisitionRequestManager,

app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/network/NetworkCookieManagerImpl.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package com.x8bit.bitwarden.data.platform.manager.network
22

33
import com.bitwarden.data.datasource.disk.ConfigDiskSource
44
import com.bitwarden.network.model.NetworkCookie
5+
import com.bitwarden.ui.platform.resource.BitwardenString
56
import com.x8bit.bitwarden.data.platform.datasource.disk.CookieDiskSource
67
import com.x8bit.bitwarden.data.platform.datasource.disk.model.CookieConfigurationData
78
import com.x8bit.bitwarden.data.platform.manager.CookieAcquisitionRequestManager
89
import com.x8bit.bitwarden.data.platform.manager.model.CookieAcquisitionRequest
910
import com.x8bit.bitwarden.data.platform.manager.util.toNetworkCookieList
11+
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
1012
import timber.log.Timber
1113

1214
private const val BOOTSTRAP_TYPE_SSO_COOKIE_VENDOR = "ssoCookieVendor"
@@ -15,6 +17,7 @@ private const val BOOTSTRAP_TYPE_SSO_COOKIE_VENDOR = "ssoCookieVendor"
1517
* Default implementation of [NetworkCookieManager].
1618
*/
1719
class NetworkCookieManagerImpl(
20+
private val resourceManager: ResourceManager,
1821
private val configDiskSource: ConfigDiskSource,
1922
private val cookieDiskSource: CookieDiskSource,
2023
private val cookieAcquisitionRequestManager: CookieAcquisitionRequestManager,
@@ -32,6 +35,12 @@ class NetworkCookieManagerImpl(
3235
?.takeIf { it.type == BOOTSTRAP_TYPE_SSO_COOKIE_VENDOR }
3336
?.cookieDomain
3437

38+
override val errorMessageString: String
39+
get() = resourceManager.getString(
40+
resId = BitwardenString
41+
.your_request_was_interrupted_because_the_app_needed_to_reauthenticate,
42+
)
43+
3544
override fun needsBootstrap(hostname: String): Boolean {
3645
val result = configDiskSource
3746
.serverConfig

app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/glide/GlideCookieInterceptor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class GlideCookieInterceptor(
4343
response.close()
4444
throw CookieRedirectException(
4545
hostname = response.request.url.host,
46+
message = cookieProvider.errorMessageString,
4647
)
4748
}
4849
}

app/src/test/kotlin/com/x8bit/bitwarden/data/platform/manager/network/NetworkCookieManagerTest.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import com.bitwarden.data.datasource.disk.model.ServerConfig
44
import com.bitwarden.data.datasource.disk.util.FakeConfigDiskSource
55
import com.bitwarden.network.model.ConfigResponseJson
66
import com.bitwarden.network.model.NetworkCookie
7+
import com.bitwarden.ui.platform.resource.BitwardenString
78
import com.x8bit.bitwarden.data.platform.datasource.disk.CookieDiskSource
89
import com.x8bit.bitwarden.data.platform.datasource.disk.model.CookieConfigurationData
910
import com.x8bit.bitwarden.data.platform.manager.CookieAcquisitionRequestManager
1011
import com.x8bit.bitwarden.data.platform.manager.model.CookieAcquisitionRequest
12+
import com.x8bit.bitwarden.ui.platform.manager.resource.ResourceManager
1113
import io.mockk.every
1214
import io.mockk.just
1315
import io.mockk.mockk
@@ -20,6 +22,9 @@ import org.junit.jupiter.api.Test
2022

2123
class NetworkCookieManagerTest {
2224

25+
private val resourceManager: ResourceManager = mockk {
26+
every { getString(resId = any()) } returns ERROR_MESSAGE
27+
}
2328
private val fakeConfigDiskSource = FakeConfigDiskSource()
2429
private val mockCookieDiskSource: CookieDiskSource = mockk()
2530
private val mockCookieAcquisitionRequestManager: CookieAcquisitionRequestManager =
@@ -28,11 +33,25 @@ class NetworkCookieManagerTest {
2833
}
2934

3035
private val manager = NetworkCookieManagerImpl(
36+
resourceManager = resourceManager,
3137
configDiskSource = fakeConfigDiskSource,
3238
cookieDiskSource = mockCookieDiskSource,
3339
cookieAcquisitionRequestManager = mockCookieAcquisitionRequestManager,
3440
)
3541

42+
@Test
43+
fun `errorMessageString should return appropriate message`() {
44+
val result = manager.errorMessageString
45+
46+
assertEquals(ERROR_MESSAGE, result)
47+
verify(exactly = 1) {
48+
resourceManager.getString(
49+
resId = BitwardenString
50+
.your_request_was_interrupted_because_the_app_needed_to_reauthenticate,
51+
)
52+
}
53+
}
54+
3655
@Test
3756
fun `needsBootstrap should return false when serverConfig is null`() {
3857
fakeConfigDiskSource.serverConfig = null
@@ -284,3 +303,5 @@ private fun createCookieConfig(
284303
hostname = hostname,
285304
cookies = cookies,
286305
)
306+
307+
private const val ERROR_MESSAGE: String = "Error Message"

app/src/test/kotlin/com/x8bit/bitwarden/data/platform/util/ThrowableExtensionsTest.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ class ThrowableExtensionsTest {
1010

1111
@Test
1212
fun `userFriendlyMessage should return message for CookieRedirectException`() {
13-
val exception = CookieRedirectException(hostname = "example.com")
13+
val message = "Your request was interrupted because the app needed to " +
14+
"re-authenticate. Please try again."
15+
val exception = CookieRedirectException(
16+
hostname = "example.com",
17+
message = message,
18+
)
1419
assertEquals(
15-
"Your request was interrupted because the app needed to " +
16-
"re-authenticate. Please try again.",
20+
message,
1721
exception.userFriendlyMessage,
1822
)
1923
}

app/src/test/kotlin/com/x8bit/bitwarden/data/vault/manager/CipherManagerTest.kt

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,7 +2941,9 @@ class CipherManagerTest {
29412941
runTest {
29422942
fakeAuthDiskSource.userState = MOCK_USER_STATE
29432943
val cipherId = "mockId-1"
2944-
val error = CookieRedirectException("test.host")
2944+
val message = "Your request was interrupted because " +
2945+
"the app needed to re-authenticate. Please try again."
2946+
val error = CookieRedirectException(hostname = "test.host", message = message)
29452947
coEvery {
29462948
ciphersService.hardDeleteCipher(cipherId = cipherId)
29472949
} returns error.asFailure()
@@ -2950,8 +2952,7 @@ class CipherManagerTest {
29502952

29512953
assertEquals(
29522954
DeleteCipherResult.Error(
2953-
errorMessage = "Your request was interrupted because " +
2954-
"the app needed to re-authenticate. Please try again.",
2955+
errorMessage = message,
29552956
error = error,
29562957
),
29572958
result,
@@ -2967,7 +2968,9 @@ class CipherManagerTest {
29672968
val cipherId = "mockId-1"
29682969
val cipherView = createMockCipherView(number = 1)
29692970
val encryptionContext = createMockEncryptionContext(number = 1)
2970-
val error = CookieRedirectException("test.host")
2971+
val message = "Your request was interrupted because " +
2972+
"the app needed to re-authenticate. Please try again."
2973+
val error = CookieRedirectException(hostname = "test.host", message = message)
29712974
coEvery {
29722975
vaultSdkSource.encryptCipher(userId = userId, cipherView = cipherView)
29732976
} returns encryptionContext.asSuccess()
@@ -2982,8 +2985,7 @@ class CipherManagerTest {
29822985

29832986
assertEquals(
29842987
DeleteCipherResult.Error(
2985-
errorMessage = "Your request was interrupted because " +
2986-
"the app needed to re-authenticate. Please try again.",
2988+
errorMessage = message,
29872989
error = error,
29882990
),
29892991
result,
@@ -2997,7 +2999,9 @@ class CipherManagerTest {
29972999
fakeAuthDiskSource.userState = MOCK_USER_STATE
29983000
val cipherId = "mockId-1"
29993001
val cipherView = createMockCipherView(number = 1)
3000-
val error = CookieRedirectException("test.host")
3002+
val message = "Your request was interrupted because " +
3003+
"the app needed to re-authenticate. Please try again."
3004+
val error = CookieRedirectException(hostname = "test.host", message = message)
30013005
coEvery {
30023006
ciphersService.restoreCipher(cipherId = cipherId)
30033007
} returns error.asFailure()
@@ -3009,8 +3013,7 @@ class CipherManagerTest {
30093013

30103014
assertEquals(
30113015
RestoreCipherResult.Error(
3012-
errorMessage = "Your request was interrupted because " +
3013-
"the app needed to re-authenticate. Please try again.",
3016+
errorMessage = message,
30143017
error = error,
30153018
),
30163019
result,
@@ -3023,7 +3026,9 @@ class CipherManagerTest {
30233026
runTest {
30243027
fakeAuthDiskSource.userState = MOCK_USER_STATE
30253028
val cipherId = "mockId-1"
3026-
val error = CookieRedirectException("test.host")
3029+
val message = "Your request was interrupted because " +
3030+
"the app needed to re-authenticate. Please try again."
3031+
val error = CookieRedirectException(hostname = "test.host", message = message)
30273032
coEvery {
30283033
ciphersService.archiveCipher(cipherId = cipherId)
30293034
} returns error.asFailure()
@@ -3035,8 +3040,7 @@ class CipherManagerTest {
30353040

30363041
assertEquals(
30373042
ArchiveCipherResult.Error(
3038-
errorMessage = "Your request was interrupted because " +
3039-
"the app needed to re-authenticate. Please try again.",
3043+
errorMessage = message,
30403044
error = error,
30413045
),
30423046
result,

app/src/test/kotlin/com/x8bit/bitwarden/data/vault/manager/SendManagerTest.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,9 @@ class SendManagerTest {
686686
runTest {
687687
fakeAuthDiskSource.userState = MOCK_USER_STATE
688688
val sendId = "mockId-1"
689-
val error = CookieRedirectException(hostname = "example.com")
689+
val message = "Your request was interrupted because " +
690+
"the app needed to re-authenticate. Please try again."
691+
val error = CookieRedirectException(hostname = "test.host", message = message)
690692
coEvery {
691693
sendsService.deleteSend(sendId = sendId)
692694
} returns error.asFailure()
@@ -695,7 +697,7 @@ class SendManagerTest {
695697

696698
assertEquals(
697699
DeleteSendResult.Error(
698-
errorMessage = error.message,
700+
errorMessage = message,
699701
error = error,
700702
),
701703
result,

app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/glide/GlideCookieInterceptorTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class GlideCookieInterceptorTest {
102102
every {
103103
mockCookieProvider.getCookies("vault.bitwarden.com")
104104
} returns emptyList()
105+
every { mockCookieProvider.errorMessageString } returns "Error"
105106

106107
val exception = assertThrows<CookieRedirectException> {
107108
interceptor.intercept(chain)
@@ -134,6 +135,7 @@ class GlideCookieInterceptorTest {
134135
} returns listOf(
135136
NetworkCookie(name = "awselb", value = "session123"),
136137
)
138+
every { mockCookieProvider.errorMessageString } returns "Error"
137139

138140
val exception = assertThrows<CookieRedirectException> {
139141
interceptor.intercept(chain)

app/src/test/kotlin/com/x8bit/bitwarden/ui/vault/feature/vault/VaultViewModelTest.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,9 +1760,11 @@ class VaultViewModelTest : BaseViewModelTest() {
17601760
@Test
17611761
fun `vaultDataStateFlow Error with CookieRedirectException should show user-friendly message`() =
17621762
runTest {
1763+
val message = "Your request was interrupted because " +
1764+
"the app needed to re-authenticate. Please try again."
17631765
mutableVaultDataStateFlow.tryEmit(
17641766
value = DataState.Error(
1765-
error = CookieRedirectException(hostname = "example.com"),
1767+
error = CookieRedirectException(hostname = "example.com", message = message),
17661768
),
17671769
)
17681770

@@ -1771,10 +1773,7 @@ class VaultViewModelTest : BaseViewModelTest() {
17711773
assertEquals(
17721774
createMockVaultState(
17731775
viewState = VaultState.ViewState.Error(
1774-
message = (
1775-
"Your request was interrupted because the app needed to " +
1776-
"re-authenticate. Please try again."
1777-
).asText(),
1776+
message = message.asText(),
17781777
),
17791778
),
17801779
viewModel.stateFlow.value,
@@ -1856,9 +1855,11 @@ class VaultViewModelTest : BaseViewModelTest() {
18561855
@Test
18571856
fun `vaultDataStateFlow Error with CookieRedirectException with items should show user-friendly error dialog`() =
18581857
runTest {
1858+
val message = "Your request was interrupted because " +
1859+
"the app needed to re-authenticate. Please try again."
18591860
mutableVaultDataStateFlow.tryEmit(
18601861
value = DataState.Error(
1861-
error = CookieRedirectException(hostname = "example.com"),
1862+
error = CookieRedirectException(hostname = "example.com", message = message),
18621863
data = VaultData(
18631864
decryptCipherListResult = createMockDecryptCipherListResult(
18641865
number = 1,

authenticator/src/main/kotlin/com/bitwarden/authenticator/data/platform/datasource/network/di/PlatformNetworkModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ object PlatformNetworkModule {
7575
override fun getPrivateKey(alias: String?): PrivateKey? = null
7676
},
7777
cookieProvider = object : CookieProvider {
78+
override val errorMessageString: String get() = "Error"
79+
7880
override fun needsBootstrap(hostname: String): Boolean = false
7981

8082
override fun getCookies(hostname: String): List<NetworkCookie> = emptyList()

0 commit comments

Comments
 (0)