diff options
| author | Albin <albin@mullvad.net> | 2024-08-21 11:12:44 +0200 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2024-08-21 11:12:44 +0200 |
| commit | 114d58677e77213df647aab2ae35c5235a24cb5b (patch) | |
| tree | abc325946db7d2aa627282e626cbd3fde72ee0a8 /android/lib | |
| parent | 766cdae544ac89151794957c696de04fff851162 (diff) | |
| parent | e12c64a82809d0bf17f3ab59cfafe3ed7ab7793c (diff) | |
| download | mullvadvpn-114d58677e77213df647aab2ae35c5235a24cb5b.tar.xz mullvadvpn-114d58677e77213df647aab2ae35c5235a24cb5b.zip | |
Merge branch 'add-voucher-error-message-droid-923'
Diffstat (limited to 'android/lib')
6 files changed, 77 insertions, 3 deletions
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt index 95679cb43d..36460ae1fa 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt @@ -116,6 +116,7 @@ import net.mullvad.mullvadvpn.lib.model.UnknownApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.UnknownCustomListError import net.mullvad.mullvadvpn.lib.model.UpdateApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.UpdateCustomListError +import net.mullvad.mullvadvpn.lib.model.VoucherCode import net.mullvad.mullvadvpn.lib.model.WebsiteAuthToken import net.mullvad.mullvadvpn.lib.model.WireguardConstraints as ModelWireguardConstraints import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData as ModelWireguardEndpointData @@ -575,8 +576,10 @@ class ManagementService( .mapLeft(SetWireguardConstraintsError::Unknown) .mapEmpty() - suspend fun submitVoucher(voucher: String): Either<RedeemVoucherError, RedeemVoucherSuccess> = - Either.catch { grpc.submitVoucher(StringValue.of(voucher)).toDomain() } + suspend fun submitVoucher( + voucher: VoucherCode + ): Either<RedeemVoucherError, RedeemVoucherSuccess> = + Either.catch { grpc.submitVoucher(StringValue.of(voucher.value)).toDomain() } .mapLeftStatus { when (it.status.code) { Status.Code.INVALID_ARGUMENT, diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RedeemVoucherError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RedeemVoucherError.kt index d14a2f236b..6df604c4a6 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RedeemVoucherError.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RedeemVoucherError.kt @@ -5,6 +5,10 @@ sealed class RedeemVoucherError { data object VoucherAlreadyUsed : RedeemVoucherError() + data object TooShortVoucher : RedeemVoucherError() + + data object EnteredAccountNumber : RedeemVoucherError() + data object RpcError : RedeemVoucherError() data class Unknown(val error: Throwable) : RedeemVoucherError() diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCode.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCode.kt new file mode 100644 index 0000000000..9790096d55 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCode.kt @@ -0,0 +1,31 @@ +package net.mullvad.mullvadvpn.lib.model + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure + +@JvmInline +value class VoucherCode private constructor(val value: String) { + + companion object { + // Parsing reference: + // <services-repository>/services/docs/adr/0018-distinguish-voucher-codes-from-account-numbers.md + fun fromString(value: String): Either<ParseVoucherCodeError, VoucherCode> = either { + val trimmedValue = value.trim() + ensure(trimmedValue.length >= MIN_VOUCHER_LENGTH) { + ParseVoucherCodeError.TooShort(trimmedValue) + } + ensure(!value.all { it.isDigit() }) { ParseVoucherCodeError.AllDigit(trimmedValue) } + VoucherCode(trimmedValue) + } + + const val MIN_VOUCHER_LENGTH = 16 + } +} + +sealed interface ParseVoucherCodeError { + + data class AllDigit(val value: String) : ParseVoucherCodeError + + data class TooShort(val value: String) : ParseVoucherCodeError +} diff --git a/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCodeTest.kt b/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCodeTest.kt new file mode 100644 index 0000000000..270e8b2503 --- /dev/null +++ b/android/lib/model/src/test/kotlin/net/mullvad/mullvadvpn/lib/model/VoucherCodeTest.kt @@ -0,0 +1,34 @@ +package net.mullvad.mullvadvpn.lib.model + +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.junit.jupiter.api.Test + +class VoucherCodeTest { + @Test + fun `parsing a too short voucher code should return TooShort`() { + val input = "mycode" + val result = VoucherCode.fromString(input) + + assertTrue(result.isLeft()) + assertEquals(ParseVoucherCodeError.TooShort(input), result.leftOrNull()) + } + + @Test + fun `numbers only should not be allowed`() { + val input = "1234123412341234" + val result = VoucherCode.fromString(input) + + assertTrue(result.isLeft()) + assertEquals(ParseVoucherCodeError.AllDigit(input), result.leftOrNull()) + } + + @Test + fun `number only input when too short should return TooShort`() { + val input = "123412341234" + val result = VoucherCode.fromString(input) + + assertTrue(result.isLeft()) + assertEquals(ParseVoucherCodeError.TooShort(input), result.leftOrNull()) + } +} diff --git a/android/lib/resource/src/main/res/values/strings.xml b/android/lib/resource/src/main/res/values/strings.xml index ef6b0bce7a..c43acdb496 100644 --- a/android/lib/resource/src/main/res/values/strings.xml +++ b/android/lib/resource/src/main/res/values/strings.xml @@ -33,6 +33,7 @@ <string name="redeem">Redeem</string> <string name="invalid_voucher">Voucher code is invalid.</string> <string name="voucher_already_used">Voucher code has already been used.</string> + <string name="voucher_is_account_number">It looks like you’ve entered an account number instead of a voucher code. If you would like to change the active account, please log out first.</string> <string name="error_occurred">An error occurred.</string> <string name="settings">Settings</string> <string name="no_internet_connection">No internet connection</string> diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/VoucherRepository.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/VoucherRepository.kt index a5783a832e..3ea55ccd9d 100644 --- a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/VoucherRepository.kt +++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/VoucherRepository.kt @@ -1,12 +1,13 @@ package net.mullvad.mullvadvpn.lib.shared import net.mullvad.mullvadvpn.lib.daemon.grpc.ManagementService +import net.mullvad.mullvadvpn.lib.model.VoucherCode class VoucherRepository( private val managementService: ManagementService, private val accountRepository: AccountRepository ) { - suspend fun submitVoucher(voucher: String) = + suspend fun submitVoucher(voucher: VoucherCode) = managementService.submitVoucher(voucher).onRight { accountRepository.onVoucherRedeemed(it.newExpiryDate) } |
