Skip to content

Commit e58ecaf

Browse files
authored
Merge pull request #222 from Hirobreak/2fa
Two-factor Auth
2 parents 84e0027 + cfe66fc commit e58ecaf

34 files changed

+320
-125
lines changed

iOS-Email-Client.xcodeproj/xcshareddata/xcschemes/iOS-Email-Client.xcscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
<EnvironmentVariable
7676
key = "forceProduction"
7777
value = "true"
78-
isEnabled = "NO">
78+
isEnabled = "YES">
7979
</EnvironmentVariable>
8080
</EnvironmentVariables>
8181
<AdditionalOptions>

iOS-Email-Client/AsyncTasks/CreateCustomJSONFileAsyncTask.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class CreateCustomJSONFileAsyncTask {
6363
handleRow($0.toDictionary(emailId: emailId))
6464
}
6565

66+
67+
6668
DispatchQueue.main.async {
6769
completion(nil, self.fileURL)
6870
}

iOS-Email-Client/Base.lproj/Main.storyboard

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,9 @@
13871387
<constraint firstAttribute="width" constant="43" id="kPw-4a-gTD"/>
13881388
</constraints>
13891389
<color key="onTintColor" red="0.0" green="0.56862745098039214" blue="1" alpha="1" colorSpace="calibratedRGB"/>
1390+
<connections>
1391+
<action selector="onSwitchToggle:" destination="ZzE-Yh-VbX" eventType="valueChanged" id="Ebg-dL-bAK"/>
1392+
</connections>
13901393
</switch>
13911394
</subviews>
13921395
<constraints>
@@ -1397,6 +1400,7 @@
13971400
</constraints>
13981401
</tableViewCellContentView>
13991402
<connections>
1403+
<outlet property="availableSwitch" destination="kgW-OS-3hM" id="oVz-ch-0Ua"/>
14001404
<outlet property="optionLabel" destination="5wZ-K9-zuW" id="niO-4k-IcX"/>
14011405
</connections>
14021406
</tableViewCell>
@@ -1558,7 +1562,7 @@
15581562
</connections>
15591563
</textField>
15601564
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NsV-eR-Br8">
1561-
<rect key="frame" x="243" y="288.5" width="105" height="38"/>
1565+
<rect key="frame" x="243" y="323.5" width="105" height="38"/>
15621566
<color key="backgroundColor" red="0.0" green="0.56862745098039214" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
15631567
<constraints>
15641568
<constraint firstAttribute="height" constant="38" id="698-sM-68Z"/>
@@ -1578,13 +1582,20 @@
15781582
</connections>
15791583
</button>
15801584
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="i2e-ku-M8K">
1581-
<rect key="frame" x="285.5" y="297.5" width="20" height="20"/>
1585+
<rect key="frame" x="285.5" y="332.5" width="20" height="20"/>
15821586
</activityIndicatorView>
1587+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Note: Changing your recovery email will turn off Two-Factor Authentication" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lM2-53-pVD">
1588+
<rect key="frame" x="27" y="276.5" width="321" height="38.5"/>
1589+
<fontDescription key="fontDescription" name="NunitoSans-Regular" family="Nunito Sans" pointSize="14"/>
1590+
<color key="textColor" red="0.44705882349999998" green="0.44705882349999998" blue="0.44705882349999998" alpha="1" colorSpace="calibratedRGB"/>
1591+
<nil key="highlightedColor"/>
1592+
</label>
15831593
</subviews>
15841594
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
15851595
<constraints>
15861596
<constraint firstItem="Upi-pd-9ph" firstAttribute="centerY" secondItem="S9Q-rO-GEN" secondAttribute="centerY" id="08s-mZ-uvB"/>
15871597
<constraint firstItem="W6o-Yn-D7Z" firstAttribute="centerX" secondItem="n3y-BG-AGw" secondAttribute="centerX" id="89z-bC-lqJ"/>
1598+
<constraint firstItem="lM2-53-pVD" firstAttribute="top" secondItem="nCs-ch-41A" secondAttribute="bottom" constant="18" id="AVH-O1-6N5"/>
15881599
<constraint firstItem="i2e-ku-M8K" firstAttribute="centerX" secondItem="NsV-eR-Br8" secondAttribute="centerX" id="C2f-ZQ-KiA"/>
15891600
<constraint firstItem="nCs-ch-41A" firstAttribute="trailing" secondItem="Zcd-QO-oCP" secondAttribute="trailing" id="Dob-nd-Ubf"/>
15901601
<constraint firstItem="nCs-ch-41A" firstAttribute="top" secondItem="Zcd-QO-oCP" secondAttribute="bottom" constant="15" id="E0I-5T-wke"/>
@@ -1598,11 +1609,13 @@
15981609
<constraint firstItem="n3y-BG-AGw" firstAttribute="top" secondItem="iNz-jU-IJX" secondAttribute="bottom" constant="15" id="UxJ-HK-xQo"/>
15991610
<constraint firstItem="Upi-pd-9ph" firstAttribute="leading" secondItem="iNz-jU-IJX" secondAttribute="trailing" id="W9j-nV-IB8"/>
16001611
<constraint firstItem="i2e-ku-M8K" firstAttribute="centerY" secondItem="NsV-eR-Br8" secondAttribute="centerY" id="h8k-fa-dyW"/>
1612+
<constraint firstItem="lM2-53-pVD" firstAttribute="trailing" secondItem="Upi-pd-9ph" secondAttribute="trailing" id="hVx-Vm-ajx"/>
16011613
<constraint firstItem="Zcd-QO-oCP" firstAttribute="trailing" secondItem="Upi-pd-9ph" secondAttribute="trailing" id="lXp-jg-rre"/>
16021614
<constraint firstItem="Upi-pd-9ph" firstAttribute="trailing" secondItem="S9Q-rO-GEN" secondAttribute="trailing" id="nca-MU-PVK"/>
1603-
<constraint firstItem="NsV-eR-Br8" firstAttribute="top" secondItem="nCs-ch-41A" secondAttribute="bottom" constant="30" id="ny8-6L-Lpd"/>
1615+
<constraint firstItem="NsV-eR-Br8" firstAttribute="top" secondItem="nCs-ch-41A" secondAttribute="bottom" constant="65" id="ny8-6L-Lpd"/>
16041616
<constraint firstItem="NsV-eR-Br8" firstAttribute="trailing" secondItem="Zcd-QO-oCP" secondAttribute="trailing" id="p5n-hV-tK1"/>
16051617
<constraint firstItem="W6o-Yn-D7Z" firstAttribute="centerY" secondItem="n3y-BG-AGw" secondAttribute="centerY" id="shV-9R-cgP"/>
1618+
<constraint firstItem="lM2-53-pVD" firstAttribute="leading" secondItem="Zcd-QO-oCP" secondAttribute="leading" id="t0P-WV-xcF"/>
16061619
<constraint firstItem="S9Q-rO-GEN" firstAttribute="leading" secondItem="Bc4-Fn-Mhk" secondAttribute="leading" constant="27" id="y1s-o5-hla"/>
16071620
<constraint firstItem="iNz-jU-IJX" firstAttribute="leading" secondItem="S9Q-rO-GEN" secondAttribute="leading" id="yd9-F4-Bbo"/>
16081621
</constraints>
@@ -1878,26 +1891,26 @@
18781891
</userDefinedRuntimeAttributes>
18791892
</imageView>
18801893
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Current Device" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="owA-aL-tUp">
1881-
<rect key="frame" x="252" y="23" width="100" height="20"/>
1894+
<rect key="frame" x="257" y="23" width="95" height="20"/>
18821895
<constraints>
1883-
<constraint firstAttribute="width" constant="100" id="7aT-Fc-td6"/>
1896+
<constraint firstAttribute="width" constant="95" id="7aT-Fc-td6"/>
18841897
<constraint firstAttribute="height" constant="20" id="cfn-aM-jge"/>
18851898
</constraints>
18861899
<fontDescription key="fontDescription" name="NunitoSans-Regular" family="Nunito Sans" pointSize="14"/>
18871900
<color key="textColor" red="0.37254901960784315" green="0.72549019607843135" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
18881901
<nil key="highlightedColor"/>
18891902
</label>
18901903
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="amW-Di-fUH">
1891-
<rect key="frame" x="61" y="13" width="186" height="40"/>
1904+
<rect key="frame" x="61" y="13" width="196" height="40"/>
18921905
<subviews>
18931906
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Samsung Galaxy S8" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K3s-zY-auf">
1894-
<rect key="frame" x="0.0" y="0.0" width="186" height="22"/>
1907+
<rect key="frame" x="0.0" y="0.0" width="196" height="22"/>
18951908
<fontDescription key="fontDescription" name="NunitoSans-Regular" family="Nunito Sans" pointSize="16"/>
18961909
<nil key="textColor"/>
18971910
<nil key="highlightedColor"/>
18981911
</label>
1899-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Guayaquil - 12 hours ago" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0bv-pm-gsw">
1900-
<rect key="frame" x="0.0" y="22" width="186" height="18"/>
1912+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Guayaquil - 12 hours ago" textAlignment="natural" lineBreakMode="characterWrap" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0bv-pm-gsw">
1913+
<rect key="frame" x="0.0" y="22" width="196" height="18"/>
19011914
<fontDescription key="fontDescription" name="NunitoSans-Regular" family="Nunito Sans" pointSize="13"/>
19021915
<nil key="textColor"/>
19031916
<nil key="highlightedColor"/>
@@ -1917,7 +1930,7 @@
19171930
</button>
19181931
</subviews>
19191932
<constraints>
1920-
<constraint firstItem="owA-aL-tUp" firstAttribute="leading" secondItem="amW-Di-fUH" secondAttribute="trailing" constant="5" id="8hW-Je-NRb"/>
1933+
<constraint firstItem="owA-aL-tUp" firstAttribute="leading" secondItem="amW-Di-fUH" secondAttribute="trailing" id="8hW-Je-NRb"/>
19211934
<constraint firstItem="amW-Di-fUH" firstAttribute="centerY" secondItem="9C0-OI-bsM" secondAttribute="centerY" id="F5c-bO-nVr"/>
19221935
<constraint firstItem="AGu-bu-kQR" firstAttribute="trailing" secondItem="owA-aL-tUp" secondAttribute="trailing" id="Lza-yA-9XS"/>
19231936
<constraint firstItem="AGu-bu-kQR" firstAttribute="centerY" secondItem="owA-aL-tUp" secondAttribute="centerY" id="UZu-zA-hrs"/>

