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 /gui/src | |
| parent | 5ed9fdaff6dcb709a0c1a4101c444c697cb948bc (diff) | |
| parent | fd8f186f7289760532ee0ed56c3405c5700e9822 (diff) | |
| download | mullvadvpn-ffa5d846607f680a35b59266845196c34971a2ba.tar.xz mullvadvpn-ffa5d846607f680a35b59266845196c34971a2ba.zip | |
Merge branch 'rename-account_token-account_number-des-1029'
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/account-data-cache.ts | 48 | ||||
| -rw-r--r-- | gui/src/main/account.ts | 34 | ||||
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 20 | ||||
| -rw-r--r-- | gui/src/main/grpc-type-convertions.ts | 2 | ||||
| -rw-r--r-- | gui/src/main/index.ts | 2 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 26 | ||||
| -rw-r--r-- | gui/src/renderer/components/Account.tsx | 6 | ||||
| -rw-r--r-- | gui/src/renderer/components/AccountNumberLabel.tsx | 20 | ||||
| -rw-r--r-- | gui/src/renderer/components/AccountTokenLabel.tsx | 20 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountErrorView.tsx | 19 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx | 8 | ||||
| -rw-r--r-- | gui/src/renderer/components/Login.tsx | 68 | ||||
| -rw-r--r-- | gui/src/renderer/components/TooManyDevices.tsx | 16 | ||||
| -rw-r--r-- | gui/src/renderer/containers/LoginPage.tsx | 8 | ||||
| -rw-r--r-- | gui/src/renderer/lib/account.ts | 4 | ||||
| -rw-r--r-- | gui/src/renderer/redux/account/actions.ts | 40 | ||||
| -rw-r--r-- | gui/src/renderer/redux/account/reducers.ts | 20 | ||||
| -rw-r--r-- | gui/src/shared/daemon-rpc-types.ts | 6 | ||||
| -rw-r--r-- | gui/src/shared/ipc-schema.ts | 10 |
19 files changed, 190 insertions, 187 deletions
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: { |
