diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityService.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityService.kt index 09bd21c38..5d73cace0 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityService.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityService.kt @@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterFinishRequ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson 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.SendVerificationEmailResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorDataModel import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenResponseJson @@ -68,7 +69,7 @@ interface IdentityService { */ suspend fun sendVerificationEmail( body: SendVerificationEmailRequestJson, - ): Result + ): Result /** * Register a new account to Bitwarden using email verification flow. diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt index cb2a8e4f9..cf0efd887 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceImpl.kt @@ -11,6 +11,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterFinishRequ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson 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.SendVerificationEmailResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorDataModel import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifyEmailTokenResponseJson @@ -132,11 +133,20 @@ class IdentityServiceImpl( override suspend fun sendVerificationEmail( body: SendVerificationEmailRequestJson, - ): Result { + ): Result { return unauthenticatedIdentityApi .sendVerificationEmail(body = body) .toResult() - .map { it?.content } + .map { SendVerificationEmailResponseJson.Success(it?.content) } + .recoverCatching { throwable -> + throwable + .toBitwardenError() + .parseErrorBodyOrNull( + code = 400, + json = json, + ) + ?: throw throwable + } } override suspend fun verifyEmailRegistrationToken( diff --git a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt index a769f88aa..ca0521540 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryImpl.kt @@ -22,6 +22,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJs import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailRequestJson +import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorAuthMethod @@ -1282,7 +1283,15 @@ class AuthRepositoryImpl( ) .fold( onSuccess = { - SendVerificationEmailResult.Success(it) + when (it) { + is SendVerificationEmailResponseJson.Invalid -> { + SendVerificationEmailResult.Error(it.message) + } + + is SendVerificationEmailResponseJson.Success -> { + SendVerificationEmailResult.Success(it.emailVerificationToken) + } + } }, onFailure = { SendVerificationEmailResult.Error(null) diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt index 90d64d205..30d4fa39b 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/datasource/network/service/IdentityServiceTest.kt @@ -13,6 +13,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterFinishRequ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterRequestJson 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.SendVerificationEmailResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorAuthMethod import com.x8bit.bitwarden.data.auth.datasource.network.model.UserDecryptionOptionsJson @@ -370,14 +371,19 @@ class IdentityServiceTest : BaseServiceTest() { runTest { server.enqueue(MockResponse().setResponseCode(200).setBody(EMAIL_TOKEN)) val result = identityService.sendVerificationEmail(SEND_VERIFICATION_EMAIL_REQUEST) - assertEquals(JsonPrimitive(EMAIL_TOKEN).content.asSuccess(), result) + assertEquals( + SendVerificationEmailResponseJson + .Success(JsonPrimitive(EMAIL_TOKEN).content) + .asSuccess(), + result, + ) } @Test fun `sendVerificationEmail should return null when response is empty success`() = runTest { server.enqueue(MockResponse().setResponseCode(204)) val result = identityService.sendVerificationEmail(SEND_VERIFICATION_EMAIL_REQUEST) - assertEquals(null.asSuccess(), result) + assertEquals(SendVerificationEmailResponseJson.Success(null).asSuccess(), result) } @Test @@ -422,7 +428,6 @@ class IdentityServiceTest : BaseServiceTest() { ) } - @Suppress("MaxLineLength") @Test fun `verifyEmailToken should return Invalid when response message is non expired error`() = runTest { diff --git a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt index 5e0882b33..3aae102b4 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/auth/repository/AuthRepositoryTest.kt @@ -38,6 +38,7 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.RegisterResponseJs import com.x8bit.bitwarden.data.auth.datasource.network.model.ResendEmailRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.ResetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailRequestJson +import com.x8bit.bitwarden.data.auth.datasource.network.model.SendVerificationEmailResponseJson import com.x8bit.bitwarden.data.auth.datasource.network.model.SetPasswordRequestJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TrustedDeviceUserDecryptionOptionsJson import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorAuthMethod @@ -6043,7 +6044,7 @@ class AuthRepositoryTest { receiveMarketingEmails = true, ), ) - } returns EMAIL_VERIFICATION_TOKEN.asSuccess() + } returns SendVerificationEmailResponseJson.Success(EMAIL_VERIFICATION_TOKEN).asSuccess() val result = repository.sendVerificationEmail( email = EMAIL, @@ -6056,6 +6057,32 @@ class AuthRepositoryTest { ) } + @Test + fun `sendVerificationEmail success with invalid email should return error`() = runTest { + val errorMessage = "Failure" + coEvery { + identityService.sendVerificationEmail( + SendVerificationEmailRequestJson( + email = EMAIL, + name = NAME, + receiveMarketingEmails = true, + ), + ) + } returns SendVerificationEmailResponseJson + .Invalid(invalidMessage = errorMessage, validationErrors = null) + .asSuccess() + + val result = repository.sendVerificationEmail( + email = EMAIL, + name = NAME, + receiveMarketingEmails = true, + ) + assertEquals( + SendVerificationEmailResult.Error(errorMessage = errorMessage), + result, + ) + } + @Test fun `sendVerificationEmail failure should return success if body null`() = runTest { coEvery { @@ -6066,7 +6093,7 @@ class AuthRepositoryTest { receiveMarketingEmails = true, ), ) - } returns null.asSuccess() + } returns SendVerificationEmailResponseJson.Success(null).asSuccess() val result = repository.sendVerificationEmail( email = EMAIL, @@ -6089,7 +6116,7 @@ class AuthRepositoryTest { receiveMarketingEmails = true, ), ) - } returns EMAIL_VERIFICATION_TOKEN.asSuccess() + } returns SendVerificationEmailResponseJson.Success(EMAIL_VERIFICATION_TOKEN).asSuccess() val result = repository.sendVerificationEmail( email = EMAIL,