iOS-Email-Client/Controllers/ConnectUploadViewController.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class ConnectUploadViewController: UIViewController{
114114
self.presentProcessInterrupted()
115115
return
116116
}
117+
CriptextFileManager.deleteFile(url: myUrl)
118+
CriptextFileManager.deleteFile(path: compressedPath)
117119
self.databasePath = outputPath
118120
self.state = .waiting
119121
self.handleState()
@@ -143,6 +145,7 @@ class ConnectUploadViewController: UIViewController{
143145
self.presentProcessInterrupted()
144146
return
145147
}
148+
CriptextFileManager.deleteFile(path: path)
146149
self.state = .sendData
147150
self.handleState()
148151
}

iOS-Email-Client/Controllers/CustomTabsController.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CustomTabsController: TabsController {
2828
}
2929

3030
func loadData(){
31+
let myDevice = Device.createActiveDevice(deviceId: myAccount.deviceId)
3132
APIManager.getSettings(token: myAccount.jwt) { (responseData) in
3233
if case .Unauthorized = responseData {
3334
self.logout()
@@ -39,20 +40,17 @@ class CustomTabsController: TabsController {
3940
}
4041
guard case let .SuccessDictionary(settings) = responseData,
4142
let devices = settings["devices"] as? [[String: Any]],
42-
let recoveryData = settings["recoveryEmail"] as? [String: Any] else {
43+
let general = settings["general"] as? [String: Any] else {
4344
return
4445
}
45-
for device in devices {
46-
let newDevice = Device.fromDictionary(data: device)
47-
guard !self.devicesData.devices.contains(where: {$0.id == newDevice.id && $0.active}) else {
48-
continue
49-
}
50-
self.devicesData.devices.append(newDevice)
51-
}
52-
let email = recoveryData["address"] as! String
53-
let status = recoveryData["status"] as! Int
46+
let myDevices = devices.map({Device.fromDictionary(data: $0)}).filter({$0.id != myDevice.id}).sorted(by: {$0.safeDate > $1.safeDate})
47+
self.devicesData.devices.append(contentsOf: myDevices)
48+
let email = general["recoveryEmail"] as! String
49+
let status = general["recoveryEmailConfirmed"] as! Int
50+
let isTwoFactor = general["twoFactorAuth"] as! Int
5451
self.generalData.recoveryEmail = email
5552
self.generalData.recoveryEmailStatus = email.isEmpty ? .none : status == self.STATUS_NOT_CONFIRMED ? .pending : .verified
53+
self.generalData.isTwoFactor = isTwoFactor == 1 ? true : false
5654
self.reloadChildViews()
5755
}
5856
}

iOS-Email-Client/Controllers/EmailDetailViewController.swift

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ class EmailDetailViewController: UIViewController {
5151
self.coachMarksController.overlay.allowTap = true
5252
self.coachMarksController.overlay.color = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.85)
5353
self.coachMarksController.dataSource = self
54-
55-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
56-
guard let lastIndex = self.emailData.emails.index(where: {$0.isExpanded}) else {
57-
return
58-
}
59-
self.emailsTableView.scrollToRow(at: IndexPath(row: lastIndex, section: 0), at: .bottom, animated: false)
60-
}
6154
}
6255

