summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2020-04-01 13:19:36 +0200
committerAndrej Mihajlov <and@mullvad.net>2020-04-01 17:16:01 +0200
commit870209534582bd0ea108ef908498c8ae4a6a0ec8 (patch)
tree02839952039f781b8372d90d133abf1e0314bfcd
parent6d9cfe858485a9a3271ff5bea5ccb0c0c1603f9a (diff)
downloadmullvadvpn-870209534582bd0ea108ef908498c8ae4a6a0ec8.tar.xz
mullvadvpn-870209534582bd0ea108ef908498c8ae4a6a0ec8.zip
Add ability to log in using the newly created account token
-rw-r--r--ios/MullvadVPN/Account.swift32
-rw-r--r--ios/MullvadVPN/Base.lproj/Main.storyboard46
-rw-r--r--ios/MullvadVPN/LoginViewController.swift22
-rw-r--r--ios/MullvadVPN/MullvadAPI.swift6
4 files changed, 84 insertions, 22 deletions
diff --git a/ios/MullvadVPN/Account.swift b/ios/MullvadVPN/Account.swift
index cc1f10e8e6..3b178551a2 100644
--- a/ios/MullvadVPN/Account.swift
+++ b/ios/MullvadVPN/Account.swift
@@ -17,6 +17,9 @@ enum AccountError: Error {
/// A failure to perform the login
case login(AccountLoginError)
+ /// A failure to login with the new account
+ case createNew(CreateAccountError)
+
/// A failure to log out
case logout(TunnelManagerError)
}
@@ -27,6 +30,11 @@ enum AccountLoginError: Error {
case tunnelConfiguration(TunnelManagerError)
}
+enum CreateAccountError: Error {
+ case newAccountToken
+ case tunnelConfiguration(TunnelManagerError)
+}
+
extension AccountError: LocalizedError {
var errorDescription: String? {
switch self {
@@ -35,6 +43,9 @@ extension AccountError: LocalizedError {
case .logout:
return NSLocalizedString("Log out error", comment: "")
+
+ case .createNew:
+ return NSLocalizedString("Create account error", comment: "")
}
}
@@ -115,6 +126,27 @@ class Account {
UserDefaults.standard.set(true, forKey: UserDefaultsKeys.isAgreedToTermsOfService.rawValue)
}
+ func loginWithNewAccount() -> AnyPublisher<String, AccountError> {
+ return apiClient.createAccount()
+ .mapError { _ in CreateAccountError.newAccountToken }
+ .flatMap { (response) -> AnyPublisher<(String, Date), CreateAccountError> in
+ response.result
+ .mapError { _ in CreateAccountError.newAccountToken }
+ .publisher
+ .flatMap { (accountToken) in
+ TunnelManager.shared.setAccount(accountToken: accountToken)
+ .mapError { CreateAccountError.tunnelConfiguration($0) }
+ .map { (accountToken, Date()) }
+ }.eraseToAnyPublisher()
+ }.mapError { AccountError.createNew($0) }
+ .receive(on: DispatchQueue.main)
+ .map { (accountToken, expiry) -> String in
+ self.saveAccountToPreferences(accountToken: accountToken, expiry: expiry)
+
+ return accountToken
+ }.eraseToAnyPublisher()
+ }
+
/// Perform the login and save the account token along with expiry (if available) to the
/// application preferences.
func login(with accountToken: String) -> AnyPublisher<(), AccountError> {
diff --git a/ios/MullvadVPN/Base.lproj/Main.storyboard b/ios/MullvadVPN/Base.lproj/Main.storyboard
index 032472749a..cb036b1897 100644
--- a/ios/MullvadVPN/Base.lproj/Main.storyboard
+++ b/ios/MullvadVPN/Base.lproj/Main.storyboard
@@ -186,8 +186,8 @@
<constraint firstItem="V3j-Lb-fSQ" firstAttribute="leading" secondItem="0ZY-Kh-JiM" secondAttribute="leading" id="alr-G1-L4w"/>
</constraints>
</view>
- <view hidden="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ire-2z-eJu" userLabel="Footer">
- <rect key="frame" x="0.0" y="576.5" width="375" height="90.5"/>
+ <view contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ire-2z-eJu" userLabel="Footer">
+ <rect key="frame" x="0.0" y="556.5" width="375" height="110.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Don't have an account number?" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QcG-Tf-YdQ">
<rect key="frame" x="24" y="16" width="327" height="20.5"/>
@@ -196,12 +196,15 @@
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="osm-vd-aTb" customClass="AppButton" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="24" y="44.5" width="327" height="22"/>
+ <rect key="frame" x="24" y="44.5" width="327" height="42"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="42" placeholder="YES" id="NNo-Ki-ThF"/>
+ </constraints>
<state key="normal" title="Create account" backgroundImage="DefaultButton">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<connections>
- <action selector="openCreateAccount" destination="BYZ-38-t0r" eventType="touchUpInside" id="Ejr-wN-rdN"/>
+ <action selector="createNewAccount" destination="BYZ-38-t0r" eventType="touchUpInside" id="d7p-Uy-6Wc"/>
</connections>
</button>
</subviews>
@@ -235,6 +238,7 @@
<outlet property="accountInputGroup" destination="VmT-ya-ufe" id="ku3-qa-yfV"/>
<outlet property="accountTextField" destination="XOB-ct-yLU" id="mXd-SV-E16"/>
<outlet property="activityIndicator" destination="pID-oa-Rrg" id="GG2-Hv-FWl"/>
+ <outlet property="createAccountButton" destination="osm-vd-aTb" id="2Gr-84-Sg5"/>
<outlet property="keyboardToolbar" destination="waX-JF-VTG" id="kav-5t-mkA"/>
<outlet property="keyboardToolbarLoginButton" destination="0VH-wf-oEs" id="fsM-6o-9nL"/>
<outlet property="loginForm" destination="V3j-Lb-fSQ" id="tYu-S8-ylm"/>
@@ -371,20 +375,20 @@
<color key="separatorColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Account" id="ghE-jC-RWf" customClass="SettingsAccountCell" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="0.0" y="55.5" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="55.5" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ghE-jC-RWf" id="sTl-gI-g2a">
- <rect key="frame" x="0.0" y="0.0" width="348" height="43.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="348" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Account" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Lve-Kd-qTr">
- <rect key="frame" x="16" y="11" width="63.5" height="21.5"/>
+ <rect key="frame" x="16" y="11" width="63.5" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="A YEAR LEFT" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QeD-EQ-Ruo">
- <rect key="frame" x="259" y="11" width="81" height="21.5"/>
+ <rect key="frame" x="259" y="11" width="81" height="21"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -409,20 +413,20 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="AppVersion" id="pbd-iC-Emm" customClass="SettingsAppVersionCell" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="0.0" y="99" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="98.5" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pbd-iC-Emm" id="lYp-Z8-1sN">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="App version" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pYC-Zb-8N9">
- <rect key="frame" x="16" y="11" width="91" height="21.5"/>
+ <rect key="frame" x="16" y="11" width="91" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="2018.3" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sOr-vj-cg7">
- <rect key="frame" x="316.5" y="11" width="42.5" height="21.5"/>
+ <rect key="frame" x="316.5" y="11" width="42.5" height="21"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="13"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -444,14 +448,14 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="BasicDisclosure" id="Ahs-gu-nTM" customClass="SettingsBasicCell" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="0.0" y="142.5" width="375" height="43.5"/>
+ <rect key="frame" x="0.0" y="141.5" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ahs-gu-nTM" id="Drq-vk-8F2">
- <rect key="frame" x="0.0" y="0.0" width="348" height="43.5"/>
+ <rect key="frame" x="0.0" y="0.0" width="348" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Amw-A3-ePS">
- <rect key="frame" x="16" y="11" width="324" height="21.5"/>
+ <rect key="frame" x="16" y="11" width="324" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@@ -1135,31 +1139,31 @@
</view>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" id="aFz-H5-sPu" customClass="SelectLocationCell" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="0.0" y="173" width="375" height="43"/>
+ <rect key="frame" x="0.0" y="173" width="375" height="48.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aFz-H5-sPu" id="6nQ-gT-vzf">
- <rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="48.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5ag-N4-pUg" customClass="RelayStatusIndicatorView" customModule="MullvadVPN" customModuleProvider="target">
- <rect key="frame" x="16" y="13.5" width="16" height="16"/>
+ <rect key="frame" x="16" y="16.5" width="16" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="QWj-hh-I3P"/>
<constraint firstAttribute="width" constant="16" id="TFV-yi-LXG"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="y7o-0b-MUV">
- <rect key="frame" x="44" y="11" width="42" height="21"/>
+ <rect key="frame" x="44" y="11" width="42" height="26.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="IconTick" translatesAutoresizingMaskIntoConstraints="NO" id="e1o-Bl-zd5">
- <rect key="frame" x="12" y="9.5" width="24" height="24"/>
+ <rect key="frame" x="0.0" y="0.5" width="48" height="48"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KaW-bN-I51">
- <rect key="frame" x="311" y="0.0" width="64" height="43"/>
+ <rect key="frame" x="311" y="0.0" width="64" height="48.5"/>
<accessibility key="accessibilityConfiguration" identifier="ExpandButton"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="UU3-Di-65E"/>
diff --git a/ios/MullvadVPN/LoginViewController.swift b/ios/MullvadVPN/LoginViewController.swift
index 4383732191..e50266ae49 100644
--- a/ios/MullvadVPN/LoginViewController.swift
+++ b/ios/MullvadVPN/LoginViewController.swift
@@ -25,6 +25,7 @@ class LoginViewController: UIViewController, UITextFieldDelegate, RootContainmen
@IBOutlet var loginFormWrapperBottomConstraint: NSLayoutConstraint!
@IBOutlet var activityIndicator: SpinnerActivityIndicatorView!
@IBOutlet var statusImageView: UIImageView!
+ @IBOutlet var createAccountButton: AppButton!
private var loginSubscriber: AnyCancellable?
@@ -170,7 +171,24 @@ class LoginViewController: UIViewController, UITextFieldDelegate, RootContainmen
}, receiveValue: { _ in })
}
- @IBAction func openCreateAccount() {}
+ @IBAction func createNewAccount() {
+ beginLogin()
+
+ accountTextField.text = ""
+
+ loginSubscriber = Account.shared.loginWithNewAccount()
+ .receive(on: DispatchQueue.main)
+ .sink(receiveCompletion: { (completionResult) in
+ switch completionResult {
+ case .finished:
+ self.endLogin(.success)
+ case .failure(let error):
+ self.endLogin(.failure(error))
+ }
+ }, receiveValue: { (newAccountToken) in
+ self.accountTextField.text = newAccountToken
+ })
+ }
// MARK: - Private
@@ -183,6 +201,7 @@ class LoginViewController: UIViewController, UITextFieldDelegate, RootContainmen
switch loginState {
case .authenticating:
activityIndicator.startAnimating()
+ createAccountButton.isEnabled = false
// Fallthrough to make sure that the settings button is disabled
// in .authenticating and .success cases.
@@ -193,6 +212,7 @@ class LoginViewController: UIViewController, UITextFieldDelegate, RootContainmen
case .default, .failure:
rootContainerController?.headerBarSettingsButton.isEnabled = true
+ createAccountButton.isEnabled = true
activityIndicator.stopAnimating()
}
diff --git a/ios/MullvadVPN/MullvadAPI.swift b/ios/MullvadVPN/MullvadAPI.swift
index 7ba5de4d5c..4fbaa1d430 100644
--- a/ios/MullvadVPN/MullvadAPI.swift
+++ b/ios/MullvadVPN/MullvadAPI.swift
@@ -114,6 +114,12 @@ class MullvadAPI {
self.session = session
}
+ func createAccount() -> AnyPublisher<Response<String>, MullvadAPI.Error> {
+ let request = JsonRpcRequest(method: "create_account", params: [])
+
+ return MullvadAPI.makeDataTaskPublisher(request: request)
+ }
+
func getRelayList() -> AnyPublisher<Response<RelayList>, MullvadAPI.Error> {
let request = JsonRpcRequest(method: "relay_list_v3", params: [])