diff options
| author | Joakim Hulthe <joakim.hulthe@mullvad.net> | 2024-10-01 16:27:02 +0200 |
|---|---|---|
| committer | Joakim Hulthe <joakim.hulthe@mullvad.net> | 2024-10-01 16:27:02 +0200 |
| commit | ffa5d846607f680a35b59266845196c34971a2ba (patch) | |
| tree | 576ffb14c14a666371f0fea2bd784f64ce411187 | |
| parent | 5ed9fdaff6dcb709a0c1a4101c444c697cb948bc (diff) | |
| parent | fd8f186f7289760532ee0ed56c3405c5700e9822 (diff) | |
| download | mullvadvpn-ffa5d846607f680a35b59266845196c34971a2ba.tar.xz mullvadvpn-ffa5d846607f680a35b59266845196c34971a2ba.zip | |
Merge branch 'rename-account_token-account_number-des-1029'
69 files changed, 502 insertions, 493 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 3ffbe0fc4a..4e74a8f78b 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 @@ -270,7 +270,7 @@ class ManagementService( Either.catch { grpc.removeDevice( ManagementInterface.DeviceRemoval.newBuilder() - .setAccountToken(token.value) + .setAccountNumber(token.value) .setDeviceId(deviceId.value.toString()) .build() ) @@ -347,8 +347,8 @@ class ManagementService( suspend fun getAccountHistory(): Either<GetAccountHistoryError, AccountNumber?> = Either.catch { val history = grpc.getAccountHistory(Empty.getDefaultInstance()) - if (history.hasToken()) { - AccountNumber(history.token.value) + if (history.hasNumber()) { + AccountNumber(history.number.value) } else { null } diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt index 99b4554f0b..4a8ee04683 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt @@ -524,7 +524,7 @@ internal fun ManagementInterface.Device.toDomain(): Device = internal fun ManagementInterface.DeviceState.toDomain(): DeviceState = when (state) { ManagementInterface.DeviceState.State.LOGGED_IN -> - DeviceState.LoggedIn(AccountNumber(device.accountToken), device.device.toDomain()) + DeviceState.LoggedIn(AccountNumber(device.accountNumber), device.device.toDomain()) ManagementInterface.DeviceState.State.LOGGED_OUT -> DeviceState.LoggedOut ManagementInterface.DeviceState.State.REVOKED -> DeviceState.Revoked ManagementInterface.DeviceState.State.UNRECOGNIZED -> diff --git a/android/test/e2e/README.md b/android/test/e2e/README.md index be41a83341..b1f08c8751 100644 --- a/android/test/e2e/README.md +++ b/android/test/e2e/README.md @@ -1,23 +1,23 @@ # End-to-end (e2e) test module ## Overview -The tests in this module are end-to-end tests that rely on the publicly accessible Mullvad infrastucture and APIs. It's therefore required to provide a valid account token (not expired) that can be used to login, connect etc. It's also required to provide an invalid account token which for example is used for negative tests of the login flow. The invalid account token should not exist in the Mullvad infrastucture, however it must be at least 9 characters for some tests to properly run due to input validation. +The tests in this module are end-to-end tests that rely on the publicly accessible Mullvad infrastucture and APIs. It's therefore required to provide a valid account number (not expired) that can be used to login, connect etc. It's also required to provide an invalid account number which for example is used for negative tests of the login flow. The invalid account number should not exist in the Mullvad infrastucture, however it must be at least 9 characters for some tests to properly run due to input validation. ## How to run the tests ### Locally -Set tokens in the below command and then execute the command in the `android` directory to run the tests on a local device: +Set account numbers in the below command and then execute the command in the `android` directory to run the tests on a local device: ``` ./gradlew :test:e2e:connectedDebugAndroidTest \ -Pvalid_test_account_number=XXXX \ -Pinvalid_test_account_number=XXXX ``` -For convenience, the tokens can also be set in `<REPO-ROOT>/android/local.properties` in the following way: +For convenience, the numbers can also be set in `<REPO-ROOT>/android/local.properties` in the following way: ``` valid_test_account_number=XXXX invalid_test_account_number=XXXX ``` -It's also possible to provide the tokens to the test runner during test execution. However note that this requires [the APKs to be installed manually](https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner#architecture). +It's also possible to provide the numbers to the test runner during test execution. However note that this requires [the APKs to be installed manually](https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner#architecture). ``` adb shell 'CLASSPATH=$(pm path androidx.test.services) app_process / \ androidx.test.services.shellexecutor.ShellMain am instrument -w \ @@ -33,7 +33,7 @@ Firebase Test Lab can be used to run the tests on vast collection of physical an 1. Setup the gcloud CLI by following the [official documentation](https://firebase.google.com/docs/test-lab/android/command-line). -2. Set tokens in the below command and then execute the command in the `android` directory to run the tests (on a Pixel 5e): +2. Set numbers in the below command and then execute the command in the `android` directory to run the tests (on a Pixel 5e): ``` gcloud firebase test android run \ --type instrumentation \ diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt index d7fcfb05e8..3373691923 100644 --- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt +++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/SimpleMullvadHttpClient.kt @@ -31,7 +31,7 @@ class SimpleMullvadHttpClient(context: Context) { } fun login(accountNumber: String): String { - Logger.v("Attempt login with account token: $accountNumber") + Logger.v("Attempt login with account number: $accountNumber") val json = JSONObject().apply { put("account_number", accountNumber) } return sendSimpleSynchronousRequest(Request.Method.POST, AUTH_URL, json)!!.let { response -> response.getString("access_token").also { accessToken -> diff --git a/gui/locales/da/messages.po b/gui/locales/da/messages.po index e1c8ceff77..a5155de5d8 100644 --- a/gui/locales/da/messages.po +++ b/gui/locales/da/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Udvid %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Glem %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Glem %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/de/messages.po b/gui/locales/de/messages.po index 679c920467..4f4301801c 100644 --- a/gui/locales/de/messages.po +++ b/gui/locales/de/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "%(location)s ausklappen" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)s vergessen" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)s vergessen" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/es/messages.po b/gui/locales/es/messages.po index d6568f33f1..badf07e102 100644 --- a/gui/locales/es/messages.po +++ b/gui/locales/es/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Expandir %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Olvidar %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Olvidar %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/fi/messages.po b/gui/locales/fi/messages.po index 6c041eb401..e5d71ce005 100644 --- a/gui/locales/fi/messages.po +++ b/gui/locales/fi/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Näytä enemmän: %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Unohda %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Unohda %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/fr/messages.po b/gui/locales/fr/messages.po index d00743c340..ab7f062c28 100644 --- a/gui/locales/fr/messages.po +++ b/gui/locales/fr/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Maximiser %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Oublier %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Oublier %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/it/messages.po b/gui/locales/it/messages.po index 525e87e880..ad6feac226 100644 --- a/gui/locales/it/messages.po +++ b/gui/locales/it/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Espandi %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Dimentica %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Dimentica %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/ja/messages.po b/gui/locales/ja/messages.po index 473331d649..30ea000703 100644 --- a/gui/locales/ja/messages.po +++ b/gui/locales/ja/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "%(location)sを展開する" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)sを忘れる" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)sを忘れる" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/ko/messages.po b/gui/locales/ko/messages.po index 59545d7e4d..92acd04d80 100644 --- a/gui/locales/ko/messages.po +++ b/gui/locales/ko/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "%(location)s 확장" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)s 지우기" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)s 지우기" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot index 43a4ebfb81..0587d174d1 100644 --- a/gui/locales/messages.pot +++ b/gui/locales/messages.pot @@ -325,7 +325,7 @@ msgid "Expand %(location)s" msgstr "" msgctxt "accessibility" -msgid "Forget %(accountToken)s" +msgid "Forget %(accountNumber)s" msgstr "" #. Provided to accessibility tools such as screenreaders to describe diff --git a/gui/locales/my/messages.po b/gui/locales/my/messages.po index 71457563a4..07e0d0186f 100644 --- a/gui/locales/my/messages.po +++ b/gui/locales/my/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "%(location)s ကို ဖြန့်ပြရန်" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)s ကို မမှတ်ရန်" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)s ကို မမှတ်ရန်" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/nb/messages.po b/gui/locales/nb/messages.po index bfd27d6fd9..f265c353dd 100644 --- a/gui/locales/nb/messages.po +++ b/gui/locales/nb/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Vis mer %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Glem %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Glem %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/nl/messages.po b/gui/locales/nl/messages.po index 1ce8c072d2..22d37771d6 100644 --- a/gui/locales/nl/messages.po +++ b/gui/locales/nl/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "%(location)s uitvouwen" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)s vergeten" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)s vergeten" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/pl/messages.po b/gui/locales/pl/messages.po index 7a6911cf94..742c658871 100644 --- a/gui/locales/pl/messages.po +++ b/gui/locales/pl/messages.po @@ -310,8 +310,8 @@ msgid "Expand %(location)s" msgstr "Rozwiń %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Zapomnij %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Zapomnij %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/pt/messages.po b/gui/locales/pt/messages.po index 4de22a5012..b7367700ca 100644 --- a/gui/locales/pt/messages.po +++ b/gui/locales/pt/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Expandir %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Esquecer %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Esquecer %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/ru/messages.po b/gui/locales/ru/messages.po index 8e3c68df3b..5f83fc6203 100644 --- a/gui/locales/ru/messages.po +++ b/gui/locales/ru/messages.po @@ -310,8 +310,8 @@ msgid "Expand %(location)s" msgstr "Развернуть %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Забыть %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Забыть %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/sv/messages.po b/gui/locales/sv/messages.po index 08783e0c14..672bceccd0 100644 --- a/gui/locales/sv/messages.po +++ b/gui/locales/sv/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "Visa %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "Glöm %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "Glöm %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/th/messages.po b/gui/locales/th/messages.po index 359e438443..6053d0bc9e 100644 --- a/gui/locales/th/messages.po +++ b/gui/locales/th/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "ขยาย %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "ลืม %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "ลืม %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/tr/messages.po b/gui/locales/tr/messages.po index cd57b45f7e..b9fe634ede 100644 --- a/gui/locales/tr/messages.po +++ b/gui/locales/tr/messages.po @@ -298,8 +298,8 @@ msgid "Expand %(location)s" msgstr "%(location)s listesini genişlet" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "%(accountToken)s unut" +msgid "Forget %(accountNumber)s" +msgstr "%(accountNumber)s unut" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/zh-CN/messages.po b/gui/locales/zh-CN/messages.po index ee029cd78f..c9153860a1 100644 --- a/gui/locales/zh-CN/messages.po +++ b/gui/locales/zh-CN/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "展开 %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "忘记 %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "忘记 %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/locales/zh-TW/messages.po b/gui/locales/zh-TW/messages.po index 379d1ed432..69400f4201 100644 --- a/gui/locales/zh-TW/messages.po +++ b/gui/locales/zh-TW/messages.po @@ -292,8 +292,8 @@ msgid "Expand %(location)s" msgstr "展開 %(location)s" msgctxt "accessibility" -msgid "Forget %(accountToken)s" -msgstr "忘記 %(accountToken)s" +msgid "Forget %(accountNumber)s" +msgstr "忘記 %(accountNumber)s" #. Provided to accessibility tools such as screenreaders to describe #. the button which obscures the account number. diff --git a/gui/src/main/account-data-cache.ts b/gui/src/main/account-data-cache.ts index a5860f9073..a36d48b2ce 100644 --- a/gui/src/main/account-data-cache.ts +++ b/gui/src/main/account-data-cache.ts @@ -2,7 +2,7 @@ import { closeToExpiry, hasExpired } from '../shared/account-expiry'; import { AccountDataError, AccountDataResponse, - AccountToken, + AccountNumber, IAccountData, VoucherResponse, } from '../shared/daemon-rpc-types'; @@ -25,7 +25,7 @@ const ACCOUNT_DATA_EXPIRED_VALIDITY_SECONDS = 10_000; // An account data cache that helps to throttle RPC requests to get_account_data and retain the // cached value for 1 minute. export default class AccountDataCache { - private currentAccount?: AccountToken; + private currentAccount?: AccountNumber; private validUntil?: Date; private performingFetch = false; private waitStrategy = new WaitStrategy(); @@ -33,15 +33,15 @@ export default class AccountDataCache { private watchers: IAccountFetchWatcher[] = []; constructor( - private fetchHandler: (token: AccountToken) => Promise<AccountDataResponse>, + private fetchHandler: (number: AccountNumber) => Promise<AccountDataResponse>, private updateHandler: (data?: IAccountData) => void, ) {} - public fetch(accountToken: AccountToken, watcher?: IAccountFetchWatcher) { - // invalidate cache if account token has changed - if (accountToken !== this.currentAccount) { + public fetch(accountNumber: AccountNumber, watcher?: IAccountFetchWatcher) { + // invalidate cache if account number has changed + if (accountNumber !== this.currentAccount) { this.invalidate(); - this.currentAccount = accountToken; + this.currentAccount = accountNumber; } // Only fetch if value has expired @@ -56,7 +56,7 @@ export default class AccountDataCache { // Only fetch if there's no fetch for this account number in progress. if (!this.performingFetch) { - void this.performFetch(accountToken); + void this.performFetch(accountNumber); } } else if (watcher) { watcher.onFinish(); @@ -75,8 +75,8 @@ export default class AccountDataCache { }); } - public handleVoucherResponse(accountToken: AccountToken, voucherResponse: VoucherResponse) { - if (accountToken === this.currentAccount && voucherResponse.type === 'success') { + public handleVoucherResponse(accountNumber: AccountNumber, voucherResponse: VoucherResponse) { + if (accountNumber === this.currentAccount && voucherResponse.type === 'success') { this.setValue({ expiry: voucherResponse.newExpiry }); } } @@ -99,24 +99,24 @@ export default class AccountDataCache { } } - private async performFetch(accountToken: AccountToken) { + private async performFetch(accountNumber: AccountNumber) { this.performingFetch = true; - // it's possible for invalidate() to be called or for a fetch for a different account token - // to start before this fetch completes, so checking if the current account token is the one + // it's possible for invalidate() to be called or for a fetch for a different account number + // to start before this fetch completes, so checking if the current account number is the one // used is necessary below. - const response = await this.fetchHandler(accountToken); + const response = await this.fetchHandler(accountNumber); if ('error' in response) { - if (this.currentAccount === accountToken) { - this.handleFetchError(accountToken, response.error); + if (this.currentAccount === accountNumber) { + this.handleFetchError(accountNumber, response.error); this.performingFetch = false; } } else { - if (this.currentAccount === accountToken) { + if (this.currentAccount === accountNumber) { this.setValue(response); const refetchDelay = this.calculateRefetchDelay(response.expiry); if (refetchDelay) { - this.scheduleFetch(accountToken, refetchDelay); + this.scheduleFetch(accountNumber, refetchDelay); } this.waitStrategy.reset(); @@ -136,25 +136,25 @@ export default class AccountDataCache { } } - private handleFetchError(accountToken: AccountToken, error: AccountDataError['error']) { + private handleFetchError(accountNumber: AccountNumber, error: AccountDataError['error']) { this.notifyWatchers((w) => w.onError(error)); if (error !== 'invalid-account') { - this.scheduleRetry(accountToken); + this.scheduleRetry(accountNumber); } } - private scheduleRetry(accountToken: AccountToken) { + private scheduleRetry(accountNumber: AccountNumber) { this.waitStrategy.increase(); const delay = this.waitStrategy.delay(); log.warn(`Failed to fetch account data. Retrying in ${delay} ms`); - this.scheduleFetch(accountToken, delay); + this.scheduleFetch(accountNumber, delay); } - private scheduleFetch(accountToken: AccountToken, delay: number) { + private scheduleFetch(accountNumber: AccountNumber, delay: number) { this.fetchRetryScheduler.schedule(() => { - void this.performFetch(accountToken); + void this.performFetch(accountNumber); }, delay); } diff --git a/gui/src/main/account.ts b/gui/src/main/account.ts index ca4f1f9968..024e4a7208 100644 --- a/gui/src/main/account.ts +++ b/gui/src/main/account.ts @@ -1,7 +1,7 @@ import { closeToExpiry } from '../shared/account-expiry'; import { AccountDataError, - AccountToken, + AccountNumber, DeviceEvent, DeviceState, IAccountData, @@ -31,13 +31,13 @@ export interface AccountDelegate { export default class Account { private accountDataValue?: IAccountData = undefined; - private accountHistoryValue?: AccountToken = undefined; + private accountHistoryValue?: AccountNumber = undefined; private expiryNotificationFrequencyScheduler = new Scheduler(); private firstExpiryNotificationScheduler = new Scheduler(); private accountDataCache = new AccountDataCache( - (accountToken) => { - return this.daemonRpc.getAccountData(accountToken); + (accountNumber) => { + return this.daemonRpc.getAccountData(accountNumber); }, (accountData) => { this.accountDataValue = accountData; @@ -70,16 +70,16 @@ export default class Account { public registerIpcListeners() { IpcMainEventChannel.account.handleCreate(() => this.createNewAccount()); IpcMainEventChannel.account.handleLogin( - async (token: AccountToken) => (await this.login(token)) ?? undefined, + async (number: AccountNumber) => (await this.login(number)) ?? undefined, ); IpcMainEventChannel.account.handleLogout(() => this.logout()); IpcMainEventChannel.account.handleGetWwwAuthToken(() => this.daemonRpc.getWwwAuthToken()); IpcMainEventChannel.account.handleSubmitVoucher(async (voucherCode: string) => { - const currentAccountToken = this.getAccountToken(); + const currentAccountNumber = this.getAccountNumber(); const response = await this.daemonRpc.submitVoucher(voucherCode); - if (currentAccountToken) { - this.accountDataCache.handleVoucherResponse(currentAccountToken, response); + if (currentAccountNumber) { + this.accountDataCache.handleVoucherResponse(currentAccountNumber, response); } return response; @@ -91,8 +91,8 @@ export default class Account { void this.updateAccountHistory(); }); - IpcMainEventChannel.account.handleListDevices((accountToken: AccountToken) => { - return this.daemonRpc.listDevices(accountToken); + IpcMainEventChannel.account.handleListDevices((accountNumber: AccountNumber) => { + return this.daemonRpc.listDevices(accountNumber); }); IpcMainEventChannel.account.handleRemoveDevice((deviceRemoval: IDeviceRemoval) => { return this.daemonRpc.removeDevice(deviceRemoval); @@ -105,7 +105,7 @@ export default class Account { public updateAccountData = () => { if (this.daemonRpc.isConnected && this.isLoggedIn()) { - this.accountDataCache.fetch(this.getAccountToken()!); + this.accountDataCache.fetch(this.getAccountNumber()!); } }; @@ -126,7 +126,7 @@ export default class Account { switch (deviceEvent.deviceState.type) { case 'logged in': - this.accountDataCache.fetch(deviceEvent.deviceState.accountAndDevice.accountToken); + this.accountDataCache.fetch(deviceEvent.deviceState.accountAndDevice.accountNumber); break; case 'logged out': case 'revoked': @@ -140,7 +140,7 @@ export default class Account { IpcMainEventChannel.account.notifyDevice?.(deviceEvent); } - public setAccountHistory(accountHistory?: AccountToken) { + public setAccountHistory(accountHistory?: AccountNumber) { this.accountHistoryValue = accountHistory; IpcMainEventChannel.accountHistory.notify?.(accountHistory); @@ -156,8 +156,8 @@ export default class Account { } } - private async login(accountToken: AccountToken): Promise<AccountDataError | void> { - const error = await this.daemonRpc.loginAccount(accountToken); + private async login(accountNumber: AccountNumber): Promise<AccountDataError | void> { + const error = await this.daemonRpc.loginAccount(accountNumber); if (error) { log.error(`Failed to login: ${error.error}`); @@ -231,9 +231,9 @@ export default class Account { } } - private getAccountToken(): AccountToken | undefined { + private getAccountNumber(): AccountNumber | undefined { return this.deviceState?.type === 'logged in' - ? this.deviceState.accountAndDevice.accountToken + ? this.deviceState.accountAndDevice.accountNumber : undefined; } } diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 4bd5d58116..76b7dcb3f6 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -6,7 +6,7 @@ import { AccessMethodSetting, AccountDataError, AccountDataResponse, - AccountToken, + AccountNumber, BridgeSettings, BridgeState, CustomListError, @@ -120,11 +120,11 @@ export class DaemonRpc extends GrpcClient { } } - public async getAccountData(accountToken: AccountToken): Promise<AccountDataResponse> { + public async getAccountData(accountNumber: AccountNumber): Promise<AccountDataResponse> { try { const response = await this.callString<grpcTypes.AccountData>( this.client.getAccountData, - accountToken, + accountNumber, ); const expiry = response.getExpiry()!.toDate().toISOString(); return { type: 'success', expiry }; @@ -197,9 +197,9 @@ export class DaemonRpc extends GrpcClient { return response.getValue(); } - public async loginAccount(accountToken: AccountToken): Promise<AccountDataError | void> { + public async loginAccount(accountNumber: AccountNumber): Promise<AccountDataError | void> { try { - await this.callString(this.client.loginAccount, accountToken); + await this.callString(this.client.loginAccount, accountNumber); } catch (e) { const error = e as grpc.ServiceError; switch (error.code) { @@ -382,9 +382,9 @@ export class DaemonRpc extends GrpcClient { return convertFromSettings(response)!; } - public async getAccountHistory(): Promise<AccountToken | undefined> { + public async getAccountHistory(): Promise<AccountNumber | undefined> { const response = await this.callEmpty<grpcTypes.AccountHistory>(this.client.getAccountHistory); - return response.getToken()?.getValue(); + return response.getNumber()?.getValue(); } public async clearAccountHistory(): Promise<void> { @@ -472,11 +472,11 @@ export class DaemonRpc extends GrpcClient { await this.callBool(this.client.setDaitaSmartRouting, value); } - public async listDevices(accountToken: AccountToken): Promise<Array<IDevice>> { + public async listDevices(accountNumber: AccountNumber): Promise<Array<IDevice>> { try { const response = await this.callString<grpcTypes.DeviceList>( this.client.listDevices, - accountToken, + accountNumber, ); return response.getDevicesList().map(convertFromDevice); @@ -487,7 +487,7 @@ export class DaemonRpc extends GrpcClient { public async removeDevice(deviceRemoval: IDeviceRemoval): Promise<void> { const grpcDeviceRemoval = new grpcTypes.DeviceRemoval(); - grpcDeviceRemoval.setAccountToken(deviceRemoval.accountToken); + grpcDeviceRemoval.setAccountNumber(deviceRemoval.accountNumber); grpcDeviceRemoval.setDeviceId(deviceRemoval.deviceId); await this.call<grpcTypes.DeviceRemoval, Empty>(this.client.removeDevice, grpcDeviceRemoval); diff --git a/gui/src/main/grpc-type-convertions.ts b/gui/src/main/grpc-type-convertions.ts index caa4e8f160..d37dd3a9b8 100644 --- a/gui/src/main/grpc-type-convertions.ts +++ b/gui/src/main/grpc-type-convertions.ts @@ -1008,7 +1008,7 @@ export function convertFromDeviceState(deviceState: grpcTypes.DeviceState): Devi return { type: 'logged in', accountAndDevice: { - accountToken: accountAndDevice.getAccountToken(), + accountNumber: accountAndDevice.getAccountNumber(), device: device && convertFromDevice(device), }, }; diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 3eccc403b1..3eb0117ffa 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -890,7 +890,7 @@ class ApplicationMain log.info('Skip autoconnect because GUI setting is disabled'); } } else { - log.info('Skip autoconnect because account token is not set'); + log.info('Skip autoconnect because account number is not set'); } } diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index 563899000e..7f8cf02ddd 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -10,7 +10,7 @@ import { } from '../shared/application-types'; import { AccessMethodSetting, - AccountToken, + AccountNumber, BridgeSettings, BridgeState, CustomProxy, @@ -149,7 +149,7 @@ export default class AppRenderer { this.reduxActions.account.updateDevices(devices); }); - IpcRendererEventChannel.accountHistory.listen((newAccountHistory?: AccountToken) => { + IpcRendererEventChannel.accountHistory.listen((newAccountHistory?: AccountNumber) => { this.setAccountHistory(newAccountHistory); }); @@ -384,20 +384,20 @@ export default class AppRenderer { public setAnimateMap = (displayMap: boolean): void => IpcRendererEventChannel.guiSettings.setAnimateMap(displayMap); - public login = async (accountToken: AccountToken) => { + public login = async (accountNumber: AccountNumber) => { const actions = this.reduxActions; - actions.account.startLogin(accountToken); + actions.account.startLogin(accountNumber); log.info('Logging in'); this.previousLoginState = this.loginState; this.loginState = 'logging in'; - const response = await IpcRendererEventChannel.account.login(accountToken); + const response = await IpcRendererEventChannel.account.login(accountNumber); if (response?.type === 'error') { if (response.error === 'too-many-devices') { try { - await this.fetchDevices(accountToken); + await this.fetchDevices(accountNumber); actions.account.loginTooManyDevices(); this.loginState = 'too many devices'; @@ -450,8 +450,8 @@ export default class AppRenderer { } } - public fetchDevices = async (accountToken: AccountToken): Promise<Array<IDevice>> => { - const devices = await IpcRendererEventChannel.account.listDevices(accountToken); + public fetchDevices = async (accountNumber: AccountNumber): Promise<Array<IDevice>> => { + const devices = await IpcRendererEventChannel.account.listDevices(accountNumber); this.reduxActions.account.updateDevices(devices); return devices; }; @@ -773,7 +773,7 @@ export default class AppRenderer { } } - private setAccountHistory(accountHistory?: AccountToken) { + private setAccountHistory(accountHistory?: AccountNumber) { this.reduxActions.account.updateAccountHistory(accountHistory); } @@ -876,16 +876,16 @@ export default class AppRenderer { switch (deviceEvent.type) { case 'logged in': { - const accountToken = deviceEvent.deviceState.accountAndDevice.accountToken; + const accountNumber = deviceEvent.deviceState.accountAndDevice.accountNumber; const device = deviceEvent.deviceState.accountAndDevice.device; switch (this.loginState) { case 'none': - reduxAccount.loggedIn(accountToken, device); + reduxAccount.loggedIn(accountNumber, device); this.resetNavigation(); break; case 'logging in': - reduxAccount.loggedIn(accountToken, device); + reduxAccount.loggedIn(accountNumber, device); if (this.previousLoginState === 'too many devices') { this.resetNavigation(); @@ -894,7 +894,7 @@ export default class AppRenderer { } break; case 'creating account': - reduxAccount.accountCreated(accountToken, device, new Date().toISOString()); + reduxAccount.accountCreated(accountNumber, device, new Date().toISOString()); break; } break; diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx index 431ace2865..c92e56ab1b 100644 --- a/gui/src/renderer/components/Account.tsx +++ b/gui/src/renderer/components/Account.tsx @@ -6,6 +6,7 @@ import { messages } from '../../shared/gettext'; import { useAppContext } from '../context'; import { useHistory } from '../lib/history'; import { useSelector } from '../redux/store'; +import AccountNumberLabel from './AccountNumberLabel'; import { AccountContainer, AccountOutOfTime, @@ -16,7 +17,6 @@ import { DeviceRowValue, StyledDeviceNameRow, } from './AccountStyles'; -import AccountTokenLabel from './AccountTokenLabel'; import * as AppButton from './AppButton'; import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup'; import DeviceInfoButton from './DeviceInfoButton'; @@ -131,8 +131,8 @@ function DeviceNameRow() { } function AccountNumberRow() { - const accountToken = useSelector((state) => state.account.accountToken); - return <AccountRowValue as={AccountTokenLabel} accountToken={accountToken || ''} />; + const accountNumber = useSelector((state) => state.account.accountNumber); + return <AccountRowValue as={AccountNumberLabel} accountNumber={accountNumber || ''} />; } function AccountExpiryRow() { diff --git a/gui/src/renderer/components/AccountNumberLabel.tsx b/gui/src/renderer/components/AccountNumberLabel.tsx new file mode 100644 index 0000000000..c41a6248aa --- /dev/null +++ b/gui/src/renderer/components/AccountNumberLabel.tsx @@ -0,0 +1,20 @@ +import { formatAccountNumber } from '../lib/account'; +import ClipboardLabel from './ClipboardLabel'; + +interface IAccountNumberLabelProps { + accountNumber: string; + obscureValue?: boolean; + className?: string; +} + +export default function AccountNumberLabel(props: IAccountNumberLabelProps) { + return ( + <ClipboardLabel + value={props.accountNumber} + displayValue={formatAccountNumber(props.accountNumber)} + obscureValue={props.obscureValue} + className={props.className} + data-testid="account-number" + /> + ); +} diff --git a/gui/src/renderer/components/AccountTokenLabel.tsx b/gui/src/renderer/components/AccountTokenLabel.tsx deleted file mode 100644 index 479beed9a1..0000000000 --- a/gui/src/renderer/components/AccountTokenLabel.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { formatAccountToken } from '../lib/account'; -import ClipboardLabel from './ClipboardLabel'; - -interface IAccountTokenLabelProps { - accountToken: string; - obscureValue?: boolean; - className?: string; -} - -export default function AccountTokenLabel(props: IAccountTokenLabelProps) { - return ( - <ClipboardLabel - value={props.accountToken} - displayValue={formatAccountToken(props.accountToken)} - obscureValue={props.obscureValue} - className={props.className} - data-testid="account-number" - /> - ); -} diff --git a/gui/src/renderer/components/ExpiredAccountErrorView.tsx b/gui/src/renderer/components/ExpiredAccountErrorView.tsx index 2784f64cd2..b15d74329a 100644 --- a/gui/src/renderer/components/ExpiredAccountErrorView.tsx +++ b/gui/src/renderer/components/ExpiredAccountErrorView.tsx @@ -14,9 +14,9 @@ import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGrou import * as Cell from './cell'; import DeviceInfoButton from './DeviceInfoButton'; import { - StyledAccountTokenContainer, - StyledAccountTokenLabel, - StyledAccountTokenMessage, + StyledAccountNumberContainer, + StyledAccountNumberLabel, + StyledAccountNumberMessage, StyledBody, StyledContainer, StyledCustomScrollbars, @@ -113,12 +113,15 @@ function WelcomeView() { <StyledTitle data-testid="title"> {messages.pgettext('connect-view', 'Congrats!')} </StyledTitle> - <StyledAccountTokenMessage> + <StyledAccountNumberMessage> {messages.pgettext('connect-view', 'Here’s your account number. Save it!')} - <StyledAccountTokenContainer> - <StyledAccountTokenLabel accountToken={account.accountToken || ''} obscureValue={false} /> - </StyledAccountTokenContainer> - </StyledAccountTokenMessage> + <StyledAccountNumberContainer> + <StyledAccountNumberLabel + accountNumber={account.accountNumber || ''} + obscureValue={false} + /> + </StyledAccountNumberContainer> + </StyledAccountNumberMessage> <StyledDeviceLabel> <span> diff --git a/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx b/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx index 753ecdacef..53450a41ee 100644 --- a/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx +++ b/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx @@ -1,7 +1,7 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; -import AccountTokenLabel from './AccountTokenLabel'; +import AccountNumberLabel from './AccountNumberLabel'; import * as Cell from './cell'; import { hugeText, measurements, tinyText } from './common-styles'; import CustomScrollbars from './CustomScrollbars'; @@ -12,7 +12,7 @@ export const StyledHeader = styled(DefaultHeaderBar)({ flex: 0, }); -export const StyledAccountTokenLabel = styled(AccountTokenLabel)({ +export const StyledAccountNumberLabel = styled(AccountNumberLabel)({ fontFamily: 'Open Sans', lineHeight: '20px', fontSize: '20px', @@ -53,7 +53,7 @@ export const StyledMessage = styled.span(tinyText, { color: colors.white, }); -export const StyledAccountTokenMessage = styled.span(tinyText, { +export const StyledAccountNumberMessage = styled.span(tinyText, { color: colors.white, }); @@ -64,7 +64,7 @@ export const StyledStatusIcon = styled.div({ marginBottom: '18px', }); -export const StyledAccountTokenContainer = styled.div({ +export const StyledAccountNumberContainer = styled.div({ display: 'flex', height: '50px', alignItems: 'center', diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx index e5f981eafb..8f17c35651 100644 --- a/gui/src/renderer/components/Login.tsx +++ b/gui/src/renderer/components/Login.tsx @@ -2,10 +2,10 @@ import React, { useCallback } from 'react'; import { sprintf } from 'sprintf-js'; import { colors } from '../../config.json'; -import { AccountDataError, AccountToken } from '../../shared/daemon-rpc-types'; +import { AccountDataError, AccountNumber } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import { useAppContext } from '../context'; -import { formatAccountToken } from '../lib/account'; +import { formatAccountNumber } from '../lib/account'; import { formatHtml } from '../lib/html-formatter'; import { LoginState } from '../redux/account/reducers'; import { useSelector } from '../redux/store'; @@ -41,14 +41,14 @@ import { } from './LoginStyles'; interface IProps { - accountToken?: AccountToken; - accountHistory?: AccountToken; + accountNumber?: AccountNumber; + accountHistory?: AccountNumber; loginState: LoginState; showBlockMessage: boolean; openExternalLink: (type: string) => void; - login: (accountToken: AccountToken) => void; + login: (accountNumber: AccountNumber) => void; resetLoginError: () => void; - updateAccountToken: (accountToken: AccountToken) => void; + updateAccountNumber: (accountNumber: AccountNumber) => void; clearAccountHistory: () => Promise<void>; createNewAccount: () => void; isPerformingPostUpgrade?: boolean; @@ -58,7 +58,7 @@ interface IState { isActive: boolean; } -const MIN_ACCOUNT_TOKEN_LENGTH = 10; +const MIN_ACCOUNT_NUMBER_LENGTH = 10; export default class Login extends React.Component<IProps, IState> { public state: IState = { @@ -133,19 +133,19 @@ export default class Login extends React.Component<IProps, IState> { private onSubmit = (event?: React.FormEvent) => { event?.preventDefault(); - if (this.accountTokenValid()) { - this.props.login(this.props.accountToken!); + if (this.accountNumberValid()) { + this.props.login(this.props.accountNumber!); } }; - private onInputChange = (accountToken: string) => { + private onInputChange = (accountNumber: string) => { // reset error when user types in the new account number if (this.shouldResetLoginError) { this.shouldResetLoginError = false; this.props.resetLoginError(); } - this.props.updateAccountToken(accountToken); + this.props.updateAccountNumber(accountNumber); }; private formTitle() { @@ -254,22 +254,22 @@ export default class Login extends React.Component<IProps, IState> { } private allowCreateAccount() { - const { accountToken } = this.props; - return this.allowInteraction() && (accountToken === undefined || accountToken.length === 0); + const { accountNumber } = this.props; + return this.allowInteraction() && (accountNumber === undefined || accountNumber.length === 0); } - private accountTokenValid(): boolean { - const { accountToken } = this.props; - return accountToken !== undefined && accountToken.length >= MIN_ACCOUNT_TOKEN_LENGTH; + private accountNumberValid(): boolean { + const { accountNumber } = this.props; + return accountNumber !== undefined && accountNumber.length >= MIN_ACCOUNT_NUMBER_LENGTH; } private shouldShowAccountHistory() { return this.allowInteraction() && this.props.accountHistory !== undefined; } - private onSelectAccountFromHistory = (accountToken: string) => { - this.props.updateAccountToken(accountToken); - this.props.login(accountToken); + private onSelectAccountFromHistory = (accountNumber: string) => { + this.props.updateAccountNumber(accountNumber); + this.props.login(accountNumber); }; private onClearAccountHistory = () => { @@ -288,7 +288,7 @@ export default class Login extends React.Component<IProps, IState> { private createLoginForm() { const allowInteraction = this.allowInteraction(); - const allowLogin = allowInteraction && this.accountTokenValid(); + const allowLogin = allowInteraction && this.accountNumberValid(); const hasError = this.props.loginState.type === 'failed' && this.props.loginState.method === 'existing_account'; @@ -307,7 +307,7 @@ export default class Login extends React.Component<IProps, IState> { separator=" " groupLength={4} placeholder="0000 0000 0000 0000" - value={this.props.accountToken || ''} + value={this.props.accountNumber || ''} disabled={!allowInteraction} onFocus={this.onFocus} onBlur={this.onBlur} @@ -366,20 +366,20 @@ export default class Login extends React.Component<IProps, IState> { } interface IAccountDropdownProps { - item?: AccountToken; - onSelect: (value: AccountToken) => void; - onRemove: (value: AccountToken) => void; + item?: AccountNumber; + onSelect: (value: AccountNumber) => void; + onRemove: (value: AccountNumber) => void; } function AccountDropdown(props: IAccountDropdownProps) { - const token = props.item; - if (!token) { + const accountNumber = props.item; + if (!accountNumber) { return null; } - const label = formatAccountToken(token); + const label = formatAccountNumber(accountNumber); return ( <AccountDropdownItem - value={token} + value={accountNumber} label={label} onSelect={props.onSelect} onRemove={props.onRemove} @@ -389,9 +389,9 @@ function AccountDropdown(props: IAccountDropdownProps) { interface IAccountDropdownItemProps { label: string; - value: AccountToken; - onRemove: (value: AccountToken) => void; - onSelect: (value: AccountToken) => void; + value: AccountNumber; + onRemove: (value: AccountNumber) => void; + onSelect: (value: AccountNumber) => void; } function AccountDropdownItem(props: IAccountDropdownItemProps) { @@ -427,9 +427,9 @@ function AccountDropdownItem(props: IAccountDropdownItemProps) { aria-label={ // TRANSLATORS: This is used by screenreaders to communicate the "x" button next to a saved account number. // TRANSLATORS: Available placeholders: - // TRANSLATORS: %(accountToken)s - the account token to the left of the button - sprintf(messages.pgettext('accessibility', 'Forget %(accountToken)s'), { - accountToken: props.label, + // TRANSLATORS: %(accountNumber)s - the account number to the left of the button + sprintf(messages.pgettext('accessibility', 'Forget %(accountNumber)s'), { + accountNumber: props.label, }) }> <StyledAccountDropdownRemoveIcon diff --git a/gui/src/renderer/components/TooManyDevices.tsx b/gui/src/renderer/components/TooManyDevices.tsx index 5f5858b651..1f1fcf9247 100644 --- a/gui/src/renderer/components/TooManyDevices.tsx +++ b/gui/src/renderer/components/TooManyDevices.tsx @@ -95,21 +95,21 @@ const StyledRemoveDeviceButton = styled.button({ export default function TooManyDevices() { const history = useHistory(); const { removeDevice, login, cancelLogin } = useAppContext(); - const accountToken = useSelector((state) => state.account.accountToken)!; + const accountNumber = useSelector((state) => state.account.accountNumber)!; const devices = useSelector((state) => state.account.devices); const loginState = useSelector((state) => state.account.status); const onRemoveDevice = useCallback( async (deviceId: string) => { - await removeDevice({ accountToken, deviceId }); + await removeDevice({ accountNumber, deviceId }); }, - [removeDevice, accountToken], + [removeDevice, accountNumber], ); const continueLogin = useCallback(() => { - void login(accountToken); + void login(accountNumber); history.reset(RoutePath.login, { transition: transitions.pop }); - }, [login, accountToken]); + }, [login, accountNumber]); const cancel = useCallback(() => { cancelLogin(); history.reset(RoutePath.login, { transition: transitions.pop }); @@ -189,7 +189,7 @@ interface IDeviceProps { function Device(props: IDeviceProps) { const { fetchDevices } = useAppContext(); - const accountToken = useSelector((state) => state.account.accountToken)!; + const accountNumber = useSelector((state) => state.account.accountNumber)!; const [confirmationVisible, showConfirmation, hideConfirmation] = useBoolean(false); const [deleting, setDeleting, unsetDeleting] = useBoolean(false); const [error, setError, resetError] = useBoolean(false); @@ -200,7 +200,7 @@ function Device(props: IDeviceProps) { let devices: Array<IDevice> | undefined = undefined; try { - devices = await fetchDevices(accountToken); + devices = await fetchDevices(accountNumber); } catch { /* no-op */ } @@ -211,7 +211,7 @@ function Device(props: IDeviceProps) { setError(); } }, - [fetchDevices, accountToken, hideConfirmation, setError], + [fetchDevices, accountNumber, hideConfirmation, setError], ); const onRemove = useCallback(async () => { diff --git a/gui/src/renderer/containers/LoginPage.tsx b/gui/src/renderer/containers/LoginPage.tsx index fd5aa5cbcd..49fdbba839 100644 --- a/gui/src/renderer/containers/LoginPage.tsx +++ b/gui/src/renderer/containers/LoginPage.tsx @@ -9,14 +9,14 @@ import { IReduxState, ReduxDispatch } from '../redux/store'; const mapStateToProps = (state: IReduxState) => { const tunnelState = state.connection.status; const blockWhenDisconnected = state.settings.blockWhenDisconnected; - const { accountToken, accountHistory, status } = state.account; + const { accountNumber, accountHistory, status } = state.account; const showBlockMessage = tunnelState.state === 'error' || blockWhenDisconnected; const isPerformingPostUpgrade = state.userInterface.isPerformingPostUpgrade; return { - accountToken, + accountNumber, accountHistory, loginState: status, showBlockMessage, @@ -24,7 +24,7 @@ const mapStateToProps = (state: IReduxState) => { }; }; const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { - const { resetLoginError, updateAccountToken } = bindActionCreators(accountActions, dispatch); + const { resetLoginError, updateAccountNumber } = bindActionCreators(accountActions, dispatch); return { login: (account: string) => { void props.app.login(account); @@ -33,7 +33,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { resetLoginError(); }, openExternalLink: (url: string) => props.app.openUrl(url), - updateAccountToken, + updateAccountNumber, clearAccountHistory: () => props.app.clearAccountHistory(), createNewAccount: () => void props.app.createNewAccount(), }; diff --git a/gui/src/renderer/lib/account.ts b/gui/src/renderer/lib/account.ts index 0909b9670b..e15097a7fd 100644 --- a/gui/src/renderer/lib/account.ts +++ b/gui/src/renderer/lib/account.ts @@ -1,5 +1,5 @@ -export function formatAccountToken(accountToken: string) { +export function formatAccountNumber(accountNumber: string) { const parts = - accountToken.replace(/\s+| /g, '').substring(0, 16).match(new RegExp('.{1,4}', 'g')) || []; + accountNumber.replace(/\s+| /g, '').substring(0, 16).match(new RegExp('.{1,4}', 'g')) || []; return parts.join(' '); } diff --git a/gui/src/renderer/redux/account/actions.ts b/gui/src/renderer/redux/account/actions.ts index 4f1e1d9c59..98a689cd76 100644 --- a/gui/src/renderer/redux/account/actions.ts +++ b/gui/src/renderer/redux/account/actions.ts @@ -1,14 +1,14 @@ import { hasExpired } from '../../../shared/account-expiry'; -import { AccountDataError, AccountToken, IDevice } from '../../../shared/daemon-rpc-types'; +import { AccountDataError, AccountNumber, IDevice } from '../../../shared/daemon-rpc-types'; interface IStartLoginAction { type: 'START_LOGIN'; - accountToken: AccountToken; + accountNumber: AccountNumber; } interface ILoggedInAction { type: 'LOGGED_IN'; - accountToken: AccountToken; + accountNumber: AccountNumber; deviceName?: string; } @@ -44,7 +44,7 @@ interface ICreateAccountFailed { interface IAccountCreated { type: 'ACCOUNT_CREATED'; - accountToken: AccountToken; + accountNumber: AccountNumber; deviceName?: string; expiry: string; } @@ -57,14 +57,14 @@ interface IHideNewDeviceBanner { type: 'HIDE_NEW_DEVICE_BANNER'; } -interface IUpdateAccountTokenAction { - type: 'UPDATE_ACCOUNT_TOKEN'; - accountToken: AccountToken; +interface IUpdateAccountNumberAction { + type: 'UPDATE_ACCOUNT_NUMBER'; + accountNumber: AccountNumber; } interface IUpdateAccountHistoryAction { type: 'UPDATE_ACCOUNT_HISTORY'; - accountHistory?: AccountToken; + accountHistory?: AccountNumber; } interface IUpdateAccountExpiryAction { @@ -91,22 +91,22 @@ export type AccountAction = | IAccountCreated | IAccountSetupFinished | IHideNewDeviceBanner - | IUpdateAccountTokenAction + | IUpdateAccountNumberAction | IUpdateAccountHistoryAction | IUpdateAccountExpiryAction | IUpdateDevicesAction; -function startLogin(accountToken: AccountToken): IStartLoginAction { +function startLogin(accountNumber: AccountNumber): IStartLoginAction { return { type: 'START_LOGIN', - accountToken, + accountNumber, }; } -function loggedIn(accountToken: AccountToken, device?: IDevice): ILoggedInAction { +function loggedIn(accountNumber: AccountNumber, device?: IDevice): ILoggedInAction { return { type: 'LOGGED_IN', - accountToken, + accountNumber, deviceName: device?.name, }; } @@ -156,13 +156,13 @@ function createAccountFailed(error: Error): ICreateAccountFailed { } function accountCreated( - accountToken: AccountToken, + accountNumber: AccountNumber, device: IDevice | undefined, expiry: string, ): IAccountCreated { return { type: 'ACCOUNT_CREATED', - accountToken: accountToken, + accountNumber: accountNumber, deviceName: device?.name, expiry, }; @@ -176,14 +176,14 @@ function hideNewDeviceBanner(): IHideNewDeviceBanner { return { type: 'HIDE_NEW_DEVICE_BANNER' }; } -function updateAccountToken(accountToken: AccountToken): IUpdateAccountTokenAction { +function updateAccountNumber(accountNumber: AccountNumber): IUpdateAccountNumberAction { return { - type: 'UPDATE_ACCOUNT_TOKEN', - accountToken, + type: 'UPDATE_ACCOUNT_NUMBER', + accountNumber, }; } -function updateAccountHistory(accountHistory?: AccountToken): IUpdateAccountHistoryAction { +function updateAccountHistory(accountHistory?: AccountNumber): IUpdateAccountHistoryAction { return { type: 'UPDATE_ACCOUNT_HISTORY', accountHistory, @@ -218,7 +218,7 @@ export default { accountCreated, accountSetupFinished, hideNewDeviceBanner, - updateAccountToken, + updateAccountNumber, updateAccountHistory, updateAccountExpiry, updateDevices, diff --git a/gui/src/renderer/redux/account/reducers.ts b/gui/src/renderer/redux/account/reducers.ts index 238d1893bc..a5cf1611ac 100644 --- a/gui/src/renderer/redux/account/reducers.ts +++ b/gui/src/renderer/redux/account/reducers.ts @@ -1,4 +1,4 @@ -import { AccountDataError, AccountToken, IDevice } from '../../../shared/daemon-rpc-types'; +import { AccountDataError, AccountNumber, IDevice } from '../../../shared/daemon-rpc-types'; import { ReduxAction } from '../store'; type LoginMethod = 'existing_account' | 'new_account'; @@ -12,16 +12,16 @@ export type LoginState = | { type: 'failed'; method: 'existing_account'; error: AccountDataError['error'] } | { type: 'failed'; method: 'new_account'; error: Error }; export interface IAccountReduxState { - accountToken?: AccountToken; + accountNumber?: AccountNumber; deviceName?: string; devices: Array<IDevice>; - accountHistory?: AccountToken; + accountHistory?: AccountNumber; expiry?: string; // ISO8601 status: LoginState; } const initialState: IAccountReduxState = { - accountToken: undefined, + accountNumber: undefined, deviceName: undefined, devices: [], accountHistory: undefined, @@ -38,7 +38,7 @@ export default function ( return { ...state, status: { type: 'logging in', method: 'existing_account' }, - accountToken: action.accountToken, + accountNumber: action.accountNumber, }; case 'LOGGED_IN': return { @@ -48,7 +48,7 @@ export default function ( method: 'existing_account', newDeviceBanner: state.status.type === 'logging in', }, - accountToken: action.accountToken, + accountNumber: action.accountNumber, deviceName: action.deviceName, }; case 'LOGIN_FAILED': @@ -65,7 +65,7 @@ export default function ( return { ...state, status: { type: 'none', deviceRevoked: false }, - accountToken: undefined, + accountNumber: undefined, expiry: undefined, }; case 'RESET_LOGIN_ERROR': @@ -97,7 +97,7 @@ export default function ( newDeviceBanner: true, expiredState: 'expired', }, - accountToken: action.accountToken, + accountNumber: action.accountNumber, deviceName: action.deviceName, expiry: action.expiry, }; @@ -115,10 +115,10 @@ export default function ( ...state, status: { ...state.status, newDeviceBanner: false }, }; - case 'UPDATE_ACCOUNT_TOKEN': + case 'UPDATE_ACCOUNT_NUMBER': return { ...state, - accountToken: action.accountToken, + accountNumber: action.accountNumber, }; case 'UPDATE_ACCOUNT_HISTORY': return { diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts index 4943bee933..dcd12d8ccb 100644 --- a/gui/src/shared/daemon-rpc-types.ts +++ b/gui/src/shared/daemon-rpc-types.ts @@ -9,7 +9,7 @@ export type AccountDataError = { export type AccountDataResponse = ({ type: 'success' } & IAccountData) | AccountDataError; -export type AccountToken = string; +export type AccountNumber = string; export type Ip = string; export interface ILocation { ipv4?: string; @@ -391,7 +391,7 @@ export interface IAppVersionInfo { } export interface IAccountAndDevice { - accountToken: AccountToken; + accountNumber: AccountNumber; device?: IDevice; } @@ -411,7 +411,7 @@ export interface IDevice { } export interface IDeviceRemoval { - accountToken: string; + accountNumber: string; deviceId: string; } diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts index 8fa7c8c306..ef3bb44c7b 100644 --- a/gui/src/shared/ipc-schema.ts +++ b/gui/src/shared/ipc-schema.ts @@ -4,7 +4,7 @@ import { ILinuxSplitTunnelingApplication, ISplitTunnelingApplication } from './a import { AccessMethodSetting, AccountDataError, - AccountToken, + AccountNumber, BridgeSettings, BridgeState, CustomListError, @@ -59,7 +59,7 @@ export interface IAppStateSnapshot { isConnected: boolean; autoStart: boolean; accountData?: IAccountData; - accountHistory?: AccountToken; + accountHistory?: AccountNumber; tunnelState: TunnelState; settings: ISettings; isPerformingPostUpgrade: boolean; @@ -214,16 +214,16 @@ export const ipcSchema = { device: notifyRenderer<DeviceEvent>(), devices: notifyRenderer<Array<IDevice>>(), create: invoke<void, string>(), - login: invoke<AccountToken, AccountDataError | undefined>(), + login: invoke<AccountNumber, AccountDataError | undefined>(), logout: invoke<void, void>(), getWwwAuthToken: invoke<void, string>(), submitVoucher: invoke<string, VoucherResponse>(), updateData: send<void>(), - listDevices: invoke<AccountToken, Array<IDevice>>(), + listDevices: invoke<AccountNumber, Array<IDevice>>(), removeDevice: invoke<IDeviceRemoval, void>(), }, accountHistory: { - '': notifyRenderer<AccountToken | undefined>(), + '': notifyRenderer<AccountNumber | undefined>(), clear: invoke<void, void>(), }, autoStart: { diff --git a/gui/test/e2e/setup/main.ts b/gui/test/e2e/setup/main.ts index 8b1d6afcfe..e344a53b90 100644 --- a/gui/test/e2e/setup/main.ts +++ b/gui/test/e2e/setup/main.ts @@ -45,7 +45,7 @@ class ApplicationMain { private deviceState: DeviceState = { type: 'logged in', accountAndDevice: { - accountToken: '1234123412341234', + accountNumber: '1234123412341234', device: { id: '1234', name: 'Testing Mole', diff --git a/gui/test/unit/account-data-cache.spec.ts b/gui/test/unit/account-data-cache.spec.ts index cf1c4299d8..d4147a6603 100644 --- a/gui/test/unit/account-data-cache.spec.ts +++ b/gui/test/unit/account-data-cache.spec.ts @@ -5,7 +5,7 @@ import AccountDataCache, { AccountFetchError } from '../../src/main/account-data import { AccountDataResponse, IAccountData } from '../../src/shared/daemon-rpc-types'; describe('IAccountData cache', () => { - const dummyAccountToken = '9876543210'; + const dummyAccountNumber = '9876543210'; const dummyAccountData: AccountDataResponse = { type: 'success', expiry: new Date('2038-01-01').toISOString(), @@ -23,12 +23,12 @@ describe('IAccountData cache', () => { it('should notify when fetch succeeds on the first attempt', async () => { const cache = new AccountDataCache( - (_token) => Promise.resolve(dummyAccountData), + (_number) => Promise.resolve(dummyAccountData), (_data) => {}, ); const watcher = new Promise<void>((resolve, reject) => { - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => resolve(), onError: (_error: AccountFetchError) => reject(), }); @@ -39,12 +39,12 @@ describe('IAccountData cache', () => { it('should notify when fetch fails on the first attempt', async () => { const cache = new AccountDataCache( - (_token) => Promise.resolve({ type: 'error', error: 'invalid-account' }), + (_number) => Promise.resolve({ type: 'error', error: 'invalid-account' }), (_data) => {}, ); const watcher = new Promise<void>((resolve, reject) => { - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => resolve(), onError: (_error: AccountFetchError) => reject(), }); @@ -60,7 +60,7 @@ describe('IAccountData cache', () => { () => resolve(), ); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => {}, onError: (_error: AccountFetchError) => reject(), }); @@ -85,7 +85,7 @@ describe('IAccountData cache', () => { const cache = new AccountDataCache(fetch, () => resolve()); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => reject(), onError: (_error: AccountFetchError) => {}, }); @@ -100,7 +100,7 @@ describe('IAccountData cache', () => { const update = new Promise<IAccountData | void>((resolve, reject) => { let firstAttempt = true; - const fetch = (_token: string) => { + const fetch = (_number: string) => { if (firstAttempt) { firstAttempt = false; @@ -124,7 +124,7 @@ describe('IAccountData cache', () => { setTimeout(resolve, 12000); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: reject, onError: firstError, }); @@ -159,12 +159,12 @@ describe('IAccountData cache', () => { const cache = new AccountDataCache(fetch, updateHandler); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => {}, onError: (_error: AccountFetchError) => firstError(), }); setTimeout(() => { - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => { secondSuccess(); setTimeout(resolve); @@ -191,8 +191,8 @@ describe('IAccountData cache', () => { const cache = new AccountDataCache(fetch, () => {}); const onError = (_error: AccountFetchError) => {}; - cache.fetch(dummyAccountToken, { onFinish: () => {}, onError }); - cache.fetch(dummyAccountToken, { onFinish: () => resolve(), onError }); + cache.fetch(dummyAccountNumber, { onFinish: () => {}, onError }); + cache.fetch(dummyAccountNumber, { onFinish: () => resolve(), onError }); }); return expect(update).to.eventually.be.fulfilled.then(() => { @@ -207,7 +207,7 @@ describe('IAccountData cache', () => { const update = new Promise<void>((resolve, reject) => { let firstAttempt = true; - const fetch = (_accountToken: string): Promise<AccountDataResponse> => { + const fetch = (_accountNumber: string): Promise<AccountDataResponse> => { if (firstAttempt) { firstAttempt = false; setTimeout(() => clock.tick(120_000), 0); @@ -220,7 +220,7 @@ describe('IAccountData cache', () => { const cache = new AccountDataCache(fetch, () => {}); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => {}, onError: (_error: AccountFetchError) => reject(), }); @@ -235,26 +235,26 @@ describe('IAccountData cache', () => { const update = new Promise<void>((resolve, reject) => { const cache = new AccountDataCache( - (_accountToken) => { + (_accountNumber) => { fetchSpy(); return Promise.resolve<AccountDataResponse>({ type: 'success', expiry }); }, () => {}, ); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: async () => { clock.tick(59_000); // Timeout to let asynchronous tasks finish await new Promise((resolve) => setTimeout(resolve)); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: async () => { clock.tick(1_000); // Timeout to let asynchronous tasks finish await new Promise((resolve) => setTimeout(resolve)); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => resolve(), onError: (_error: AccountFetchError) => reject(), }); @@ -277,26 +277,26 @@ describe('IAccountData cache', () => { const update = new Promise<void>((resolve, reject) => { const cache = new AccountDataCache( - (_accountToken) => { + (_accountNumber) => { fetchSpy(); return Promise.resolve<AccountDataResponse>({ type: 'success', expiry }); }, () => {}, ); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: async () => { clock.tick(9_000); // Timeout to let asynchronous tasks finish await new Promise((resolve) => setTimeout(resolve)); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: async () => { clock.tick(1_000); // Timeout to let asynchronous tasks finish await new Promise((resolve) => setTimeout(resolve)); - cache.fetch(dummyAccountToken, { + cache.fetch(dummyAccountNumber, { onFinish: () => resolve(), onError: (_error: AccountFetchError) => reject(), }); diff --git a/mullvad-api/src/access.rs b/mullvad-api/src/access.rs index dba9e4befd..68e6c773d7 100644 --- a/mullvad-api/src/access.rs +++ b/mullvad-api/src/access.rs @@ -7,7 +7,7 @@ use futures::{ StreamExt, }; use hyper::StatusCode; -use mullvad_types::account::{AccessToken, AccessTokenData, AccountToken}; +use mullvad_types::account::{AccessToken, AccessTokenData, AccountNumber}; use std::{borrow::Cow, collections::HashMap}; use tokio::select; @@ -19,13 +19,13 @@ pub struct AccessTokenStore { } enum StoreAction { - /// Request an access token for `AccountToken`, or return a saved one if it's not expired. + /// Request an access token for `AccountNumber`, or return a saved one if it's not expired. GetAccessToken( - AccountToken, + AccountNumber, oneshot::Sender<Result<AccessToken, rest::Error>>, ), - /// Forget cached access token for `AccountToken`, and drop any in-flight requests - InvalidateToken(AccountToken), + /// Forget cached access token for `AccountNumber`, and drop any in-flight requests + InvalidateToken(AccountNumber), } #[derive(Default)] @@ -51,7 +51,7 @@ impl AccessTokenStore { service: RequestServiceHandle, factory: RequestFactory, ) { - let mut account_states: HashMap<AccountToken, AccountState> = HashMap::new(); + let mut account_states: HashMap<AccountNumber, AccountState> = HashMap::new(); let (completed_tx, mut completed_rx) = mpsc::unbounded(); @@ -145,7 +145,7 @@ impl AccessTokenStore { } /// Obtain access token for an account, requesting a new one from the API if necessary. - pub async fn get_token(&self, account: &AccountToken) -> Result<AccessToken, rest::Error> { + pub async fn get_token(&self, account: &AccountNumber) -> Result<AccessToken, rest::Error> { let (tx, rx) = oneshot::channel(); let _ = self .tx @@ -154,7 +154,7 @@ impl AccessTokenStore { } /// Remove an access token if the API response calls for it. - pub fn check_response<T>(&self, account: &AccountToken, response: &Result<T, rest::Error>) { + pub fn check_response<T>(&self, account: &AccountNumber, response: &Result<T, rest::Error>) { if let Err(rest::Error::ApiError(_status, code)) = response { if code == crate::INVALID_ACCESS_TOKEN { let _ = self @@ -168,15 +168,13 @@ impl AccessTokenStore { async fn fetch_access_token( service: RequestServiceHandle, factory: RequestFactory, - account_token: AccountToken, + account_number: AccountNumber, ) -> Result<AccessTokenData, rest::Error> { #[derive(serde::Serialize)] struct AccessTokenRequest { account_number: String, } - let request = AccessTokenRequest { - account_number: account_token, - }; + let request = AccessTokenRequest { account_number }; let rest_request = factory .post_json(&format!("{AUTH_URL_PREFIX}/token"), &request)? diff --git a/mullvad-api/src/device.rs b/mullvad-api/src/device.rs index a4b609e8aa..036beb731f 100644 --- a/mullvad-api/src/device.rs +++ b/mullvad-api/src/device.rs @@ -1,7 +1,7 @@ use chrono::{DateTime, Utc}; use http::StatusCode; use mullvad_types::{ - account::AccountToken, + account::AccountNumber, device::{Device, DeviceId, DeviceName}, }; use std::future::Future; @@ -34,7 +34,7 @@ impl DevicesProxy { pub fn create( &self, - account: AccountToken, + account: AccountNumber, pubkey: wireguard::PublicKey, ) -> impl Future<Output = Result<(Device, mullvad_types::wireguard::AssociatedAddresses), rest::Error>> { @@ -87,7 +87,7 @@ impl DevicesProxy { pub fn get( &self, - account: AccountToken, + account: AccountNumber, id: DeviceId, ) -> impl Future<Output = Result<Device, rest::Error>> { let service = self.handle.service.clone(); @@ -103,7 +103,7 @@ impl DevicesProxy { pub fn list( &self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<Vec<Device>, rest::Error>> { let service = self.handle.service.clone(); let factory = self.handle.factory.clone(); @@ -118,7 +118,7 @@ impl DevicesProxy { pub fn remove( &self, - account: AccountToken, + account: AccountNumber, id: DeviceId, ) -> impl Future<Output = Result<(), rest::Error>> { let service = self.handle.service.clone(); @@ -135,7 +135,7 @@ impl DevicesProxy { pub fn replace_wg_key( &self, - account: AccountToken, + account: AccountNumber, id: DeviceId, pubkey: wireguard::PublicKey, ) -> impl Future<Output = Result<mullvad_types::wireguard::AssociatedAddresses, rest::Error>> diff --git a/mullvad-api/src/lib.rs b/mullvad-api/src/lib.rs index ebc1401a5f..93fb098bae 100644 --- a/mullvad-api/src/lib.rs +++ b/mullvad-api/src/lib.rs @@ -5,7 +5,7 @@ use hyper::Method; #[cfg(target_os = "android")] use mullvad_types::account::{PlayPurchase, PlayPurchasePaymentToken}; use mullvad_types::{ - account::{AccountData, AccountToken, VoucherSubmission}, + account::{AccountData, AccountNumber, VoucherSubmission}, version::AppVersion, }; use proxy::{ApiConnectionMode, ConnectionModeProvider}; @@ -50,7 +50,7 @@ pub const VOUCHER_USED: &str = "VOUCHER_USED"; /// Error code returned by the Mullvad API if the voucher code is invalid. pub const INVALID_VOUCHER: &str = "INVALID_VOUCHER"; -/// Error code returned by the Mullvad API if the account token is invalid. +/// Error code returned by the Mullvad API if the account number is invalid. pub const INVALID_ACCOUNT: &str = "INVALID_ACCOUNT"; /// Error code returned by the Mullvad API if the device does not exist. @@ -490,7 +490,7 @@ impl AccountsProxy { pub fn get_data( &self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<AccountData, rest::Error>> { let service = self.handle.service.clone(); let factory = self.handle.factory.clone(); @@ -504,10 +504,10 @@ impl AccountsProxy { } } - pub fn create_account(&self) -> impl Future<Output = Result<AccountToken, rest::Error>> { + pub fn create_account(&self) -> impl Future<Output = Result<AccountNumber, rest::Error>> { #[derive(serde::Deserialize)] struct AccountCreationResponse { - number: AccountToken, + number: AccountNumber, } let service = self.handle.service.clone(); @@ -525,7 +525,7 @@ impl AccountsProxy { pub fn submit_voucher( &self, - account: AccountToken, + account: AccountNumber, voucher_code: String, ) -> impl Future<Output = Result<VoucherSubmission, rest::Error>> { #[derive(serde::Serialize)] @@ -549,7 +549,7 @@ impl AccountsProxy { #[cfg(target_os = "ios")] pub fn delete_account( &self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<(), rest::Error>> { let service = self.handle.service.clone(); let factory = self.handle.factory.clone(); @@ -569,7 +569,7 @@ impl AccountsProxy { #[cfg(target_os = "android")] pub fn init_play_purchase( &mut self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<PlayPurchasePaymentToken, rest::Error>> { #[derive(serde::Deserialize)] struct PlayPurchaseInitResponse { @@ -595,7 +595,7 @@ impl AccountsProxy { #[cfg(target_os = "android")] pub fn verify_play_purchase( &mut self, - account: AccountToken, + account: AccountNumber, play_purchase: PlayPurchase, ) -> impl Future<Output = Result<(), rest::Error>> { let service = self.handle.service.clone(); @@ -616,7 +616,7 @@ impl AccountsProxy { pub fn get_www_auth_token( &self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<String, rest::Error>> { #[derive(serde::Deserialize)] struct AuthTokenResponse { diff --git a/mullvad-api/src/rest.rs b/mullvad-api/src/rest.rs index bbcef79903..c8df2aea8e 100644 --- a/mullvad-api/src/rest.rs +++ b/mullvad-api/src/rest.rs @@ -16,7 +16,7 @@ use hyper::{ header::{self, HeaderValue}, Method, Uri, }; -use mullvad_types::account::AccountToken; +use mullvad_types::account::AccountNumber; use std::{ borrow::Cow, error::Error as StdError, @@ -65,7 +65,7 @@ pub enum Error { #[error("Not a valid URI")] InvalidUri, - #[error("Set account token on factory with no access token store")] + #[error("Set account number on factory with no access token store")] NoAccessTokenStore, } @@ -271,7 +271,7 @@ pub struct Request { request: hyper::Request<hyper::Body>, timeout: Duration, access_token_store: Option<AccessTokenStore>, - account: Option<AccountToken>, + account: Option<AccountNumber>, expected_status: &'static [hyper::StatusCode], } @@ -308,9 +308,9 @@ impl Request { } } - /// Set the account token to obtain authentication for. + /// Set the account number to obtain authentication for. /// This fails if no store is set. - pub fn account(mut self, account: AccountToken) -> Result<Self> { + pub fn account(mut self, account: AccountNumber) -> Result<Self> { if self.access_token_store.is_none() { return Err(Error::NoAccessTokenStore); } diff --git a/mullvad-cli/src/cmds/account.rs b/mullvad-cli/src/cmds/account.rs index 229c2a9aa0..c8983994f8 100644 --- a/mullvad-cli/src/cmds/account.rs +++ b/mullvad-cli/src/cmds/account.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, Result}; use clap::Subcommand; use itertools::Itertools; use mullvad_management_interface::MullvadProxyClient; -use mullvad_types::{account::AccountToken, device::DeviceState}; +use mullvad_types::{account::AccountNumber, device::DeviceState}; use std::io::{self, Write}; const NOT_LOGGED_IN_MESSAGE: &str = "Not logged in on any account"; @@ -15,7 +15,7 @@ pub enum Account { /// Log in on an account Login { - /// The Mullvad account token to configure the client with + /// The Mullvad account number to configure the client with account: Option<String>, }, @@ -87,9 +87,9 @@ impl Account { Self::get(rpc, false).await } - async fn login(rpc: &mut MullvadProxyClient, token: AccountToken) -> Result<()> { - rpc.login_account(token.clone()).await?; - println!("Mullvad account \"{token}\" set"); + async fn login(rpc: &mut MullvadProxyClient, account_number: AccountNumber) -> Result<()> { + rpc.login_account(account_number.clone()).await?; + println!("Mullvad account \"{account_number}\" set"); Ok(()) } @@ -106,9 +106,9 @@ impl Account { match state { DeviceState::LoggedIn(device) => { - println!("{:<20}{}", "Mullvad account:", device.account_token); + println!("{:<20}{}", "Mullvad account:", device.account_number); - let data = rpc.get_account_data(device.account_token).await?; + let data = rpc.get_account_data(device.account_number).await?; println!( "{:<20}{}", "Expires at:", @@ -130,8 +130,8 @@ impl Account { } DeviceState::Revoked => { println!("{REVOKED_MESSAGE}"); - if let Some(account_token) = rpc.get_account_history().await? { - println!("Mullvad account: {}", account_token); + if let Some(account_number) = rpc.get_account_history().await? { + println!("Mullvad account: {}", account_number); } } } @@ -144,8 +144,8 @@ impl Account { account: Option<String>, verbose: bool, ) -> Result<()> { - let token = account_else_current(rpc, account).await?; - let mut device_list = rpc.list_devices(token).await?; + let account_number = account_else_current(rpc, account).await?; + let mut device_list = rpc.list_devices(account_number).await?; println!("Devices on the account:"); device_list.sort_unstable_by_key(|dev| dev.created.timestamp()); @@ -172,9 +172,9 @@ impl Account { device: String, account: Option<String>, ) -> Result<()> { - let token = account_else_current(rpc, account).await?; + let account_number = account_else_current(rpc, account).await?; - let device_list = rpc.list_devices(token.clone()).await?; + let device_list = rpc.list_devices(account_number.clone()).await?; let device_id = device_list .into_iter() .find(|dev| { @@ -183,7 +183,7 @@ impl Account { .map(|dev| dev.id) .ok_or(mullvad_management_interface::Error::DeviceNotFound)?; - rpc.remove_device(token, device_id).await?; + rpc.remove_device(account_number, device_id).await?; println!("Removed device"); Ok(()) } @@ -206,14 +206,14 @@ impl Account { async fn account_else_current( rpc: &mut MullvadProxyClient, - token: Option<String>, + account_number: Option<String>, ) -> Result<String> { - match token { + match account_number { Some(account) => Ok(account), None => { let state = rpc.get_device().await?; match state { - DeviceState::LoggedIn(account) => Ok(account.account_token), + DeviceState::LoggedIn(account) => Ok(account.account_number), _ => Err(anyhow!("Log in or specify an account")), } } diff --git a/mullvad-daemon/src/account_history.rs b/mullvad-daemon/src/account_history.rs index 09e0f47a38..5a8677e464 100644 --- a/mullvad-daemon/src/account_history.rs +++ b/mullvad-daemon/src/account_history.rs @@ -1,4 +1,4 @@ -use mullvad_types::account::AccountToken; +use mullvad_types::account::AccountNumber; use regex::Regex; use std::{path::Path, sync::LazyLock}; use talpid_types::ErrorExt; @@ -28,7 +28,7 @@ static ACCOUNT_HISTORY_FILE: &str = "account-history.json"; pub struct AccountHistory { file: io::BufWriter<fs::File>, - token: Option<AccountToken>, + number: Option<AccountNumber>, } static ACCOUNT_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[0-9]+$").unwrap()); @@ -36,7 +36,7 @@ static ACCOUNT_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[0-9]+$") impl AccountHistory { pub async fn new( settings_dir: &Path, - current_token: Option<AccountToken>, + current_number: Option<AccountNumber>, ) -> Result<AccountHistory> { let mut options = fs::OpenOptions::new(); #[cfg(unix)] @@ -61,18 +61,18 @@ impl AccountHistory { .map_err(Error::Read)?; let mut buffer = String::new(); - let (token, should_save): (Option<AccountToken>, bool) = + let (number, should_save): (Option<AccountNumber>, bool) = match reader.read_to_string(&mut buffer).await { Ok(_) if ACCOUNT_REGEX.is_match(&buffer) => (Some(buffer), false), - Ok(0) => (current_token, true), + Ok(0) => (current_number, true), Ok(_) | Err(_) => { log::warn!("Failed to parse account history"); - (current_token, true) + (current_number, true) } }; let file = io::BufWriter::new(reader.into_inner()); - let mut history = AccountHistory { file, token }; + let mut history = AccountHistory { file, number }; if should_save { if let Err(error) = history.save_to_disk().await { log::error!( @@ -84,20 +84,20 @@ impl AccountHistory { Ok(history) } - /// Gets the account token in the history - pub fn get(&self) -> Option<AccountToken> { - self.token.clone() + /// Gets the account number in the history + pub fn get(&self) -> Option<AccountNumber> { + self.number.clone() } - /// Replace the account token in the history - pub async fn set(&mut self, new_entry: AccountToken) -> Result<()> { - self.token = Some(new_entry); + /// Replace the account number in the history + pub async fn set(&mut self, new_entry: AccountNumber) -> Result<()> { + self.number = Some(new_entry); self.save_to_disk().await } /// Remove account history pub async fn clear(&mut self) -> Result<()> { - self.token = None; + self.number = None; self.save_to_disk().await } @@ -107,9 +107,9 @@ impl AccountHistory { .seek(io::SeekFrom::Start(0)) .await .map_err(Error::Write)?; - if let Some(ref token) = self.token { + if let Some(ref number) = self.number { self.file - .write_all(token.as_bytes()) + .write_all(number.as_bytes()) .await .map_err(Error::Write)?; } diff --git a/mullvad-daemon/src/device/mod.rs b/mullvad-daemon/src/device/mod.rs index 16a5a37460..829b3f2060 100644 --- a/mullvad-daemon/src/device/mod.rs +++ b/mullvad-daemon/src/device/mod.rs @@ -8,7 +8,7 @@ use mullvad_api::rest; #[cfg(target_os = "android")] use mullvad_types::account::{PlayPurchase, PlayPurchasePaymentToken}; use mullvad_types::{ - account::{AccountToken, VoucherSubmission}, + account::{AccountNumber, VoucherSubmission}, device::{ AccountAndDevice, Device, DeviceEvent, DeviceEventCause, DeviceId, DeviceName, DeviceState, }, @@ -154,17 +154,18 @@ impl From<PrivateDeviceState> for DeviceState { } } -/// Same as [PrivateDevice] but also contains the associated account token. +/// Same as [PrivateDevice] but also contains the associated account number. #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, PartialEq, Eq)] pub struct PrivateAccountAndDevice { - pub account_token: AccountToken, + #[serde(alias = "account_token")] + pub account_number: AccountNumber, pub device: PrivateDevice, } impl From<PrivateAccountAndDevice> for AccountAndDevice { fn from(config: PrivateAccountAndDevice) -> Self { AccountAndDevice { - account_token: config.account_token, + account_number: config.account_number, device: Device::from(config.device), } } @@ -297,7 +298,7 @@ impl Error { type ResponseTx<T> = oneshot::Sender<Result<T, Error>>; enum AccountManagerCommand { - Login(AccountToken, ResponseTx<()>), + Login(AccountNumber, ResponseTx<()>), Logout(ResponseTx<()>), SetData(PrivateAccountAndDevice, ResponseTx<()>), GetData(ResponseTx<PrivateDeviceState>), @@ -322,8 +323,8 @@ pub(crate) struct AccountManagerHandle { } impl AccountManagerHandle { - pub async fn login(&self, token: AccountToken) -> Result<(), Error> { - self.send_command(|tx| AccountManagerCommand::Login(token, tx)) + pub async fn login(&self, number: AccountNumber) -> Result<(), Error> { + self.send_command(|tx| AccountManagerCommand::Login(number, tx)) .await } @@ -424,10 +425,10 @@ impl AccountManager { listener_tx: impl Sender<AccountEvent> + Send + 'static, ) -> Result<(AccountManagerHandle, PrivateDeviceState), Error> { let (cacher, data) = DeviceCacher::new(settings_dir).await?; - let token = data.device().map(|state| state.account_token.clone()); + let number = data.device().map(|state| state.account_number.clone()); let api_availability = rest_handle.availability.clone(); let account_service = - service::spawn_account_service(rest_handle.clone(), token, api_availability.clone()); + service::spawn_account_service(rest_handle.clone(), number, api_availability.clone()); let (cmd_tx, cmd_rx) = mpsc::unbounded(); @@ -477,9 +478,9 @@ impl AccountManager { shutdown_tx = Some(tx); break; } - Some(AccountManagerCommand::Login(token, tx)) => { + Some(AccountManagerCommand::Login(number, tx)) => { let job = self.device_service - .generate_for_account(token); + .generate_for_account(number); current_api_call.set_login(Box::pin(job), tx); } Some(AccountManagerCommand::Logout(tx)) => { @@ -599,9 +600,13 @@ impl AccountManager { let create_submission = move || { let old_config = self.data.device().ok_or(Error::NoDevice)?; - let account_token = old_config.account_token.clone(); + let account_number = old_config.account_number.clone(); let account_service = self.account_service.clone(); - Ok(async move { account_service.submit_voucher(account_token, voucher).await }) + Ok(async move { + account_service + .submit_voucher(account_number, voucher) + .await + }) }; match create_submission() { @@ -627,9 +632,9 @@ impl AccountManager { let init_play_purchase_api_call = move || { let old_config = self.data.device().ok_or(Error::NoDevice)?; - let account_token = old_config.account_token.clone(); + let account_number = old_config.account_number.clone(); let account_service = self.account_service.clone(); - Ok(async move { account_service.init_play_purchase(account_token).await }) + Ok(async move { account_service.init_play_purchase(account_number).await }) }; match init_play_purchase_api_call() { @@ -681,11 +686,11 @@ impl AccountManager { let play_purchase_verify_api_call = move || { let old_config = self.data.device().ok_or(Error::NoDevice)?; - let account_token = old_config.account_token.clone(); + let account_number = old_config.account_number.clone(); let account_service = self.account_service.clone(); Ok(async move { account_service - .verify_play_purchase(account_token, play_purchase) + .verify_play_purchase(account_number, play_purchase) .await }) }; @@ -847,10 +852,10 @@ impl AccountManager { if !self.rotation_requests.is_empty() || !self.validation_requests.is_empty() { if let Some(updated_config) = self.data.device() { let device_service = self.device_service.clone(); - let token = updated_config.account_token.clone(); + let number = updated_config.account_number.clone(); let device_id = updated_config.device.id.clone(); api_call.set_oneshot_rotation(Box::pin(async move { - device_service.rotate_key(token, device_id).await + device_service.rotate_key(number, device_id).await })); } } @@ -945,13 +950,13 @@ impl AccountManager { let key_rotation_timer = self.key_rotation_timer(config.device.wg_data.created); let device_service = self.device_service.clone(); - let account_token = config.account_token.clone(); + let account_number = config.account_number.clone(); let device_id = config.device.id.clone(); Some(async move { key_rotation_timer.await; device_service - .rotate_key_with_backoff(account_token, device_id) + .rotate_key_with_backoff(account_number, device_id) .await }) } @@ -1015,7 +1020,7 @@ impl AccountManager { async move { if let Err(error) = service - .remove_device_with_backoff(data.account_token, data.device.id) + .remove_device_with_backoff(data.account_number, data.device.id) .await { log::error!( @@ -1057,7 +1062,7 @@ impl AccountManager { let device_service = self.device_service.clone(); Ok(async move { device_service - .rotate_key(data.account_token, data.device.id) + .rotate_key(data.account_number, data.device.id) .await }) } @@ -1094,9 +1099,9 @@ impl AccountManager { old_config: &PrivateAccountAndDevice, ) -> impl Future<Output = Result<Device, Error>> { let device_service = self.device_service.clone(); - let account_token = old_config.account_token.clone(); + let account_number = old_config.account_number.clone(); let device_id = old_config.device.id.clone(); - async move { device_service.get(account_token, device_id).await } + async move { device_service.get(account_number, device_id).await } } fn validation_call(&self) -> Result<impl Future<Output = Result<Device, Error>>, Error> { @@ -1108,11 +1113,11 @@ impl AccountManager { &self, ) -> Result<impl Future<Output = Result<chrono::DateTime<Utc>, Error>>, Error> { let old_config = self.data.device().ok_or(Error::NoDevice)?; - let account_token = old_config.account_token.clone(); + let account_number = old_config.account_number.clone(); let account_service = self.account_service.clone(); Ok(async move { account_service - .get_data_2(account_token) + .get_data_2(account_number) .await .map(|data| data.expiry) }) diff --git a/mullvad-daemon/src/device/service.rs b/mullvad-daemon/src/device/service.rs index 093dd14f67..b5d8fcd3b3 100644 --- a/mullvad-daemon/src/device/service.rs +++ b/mullvad-daemon/src/device/service.rs @@ -5,7 +5,7 @@ use futures::future::{abortable, AbortHandle}; #[cfg(target_os = "android")] use mullvad_types::account::{PlayPurchase, PlayPurchasePaymentToken}; use mullvad_types::{ - account::{AccountData, AccountToken, VoucherSubmission}, + account::{AccountData, AccountNumber, VoucherSubmission}, device::{Device, DeviceId}, wireguard::WireguardData, }; @@ -40,20 +40,20 @@ impl DeviceService { } } - /// Generate a new device for a given token + /// Generate a new device for a given account number pub fn generate_for_account( &self, - account_token: AccountToken, + account_number: AccountNumber, ) -> impl Future<Output = Result<PrivateAccountAndDevice, Error>> + Send { let private_key = PrivateKey::new_from_random(); let pubkey = private_key.public_key(); let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); - let token_copy = account_token.clone(); + let number_copy = account_number.clone(); async move { let (device, addresses) = retry_future( - move || proxy.create(token_copy.clone(), pubkey.clone()), + move || proxy.create(number_copy.clone(), pubkey.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -61,7 +61,7 @@ impl DeviceService { .map_err(map_rest_error)?; Ok(PrivateAccountAndDevice { - account_token, + account_number, device: PrivateDevice::try_from_device( device, WireguardData { @@ -76,16 +76,16 @@ impl DeviceService { pub async fn generate_for_account_with_backoff( &self, - account_token: AccountToken, + account_number: AccountNumber, ) -> Result<PrivateAccountAndDevice, Error> { let private_key = PrivateKey::new_from_random(); let pubkey = private_key.public_key(); let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); - let token_copy = account_token.clone(); + let number_copy = account_number.clone(); let (device, addresses) = retry_future( - move || api_handle.when_online(proxy.create(token_copy.clone(), pubkey.clone())), + move || api_handle.when_online(proxy.create(number_copy.clone(), pubkey.clone())), should_retry_backoff, RETRY_BACKOFF_STRATEGY, ) @@ -93,7 +93,7 @@ impl DeviceService { .map_err(map_rest_error)?; Ok(PrivateAccountAndDevice { - account_token, + account_number, device: PrivateDevice::try_from_device( device, WireguardData { @@ -107,23 +107,23 @@ impl DeviceService { pub async fn remove_device( &self, - account_token: AccountToken, + account_number: AccountNumber, device_id: DeviceId, ) -> Result<Vec<Device>, Error> { - self.remove_device_inner(account_token.clone(), device_id) + self.remove_device_inner(account_number.clone(), device_id) .await?; - self.list_devices(account_token).await + self.list_devices(account_number).await } async fn remove_device_inner( &self, - token: AccountToken, + number: AccountNumber, device: DeviceId, ) -> Result<(), Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future( - move || proxy.remove(token.clone(), device.clone()), + move || proxy.remove(number.clone(), device.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -134,7 +134,7 @@ impl DeviceService { pub async fn remove_device_with_backoff( &self, - token: AccountToken, + number: AccountNumber, device: DeviceId, ) -> Result<(), Error> { let proxy = self.proxy.clone(); @@ -142,7 +142,7 @@ impl DeviceService { retry_future( // NOTE: Not honoring "paused" state, because the account may have no time on it. - move || api_handle.when_online(proxy.remove(token.clone(), device.clone())), + move || api_handle.when_online(proxy.remove(number.clone(), device.clone())), should_retry_backoff, // Not setting a maximum interval RETRY_BACKOFF_STRATEGY.clone().max_delay(None), @@ -155,7 +155,7 @@ impl DeviceService { pub async fn rotate_key( &self, - token: AccountToken, + number: AccountNumber, device: DeviceId, ) -> Result<WireguardData, Error> { let private_key = PrivateKey::new_from_random(); @@ -164,7 +164,7 @@ impl DeviceService { let api_handle = self.api_availability.clone(); let pubkey = private_key.public_key(); let addresses = retry_future( - move || proxy.replace_wg_key(token.clone(), device.clone(), pubkey.clone()), + move || proxy.replace_wg_key(number.clone(), device.clone(), pubkey.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -180,7 +180,7 @@ impl DeviceService { pub async fn rotate_key_with_backoff( &self, - token: AccountToken, + number: AccountNumber, device: DeviceId, ) -> Result<WireguardData, Error> { let private_key = PrivateKey::new_from_random(); @@ -194,7 +194,7 @@ impl DeviceService { let addresses = retry_future( move || { api_handle.when_bg_resumes(proxy.replace_wg_key( - token.clone(), + number.clone(), device.clone(), pubkey.clone(), )) @@ -212,11 +212,11 @@ impl DeviceService { }) } - pub async fn list_devices(&self, token: AccountToken) -> Result<Vec<Device>, Error> { + pub async fn list_devices(&self, number: AccountNumber) -> Result<Vec<Device>, Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future( - move || proxy.list(token.clone()), + move || proxy.list(number.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -226,13 +226,13 @@ impl DeviceService { pub async fn list_devices_with_backoff( &self, - token: AccountToken, + number: AccountNumber, ) -> Result<Vec<Device>, Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future( - move || api_handle.when_online(proxy.list(token.clone())), + move || api_handle.when_online(proxy.list(number.clone())), should_retry_backoff, RETRY_BACKOFF_STRATEGY, ) @@ -240,11 +240,11 @@ impl DeviceService { .map_err(map_rest_error) } - pub async fn get(&self, token: AccountToken, device: DeviceId) -> Result<Device, Error> { + pub async fn get(&self, number: AccountNumber, device: DeviceId) -> Result<Device, Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future( - move || proxy.get(token.clone(), device.clone()), + move || proxy.get(number.clone(), device.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -261,7 +261,7 @@ pub struct AccountService { } impl AccountService { - pub fn create_account(&self) -> impl Future<Output = Result<AccountToken, rest::Error>> { + pub fn create_account(&self) -> impl Future<Output = Result<AccountNumber, rest::Error>> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); retry_future( @@ -273,7 +273,7 @@ impl AccountService { pub fn get_www_auth_token( &self, - account: AccountToken, + account: AccountNumber, ) -> impl Future<Output = Result<String, rest::Error>> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); @@ -284,11 +284,11 @@ impl AccountService { ) } - pub async fn get_data(&self, token: AccountToken) -> Result<AccountData, rest::Error> { + pub async fn get_data(&self, number: AccountNumber) -> Result<AccountData, rest::Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); let result = retry_future( - move || proxy.get_data(token.clone()), + move || proxy.get_data(number.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -299,19 +299,19 @@ impl AccountService { result } - pub async fn get_data_2(&self, token: AccountToken) -> Result<AccountData, Error> { - self.get_data(token).await.map_err(map_rest_error) + pub async fn get_data_2(&self, number: AccountNumber) -> Result<AccountData, Error> { + self.get_data(number).await.map_err(map_rest_error) } pub async fn submit_voucher( &self, - account_token: AccountToken, + account_number: AccountNumber, voucher: String, ) -> Result<VoucherSubmission, Error> { let proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); let result = retry_future( - move || proxy.submit_voucher(account_token.clone(), voucher.clone()), + move || proxy.submit_voucher(account_number.clone(), voucher.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -326,12 +326,12 @@ impl AccountService { #[cfg(target_os = "android")] pub async fn init_play_purchase( &self, - account_token: AccountToken, + account_number: AccountNumber, ) -> Result<PlayPurchasePaymentToken, Error> { let mut proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); let result = retry_future( - move || proxy.init_play_purchase(account_token.clone()), + move || proxy.init_play_purchase(account_number.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -346,13 +346,13 @@ impl AccountService { #[cfg(target_os = "android")] pub async fn verify_play_purchase( &self, - account_token: AccountToken, + account_number: AccountNumber, play_purchase: PlayPurchase, ) -> Result<(), Error> { let mut proxy = self.proxy.clone(); let api_handle = self.api_availability.clone(); let result = retry_future( - move || proxy.verify_play_purchase(account_token.clone(), play_purchase.clone()), + move || proxy.verify_play_purchase(account_number.clone(), play_purchase.clone()), move |result| should_retry(result, &api_handle), RETRY_ACTION_STRATEGY, ) @@ -367,7 +367,7 @@ impl AccountService { pub fn spawn_account_service( api_handle: MullvadRestHandle, - token: Option<String>, + number: Option<AccountNumber>, api_availability: ApiAvailability, ) -> AccountService { let accounts_proxy = AccountsProxy::new(api_handle); @@ -377,15 +377,13 @@ pub fn spawn_account_service( let accounts_proxy_copy = accounts_proxy.clone(); let (future, initial_check_abort_handle) = abortable(async move { - let token = if let Some(token) = token { - token - } else { + let Some(number) = number else { api_availability.pause_background(); return; }; let future_generator = move || { - let expiry_fut = api_availability.when_online(accounts_proxy.get_data(token.clone())); + let expiry_fut = api_availability.when_online(accounts_proxy.get_data(number.clone())); let api_availability_copy = api_availability.clone(); async move { handle_account_data_result(&expiry_fut.await, &api_availability_copy) } }; diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index c2e38f11b6..94df78682b 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -49,7 +49,7 @@ use mullvad_types::settings::SplitApp; use mullvad_types::wireguard::DaitaSettings; use mullvad_types::{ access_method::{AccessMethod, AccessMethodSetting}, - account::{AccountData, AccountToken, VoucherSubmission}, + account::{AccountData, AccountNumber, VoucherSubmission}, auth_failed::AuthFailed, custom_list::CustomList, device::{Device, DeviceEvent, DeviceEventCause, DeviceId, DeviceState, RemoveDeviceEvent}, @@ -159,11 +159,11 @@ pub enum Error { #[error("An account is already set")] AlreadyLoggedIn, - #[error("No account token is set")] - NoAccountToken, + #[error("No account number is set")] + NoAccountNumber, #[error("No account history available for the token")] - NoAccountTokenHistory, + NoAccountNumberHistory, #[error("Settings error")] SettingsError(#[source] settings::Error), @@ -215,14 +215,14 @@ pub enum DaemonCommand { /// Request the metadata for an account. GetAccountData( ResponseTx<AccountData, mullvad_api::rest::Error>, - AccountToken, + AccountNumber, ), /// Request www auth token for an account GetWwwAuthToken(ResponseTx<String, Error>), /// Submit voucher to add time to the current account. Returns time added in seconds SubmitVoucher(ResponseTx<VoucherSubmission, Error>, String), /// Request account history - GetAccountHistory(oneshot::Sender<Option<AccountToken>>), + GetAccountHistory(oneshot::Sender<Option<AccountNumber>>), /// Remove the last used account, if there is one ClearAccountHistory(ResponseTx<(), Error>), /// Get the list of countries and cities where there are relays. @@ -231,17 +231,17 @@ pub enum DaemonCommand { /// updated. UpdateRelayLocations, /// Log in with a given account and create a new device. - LoginAccount(ResponseTx<(), Error>, AccountToken), + LoginAccount(ResponseTx<(), Error>, AccountNumber), /// Log out of the current account and remove the device, if they exist. LogoutAccount(ResponseTx<(), Error>), /// Return the current device configuration. GetDevice(ResponseTx<DeviceState, Error>), /// Update/check the current device, if there is one. UpdateDevice(ResponseTx<(), Error>), - /// Return all the devices for a given account token. - ListDevices(ResponseTx<Vec<Device>, Error>, AccountToken), + /// Return all the devices for a given account number. + ListDevices(ResponseTx<Vec<Device>, Error>, AccountNumber), /// Remove device from a given account. - RemoveDevice(ResponseTx<(), Error>, AccountToken, DeviceId), + RemoveDevice(ResponseTx<(), Error>, AccountNumber, DeviceId), /// Place constraints on the type of tunnel and relay SetRelaySettings(ResponseTx<(), settings::Error>, RelaySettings), /// Set the allow LAN setting. @@ -705,7 +705,7 @@ impl Daemon { let account_history = account_history::AccountHistory::new( &settings_dir, - data.device().map(|device| device.account_token.clone()), + data.device().map(|device| device.account_number.clone()), ) .await .map_err(Error::LoadAccountHistory)?; @@ -1230,18 +1230,18 @@ impl Daemon { Reconnect(tx) => self.on_reconnect(tx), GetState(tx) => self.on_get_state(tx), CreateNewAccount(tx) => self.on_create_new_account(tx), - GetAccountData(tx, account_token) => self.on_get_account_data(tx, account_token), + GetAccountData(tx, account_number) => self.on_get_account_data(tx, account_number), GetWwwAuthToken(tx) => self.on_get_www_auth_token(tx).await, SubmitVoucher(tx, voucher) => self.on_submit_voucher(tx, voucher), GetRelayLocations(tx) => self.on_get_relay_locations(tx), UpdateRelayLocations => self.on_update_relay_locations().await, - LoginAccount(tx, account_token) => self.on_login_account(tx, account_token), + LoginAccount(tx, account_number) => self.on_login_account(tx, account_number), LogoutAccount(tx) => self.on_logout_account(tx), GetDevice(tx) => self.on_get_device(tx), UpdateDevice(tx) => self.on_update_device(tx), - ListDevices(tx, account_token) => self.on_list_devices(tx, account_token), - RemoveDevice(tx, account_token, device_id) => { - self.on_remove_device(tx, account_token, device_id) + ListDevices(tx, account_number) => self.on_list_devices(tx, account_number), + RemoveDevice(tx, account_number, device_id) => { + self.on_remove_device(tx, account_number, device_id) } GetAccountHistory(tx) => self.on_get_account_history(tx), ClearAccountHistory(tx) => self.on_clear_account_history(tx).await, @@ -1355,19 +1355,23 @@ impl Daemon { async fn handle_device_event(&mut self, event: AccountEvent) { match &event { AccountEvent::Device(PrivateDeviceEvent::Login(device)) => { - if let Err(error) = self.account_history.set(device.account_token.clone()).await { + if let Err(error) = self + .account_history + .set(device.account_number.clone()) + .await + { log::error!( "{}", error.display_chain_with_msg("Failed to update account history") ); } if *self.target_state == TargetState::Secured { - log::debug!("Initiating tunnel restart because the account token changed"); + log::debug!("Initiating tunnel restart because the account number changed"); self.reconnect_tunnel(); } } AccountEvent::Device(PrivateDeviceEvent::Logout) => { - log::info!("Disconnecting because account token was cleared"); + log::info!("Disconnecting because account number was cleared"); self.set_target_state(TargetState::Unsecured).await; } AccountEvent::Device(PrivateDeviceEvent::Revoked) => { @@ -1564,11 +1568,11 @@ impl Daemon { fn on_get_account_data( &mut self, tx: ResponseTx<AccountData, mullvad_api::rest::Error>, - account_token: AccountToken, + account_number: AccountNumber, ) { let account = self.account_manager.account_service.clone(); tokio::spawn(async move { - let result = account.get_data(account_token).await; + let result = account.get_data(account_number).await; Self::oneshot_send(tx, result, "account data"); }); } @@ -1578,7 +1582,7 @@ impl Daemon { let future = self .account_manager .account_service - .get_www_auth_token(device.account_token); + .get_www_auth_token(device.account_number); tokio::spawn(async { Self::oneshot_send( tx, @@ -1589,7 +1593,7 @@ impl Daemon { } else { Self::oneshot_send( tx, - Err(Error::NoAccountToken), + Err(Error::NoAccountNumber), "get_www_auth_token response", ); } @@ -1617,13 +1621,13 @@ impl Daemon { self.relay_list_updater.update().await; } - fn on_login_account(&mut self, tx: ResponseTx<(), Error>, account_token: String) { + fn on_login_account(&mut self, tx: ResponseTx<(), Error>, account_number: String) { let account_manager = self.account_manager.clone(); let availability = self.api_runtime.availability_handle(); tokio::spawn(async move { let result = async { account_manager - .login(account_token) + .login(account_number) .await .map_err(|error| { log::error!("{}", error.display_chain_with_msg("Login failed")); @@ -1659,7 +1663,7 @@ impl Daemon { account_manager .data() .await - .map_err(|_| Error::NoAccountToken) + .map_err(|_| Error::NoAccountNumber) .map(DeviceState::from), "get_device response", ); @@ -1681,7 +1685,7 @@ impl Daemon { }); } - fn on_list_devices(&self, tx: ResponseTx<Vec<Device>, Error>, token: AccountToken) { + fn on_list_devices(&self, tx: ResponseTx<Vec<Device>, Error>, token: AccountNumber) { let service = self.account_manager.device_service.clone(); tokio::spawn(async move { Self::oneshot_send( @@ -1698,7 +1702,7 @@ impl Daemon { fn on_remove_device( &mut self, tx: ResponseTx<(), Error>, - account_token: AccountToken, + account_number: AccountNumber, device_id: DeviceId, ) { let device_service = self.account_manager.device_service.clone(); @@ -1706,13 +1710,13 @@ impl Daemon { tokio::spawn(async move { let result = device_service - .remove_device(account_token.clone(), device_id) + .remove_device(account_number.clone(), device_id) .await .map(move |new_devices| { // FIXME: We should be able to get away with only returning the removed ID, // and not have to request the list from the API. notifier.notify_remove_device_event(RemoveDeviceEvent { - account_token, + account_number, new_devices, }); }); @@ -1724,7 +1728,7 @@ impl Daemon { }); } - fn on_get_account_history(&mut self, tx: oneshot::Sender<Option<AccountToken>>) { + fn on_get_account_history(&mut self, tx: oneshot::Sender<Option<AccountNumber>>) { Self::oneshot_send( tx, self.account_history.get(), @@ -2596,7 +2600,7 @@ impl Daemon { if let Ok(Some(config)) = self.account_manager.data().await.map(|s| s.into_device()) { Ok(Some(config.device.wg_data.get_public_key())) } else { - Err(Error::NoAccountToken) + Err(Error::NoAccountNumber) }; Self::oneshot_send(tx, result, "get_wireguard_key response"); } diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 2d2c81ff89..0d73354d93 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -9,7 +9,7 @@ use mullvad_management_interface::{ Code, Request, Response, ServerJoinHandle, Status, }; use mullvad_types::{ - account::AccountToken, + account::AccountNumber, relay_constraints::{ BridgeSettings, BridgeState, ObfuscationSettings, RelayOverride, RelaySettings, }, @@ -434,11 +434,11 @@ impl ManagementService for ManagementServiceImpl { .map_err(map_daemon_error) } - async fn login_account(&self, request: Request<AccountToken>) -> ServiceResult<()> { + async fn login_account(&self, request: Request<AccountNumber>) -> ServiceResult<()> { log::debug!("login_account"); - let account_token = request.into_inner(); + let account_number = request.into_inner(); let (tx, rx) = oneshot::channel(); - self.send_command_to_daemon(DaemonCommand::LoginAccount(tx, account_token))?; + self.send_command_to_daemon(DaemonCommand::LoginAccount(tx, account_number))?; self.wait_for_result(rx) .await? .map(Response::new) @@ -457,12 +457,12 @@ impl ManagementService for ManagementServiceImpl { async fn get_account_data( &self, - request: Request<AccountToken>, + request: Request<AccountNumber>, ) -> ServiceResult<types::AccountData> { log::debug!("get_account_data"); - let account_token = request.into_inner(); + let account_number = request.into_inner(); let (tx, rx) = oneshot::channel(); - self.send_command_to_daemon(DaemonCommand::GetAccountData(tx, account_token))?; + self.send_command_to_daemon(DaemonCommand::GetAccountData(tx, account_number))?; let result = self.wait_for_result(rx).await?; result .map(|account_data| Response::new(types::AccountData::from(account_data))) @@ -481,7 +481,7 @@ impl ManagementService for ManagementServiceImpl { self.send_command_to_daemon(DaemonCommand::GetAccountHistory(tx))?; self.wait_for_result(rx) .await - .map(|history| Response::new(types::AccountHistory { token: history })) + .map(|history| Response::new(types::AccountHistory { number: history })) } async fn clear_account_history(&self, _: Request<()>) -> ServiceResult<()> { @@ -543,7 +543,7 @@ impl ManagementService for ManagementServiceImpl { async fn list_devices( &self, - request: Request<AccountToken>, + request: Request<AccountNumber>, ) -> ServiceResult<types::DeviceList> { log::debug!("list_devices"); let (tx, rx) = oneshot::channel(); @@ -559,7 +559,7 @@ impl ManagementService for ManagementServiceImpl { let removal = request.into_inner(); self.send_command_to_daemon(DaemonCommand::RemoveDevice( tx, - removal.account_token, + removal.account_number, removal.device_id, ))?; self.wait_for_result(rx).await?.map_err(map_daemon_error)?; @@ -1294,7 +1294,7 @@ fn map_daemon_error(error: crate::Error) -> Status { #[cfg(any(target_os = "windows", target_os = "macos"))] DaemonError::SplitTunnelError(error) => map_split_tunnel_error(error), DaemonError::AccountHistory(error) => map_account_history_error(error), - DaemonError::NoAccountToken | DaemonError::NoAccountTokenHistory => { + DaemonError::NoAccountNumber | DaemonError::NoAccountNumberHistory => { Status::unauthenticated(error.to_string()) } DaemonError::VersionCheckError(error) => map_version_check_error(error), diff --git a/mullvad-daemon/src/migrations/account_history.rs b/mullvad-daemon/src/migrations/account_history.rs index e367ffdce4..eeaf6e67d7 100644 --- a/mullvad-daemon/src/migrations/account_history.rs +++ b/mullvad-daemon/src/migrations/account_history.rs @@ -1,5 +1,5 @@ use super::{Error, Result}; -use mullvad_types::account::AccountToken; +use mullvad_types::account::AccountNumber; use regex::Regex; use serde::Deserialize; use std::{path::Path, sync::LazyLock}; @@ -67,7 +67,7 @@ pub async fn migrate_formats(settings_dir: &Path, settings: &mut serde_json::Val fn migrate_formats_inner( account_bytes: &[u8], settings: &mut serde_json::Value, -) -> Result<Option<AccountToken>> { +) -> Result<Option<AccountNumber>> { if let Ok(result) = try_format_v2(account_bytes) { if let Some((token, wg_data)) = result { settings["wireguard"] = wg_data; @@ -89,7 +89,7 @@ fn is_format_v3(bytes: &[u8]) -> bool { } } -async fn write_format_v3(mut file: File, token: Option<AccountToken>) -> Result<()> { +async fn write_format_v3(mut file: File, token: Option<AccountNumber>) -> Result<()> { file.set_len(0).await.map_err(Error::WriteHistory)?; file.seek(io::SeekFrom::Start(0)) .await @@ -102,10 +102,10 @@ async fn write_format_v3(mut file: File, token: Option<AccountToken>) -> Result< file.sync_all().await.map_err(Error::WriteHistory) } -fn try_format_v2(bytes: &[u8]) -> Result<Option<(AccountToken, serde_json::Value)>> { +fn try_format_v2(bytes: &[u8]) -> Result<Option<(AccountNumber, serde_json::Value)>> { #[derive(Deserialize, Clone)] pub struct AccountEntry { - pub account: AccountToken, + pub account: AccountNumber, pub wireguard: serde_json::Value, } Ok(serde_json::from_slice::<'_, Vec<AccountEntry>>(bytes) @@ -115,10 +115,10 @@ fn try_format_v2(bytes: &[u8]) -> Result<Option<(AccountToken, serde_json::Value .map(|entry| (entry.account, entry.wireguard))) } -fn try_format_v1(bytes: &[u8]) -> Result<Option<AccountToken>> { +fn try_format_v1(bytes: &[u8]) -> Result<Option<AccountNumber>> { #[derive(Deserialize)] struct OldFormat { - accounts: Vec<AccountToken>, + accounts: Vec<AccountNumber>, } Ok(serde_json::from_slice::<'_, OldFormat>(bytes) .map_err(|_error| Error::ParseHistory)? diff --git a/mullvad-daemon/src/migrations/device.rs b/mullvad-daemon/src/migrations/device.rs index e2cc25eacb..d5c05c9353 100644 --- a/mullvad-daemon/src/migrations/device.rs +++ b/mullvad-daemon/src/migrations/device.rs @@ -1,6 +1,6 @@ -//! Generates a `device.json` from a WireGuard key and account token by matching them against +//! Generates a `device.json` from a WireGuard key and account number by matching them against //! devices returned by the API and sending the `DeviceMigrationEvent` event to the daemon. -//! The account token and private key may be lost if it fails, but this should not be not +//! The account number and private key may be lost if it fails, but this should not be not //! critical since the account history also contains the token. //! //! This module is allowed to import a number of types, unlike other migration modules, as it @@ -11,7 +11,7 @@ use crate::{ device::{self, DeviceService, PrivateAccountAndDevice, PrivateDevice}, DaemonEventSender, InternalDaemonEvent, }; -use mullvad_types::{account::AccountToken, wireguard::WireguardData}; +use mullvad_types::{account::AccountNumber, wireguard::WireguardData}; use std::time::Duration; use talpid_core::mpsc::Sender; use talpid_types::ErrorExt; @@ -41,13 +41,13 @@ pub(crate) fn generate_device( let api_handle = rest_handle.availability.clone(); let service = DeviceService::new(rest_handle, api_handle); let result = match (migration_data.token, wg_data) { - (token, Some(wg_data)) => { + (account_number, Some(wg_data)) => { log::info!("Creating a new device cache from previous settings"); - cache_from_wireguard_key(service, token, wg_data).await + cache_from_wireguard_key(service, account_number, wg_data).await } - (token, None) => { + (account_number, None) => { log::info!("Generating a new device for the account"); - cache_from_account(service, token).await + cache_from_account(service, account_number).await } }; let _ = daemon_tx.send(InternalDaemonEvent::DeviceMigrationEvent(result)); @@ -57,12 +57,12 @@ pub(crate) fn generate_device( async fn cache_from_wireguard_key( service: DeviceService, - account_token: AccountToken, + account_number: AccountNumber, wg_data: WireguardData, ) -> Result<PrivateAccountAndDevice, device::Error> { let devices = timeout( TIMEOUT, - service.list_devices_with_backoff(account_token.clone()), + service.list_devices_with_backoff(account_number.clone()), ) .await .map_err(|_error| { @@ -79,7 +79,7 @@ async fn cache_from_wireguard_key( for device in devices.into_iter() { if device.pubkey == wg_data.private_key.public_key() { return Ok(PrivateAccountAndDevice { - account_token, + account_number, device: PrivateDevice::try_from_device(device, wg_data)?, }); } @@ -90,11 +90,11 @@ async fn cache_from_wireguard_key( async fn cache_from_account( service: DeviceService, - account_token: AccountToken, + account_number: AccountNumber, ) -> Result<PrivateAccountAndDevice, device::Error> { timeout( TIMEOUT, - service.generate_for_account_with_backoff(account_token), + service.generate_for_account_with_backoff(account_number), ) .await .map_err(|_error| { diff --git a/mullvad-daemon/src/migrations/v5.rs b/mullvad-daemon/src/migrations/v5.rs index e458bb1a1d..178832116a 100644 --- a/mullvad-daemon/src/migrations/v5.rs +++ b/mullvad-daemon/src/migrations/v5.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; // Section for vendoring types and values that // this settings version depend on. See `mod.rs`. -pub type AccountToken = String; +pub type AccountNumber = String; /// Representation of a transport protocol, either UDP or TCP. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -50,7 +50,7 @@ pub enum SelectedObfuscation { // ====================================================== pub struct MigrationData { - pub token: AccountToken, + pub token: AccountNumber, pub wg_data: Option<serde_json::Value>, } @@ -120,7 +120,7 @@ pub fn migrate(settings: &mut serde_json::Value) -> Result<Option<MigrationData> let migration_data = if let Some(token) = settings.get("account_token").filter(|t| !t.is_null()) { - let token: AccountToken = + let token: AccountNumber = serde_json::from_value(token.clone()).map_err(|_| Error::InvalidSettingsContent)?; let migration_data = if let Some(wg_data) = settings.get("wireguard").filter(|wg| !wg.is_null()) { diff --git a/mullvad-daemon/src/settings/mod.rs b/mullvad-daemon/src/settings/mod.rs index 8a42ec6204..6a0f850e3d 100644 --- a/mullvad-daemon/src/settings/mod.rs +++ b/mullvad-daemon/src/settings/mod.rs @@ -536,7 +536,7 @@ mod test { #[test] fn test_deserialization() { let settings = br#"{ - "account_token": "0000000000000000", + "account_number": "0000000000000000", "relay_settings": { "normal": { "location": { diff --git a/mullvad-daemon/src/tunnel.rs b/mullvad-daemon/src/tunnel.rs index 73bda59635..a9c5966285 100644 --- a/mullvad-daemon/src/tunnel.rs +++ b/mullvad-daemon/src/tunnel.rs @@ -238,7 +238,7 @@ impl InnerParametersGenerator { bridge_settings: Option<CustomProxy>, ) -> TunnelParameters { openvpn::TunnelParameters { - config: openvpn::ConnectionConfig::new(endpoint, data.account_token, "-".to_string()), + config: openvpn::ConnectionConfig::new(endpoint, data.account_number, "-".to_string()), options: self.tunnel_options.openvpn.clone(), generic_options: self.tunnel_options.generic.clone(), proxy: bridge_settings, diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index eb84f6a021..4e04bcf3c1 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -136,7 +136,7 @@ message AccountData { google.protobuf.Timestamp expiry = 2; } -message AccountHistory { google.protobuf.StringValue token = 1; } +message AccountHistory { google.protobuf.StringValue number = 1; } message VoucherSubmission { uint64 seconds_added = 1; @@ -713,7 +713,7 @@ message PortRange { } message AccountAndDevice { - string account_token = 1; + string account_number = 1; Device device = 2; } @@ -728,7 +728,7 @@ message Device { message DeviceList { repeated Device devices = 1; } message DeviceRemoval { - string account_token = 1; + string account_number = 1; string device_id = 2; } @@ -755,7 +755,7 @@ message DeviceEvent { } message RemoveDeviceEvent { - string account_token = 1; + string account_number = 1; repeated Device new_device_list = 2; } diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs index f782d3ab32..73bff561a4 100644 --- a/mullvad-management-interface/src/client.rs +++ b/mullvad-management-interface/src/client.rs @@ -17,7 +17,7 @@ use mullvad_types::{ #[cfg(not(target_os = "android"))] use mullvad_types::{ access_method::{self, AccessMethod}, - account::{AccountData, AccountToken, VoucherSubmission}, + account::{AccountData, AccountNumber, VoucherSubmission}, custom_list::{CustomList, Id}, device::{Device, DeviceId, DeviceState}, features::FeatureIndicators, @@ -426,7 +426,7 @@ impl MullvadProxyClient { Ok(()) } - pub async fn create_new_account(&mut self) -> Result<AccountToken> { + pub async fn create_new_account(&mut self) -> Result<AccountNumber> { Ok(self .0 .create_new_account(()) @@ -435,7 +435,7 @@ impl MullvadProxyClient { .into_inner()) } - pub async fn login_account(&mut self, account: AccountToken) -> Result<()> { + pub async fn login_account(&mut self, account: AccountNumber) -> Result<()> { self.0 .login_account(account) .await @@ -448,7 +448,7 @@ impl MullvadProxyClient { Ok(()) } - pub async fn get_account_data(&mut self, account: AccountToken) -> Result<AccountData> { + pub async fn get_account_data(&mut self, account: AccountNumber) -> Result<AccountData> { let data = self .0 .get_account_data(account) @@ -458,14 +458,14 @@ impl MullvadProxyClient { AccountData::try_from(data).map_err(Error::InvalidResponse) } - pub async fn get_account_history(&mut self) -> Result<Option<AccountToken>> { + pub async fn get_account_history(&mut self) -> Result<Option<AccountNumber>> { let history = self .0 .get_account_history(()) .await .map_err(Error::Rpc)? .into_inner(); - Ok(history.token) + Ok(history.number) } pub async fn clear_account_history(&mut self) -> Result<()> { @@ -504,7 +504,7 @@ impl MullvadProxyClient { Ok(()) } - pub async fn list_devices(&mut self, account: AccountToken) -> Result<Vec<Device>> { + pub async fn list_devices(&mut self, account: AccountNumber) -> Result<Vec<Device>> { let list = self .0 .list_devices(account) @@ -519,12 +519,12 @@ impl MullvadProxyClient { pub async fn remove_device( &mut self, - account: AccountToken, + account: AccountNumber, device_id: DeviceId, ) -> Result<()> { self.0 .remove_device(types::DeviceRemoval { - account_token: account, + account_number: account, device_id, }) .await diff --git a/mullvad-management-interface/src/types/conversions/device.rs b/mullvad-management-interface/src/types/conversions/device.rs index fd9f05ccbc..2aef1380a7 100644 --- a/mullvad-management-interface/src/types/conversions/device.rs +++ b/mullvad-management-interface/src/types/conversions/device.rs @@ -61,7 +61,7 @@ impl TryFrom<proto::DeviceState> for mullvad_types::device::DeviceState { Ok(mullvad_types::device::DeviceState::LoggedIn( mullvad_types::device::AccountAndDevice { - account_token: account.account_token, + account_number: account.account_number, device: mullvad_types::device::Device::try_from(device)?, }, )) @@ -79,7 +79,7 @@ impl From<mullvad_types::device::DeviceState> for proto::DeviceState { proto::DeviceState { state: proto::device_state::State::from(&state) as i32, device: state.logged_in().map(|client| proto::AccountAndDevice { - account_token: client.account_token, + account_number: client.account_number, device: Some(proto::Device::from(client.device)), }), } @@ -151,7 +151,7 @@ impl From<proto::device_event::Cause> for mullvad_types::device::DeviceEventCaus impl From<mullvad_types::device::RemoveDeviceEvent> for proto::RemoveDeviceEvent { fn from(event: mullvad_types::device::RemoveDeviceEvent) -> Self { proto::RemoveDeviceEvent { - account_token: event.account_token, + account_number: event.account_number, new_device_list: event .new_devices .into_iter() @@ -171,7 +171,7 @@ impl TryFrom<proto::RemoveDeviceEvent> for mullvad_types::device::RemoveDeviceEv .map(mullvad_types::device::Device::try_from) .collect::<Result<Vec<_>, FromProtobufTypeError>>()?; Ok(mullvad_types::device::RemoveDeviceEvent { - account_token: event.account_token, + account_number: event.account_number, new_devices, }) } @@ -180,7 +180,7 @@ impl TryFrom<proto::RemoveDeviceEvent> for mullvad_types::device::RemoveDeviceEv impl From<mullvad_types::device::AccountAndDevice> for proto::AccountAndDevice { fn from(device: mullvad_types::device::AccountAndDevice) -> Self { proto::AccountAndDevice { - account_token: device.account_token, + account_number: device.account_number, device: Some(proto::Device::from(device.device)), } } diff --git a/mullvad-setup/src/main.rs b/mullvad-setup/src/main.rs index f937f04e7e..d3dfd6de8a 100644 --- a/mullvad-setup/src/main.rs +++ b/mullvad-setup/src/main.rs @@ -162,7 +162,7 @@ async fn remove_device() -> Result<(), Error> { ); let device_removal = retry_future( - move || proxy.remove(device.account_token.clone(), device.device.id.clone()), + move || proxy.remove(device.account_number.clone(), device.device.id.clone()), move |result| match result { Err(error) => error.is_network_error(), _ => false, diff --git a/mullvad-types/src/account.rs b/mullvad-types/src/account.rs index cefbf53f2a..964ae8c40d 100644 --- a/mullvad-types/src/account.rs +++ b/mullvad-types/src/account.rs @@ -2,7 +2,7 @@ use chrono::{offset::Utc, DateTime}; use serde::{Deserialize, Serialize}; /// Account identifier used for authentication. -pub type AccountToken = String; +pub type AccountNumber = String; /// Temporary authorization token derived from a Mullvad account. pub type AccessToken = String; diff --git a/mullvad-types/src/device.rs b/mullvad-types/src/device.rs index 5ee51d54ca..2066d13394 100644 --- a/mullvad-types/src/device.rs +++ b/mullvad-types/src/device.rs @@ -1,4 +1,4 @@ -use crate::account::AccountToken; +use crate::account::AccountNumber; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use talpid_types::net::wireguard::PublicKey; @@ -64,17 +64,18 @@ impl DeviceState { } } -/// A [Device] and its associated account token. +/// A [Device] and its associated account number. #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AccountAndDevice { - pub account_token: AccountToken, + #[serde(alias = "account_token")] + pub account_number: AccountNumber, pub device: Device, } impl AccountAndDevice { - pub fn new(account_token: AccountToken, device: Device) -> Self { + pub fn new(account_number: AccountNumber, device: Device) -> Self { Self { - account_token, + account_number, device, } } @@ -106,6 +107,6 @@ pub struct DeviceEvent { /// This is not sent by a normal logout or when it is revoked remotely. #[derive(Clone, Debug, Serialize)] pub struct RemoveDeviceEvent { - pub account_token: AccountToken, + pub account_number: AccountNumber, pub new_devices: Vec<Device>, } diff --git a/test/README.md b/test/README.md index 6aaff56d2f..112edb65d9 100644 --- a/test/README.md +++ b/test/README.md @@ -166,4 +166,4 @@ cargo run --bin test-manager run-tests --vm macos-ventura \ ## Note on `scripts/ci-runtests.sh` -`scripts/ci-runtests.sh` is the script that GitHub actions uses to invokes the `test-manager`, with similar functionality as `test-by-version.sh`. Note that account tokens are read (newline-delimited) from the path specified by the environment variable `ACCOUNT_TOKENS`. Round robin is used to select an account for each VM. +`scripts/ci-runtests.sh` is the script that GitHub actions uses to invokes the `test-manager`, with similar functionality as `test-by-version.sh`. Note that account numbers are read (newline-delimited) from the path specified by the environment variable `ACCOUNT_TOKENS`. Round robin is used to select an account for each VM. diff --git a/test/scripts/ci-runtests.sh b/test/scripts/ci-runtests.sh index 3e64894e74..4aeab28271 100755 --- a/test/scripts/ci-runtests.sh +++ b/test/scripts/ci-runtests.sh @@ -27,7 +27,7 @@ if [[ -z "${ACCOUNT_TOKENS+x}" ]]; then exit 1 fi if ! readarray -t tokens < "${ACCOUNT_TOKENS}"; then - echo "Specify account tokens in 'ACCOUNT_TOKENS' file" 1>&2 + echo "Specify account numbers in 'ACCOUNT_TOKENS' file" 1>&2 exit 1 fi CI_LOGS_DIR="$TEST_DIR/.ci-logs" diff --git a/test/test-by-version.sh b/test/test-by-version.sh index 56e1354419..337a0dfe83 100755 --- a/test/test-by-version.sh +++ b/test/test-by-version.sh @@ -6,7 +6,7 @@ usage() { echo "This script downloads and tests the given app version from the build repositories." echo echo "Required environment variables:" - echo " - ACCOUNT_TOKEN: Valid MullvadVPN account token" + echo " - ACCOUNT_TOKEN: Valid MullvadVPN account number" echo " - TEST_OS: Name of the VM configuration to use. List available configurations with 'cargo run --bin test-manager list'" echo "Optional environment variables:" echo " - APP_VERSION: The version of the app to test (defaults to the latest stable release)" |