6356
override func viewWillDisappear(_ animated: Bool) {
@@ -645,13 +638,19 @@ extension EmailDetailViewController: DetailMoreOptionsViewDelegate {
645638
self.presentPasswordPopover(myAccount: self.myAccount)
646639
return
647640
}
641+
if case .Conflicts = responseData {
642+
self.showAlert("Unsend Failed", message: "Failed to unsend the email. Time (1h) for unsending has already expired.", style: .alert)
643+
self.emailsTableView.reloadData()
644+
return
645+
}
648646
guard case .Success = responseData else {
649647
self.showAlert("Unsend Failed", message: "Unable to unsend email. Please try again later", style: .alert)
650648
self.emailsTableView.reloadData()
651649
return
652650
}
653651
DBManager.unsendEmail(email)
654652
email.isLoaded = false
653+
cell.isLoaded = false
655654
cell.setContent(email, myEmail: self.emailData.accountEmail)
656655
self.emailsTableView.reloadData()
657656
}

iOS-Email-Client/Controllers/GenericAlertUIPopover.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ class GenericAlertUIPopover: BaseUIPopover {
1212

1313
var myTitle: String?
1414
var myMessage: String?
15+
var myAttributedMessage: NSAttributedString?
16+
var myButton: String = "Ok"
1517
var onOkPress: (() -> (Void))?
1618
@IBOutlet weak var titleLabel: UILabel!
1719
@IBOutlet weak var messageLabel: UILabel!
20+
@IBOutlet weak var okButton: UIButton!
1821

1922

2023
init(){
@@ -28,7 +31,12 @@ class GenericAlertUIPopover: BaseUIPopover {
2831
override func viewDidLoad() {
2932
super.viewDidLoad()
3033
titleLabel.text = myTitle
31-
messageLabel.text = myMessage
34+
okButton.setTitle(myButton, for: .normal)
35+
if let attributedMessage = myAttributedMessage {
36+
messageLabel.attributedText = attributedMessage
37+
} else {
38+
messageLabel.text = myMessage
39+
}
3240
}
3341

3442
@IBAction func okPress(_ sender: Any) {

iOS-Email-Client/Controllers/InboxViewController.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ extension InboxViewController: WebSocketManagerDelegate {
283283
}
284284
settings.generalData.recoveryEmail = address
285285
settings.generalData.recoveryEmailStatus = .pending
286+
settings.generalData.isTwoFactor = false
286287
settings.reloadChildViews()
287288
case .RecoveryVerified:
288289
guard let nav = self.presentedViewController as? UINavigationController,
@@ -368,7 +369,7 @@ extension InboxViewController {
368369
menuViewController.reloadView()
369370
}
370371

371-
if result.emails.contains(where: {!$0.isInvalidated && $0.status != .unsent}) {
372+
if result.emails.contains(where: {!$0.isInvalidated && $0.status != .unsent && !$0.isSent}) {
372373
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
373374
}
374375

iOS-Email-Client/Controllers/Login/ConnectDeviceViewController.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ class ConnectDeviceViewController: UIViewController{
133133
self.presentProcessInterrupted()
134134
return
135135
}
136+
CriptextFileManager.deleteFile(path: path)
137+
CriptextFileManager.deleteFile(path: decryptedPath)
136138
state = .processDB(myAccount, decompressedPath, data)
137139
self.handleState()
138140
}
@@ -161,6 +163,7 @@ class ConnectDeviceViewController: UIViewController{
161163
}
162164
}
163165
DBManager.insertBatchRows(rows: dbRows, maps: &maps)
166+
CriptextFileManager.deleteFile(path: path)
164167
DispatchQueue.main.async {
165168
self.connectUIView.progressChange(value: self.PROGRESS_COMPLETE, message: "Decrypting Mailbox") {
166169
self.connectUIView.messageLabel.text = "Mailbox restored successfully!"

0 commit comments

Comments
 (0)