merge refactor IOS-1511
authorAlejandro Gelos <alejandro@pep-project.org>
Fri, 17 May 2019 14:07:44 +0200
branchIOS-1511
changeset 86677bd35c4adc8c
parent 8555 6ec92543fec5
parent 8622 0255cb7ebf3f
child 8668 638e51d0bebd
merge refactor
pEpForiOS.xcodeproj/project.pbxproj
pEpForiOS/Models/VerifiableAccount/BasicConnectInfo+VerifiableAccount.swift
pEpForiOS/Models/VerifiableAccount/VerifiableAccount.swift
pEpForiOS/Models/VerifiableAccount/VerifiableAccountIMAP.swift
pEpForiOS/Models/VerifiableAccount/VerifiableAccountProtocol+UI.swift
pEpForiOS/Models/VerifiableAccount/VerifiableAccountSMTP.swift
pEpForiOSTests/AccountVerificationServiceTests.swift
pEpForiOSTests/Service/VerifiableAccountTest.swift
     1.1 --- a/.hgignore	Thu May 09 17:41:47 2019 +0200
     1.2 +++ b/.hgignore	Fri May 17 14:07:44 2019 +0200
     1.3 @@ -1,4 +1,4 @@
     1.4 -regexp
     1.5 +syntax: regexp
     1.6  \.DS_Store
     1.7  xcuserdata/.*
     1.8  Pods/.*
     1.9 @@ -9,10 +9,6 @@
    1.10  pEpTrustWords\.bundle/system\.db
    1.11  build/.*
    1.12  
    1.13 -.*secret.*
    1.14 -.*Secret.*
    1.15 -.*SECRET.*
    1.16 -
    1.17  ^.*\.pyc$
    1.18  
    1.19 -glob
    1.20 +syntax: glob
     2.1 --- a/README.md	Thu May 09 17:41:47 2019 +0200
     2.2 +++ b/README.md	Fri May 17 14:07:44 2019 +0200
     2.3 @@ -86,10 +86,10 @@
     2.4  java -Dgreenmail.setup.test.all -Dgreenmail.users=test001:pwd@localhost,test002:pwd@localhost,test003:pwd@localhost -jar ~/Downloads/greenmail-standalone-1.5.9.jar
     2.5  ```
     2.6  
     2.7 -The non-existing file referenced in the unit test project, ./pEpForiOSTests/TestUtil/SecretTestData.swift, must be
     2.8 +The non-existing file referenced in the unit test project, pEpForiOSTests/../pEp_for_iOS_intern/SecretTestData.swift, must be
     2.9  created, with a class named SecretTestData, derived from TestDataBase.
    2.10  
    2.11 -In `SecretTestData.swift`, you must override `populateVerifiableAccounts`, adding servers that are either registered in the LAS database or provide DNS SRV for IMAP and SMTP in order to test the "automatic account login".
    2.12 +In `SecretTestData.swift`, you must at least override `populateVerifiableAccounts`, adding servers that are either registered in the LAS database or provide DNS SRV for IMAP and SMTP in order to test the "automatic account login".
    2.13  
    2.14  If you want to run the tests against your own servers, override `populateAccounts` accordingly.
    2.15  
    2.16 @@ -102,13 +102,13 @@
    2.17  
    2.18  ### secret.xcconfig (needed for OAuth2 config secrects and others)
    2.19  
    2.20 -Create secret.xcconfig @ pEpForiOS/secret.xcconfig, with those contents:
    2.21 +Create secret.xcconfig @ pEpForiOS/../pEp_for_iOS_intern/secret.xcconfig, with those contents:
    2.22  
    2.23  ```
    2.24 -OAUTH2_GMAIL_CLIENT_ID = some_content
    2.25 -OAUTH2_GMAIL_REDIRECT_URL_SCHEME = some_content
    2.26 +OAUTH2_GMAIL_CLIENT_ID = your_secret_content
    2.27 +OAUTH2_GMAIL_REDIRECT_URL_SCHEME = your_secret_content
    2.28  
    2.29 -OAUTH2_YAHOO_CLIENT_ID = some_content
    2.30 +OAUTH2_YAHOO_CLIENT_ID = your_secret_content
    2.31  OAUTH2_YAHOO_CLIENT_SECRET = some_content
    2.32  
    2.33  ```
     3.1 --- a/pEpForiOS.xcodeproj/project.pbxproj	Thu May 09 17:41:47 2019 +0200
     3.2 +++ b/pEpForiOS.xcodeproj/project.pbxproj	Fri May 17 14:07:44 2019 +0200
     3.3 @@ -26,7 +26,6 @@
     3.4  		0033C08320D7F41600224E61 /* ThreadedEmailViewModelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0033C08220D7F41600224E61 /* ThreadedEmailViewModelDelegate.swift */; };
     3.5  		0038494A20D25576008000EA /* ProfilePictureComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0038494920D25576008000EA /* ProfilePictureComposer.swift */; };
     3.6  		0038494C20D2587F008000EA /* PepPictureComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0038494B20D2587F008000EA /* PepPictureComposer.swift */; };
     3.7 -		003C0FA720B5581A0093A987 /* SecretTestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 003C0FA620B5581A0093A987 /* SecretTestData.swift */; };
     3.8  		004422C82179E3C500BDF6DF /* SettingsCellViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004422C72179E3C500BDF6DF /* SettingsCellViewModelTest.swift */; };
     3.9  		004422CA2179ECD600BDF6DF /* PassiveModeViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004422C92179ECD600BDF6DF /* PassiveModeViewModelTest.swift */; };
    3.10  		004422D9217A25AD00BDF6DF /* UnencryptedSubjectViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004422D8217A25AD00BDF6DF /* UnencryptedSubjectViewModelTest.swift */; };
    3.11 @@ -202,6 +201,7 @@
    3.12  		430E0BE71EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430E0BE61EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift */; };
    3.13  		430E5F201EBC87A700E5D5D3 /* LanguageListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430E5F1F1EBC87A700E5D5D3 /* LanguageListTableViewCell.swift */; };
    3.14  		43106A192045716000693144 /* OAuth2ConfigurationProtocol+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43106A182045716000693144 /* OAuth2ConfigurationProtocol+Extension.swift */; };
    3.15 +		4312BE89228439670002129D /* SecretUITestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4312BE88228439670002129D /* SecretUITestData.swift */; };
    3.16  		431394A91E4B03AA00D92F33 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 431394A81E4B03AA00D92F33 /* Settings.bundle */; };
    3.17  		4315E4C3201242BB00F68763 /* OAuth2Type+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4315E4C2201242BB00F68763 /* OAuth2Type+Extension.swift */; };
    3.18  		431798771CF87FE6007DD655 /* ReferenceCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431798761CF87FE6007DD655 /* ReferenceCounter.swift */; };
    3.19 @@ -211,7 +211,6 @@
    3.20  		431C6E041FE7A85200E23BE0 /* OAuth2ConfigurationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431C6E031FE7A85200E23BE0 /* OAuth2ConfigurationProtocol.swift */; };
    3.21  		431D60DB1E93BB2D001266D7 /* AttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431D60DA1E93BB2D001266D7 /* AttachmentsView.swift */; };
    3.22  		431D60DD1E93D580001266D7 /* MessageAttachmentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431D60DC1E93D580001266D7 /* MessageAttachmentsCell.swift */; };
    3.23 -		431E58FC1ED5926B00EFA77F /* AccountVerificationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431E58FB1ED5926B00EFA77F /* AccountVerificationServiceTests.swift */; };
    3.24  		431E65631EEAE65200B8BBFC /* HandshakeUITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431E65621EEAE65200B8BBFC /* HandshakeUITest.swift */; };
    3.25  		431E8F7E1CFDCF3A00C33647 /* EmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431E8F7D1CFDCF3A00C33647 /* EmailViewController.swift */; };
    3.26  		431F987F1F6FD3E300A1E4D2 /* HandshakePartnerTableViewCellViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431F987E1F6FD3E300A1E4D2 /* HandshakePartnerTableViewCellViewModelTests.swift */; };
    3.27 @@ -275,15 +274,14 @@
    3.28  		4356FFEC21356CB600804089 /* ReplyAllPossibleCheckerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4356FFEB21356CB600804089 /* ReplyAllPossibleCheckerTest.swift */; };
    3.29  		435F7C75215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt in Resources */ = {isa = PBXBuildFile; fileRef = 435F7C74215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt */; };
    3.30  		43628766213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43628765213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt */; };
    3.31 -		4365E85F2265DC3F00929D07 /* VerifiableAccountTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4365E85E2265DC3F00929D07 /* VerifiableAccountTest.swift */; };
    3.32 -		4365E86A226615F200929D07 /* VerifiableAccountIMAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4365E869226615F200929D07 /* VerifiableAccountIMAP.swift */; };
    3.33 -		4365E87222661B9700929D07 /* VerifiableAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4365E87122661B9700929D07 /* VerifiableAccount.swift */; };
    3.34  		436795F81EE98B9A00B03E23 /* MessageReevalutionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436795F71EE98B9A00B03E23 /* MessageReevalutionTests.swift */; };
    3.35  		436795FB1EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 436795F91EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc */; };
    3.36  		436795FC1EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch.asc in Resources */ = {isa = PBXBuildFile; fileRef = 436795FA1EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch.asc */; };
    3.37  		436795FF1EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch_sec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 436795FD1EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch_sec.asc */; };
    3.38  		436796001EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch.asc in Resources */ = {isa = PBXBuildFile; fileRef = 436795FE1EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch.asc */; };
    3.39  		436796021EE9909100B03E23 /* CommunicationTypeTests_Message_test001_to_test002.txt in Resources */ = {isa = PBXBuildFile; fileRef = 436796011EE9909100B03E23 /* CommunicationTypeTests_Message_test001_to_test002.txt */; };
    3.40 +		436981AD2282F6460006FA2D /* secret.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 436981AC2282F6460006FA2D /* secret.xcconfig */; };
    3.41 +		436981C022830AF60006FA2D /* SecretTestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436981BF22830AF60006FA2D /* SecretTestData.swift */; };
    3.42  		436D0066215B5F3800966CC2 /* Undisplayable_HTML_Message.txt in Resources */ = {isa = PBXBuildFile; fileRef = 436D0065215B5F3800966CC2 /* Undisplayable_HTML_Message.txt */; };
    3.43  		436F8E141D36706A007E9829 /* StringExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436F8E131D36706A007E9829 /* StringExtensionsTest.swift */; };
    3.44  		437027A122315B5700A77AEC /* PEPAppUtilWrappers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437027A022315B5700A77AEC /* PEPAppUtilWrappers.swift */; };
    3.45 @@ -362,9 +360,6 @@
    3.46  		43D47AC0225DD1C500E97C5B /* PantomimeFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D47ABF225DD1C500E97C5B /* PantomimeFramework.framework */; };
    3.47  		43D47AC2225DD1CE00E97C5B /* PEPObjCAdapterFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D47AC1225DD1CE00E97C5B /* PEPObjCAdapterFramework.framework */; };
    3.48  		43D51E891DD5D902008B77A8 /* SimpleOperationsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D51E881DD5D902008B77A8 /* SimpleOperationsTest.swift */; };
    3.49 -		43D541022267029400E74427 /* BasicConnectInfo+VerifiableAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D541012267029400E74427 /* BasicConnectInfo+VerifiableAccount.swift */; };
    3.50 -		43D54107226721A000E74427 /* VerifiableAccountSMTP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D54106226721A000E74427 /* VerifiableAccountSMTP.swift */; };
    3.51 -		43D5411B2268853A00E74427 /* VerifiableAccountProtocol+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D5411A2268853A00E74427 /* VerifiableAccountProtocol+UI.swift */; };
    3.52  		43DA52681CEF1B4F0023D540 /* NewAccountSetupUITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DA52671CEF1B4F0023D540 /* NewAccountSetupUITest.swift */; };
    3.53  		43DFB0331E36083D00175C9C /* MessageHeapBufferOverflow.txt in Resources */ = {isa = PBXBuildFile; fileRef = 43DFB0321E36083D00175C9C /* MessageHeapBufferOverflow.txt */; };
    3.54  		43E1619120D7B2D6003F1514 /* UpdateThreadListDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E1619020D7B2D6003F1514 /* UpdateThreadListDelegate.swift */; };
    3.55 @@ -431,7 +426,6 @@
    3.56  		B74F81021EB0E20000519FCC /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B74F81011EB0E20000519FCC /* LoginViewModel.swift */; };
    3.57  		B75FF00B1EFD420F00C57289 /* EmailListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B75FF00A1EFD420F00C57289 /* EmailListViewModel.swift */; };
    3.58  		B76CF8B320D2739B002429A8 /* MoveToFolderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B76CF8B220D2739B002429A8 /* MoveToFolderViewModel.swift */; };
    3.59 -		B7745839221C191600664282 /* SecretUITestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7745838221C191600664282 /* SecretUITestData.swift */; };
    3.60  		B78309C81EAA09040051A2E0 /* AccountCreation.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B78309C61EAA09040051A2E0 /* AccountCreation.storyboard */; };
    3.61  		B78CF8251E76D706008C1739 /* FilterTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78CF8241E76D706008C1739 /* FilterTableViewController.swift */; };
    3.62  		B78CF8291E76E0F1008C1739 /* FilterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B78CF8281E76E0F1008C1739 /* FilterViewModel.swift */; };
    3.63 @@ -509,7 +503,6 @@
    3.64  		0033C08220D7F41600224E61 /* ThreadedEmailViewModelDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadedEmailViewModelDelegate.swift; sourceTree = "<group>"; };
    3.65  		0038494920D25576008000EA /* ProfilePictureComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePictureComposer.swift; sourceTree = "<group>"; };
    3.66  		0038494B20D2587F008000EA /* PepPictureComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PepPictureComposer.swift; sourceTree = "<group>"; };
    3.67 -		003C0FA620B5581A0093A987 /* SecretTestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretTestData.swift; sourceTree = "<group>"; };
    3.68  		004422C72179E3C500BDF6DF /* SettingsCellViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCellViewModelTest.swift; sourceTree = "<group>"; };
    3.69  		004422C92179ECD600BDF6DF /* PassiveModeViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassiveModeViewModelTest.swift; sourceTree = "<group>"; };
    3.70  		004422D8217A25AD00BDF6DF /* UnencryptedSubjectViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnencryptedSubjectViewModelTest.swift; sourceTree = "<group>"; };
    3.71 @@ -686,6 +679,7 @@
    3.72  		430E0BE61EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSMutableDictionary+pEp.swift"; sourceTree = "<group>"; };
    3.73  		430E5F1F1EBC87A700E5D5D3 /* LanguageListTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageListTableViewCell.swift; sourceTree = "<group>"; };
    3.74  		43106A182045716000693144 /* OAuth2ConfigurationProtocol+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OAuth2ConfigurationProtocol+Extension.swift"; sourceTree = "<group>"; };
    3.75 +		4312BE88228439670002129D /* SecretUITestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SecretUITestData.swift; path = ../../pEp_for_iOS_intern/SecretUITestData.swift; sourceTree = "<group>"; };
    3.76  		431394A81E4B03AA00D92F33 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
    3.77  		4315E4C2201242BB00F68763 /* OAuth2Type+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OAuth2Type+Extension.swift"; sourceTree = "<group>"; };
    3.78  		431798761CF87FE6007DD655 /* ReferenceCounter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReferenceCounter.swift; sourceTree = "<group>"; };
    3.79 @@ -695,7 +689,6 @@
    3.80  		431C6E031FE7A85200E23BE0 /* OAuth2ConfigurationProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2ConfigurationProtocol.swift; sourceTree = "<group>"; };
    3.81  		431D60DA1E93BB2D001266D7 /* AttachmentsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsView.swift; sourceTree = "<group>"; };
    3.82  		431D60DC1E93D580001266D7 /* MessageAttachmentsCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageAttachmentsCell.swift; sourceTree = "<group>"; };
    3.83 -		431E58FB1ED5926B00EFA77F /* AccountVerificationServiceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountVerificationServiceTests.swift; sourceTree = "<group>"; };
    3.84  		431E65621EEAE65200B8BBFC /* HandshakeUITest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HandshakeUITest.swift; sourceTree = "<group>"; };
    3.85  		431E8F7D1CFDCF3A00C33647 /* EmailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailViewController.swift; sourceTree = "<group>"; };
    3.86  		431F987E1F6FD3E300A1E4D2 /* HandshakePartnerTableViewCellViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HandshakePartnerTableViewCellViewModelTests.swift; sourceTree = "<group>"; };
    3.87 @@ -779,15 +772,14 @@
    3.88  		4356FFEB21356CB600804089 /* ReplyAllPossibleCheckerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyAllPossibleCheckerTest.swift; sourceTree = "<group>"; };
    3.89  		435F7C74215E05DA00F21EFD /* 1364_Mail_missing_attached_image.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 1364_Mail_missing_attached_image.txt; sourceTree = "<group>"; };
    3.90  		43628765213D7A5E0066CD03 /* IOS-1300_odt_attachment.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "IOS-1300_odt_attachment.txt"; sourceTree = "<group>"; };
    3.91 -		4365E85E2265DC3F00929D07 /* VerifiableAccountTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifiableAccountTest.swift; sourceTree = "<group>"; };
    3.92 -		4365E869226615F200929D07 /* VerifiableAccountIMAP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifiableAccountIMAP.swift; sourceTree = "<group>"; };
    3.93 -		4365E87122661B9700929D07 /* VerifiableAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerifiableAccount.swift; sourceTree = "<group>"; };
    3.94  		436795F71EE98B9A00B03E23 /* MessageReevalutionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageReevalutionTests.swift; sourceTree = "<group>"; };
    3.95  		436795F91EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch_sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CommunicationTypeTests_test002@peptest.ch_sec.asc"; sourceTree = "<group>"; };
    3.96  		436795FA1EE98E9900B03E23 /* CommunicationTypeTests_test002@peptest.ch.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CommunicationTypeTests_test002@peptest.ch.asc"; sourceTree = "<group>"; };
    3.97  		436795FD1EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch_sec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CommunicationTypeTests_test001@peptest.ch_sec.asc"; sourceTree = "<group>"; };
    3.98  		436795FE1EE98F6E00B03E23 /* CommunicationTypeTests_test001@peptest.ch.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "CommunicationTypeTests_test001@peptest.ch.asc"; sourceTree = "<group>"; };
    3.99  		436796011EE9909100B03E23 /* CommunicationTypeTests_Message_test001_to_test002.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CommunicationTypeTests_Message_test001_to_test002.txt; sourceTree = "<group>"; };
   3.100 +		436981AC2282F6460006FA2D /* secret.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = secret.xcconfig; path = ../../pEp_for_iOS_intern/secret.xcconfig; sourceTree = "<group>"; };
   3.101 +		436981BF22830AF60006FA2D /* SecretTestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SecretTestData.swift; path = ../../../pEp_for_iOS_intern/SecretTestData.swift; sourceTree = "<group>"; };
   3.102  		436C5A8D1CFEDF59006A195F /* UIHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIHelper.swift; sourceTree = "<group>"; };
   3.103  		436D0065215B5F3800966CC2 /* Undisplayable_HTML_Message.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Undisplayable_HTML_Message.txt; sourceTree = "<group>"; };
   3.104  		436F8E131D36706A007E9829 /* StringExtensionsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionsTest.swift; sourceTree = "<group>"; };
   3.105 @@ -844,7 +836,6 @@
   3.106  		43AE48E61EEFC93900B92BB6 /* DebugMergePolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugMergePolicy.swift; sourceTree = "<group>"; };
   3.107  		43B0443820067CC7007BCE3F /* UIAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAccount.swift; sourceTree = "<group>"; };
   3.108  		43B0443A20067D25007BCE3F /* UITestDataProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestDataProtocol.swift; sourceTree = "<group>"; };
   3.109 -		43B044412007683E007BCE3F /* secret.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = secret.xcconfig; sourceTree = "<group>"; };
   3.110  		43B0444B20077323007BCE3F /* OAuth2Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuth2Configuration.swift; sourceTree = "<group>"; };
   3.111  		43B10C7F1EC2EE7F003E849F /* CppDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CppDummy.cpp; sourceTree = "<group>"; };
   3.112  		43B2C3161D2280ED00A08557 /* 5A90_3590_0E48_AB85_F3DB__045E_4623_C5D1_EAB6_643E.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 5A90_3590_0E48_AB85_F3DB__045E_4623_C5D1_EAB6_643E.asc; sourceTree = "<group>"; };
   3.113 @@ -880,9 +871,6 @@
   3.114  		43D47ABF225DD1C500E97C5B /* PantomimeFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PantomimeFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   3.115  		43D47AC1225DD1CE00E97C5B /* PEPObjCAdapterFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PEPObjCAdapterFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; };
   3.116  		43D51E881DD5D902008B77A8 /* SimpleOperationsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleOperationsTest.swift; sourceTree = "<group>"; };
   3.117 -		43D541012267029400E74427 /* BasicConnectInfo+VerifiableAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BasicConnectInfo+VerifiableAccount.swift"; sourceTree = "<group>"; };
   3.118 -		43D54106226721A000E74427 /* VerifiableAccountSMTP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifiableAccountSMTP.swift; sourceTree = "<group>"; };
   3.119 -		43D5411A2268853A00E74427 /* VerifiableAccountProtocol+UI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VerifiableAccountProtocol+UI.swift"; sourceTree = "<group>"; };
   3.120  		43DA52671CEF1B4F0023D540 /* NewAccountSetupUITest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewAccountSetupUITest.swift; sourceTree = "<group>"; };
   3.121  		43DFB0321E36083D00175C9C /* MessageHeapBufferOverflow.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MessageHeapBufferOverflow.txt; sourceTree = "<group>"; };
   3.122  		43E1619020D7B2D6003F1514 /* UpdateThreadListDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateThreadListDelegate.swift; sourceTree = "<group>"; };
   3.123 @@ -950,7 +938,6 @@
   3.124  		B74F81011EB0E20000519FCC /* LoginViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
   3.125  		B75FF00A1EFD420F00C57289 /* EmailListViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailListViewModel.swift; sourceTree = "<group>"; };
   3.126  		B76CF8B220D2739B002429A8 /* MoveToFolderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveToFolderViewModel.swift; sourceTree = "<group>"; };
   3.127 -		B7745838221C191600664282 /* SecretUITestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretUITestData.swift; sourceTree = "<group>"; };
   3.128  		B78309C71EAA09040051A2E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/AccountCreation.storyboard; sourceTree = "<group>"; };
   3.129  		B78CF8241E76D706008C1739 /* FilterTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterTableViewController.swift; path = Filter/FilterTableViewController.swift; sourceTree = "<group>"; };
   3.130  		B78CF8281E76E0F1008C1739 /* FilterViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterViewModel.swift; path = Filter/ViewModel/FilterViewModel.swift; sourceTree = "<group>"; };
   3.131 @@ -1074,13 +1061,13 @@
   3.132  		151F71EB202A06750057C74D /* TestUtils */ = {
   3.133  			isa = PBXGroup;
   3.134  			children = (
   3.135 +				436981BF22830AF60006FA2D /* SecretTestData.swift */,
   3.136  				151F71F6202A06750057C74D /* CdAccount+TestUtils.swift */,
   3.137  				151F71F3202A06750057C74D /* CdMessage+TestUtils.swift */,
   3.138  				151F71F1202A06750057C74D /* CoreDataDrivenTestBase.swift */,
   3.139  				1555361A207796CE00CDDAFA /* CWInternetAddress+TestUtils.swift */,
   3.140  				151F71EF202A06750057C74D /* DecryptionAttemptCounterDelegate.swift */,
   3.141  				151F71F4202A06750057C74D /* Message+TestUtils.swift */,
   3.142 -				003C0FA620B5581A0093A987 /* SecretTestData.swift */,
   3.143  				151F71F0202A06750057C74D /* MockBackgrounder.swift */,
   3.144  				151F71EE202A06750057C74D /* ReplicationServiceObserver.swift */,
   3.145  				151F71EC202A06750057C74D /* TestDataBase.swift */,
   3.146 @@ -1735,18 +1722,6 @@
   3.147  			path = Extensions;
   3.148  			sourceTree = "<group>";
   3.149  		};
   3.150 -		4365E868226615E400929D07 /* VerifiableAccount */ = {
   3.151 -			isa = PBXGroup;
   3.152 -			children = (
   3.153 -				4365E87122661B9700929D07 /* VerifiableAccount.swift */,
   3.154 -				4365E869226615F200929D07 /* VerifiableAccountIMAP.swift */,
   3.155 -				43D54106226721A000E74427 /* VerifiableAccountSMTP.swift */,
   3.156 -				43D541012267029400E74427 /* BasicConnectInfo+VerifiableAccount.swift */,
   3.157 -				43D5411A2268853A00E74427 /* VerifiableAccountProtocol+UI.swift */,
   3.158 -			);
   3.159 -			path = VerifiableAccount;
   3.160 -			sourceTree = "<group>";
   3.161 -		};
   3.162  		43800D8C1D112A0800821E34 /* HTMLParser */ = {
   3.163  			isa = PBXGroup;
   3.164  			children = (
   3.165 @@ -1813,8 +1788,8 @@
   3.166  				43980E351CBD0BCA00A7FC3C /* Info.plist */,
   3.167  				43C98AC5219C3691006418B0 /* InfoPlist.strings */,
   3.168  				43C98AC1219C275E006418B0 /* Localizable.strings */,
   3.169 +				436981AC2282F6460006FA2D /* secret.xcconfig */,
   3.170  				4388A0E02008AF61008CB98D /* public.xcconfig */,
   3.171 -				43B044412007683E007BCE3F /* secret.xcconfig */,
   3.172  				433724FC1DA2C2B1005E8DF5 /* pEp.entitlements */,
   3.173  				430C80D41D0EAB6E00CD4582 /* pEpTrustWords.bundle */,
   3.174  			);
   3.175 @@ -1835,7 +1810,6 @@
   3.176  				150707DD21006D0200AA213F /* UI */,
   3.177  				151F7202202A06D30057C74D /* Util */,
   3.178  				15F82A072006552B0084F9EA /* Tests from MessageModel in Exile due to Apple Bug */,
   3.179 -				43A601252264B5050099B45C /* Service */,
   3.180  				43980E401CBD0BCA00A7FC3C /* Info.plist */,
   3.181  				4336229D1DC76B8100133B3D /* MessageModelTests.swift */,
   3.182  				438D253B1D4B9E7500BFF7AA /* MimeTests.swift */,
   3.183 @@ -1852,7 +1826,6 @@
   3.184  				438281821E891B7E00087343 /* DateTests.swift */,
   3.185  				43FAA0D31EC9CBC0005BFC4B /* DecryptionTestsInternal.swift */,
   3.186  				43C3B15F2003851100ED48A4 /* DecryptImportedMessagesTests.swift */,
   3.187 -				431E58FB1ED5926B00EFA77F /* AccountVerificationServiceTests.swift */,
   3.188  				436795F71EE98B9A00B03E23 /* MessageReevalutionTests.swift */,
   3.189  				15B483DA1F28E2FC000FB2CF /* SpecialUseMailboxesTest.swift */,
   3.190  				43F7F0791F6AD44600BDF151 /* HandshakeTests.swift */,
   3.191 @@ -1872,7 +1845,7 @@
   3.192  		43980E481CBD0BCA00A7FC3C /* pEpForiOSUITests */ = {
   3.193  			isa = PBXGroup;
   3.194  			children = (
   3.195 -				B7745838221C191600664282 /* SecretUITestData.swift */,
   3.196 +				4312BE88228439670002129D /* SecretUITestData.swift */,
   3.197  				43B0443A20067D25007BCE3F /* UITestDataProtocol.swift */,
   3.198  				43B0443820067CC7007BCE3F /* UIAccount.swift */,
   3.199  				43980E4B1CBD0BCA00A7FC3C /* Info.plist */,
   3.200 @@ -1927,14 +1900,6 @@
   3.201  			name = Raw;
   3.202  			sourceTree = "<group>";
   3.203  		};
   3.204 -		43A601252264B5050099B45C /* Service */ = {
   3.205 -			isa = PBXGroup;
   3.206 -			children = (
   3.207 -				4365E85E2265DC3F00929D07 /* VerifiableAccountTest.swift */,
   3.208 -			);
   3.209 -			path = Service;
   3.210 -			sourceTree = "<group>";
   3.211 -		};
   3.212  		43A6E0491E5726C8005BEE69 /* Background */ = {
   3.213  			isa = PBXGroup;
   3.214  			children = (
   3.215 @@ -2035,7 +2000,6 @@
   3.216  			isa = PBXGroup;
   3.217  			children = (
   3.218  				37C3C0E52260C64D003E290C /* Log.swift */,
   3.219 -				4365E868226615E400929D07 /* VerifiableAccount */,
   3.220  				43CE63C41DE87FB200FAC505 /* Identity+pEp.swift */,
   3.221  				155475632137FD96005A52D0 /* FolderType+Extensions.swift */,
   3.222  				1554756521393036005A52D0 /* Folder+Extensions.swift */,
   3.223 @@ -2588,6 +2552,7 @@
   3.224  				1526596C216230B1006A78DF /* ComposeData.plist in Resources */,
   3.225  				43980E341CBD0BCA00A7FC3C /* LaunchScreen.storyboard in Resources */,
   3.226  				155F2D9E20530798001B4B1C /* Reusable.storyboard in Resources */,
   3.227 +				436981AD2282F6460006FA2D /* secret.xcconfig in Resources */,
   3.228  				220DCE2F1E0AB544002FE716 /* MessageData.plist in Resources */,
   3.229  				432E80FE2191AF5100359879 /* UniversLTStd-Bold.otf in Resources */,
   3.230  				43980E311CBD0BCA00A7FC3C /* Assets.xcassets in Resources */,
   3.231 @@ -2739,7 +2704,6 @@
   3.232  			files = (
   3.233  				002375D420DCF59D00663961 /* MoveToAccountViewController.swift in Sources */,
   3.234  				496C0EEB20BC4B370009B5B9 /* EmailListViewModel+EmailDisplayDelegate.swift in Sources */,
   3.235 -				4365E86A226615F200929D07 /* VerifiableAccountIMAP.swift in Sources */,
   3.236  				4315E4C3201242BB00F68763 /* OAuth2Type+Extension.swift in Sources */,
   3.237  				4351C2D11F4441190053381F /* houdini_html_u.c in Sources */,
   3.238  				B70A3C401E817CFA0036876F /* FolderViewModel.swift in Sources */,
   3.239 @@ -2799,7 +2763,6 @@
   3.240  				152A39D621905C3E00D9F8E4 /* BodyCell.swift in Sources */,
   3.241  				43ED53791CC77F95006AB156 /* UserInfoTableViewController.swift in Sources */,
   3.242  				43EC75AC2164C26100048CFE /* SetOwnKeyViewController.swift in Sources */,
   3.243 -				4365E87222661B9700929D07 /* VerifiableAccount.swift in Sources */,
   3.244  				43CE63C51DE87FB200FAC505 /* Identity+pEp.swift in Sources */,
   3.245  				220DCE2E1E0AB544002FE716 /* MessageCell.swift in Sources */,
   3.246  				B7DB7FD8221AD3BB003968DA /* UITableView+Extension.swift in Sources */,
   3.247 @@ -2875,7 +2838,6 @@
   3.248  				B7DB7FCA2215D69C003968DA /* CredentialTextField.swift in Sources */,
   3.249  				433E7438225B564400B84CD9 /* Account+Extension.swift in Sources */,
   3.250  				005A21FB20CAA5F50082D19F /* ThreadedEmailViewModel.swift in Sources */,
   3.251 -				43D541022267029400E74427 /* BasicConnectInfo+VerifiableAccount.swift in Sources */,
   3.252  				15874BD12127493E00A3A4A6 /* TrustedServerSettingsViewModel.swift in Sources */,
   3.253  				4351C2DC1F4441190053381F /* xml.c in Sources */,
   3.254  				430E0BE71EAF5E2600378EC2 /* NSMutableDictionary+pEp.swift in Sources */,
   3.255 @@ -2909,7 +2871,6 @@
   3.256  				152A39E321905C3E00D9F8E4 /* RecipientTextView.swift in Sources */,
   3.257  				43ED53701CC77F95006AB156 /* EmailListViewController.swift in Sources */,
   3.258  				496C0EE720BC2A880009B5B9 /* EmailDisplayDelegate.swift in Sources */,
   3.259 -				43D5411B2268853A00E74427 /* VerifiableAccountProtocol+UI.swift in Sources */,
   3.260  				152A39DD21905C3E00D9F8E4 /* AccountCell.swift in Sources */,
   3.261  				B7DB7FDC221ADDBD003968DA /* UIImageView+Extension.swift in Sources */,
   3.262  				37C3C0E62260C64D003E290C /* Log.swift in Sources */,
   3.263 @@ -2996,7 +2957,6 @@
   3.264  				15874BCF2127493E00A3A4A6 /* AccountSettingsTableViewController.swift in Sources */,
   3.265  				B7DB7FC72215C57F003968DA /* UIView+Autolayout.swift in Sources */,
   3.266  				B71EBBBC1E55E4AE00150177 /* FolderTableViewController.swift in Sources */,
   3.267 -				43D54107226721A000E74427 /* VerifiableAccountSMTP.swift in Sources */,
   3.268  				492EF92F20C699D0004EAE14 /* ThreadViewController+TableView.swift in Sources */,
   3.269  				43D070312133DB920013B120 /* AppSettingsProtocol.swift in Sources */,
   3.270  				43ED53781CC77F95006AB156 /* SMTPSettingsTableViewController.swift in Sources */,
   3.271 @@ -3010,7 +2970,6 @@
   3.272  			files = (
   3.273  				438D253C1D4B9E7500BFF7AA /* MimeTests.swift in Sources */,
   3.274  				004422CA2179ECD600BDF6DF /* PassiveModeViewModelTest.swift in Sources */,
   3.275 -				003C0FA720B5581A0093A987 /* SecretTestData.swift in Sources */,
   3.276  				1555361B207796CE00CDDAFA /* CWInternetAddress+TestUtils.swift in Sources */,
   3.277  				154D92CF20AC1745009A5868 /* MoveToFolderOperationTest.swift in Sources */,
   3.278  				1544BD0221524C9F0075C5A0 /* AttachmentFilterTest.swift in Sources */,
   3.279 @@ -3023,7 +2982,6 @@
   3.280  				153B2188219472A400497D3D /* BodyCellViewModelTest.swift in Sources */,
   3.281  				438BA0F5214F89CD001A4A82 /* MailParsingTests.swift in Sources */,
   3.282  				15A8B8FC20908D2300D2B0B6 /* Keychain+TestUtils.swift in Sources */,
   3.283 -				431E58FC1ED5926B00EFA77F /* AccountVerificationServiceTests.swift in Sources */,
   3.284  				0017CD1D2162614400F62F13 /* MoveToFolderCellViewModelTests.swift in Sources */,
   3.285  				0017CD1B21621E2200F62F13 /* MoveToFolderViewModelTest.swift in Sources */,
   3.286  				4336229E1DC76B8100133B3D /* MessageModelTests.swift in Sources */,
   3.287 @@ -3031,6 +2989,7 @@
   3.288  				43FAA0D41EC9CBC0005BFC4B /* DecryptionTestsInternal.swift in Sources */,
   3.289  				F73E4F72217F238300CCFFED /* FolderSectionViewModelTests.swift in Sources */,
   3.290  				15A763D11F72D68000670313 /* KeyChainTest.swift in Sources */,
   3.291 +				436981C022830AF60006FA2D /* SecretTestData.swift in Sources */,
   3.292  				43EC75B32164E97800048CFE /* DecryptionUtil.swift in Sources */,
   3.293  				43C7B9D11CEC4DDF007A612F /* MiscTests.swift in Sources */,
   3.294  				434DDC2B20D10F9A00755F44 /* EncryptionTests.swift in Sources */,
   3.295 @@ -3094,7 +3053,6 @@
   3.296  				15D439A5216F7E0E00EB3933 /* AccountPickerViewModelTest.swift in Sources */,
   3.297  				1574D07D2114696B00FEDC93 /* URL+MailToTest.swift in Sources */,
   3.298  				43C273DD21C9024A002EB4C8 /* LoggerTest.swift in Sources */,
   3.299 -				4365E85F2265DC3F00929D07 /* VerifiableAccountTest.swift in Sources */,
   3.300  				4356FFEC21356CB600804089 /* ReplyAllPossibleCheckerTest.swift in Sources */,
   3.301  				430C80E01D0EADC200CD4582 /* PepAdapterTests.swift in Sources */,
   3.302  				00DF2C3B2164C53F004EBA6C /* FolderViewModelTest.swift in Sources */,
   3.303 @@ -3120,7 +3078,7 @@
   3.304  				434C051B20F8BAB6009B271D /* XCUIElement+Extension.swift in Sources */,
   3.305  				431E65631EEAE65200B8BBFC /* HandshakeUITest.swift in Sources */,
   3.306  				43B0443B20067D25007BCE3F /* UITestDataProtocol.swift in Sources */,
   3.307 -				B7745839221C191600664282 /* SecretUITestData.swift in Sources */,
   3.308 +				4312BE89228439670002129D /* SecretUITestData.swift in Sources */,
   3.309  			);
   3.310  			runOnlyForDeploymentPostprocessing = 0;
   3.311  		};
     4.1 --- a/pEpForiOS/Base.lproj/Settings.storyboard	Thu May 09 17:41:47 2019 +0200
     4.2 +++ b/pEpForiOS/Base.lproj/Settings.storyboard	Fri May 17 14:07:44 2019 +0200
     4.3 @@ -1,11 +1,11 @@
     4.4  <?xml version="1.0" encoding="UTF-8"?>
     4.5 -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="cPx-YX-3ty">
     4.6 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="cPx-YX-3ty">
     4.7      <device id="retina4_7" orientation="portrait">
     4.8          <adaptation id="fullscreen"/>
     4.9      </device>
    4.10      <dependencies>
    4.11          <deployment identifier="iOS"/>
    4.12 -        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
    4.13 +        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
    4.14          <capability name="Safe area layout guides" minToolsVersion="9.0"/>
    4.15          <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    4.16      </dependencies>
    4.17 @@ -651,6 +651,7 @@
    4.18                      <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
    4.19                      <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
    4.20                      <connections>
    4.21 +                        <outlet property="doneButton" destination="Xy6-Rf-YDv" id="twm-qo-BhD"/>
    4.22                          <outlet property="emailTextfield" destination="FIa-wa-uSF" id="RVW-cY-4Ny"/>
    4.23                          <outlet property="imapPortTextfield" destination="ukB-K0-MMG" id="rGA-tC-CYA"/>
    4.24                          <outlet property="imapSecurityTextfield" destination="rCJ-UW-Jmn" id="Vz4-6T-rdl"/>
     5.1 --- a/pEpForiOS/Models/VerifiableAccount/BasicConnectInfo+VerifiableAccount.swift	Thu May 09 17:41:47 2019 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,49 +0,0 @@
     5.4 -//
     5.5 -//  BasicConnectInfo+VerifiableAccount.swift
     5.6 -//  pEp
     5.7 -//
     5.8 -//  Created by Dirk Zimmermann on 16.04.19.
     5.9 -//  Copyright © 2019 p≡p Security S.A. All rights reserved.
    5.10 -//
    5.11 -
    5.12 -import Foundation
    5.13 -
    5.14 -import PantomimeFramework
    5.15 -import MessageModel
    5.16 -
    5.17 -public extension BasicConnectInfo {
    5.18 -    init?(verifiableAccount: VerifiableAccountProtocol, emailProtocol: EmailProtocol) {
    5.19 -        guard let theAddress = verifiableAccount.address else {
    5.20 -            return nil
    5.21 -        }
    5.22 -
    5.23 -        switch emailProtocol {
    5.24 -        case .imap:
    5.25 -            guard let severAddress = verifiableAccount.serverIMAP else {
    5.26 -                return nil
    5.27 -            }
    5.28 -            self.init(accountEmailAddress: theAddress,
    5.29 -                      loginName: verifiableAccount.loginName,
    5.30 -                      loginPassword: verifiableAccount.password,
    5.31 -                      accessToken: verifiableAccount.accessToken,
    5.32 -                      networkAddress: severAddress,
    5.33 -                      networkPort: verifiableAccount.portIMAP,
    5.34 -                      connectionTransport: verifiableAccount.transportIMAP,
    5.35 -                      authMethod: verifiableAccount.authMethod,
    5.36 -                      emailProtocol: emailProtocol)
    5.37 -        case .smtp:
    5.38 -            guard let severAddress = verifiableAccount.serverSMTP else {
    5.39 -                return nil
    5.40 -            }
    5.41 -            self.init(accountEmailAddress: theAddress,
    5.42 -                      loginName: verifiableAccount.loginName,
    5.43 -                      loginPassword: verifiableAccount.password,
    5.44 -                      accessToken: verifiableAccount.accessToken,
    5.45 -                      networkAddress: severAddress,
    5.46 -                      networkPort: verifiableAccount.portSMTP,
    5.47 -                      connectionTransport: verifiableAccount.transportSMTP,
    5.48 -                      authMethod: verifiableAccount.authMethod,
    5.49 -                      emailProtocol: emailProtocol)
    5.50 -        }
    5.51 -    }
    5.52 -}
     6.1 --- a/pEpForiOS/Models/VerifiableAccount/VerifiableAccount.swift	Thu May 09 17:41:47 2019 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,475 +0,0 @@
     6.4 -//
     6.5 -//  VerifiableAccount.swift
     6.6 -//  pEpForiOS
     6.7 -//
     6.8 -//  Created by buff on 04.08.17.
     6.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
    6.10 -//
    6.11 -
    6.12 -import MessageModel
    6.13 -import PantomimeFramework
    6.14 -import CoreData
    6.15 -
    6.16 -public class VerifiableAccount: VerifiableAccountProtocol {
    6.17 -    // MARK: - VerifiableAccountProtocol (data)
    6.18 -
    6.19 -    public weak var verifiableAccountDelegate: VerifiableAccountDelegate?
    6.20 -
    6.21 -    public var address: String?
    6.22 -
    6.23 -    /**
    6.24 -     The actual name of the user, or nick name. Not to be confused with the login name.
    6.25 -     */
    6.26 -    public var userName: String?
    6.27 -
    6.28 -    /**
    6.29 -     An optional name for the servers, if needed.
    6.30 -     */
    6.31 -    public var loginName: String?
    6.32 -
    6.33 -    /**
    6.34 -     Currently, the only use case for this is .saslXoauth2. In all other cases,
    6.35 -     this should be nil.
    6.36 -     */
    6.37 -    public var authMethod: AuthMethod?
    6.38 -
    6.39 -    public var password: String?
    6.40 -
    6.41 -    /**
    6.42 -     If the user chose OAuth2, this is the token. `password` then should be nil.
    6.43 -     */
    6.44 -    public var accessToken: OAuth2AccessTokenProtocol?
    6.45 -
    6.46 -    public var serverIMAP: String?
    6.47 -    public var portIMAP: UInt16 = 993
    6.48 -    public var transportIMAP = ConnectionTransport.TLS
    6.49 -    public var serverSMTP: String?
    6.50 -    public var portSMTP: UInt16 = 587
    6.51 -    public var transportSMTP = ConnectionTransport.startTLS
    6.52 -
    6.53 -    public var trustedImapServer: Bool
    6.54 -
    6.55 -    public init(verifiableAccountDelegate: VerifiableAccountDelegate?,
    6.56 -                address: String?,
    6.57 -                userName: String?,
    6.58 -                loginName: String?,
    6.59 -                authMethod: AuthMethod?,
    6.60 -                password: String?,
    6.61 -                accessToken: OAuth2AccessTokenProtocol?,
    6.62 -                serverIMAP: String?,
    6.63 -                portIMAP: UInt16,
    6.64 -                transportIMAP: ConnectionTransport,
    6.65 -                serverSMTP: String?,
    6.66 -                portSMTP: UInt16,
    6.67 -                transportSMTP: ConnectionTransport,
    6.68 -                trustedImapServer: Bool) {
    6.69 -        self.verifiableAccountDelegate = verifiableAccountDelegate
    6.70 -        self.address = address
    6.71 -        self.userName = userName
    6.72 -        self.loginName = loginName
    6.73 -        self.authMethod = authMethod
    6.74 -        self.password = password
    6.75 -        self.accessToken = accessToken
    6.76 -        self.serverIMAP = serverIMAP
    6.77 -        self .portIMAP = portIMAP
    6.78 -        self.transportIMAP = transportIMAP
    6.79 -        self.serverSMTP = serverSMTP
    6.80 -        self.portSMTP = portSMTP
    6.81 -        self.transportSMTP = transportSMTP
    6.82 -        self.trustedImapServer = trustedImapServer
    6.83 -    }
    6.84 -
    6.85 -    public convenience init() {
    6.86 -        self.init(verifiableAccountDelegate: nil,
    6.87 -                  address: nil,
    6.88 -                  userName: nil,
    6.89 -                  loginName: nil,
    6.90 -                  authMethod: nil,
    6.91 -                  password: nil,
    6.92 -                  accessToken: nil,
    6.93 -                  serverIMAP: nil,
    6.94 -                  portIMAP: 993,
    6.95 -                  transportIMAP: ConnectionTransport.TLS,
    6.96 -                  serverSMTP: nil,
    6.97 -                  portSMTP: 587,
    6.98 -                  transportSMTP: ConnectionTransport.startTLS,
    6.99 -                  trustedImapServer: false)
   6.100 -    }
   6.101 -
   6.102 -    // MARK: - Internal
   6.103 -
   6.104 -    private var imapVerifier: VerifiableAccountIMAP?
   6.105 -    private var smtpVerifier: VerifiableAccountSMTP?
   6.106 -
   6.107 -    var imapResult: Result<Void, Error>? = nil
   6.108 -    var smtpResult: Result<Void, Error>? = nil
   6.109 -
   6.110 -    /// Used for synchronizing the 2 asynchronous results (IMAP and SMTP verification).
   6.111 -    private let syncQueue = DispatchQueue(label: "VerifiableAccountSynchronization")
   6.112 -
   6.113 -    // MARK: - VerifiableAccountProtocol (behavior)
   6.114 -
   6.115 -    private func isValid() -> Bool {
   6.116 -        let isValid =
   6.117 -            (address?.count ?? 0) > 0 &&
   6.118 -                ((authMethod == .saslXoauth2 && accessToken != nil && password == nil) ||
   6.119 -                    (accessToken == nil && password != nil)) &&
   6.120 -                portIMAP > 0 &&
   6.121 -                portSMTP > 0 &&
   6.122 -                (serverIMAP?.count ?? 0) > 0 &&
   6.123 -                (serverSMTP?.count ?? 0) > 0
   6.124 -        return isValid
   6.125 -    }
   6.126 -
   6.127 -    private func startImapVerification() throws {
   6.128 -        let theVerifier = VerifiableAccountIMAP()
   6.129 -        self.imapVerifier = theVerifier
   6.130 -        theVerifier.verifiableAccountDelegate = self
   6.131 -        guard let imapConnectInfo = BasicConnectInfo(
   6.132 -            verifiableAccount: self, emailProtocol: .imap) else {
   6.133 -                // Assuming this is caused by invalid data.
   6.134 -                throw VerifiableAccountError.invalidUserData
   6.135 -        }
   6.136 -        theVerifier.verify(basicConnectInfo: imapConnectInfo)
   6.137 -    }
   6.138 -
   6.139 -    private func startSmtpVerification() throws {
   6.140 -        let theVerifier = VerifiableAccountSMTP()
   6.141 -        self.smtpVerifier = theVerifier
   6.142 -        theVerifier.verifiableAccountDelegate = self
   6.143 -        guard let smtpConnectInfo = BasicConnectInfo(
   6.144 -            verifiableAccount: self, emailProtocol: .smtp) else {
   6.145 -                // Assuming this is caused by invalid data.
   6.146 -                throw VerifiableAccountError.invalidUserData
   6.147 -        }
   6.148 -        theVerifier.verify(basicConnectInfo: smtpConnectInfo)
   6.149 -    }
   6.150 -
   6.151 -    public func verify() throws {
   6.152 -        if !isValid() {
   6.153 -            throw VerifiableAccountError.invalidUserData
   6.154 -        }
   6.155 -
   6.156 -        try startImapVerification()
   6.157 -        try startSmtpVerification()
   6.158 -    }
   6.159 -
   6.160 -    public func save() throws {
   6.161 -        if !isValid() {
   6.162 -            throw VerifiableAccountError.invalidUserData
   6.163 -        }
   6.164 -
   6.165 -        guard let addressImap = serverIMAP else {
   6.166 -            throw VerifiableAccountError.invalidUserData
   6.167 -        }
   6.168 -
   6.169 -        guard let addressSmtp = serverSMTP else {
   6.170 -            throw VerifiableAccountError.invalidUserData
   6.171 -        }
   6.172 -
   6.173 -        let moc = Record.Context.background
   6.174 -
   6.175 -        moc.performAndWait {
   6.176 -            let cdIdentity = updateOrCreateOwnIdentity(context: moc,
   6.177 -                                                       address: address,
   6.178 -                                                       userName: userName)
   6.179 -
   6.180 -            let cdAccount = findOrCreateAccount(context: moc, identity: cdIdentity)
   6.181 -
   6.182 -            // TODO: Reuse server!
   6.183 -            if let theServer = cdAccount.imapCdServer {
   6.184 -                delete(server: theServer, fromAccount: cdAccount)
   6.185 -            }
   6.186 -
   6.187 -            // TODO: Reuse server!
   6.188 -            if let theServer = cdAccount.smtpCdServer {
   6.189 -                delete(server: theServer, fromAccount: cdAccount)
   6.190 -            }
   6.191 -
   6.192 -            let imapServer = createServer(context: moc,
   6.193 -                                          address: addressImap,
   6.194 -                                          port: portIMAP,
   6.195 -                                          serverType: .imap,
   6.196 -                                          authMethod: authMethod,
   6.197 -                                          trusted: trustedImapServer,
   6.198 -                                          transport: transportIMAP)
   6.199 -
   6.200 -            let smtpServer = createServer(context: moc,
   6.201 -                                          address: addressSmtp,
   6.202 -                                          port: portSMTP,
   6.203 -                                          serverType: .smtp,
   6.204 -                                          authMethod: authMethod,
   6.205 -                                          trusted: false,
   6.206 -                                          transport: transportSMTP)
   6.207 -
   6.208 -            let credentialsImap = createCredentials(context: moc,
   6.209 -                                                    loginName: loginName,
   6.210 -                                                    address: address,
   6.211 -                                                    password: password,
   6.212 -                                                    accessToken: accessToken)
   6.213 -            credentialsImap.servers = NSSet(array: [imapServer])
   6.214 -            imapServer.credentials = credentialsImap
   6.215 -
   6.216 -            let credentialsSmtp = createCredentials(context: moc,
   6.217 -                                                    loginName: loginName,
   6.218 -                                                    address: address,
   6.219 -                                                    password: password,
   6.220 -                                                    accessToken: accessToken)
   6.221 -            credentialsSmtp.servers = NSSet(array: [smtpServer])
   6.222 -            smtpServer.credentials = credentialsSmtp
   6.223 -
   6.224 -            cdAccount.servers = NSSet(array: [imapServer, smtpServer])
   6.225 -
   6.226 -            moc.saveAndLogErrors()
   6.227 -        }
   6.228 -    }
   6.229 -
   6.230 -    // MARK: - Used by the UI, when using class directly
   6.231 -
   6.232 -    public var isValidName: Bool {
   6.233 -        return (userName?.count ?? 0) >= 1
   6.234 -    }
   6.235 -
   6.236 -    public var isValidUser: Bool {
   6.237 -        return isValidName && isValidEmail && isValidPassword
   6.238 -    }
   6.239 -
   6.240 -    private var isValidEmail: Bool {
   6.241 -        return address?.isProbablyValidEmail() ?? false
   6.242 -    }
   6.243 -
   6.244 -    private var isValidPassword: Bool {
   6.245 -        if let pass = password {
   6.246 -            return pass.count > 0
   6.247 -        }
   6.248 -        return false
   6.249 -    }
   6.250 -
   6.251 -    // MARK: - Helpers for saving
   6.252 -
   6.253 -    /// Deletes the given server from the account, including its credentials
   6.254 -    /// and entries in the key chain.
   6.255 -    private func delete(server: CdServer, fromAccount: CdAccount) {
   6.256 -        if let creds = server.credentials {
   6.257 -            if let key = creds.key {
   6.258 -                KeyChain.updateCreateOrDelete(password: nil, forKey: key)
   6.259 -            }
   6.260 -            server.credentials = nil
   6.261 -            creds.delete()
   6.262 -        }
   6.263 -        fromAccount.removeFromServers(server)
   6.264 -    }
   6.265 -
   6.266 -    private func findOrCreateAccount(context: NSManagedObjectContext,
   6.267 -                                     identity: CdIdentity) -> CdAccount {
   6.268 -        let p = NSPredicate(
   6.269 -            format: "%K = %@" , CdAccount.RelationshipName.identity, identity)
   6.270 -        if let cdAccount = CdAccount.first(predicate: p, in: context) {
   6.271 -            return cdAccount
   6.272 -        } else {
   6.273 -            let cdAccount = CdAccount.create(context: context)
   6.274 -            cdAccount.identity = identity
   6.275 -            return cdAccount
   6.276 -        }
   6.277 -    }
   6.278 -
   6.279 -    private func updateOrCreateOwnIdentity(context: NSManagedObjectContext,
   6.280 -                                           address: String?,
   6.281 -                                           userName: String?) -> CdIdentity {
   6.282 -        if let theAddress = address,
   6.283 -            let identity = CdIdentity.search(address: theAddress) {
   6.284 -            update(identity: identity, address: address, userName: userName)
   6.285 -            return identity
   6.286 -        } else {
   6.287 -        let cdId = CdIdentity.create(context: context)
   6.288 -            update(identity: cdId, address: address, userName: userName)
   6.289 -            return cdId
   6.290 -        }
   6.291 -    }
   6.292 -
   6.293 -    private func update(identity: CdIdentity,
   6.294 -                        address: String?,
   6.295 -                        userName: String?) {
   6.296 -        identity.address = address
   6.297 -        identity.userName = userName
   6.298 -        identity.userID = CdIdentity.pEpOwnUserID
   6.299 -    }
   6.300 -
   6.301 -    /// Create credentials for the given parameters.
   6.302 -    ///
   6.303 -    /// - Note: There is either an ordinary password, so a key chain entry
   6.304 -    ///         gets produced, or an access token (for OAUTH2),
   6.305 -    ///         in which case the token gets persisted into the key chain.
   6.306 -    private func createCredentials(context: NSManagedObjectContext,
   6.307 -                                   loginName: String?,
   6.308 -                                   address: String?,
   6.309 -                                   password: String?,
   6.310 -                                   accessToken: OAuth2AccessTokenProtocol?)
   6.311 -        -> CdServerCredentials {
   6.312 -            let credentials = CdServerCredentials.create(context: context)
   6.313 -            credentials.loginName = loginName ?? address
   6.314 -
   6.315 -            let keyChainId = UUID().uuidString
   6.316 -            var payload: String? = nil
   6.317 -            if let token = accessToken {
   6.318 -                payload = token.persistBase64Encoded()
   6.319 -            } else {
   6.320 -                payload = password
   6.321 -            }
   6.322 -
   6.323 -            KeyChain.updateCreateOrDelete(password: payload, forKey: keyChainId)
   6.324 -            credentials.key = keyChainId
   6.325 -
   6.326 -            return credentials
   6.327 -    }
   6.328 -
   6.329 -    private func createServer(context: NSManagedObjectContext,
   6.330 -                              address: String,
   6.331 -                              port: UInt16,
   6.332 -                              serverType: Server.ServerType,
   6.333 -                              authMethod: AuthMethod?,
   6.334 -                              trusted: Bool,
   6.335 -                              transport: ConnectionTransport) -> CdServer {
   6.336 -        let server = CdServer.create(context: context)
   6.337 -        update(server: server,
   6.338 -               address: address,
   6.339 -               port: port,
   6.340 -               serverType: serverType,
   6.341 -               authMethod: authMethod,
   6.342 -               trusted: trusted,
   6.343 -               transport: transport)
   6.344 -        return server
   6.345 -    }
   6.346 -
   6.347 -    private func update(server: CdServer,
   6.348 -                        address: String,
   6.349 -                        port: UInt16,
   6.350 -                        serverType: Server.ServerType,
   6.351 -                        authMethod: AuthMethod?,
   6.352 -                        trusted: Bool,
   6.353 -                        transport: ConnectionTransport) {
   6.354 -        server.address = address
   6.355 -        server.port = NSNumber.init(value: port)
   6.356 -        server.authMethod = authMethod?.rawValue
   6.357 -        server.serverType = serverType
   6.358 -        server.trusted = trusted
   6.359 -        server.transport = transport.toServerTransport()
   6.360 -        server.serverType = serverType
   6.361 -    }
   6.362 -
   6.363 -    // MARK: - Legacy
   6.364 -
   6.365 -    /// Returns an Account instance filled with data of self.
   6.366 -    /// It does not deal with Core Data (does not persist).
   6.367 -    /// Only data from this model is taken into account, not needsVerivication or others.
   6.368 -    ///
   6.369 -    /// - Returns: filled Account
   6.370 -    /// - Throws: AccountSettingsUserInputError
   6.371 -    public func account() throws -> Account {
   6.372 -        guard let address = self.address, address != "" else {
   6.373 -            let msg = NSLocalizedString("E-mail must not be empty",
   6.374 -                                        comment: "Alert message for empty e-mail address field")
   6.375 -            throw AccountSettingsUserInputError.invalidInputEmailAddress(localizedMessage: msg)
   6.376 -        }
   6.377 -
   6.378 -        guard let userName = self.userName, userName != "" else {
   6.379 -            let msg = NSLocalizedString("Username must not be empty",
   6.380 -                                        comment: "Alert message for empty username")
   6.381 -            throw AccountSettingsUserInputError.invalidInputUserName(localizedMessage: msg)
   6.382 -        }
   6.383 -
   6.384 -        guard let serverIMAP = self.serverIMAP, serverIMAP != "" else {
   6.385 -            let msg = NSLocalizedString("IMAP server must not be empty",
   6.386 -                                        comment: "Alert message for empty IMAP server")
   6.387 -            throw AccountSettingsUserInputError.invalidInputServer(localizedMessage: msg)
   6.388 -        }
   6.389 -        guard let serverSMTP = self.serverSMTP, serverSMTP != "" else {
   6.390 -            let msg = NSLocalizedString("SMTP server must not be empty",
   6.391 -                                        comment: "Alert message for empty SMTP server")
   6.392 -            throw AccountSettingsUserInputError.invalidInputServer(localizedMessage: msg)
   6.393 -        }
   6.394 -
   6.395 -        let identity = Identity.create(address: address, userID: nil, userName: userName,
   6.396 -                                       isMySelf: true)
   6.397 -
   6.398 -        var logIn = self.loginName ?? address
   6.399 -        if logIn.isEmpty {
   6.400 -            logIn = address
   6.401 -        }
   6.402 -
   6.403 -        let thePassword = accessToken?.persistBase64Encoded() ?? password
   6.404 -        // The key is created upfront, in case of SASL XOAUTH2, where we want to link
   6.405 -        // the token to the same key
   6.406 -        let credentialsImap = ServerCredentials.create(loginName: logIn,
   6.407 -                                                       key: accessToken?.keyChainID)
   6.408 -        credentialsImap.password = thePassword
   6.409 -
   6.410 -        let imapServer = Server.create(serverType: .imap, port: self.portIMAP, address: serverIMAP,
   6.411 -                                       transport: self.transportIMAP.toServerTransport(),
   6.412 -                                       authMethod: authMethod?.rawValue,
   6.413 -                                       credentials: credentialsImap)
   6.414 -
   6.415 -        let credentialsSmtp: ServerCredentials
   6.416 -        if authMethod == .saslXoauth2 {
   6.417 -            // In case of SASL XOAUTH2, there will be only 1 credential, with our created key
   6.418 -            credentialsSmtp = credentialsImap
   6.419 -        } else {
   6.420 -            credentialsSmtp = ServerCredentials.create(loginName: logIn, key: accessToken?.keyChainID)
   6.421 -            credentialsSmtp.password = thePassword
   6.422 -        }
   6.423 -
   6.424 -        let smtpServer = Server.create(serverType: .smtp,
   6.425 -                                       port: self.portSMTP,
   6.426 -                                       address: serverSMTP,
   6.427 -                                       transport: self.transportSMTP.toServerTransport(),
   6.428 -                                       authMethod: authMethod?.rawValue,
   6.429 -                                       credentials: credentialsSmtp)
   6.430 -
   6.431 -        let account = Account(user: identity, servers: [imapServer, smtpServer])
   6.432 -        return account
   6.433 -    }
   6.434 -
   6.435 -    // MARK: - Internal (Behaviour)
   6.436 -
   6.437 -    private func checkSuccess() {
   6.438 -        guard let theImapResult = imapResult, let theSmtpResult = smtpResult else {
   6.439 -            return
   6.440 -        }
   6.441 -
   6.442 -        switch theImapResult {
   6.443 -        case .failure(let error):
   6.444 -            verifiableAccountDelegate?.didEndVerification(result: .failure(error))
   6.445 -        case .success(()):
   6.446 -            switch theSmtpResult {
   6.447 -            case .failure(let error):
   6.448 -                verifiableAccountDelegate?.didEndVerification(result: .failure(error))
   6.449 -            case .success(()):
   6.450 -                verifiableAccountDelegate?.didEndVerification(result: .success(()))
   6.451 -            }
   6.452 -        }
   6.453 -    }
   6.454 -}
   6.455 -
   6.456 -extension VerifiableAccount: VerifiableAccountIMAPDelegate {
   6.457 -    public func verified(verifier: VerifiableAccountIMAP,
   6.458 -                         basicConnectInfo: BasicConnectInfo,
   6.459 -                         result: Result<Void, Error>) {
   6.460 -        verifier.verifiableAccountDelegate = nil
   6.461 -        syncQueue.async { [weak self] in
   6.462 -            self?.imapResult = result
   6.463 -            self?.checkSuccess()
   6.464 -        }
   6.465 -    }
   6.466 -}
   6.467 -
   6.468 -extension VerifiableAccount: VerifiableAccountSMTPDelegate {
   6.469 -    public func verified(verifier: VerifiableAccountSMTP,
   6.470 -                         basicConnectInfo: BasicConnectInfo,
   6.471 -                         result: Result<Void, Error>) {
   6.472 -        verifier.verifiableAccountDelegate = nil
   6.473 -        syncQueue.async { [weak self] in
   6.474 -            self?.smtpResult = result
   6.475 -            self?.checkSuccess()
   6.476 -        }
   6.477 -    }
   6.478 -}
     7.1 --- a/pEpForiOS/Models/VerifiableAccount/VerifiableAccountIMAP.swift	Thu May 09 17:41:47 2019 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,65 +0,0 @@
     7.4 -//
     7.5 -//  VerifiableAccountIMAP.swift
     7.6 -//  pEp
     7.7 -//
     7.8 -//  Created by Dirk Zimmermann on 16.04.19.
     7.9 -//  Copyright © 2019 p≡p Security S.A. All rights reserved.
    7.10 -//
    7.11 -
    7.12 -import Foundation
    7.13 -
    7.14 -import PantomimeFramework
    7.15 -import MessageModel
    7.16 -import pEpIOSToolbox
    7.17 -
    7.18 -public protocol VerifiableAccountIMAPDelegate: class {
    7.19 -    func verified(verifier: VerifiableAccountIMAP,
    7.20 -                  basicConnectInfo: BasicConnectInfo,
    7.21 -                  result: Result<Void, Error>)
    7.22 -}
    7.23 -
    7.24 -/// Helper for `VerifiableAccount` (verifies IMAP servers).
    7.25 -public class VerifiableAccountIMAP {
    7.26 -    public weak var verifiableAccountDelegate: VerifiableAccountIMAPDelegate?
    7.27 -
    7.28 -    private var sync: ImapSync?
    7.29 -    private var syncDelegate: VerifiableAccountSyncDelegate?
    7.30 -    private var basicConnectInfo: BasicConnectInfo?
    7.31 -
    7.32 -    /// Tries to verify the given IMAP account.
    7.33 -    public func verify(basicConnectInfo: BasicConnectInfo) {
    7.34 -        self.basicConnectInfo = basicConnectInfo
    7.35 -
    7.36 -        let theSyncDelegate = VerifiableAccountSyncDelegate(errorHandler: self)
    7.37 -        syncDelegate = theSyncDelegate
    7.38 -
    7.39 -        sync = ImapSync(connectInfo: basicConnectInfo)
    7.40 -        sync?.delegate = syncDelegate
    7.41 -        sync?.start()
    7.42 -    }
    7.43 -
    7.44 -    func authenticationCompleted(_ sync: ImapSync, notification: Notification?) {
    7.45 -        self.sync = nil
    7.46 -
    7.47 -        verifiableAccountDelegate?.verified(
    7.48 -            verifier: self,
    7.49 -            basicConnectInfo: BasicConnectInfo.force(basicConnectInfo: basicConnectInfo),
    7.50 -            result: .success(()))
    7.51 -    }
    7.52 -}
    7.53 -
    7.54 -extension VerifiableAccountIMAP: ImapSyncDelegateErrorHandlerProtocol {
    7.55 -    public func handle(error: Error) {
    7.56 -        verifiableAccountDelegate?.verified(
    7.57 -            verifier: self,
    7.58 -            basicConnectInfo: BasicConnectInfo.force(basicConnectInfo: basicConnectInfo),
    7.59 -            result: .failure(error))
    7.60 -    }
    7.61 -}
    7.62 -
    7.63 -class VerifiableAccountSyncDelegate: DefaultImapSyncDelegate {
    7.64 -    override func authenticationCompleted(_ sync: ImapSync, notification: Notification?) {
    7.65 -        (errorHandler as? VerifiableAccountIMAP)?.authenticationCompleted(
    7.66 -            sync, notification: notification)
    7.67 -    }
    7.68 -}
     8.1 --- a/pEpForiOS/Models/VerifiableAccount/VerifiableAccountProtocol+UI.swift	Thu May 09 17:41:47 2019 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,33 +0,0 @@
     8.4 -//
     8.5 -//  VerifiableAccountProtocol+UI.swift
     8.6 -//  pEp
     8.7 -//
     8.8 -//  Created by Dirk Zimmermann on 18.04.19.
     8.9 -//  Copyright © 2019 p≡p Security S.A. All rights reserved.
    8.10 -//
    8.11 -
    8.12 -import Foundation
    8.13 -
    8.14 -import MessageModel
    8.15 -
    8.16 -/// Used by the UI.
    8.17 -public extension VerifiableAccountProtocol {
    8.18 -    public var isValidName: Bool {
    8.19 -        return (userName?.count ?? 0) >= 1
    8.20 -    }
    8.21 -
    8.22 -    public var isValidUser: Bool {
    8.23 -        return isValidName && isValidEmail && isValidPassword
    8.24 -    }
    8.25 -
    8.26 -    private var isValidEmail: Bool {
    8.27 -        return address?.isProbablyValidEmail() ?? false
    8.28 -    }
    8.29 -
    8.30 -    private var isValidPassword: Bool {
    8.31 -        if let pass = password {
    8.32 -            return pass.count > 0
    8.33 -        }
    8.34 -        return false
    8.35 -    }
    8.36 -}
     9.1 --- a/pEpForiOS/Models/VerifiableAccount/VerifiableAccountSMTP.swift	Thu May 09 17:41:47 2019 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,131 +0,0 @@
     9.4 -//
     9.5 -//  VerifiableAccountSMTP.swift
     9.6 -//  pEp
     9.7 -//
     9.8 -//  Created by Dirk Zimmermann on 17.04.19.
     9.9 -//  Copyright © 2019 p≡p Security S.A. All rights reserved.
    9.10 -//
    9.11 -
    9.12 -import Foundation
    9.13 -
    9.14 -import PantomimeFramework
    9.15 -import MessageModel
    9.16 -import pEpIOSToolbox
    9.17 -
    9.18 -public protocol VerifiableAccountSMTPDelegate: class {
    9.19 -    func verified(verifier: VerifiableAccountSMTP,
    9.20 -                  basicConnectInfo: BasicConnectInfo,
    9.21 -                  result: Result<Void, Error>)
    9.22 -}
    9.23 -
    9.24 -/// Helper for `VerifiableAccount` (verifies SMTP servers).
    9.25 -public class VerifiableAccountSMTP {
    9.26 -    public weak var verifiableAccountDelegate: VerifiableAccountSMTPDelegate?
    9.27 -
    9.28 -    private var smtpSend: SmtpSend?
    9.29 -    private var basicConnectInfo: BasicConnectInfo?
    9.30 -
    9.31 -    /// Tries to verify the given IMAP account.
    9.32 -    public func verify(basicConnectInfo: BasicConnectInfo) {
    9.33 -        self.basicConnectInfo = basicConnectInfo
    9.34 -
    9.35 -        smtpSend = SmtpSend(connectInfo: basicConnectInfo)
    9.36 -        smtpSend?.delegate = self
    9.37 -        smtpSend?.start()
    9.38 -    }
    9.39 -}
    9.40 -
    9.41 -extension VerifiableAccountSMTP: SmtpSendDelegate {
    9.42 -    private func forcedConnectInfo() -> BasicConnectInfo {
    9.43 -        return BasicConnectInfo.force(basicConnectInfo: basicConnectInfo)
    9.44 -    }
    9.45 -
    9.46 -    private func notifyUnexpectedCallback(name: String) {
    9.47 -        let error = SmtpSendError.badResponse(name)
    9.48 -        verifiableAccountDelegate?.verified(
    9.49 -            verifier: self,
    9.50 -            basicConnectInfo: forcedConnectInfo(),
    9.51 -            result: .failure(error))
    9.52 -    }
    9.53 -
    9.54 -    private func notify(error: Error) {
    9.55 -        verifiableAccountDelegate?.verified(
    9.56 -            verifier: self,
    9.57 -            basicConnectInfo: forcedConnectInfo(),
    9.58 -            result: .failure(error))
    9.59 -    }
    9.60 -
    9.61 -    public func messageSent(_ smtp: SmtpSend, theNotification: Notification?) {
    9.62 -        notifyUnexpectedCallback(name: #function)
    9.63 -    }
    9.64 -
    9.65 -    public func messageNotSent(_ smtp: SmtpSend, theNotification: Notification?) {
    9.66 -        notifyUnexpectedCallback(name: #function)
    9.67 -    }
    9.68 -
    9.69 -    public func transactionInitiationCompleted(_ smtp: SmtpSend, theNotification: Notification?) {
    9.70 -        notifyUnexpectedCallback(name: #function)
    9.71 -    }
    9.72 -
    9.73 -    public func transactionInitiationFailed(_ smtp: SmtpSend, theNotification: Notification?) {
    9.74 -        notifyUnexpectedCallback(name: #function)
    9.75 -    }
    9.76 -
    9.77 -    public func recipientIdentificationCompleted(_ smtp: SmtpSend, theNotification: Notification?) {
    9.78 -        notifyUnexpectedCallback(name: #function)
    9.79 -    }
    9.80 -
    9.81 -    public func recipientIdentificationFailed(_ smtp: SmtpSend, theNotification: Notification?) {
    9.82 -        notifyUnexpectedCallback(name: #function)
    9.83 -    }
    9.84 -
    9.85 -    public func transactionResetCompleted(_ smtp: SmtpSend, theNotification: Notification?) {
    9.86 -        notifyUnexpectedCallback(name: #function)
    9.87 -    }
    9.88 -
    9.89 -    public func transactionResetFailed(_ smtp: SmtpSend, theNotification: Notification?) {
    9.90 -        notifyUnexpectedCallback(name: #function)
    9.91 -    }
    9.92 -
    9.93 -    public func authenticationCompleted(_ smtp: SmtpSend, theNotification: Notification?) {
    9.94 -    }
    9.95 -
    9.96 -    public func authenticationFailed(_ smtp: SmtpSend, theNotification: Notification?) {
    9.97 -        notify(error: SmtpSendError.authenticationFailed(
    9.98 -            #function,
    9.99 -            forcedConnectInfo().accountEmailAddress))
   9.100 -    }
   9.101 -
   9.102 -    public func connectionEstablished(_ smtp: SmtpSend, theNotification: Notification?) {}
   9.103 -
   9.104 -    public func connectionLost(_ smtp: SmtpSend, theNotification: Notification?) {
   9.105 -        notify(error: SmtpSendError.connectionLost(#function))
   9.106 -    }
   9.107 -
   9.108 -    public func connectionTerminated(_ smtp: SmtpSend, theNotification: Notification?) {
   9.109 -        notify(error: SmtpSendError.connectionTerminated(#function))
   9.110 -    }
   9.111 -
   9.112 -    public func connectionTimedOut(_ smtp: SmtpSend, theNotification: Notification?) {
   9.113 -        notify(error: SmtpSendError.connectionTimedOut(#function))
   9.114 -    }
   9.115 -
   9.116 -    public func badResponse(_ smtp: SmtpSend, response: String?) {
   9.117 -        notify(error: SmtpSendError.badResponse(#function))
   9.118 -    }
   9.119 -
   9.120 -    public func requestCancelled(_ smtp: SmtpSend, theNotification: Notification?) {
   9.121 -        notifyUnexpectedCallback(name: #function)
   9.122 -    }
   9.123 -
   9.124 -    public func serviceInitialized(_ smtp: SmtpSend, theNotification: Notification?) {
   9.125 -        verifiableAccountDelegate?.verified(
   9.126 -            verifier: self,
   9.127 -            basicConnectInfo: forcedConnectInfo(),
   9.128 -            result: .success(()))
   9.129 -    }
   9.130 -
   9.131 -    public func serviceReconnected(_ smtp: SmtpSend, theNotification: Notification?) {
   9.132 -        notifyUnexpectedCallback(name: #function)
   9.133 -    }
   9.134 -}
    10.1 --- a/pEpForiOS/UI/Login/LoginViewController.swift	Thu May 09 17:41:47 2019 +0200
    10.2 +++ b/pEpForiOS/UI/Login/LoginViewController.swift	Fri May 17 14:07:44 2019 +0200
    10.3 @@ -77,18 +77,12 @@
    10.4          }
    10.5      }
    10.6  
    10.7 -    /**
    10.8 -     The last account input as determined by LAS, and delivered via didVerify.
    10.9 -     */
   10.10 -    var lastAccountInput: VerifiableAccountProtocol?
   10.11 -
   10.12      override var prefersStatusBarHidden: Bool {
   10.13          return true
   10.14      }
   10.15  
   10.16      override func didSetAppConfig() {
   10.17          super.didSetAppConfig()
   10.18 -        loginViewModel.verificationService = VerifiableAccount()
   10.19      }
   10.20  
   10.21      override func viewDidLoad() {
   10.22 @@ -291,11 +285,7 @@
   10.23                  let vc = navVC.topViewController as? UserInfoTableViewController {
   10.24                  vc.appConfig = appConfig
   10.25  
   10.26 -                if let accountInput = lastAccountInput {
   10.27 -                    vc.model = accountInput // give the user some prefilled data in manual mode
   10.28 -                }
   10.29 -
   10.30 -                // Overwrite with more recent data that we might have (in case it was changed)
   10.31 +                // Give the next model what we know.
   10.32                  vc.model.address = emailAddress.text
   10.33                  vc.model.password = password.text
   10.34                  vc.model.userName = user.text
   10.35 @@ -309,26 +299,21 @@
   10.36  // MARK: - AccountVerificationResultDelegate
   10.37  
   10.38  extension LoginViewController: AccountVerificationResultDelegate {
   10.39 -    func didVerify(result: AccountVerificationResult,
   10.40 -                   accountInput: VerifiableAccountProtocol?) {
   10.41 +    func didVerify(result: AccountVerificationResult) {
   10.42          GCD.onMain() { [weak self] in
   10.43              guard let me = self else {
   10.44                  Log.shared.errorAndCrash("Lost MySelf")
   10.45                  return
   10.46              }
   10.47 -            me.lastAccountInput = nil
   10.48              switch result {
   10.49              case .ok:
   10.50                  me.delegate?.loginViewControllerDidCreateNewAccount(me)
   10.51                  me.navigationController?.dismiss(animated: true)
   10.52              case .imapError(let err):
   10.53 -                me.lastAccountInput = accountInput
   10.54                  me.handleLoginError(error: err, offerManualSetup: true)
   10.55              case .smtpError(let err):
   10.56 -                me.lastAccountInput = accountInput
   10.57                  me.handleLoginError(error: err, offerManualSetup: true)
   10.58              case .noImapConnectData, .noSmtpConnectData:
   10.59 -                me.lastAccountInput = accountInput
   10.60                  me.handleLoginError(error: LoginViewController.LoginError.noConnectData,
   10.61                                      offerManualSetup: true)
   10.62              }
    11.1 --- a/pEpForiOS/UI/Login/ViewModel/LoginViewModel.swift	Thu May 09 17:41:47 2019 +0200
    11.2 +++ b/pEpForiOS/UI/Login/ViewModel/LoginViewModel.swift	Fri May 17 14:07:44 2019 +0200
    11.3 @@ -25,7 +25,7 @@
    11.4  
    11.5      /// Holding both the data of the current account in verification,
    11.6      /// and also the implementation of the verification.
    11.7 -    var verificationService: VerifiableAccountProtocol?
    11.8 +    var verifiableAccount: VerifiableAccountProtocol?
    11.9  
   11.10      /** If the last login attempt was via OAuth2, this will collect temporary parameters */
   11.11      private var lastOAuth2Parameters: OAuth2Parameters?
   11.12 @@ -52,8 +52,8 @@
   11.13  
   11.14      let qualifyServerService = QualifyServerIsLocalService()
   11.15  
   11.16 -    init(verificationService: VerifiableAccountProtocol? = nil) {
   11.17 -        self.verificationService = verificationService
   11.18 +    init(verifiableAccount: VerifiableAccountProtocol? = nil) {
   11.19 +        self.verifiableAccount = verifiableAccount
   11.20      }
   11.21  
   11.22      func isThereAnAccount() -> Bool {
   11.23 @@ -116,7 +116,7 @@
   11.24              let smtpTransport = ConnectionTransport(
   11.25                  accountSettingsTransport: outgoingServer.transport, smtpPort: outgoingServer.port)
   11.26  
   11.27 -            var newAccount = verificationService ?? VerifiableAccount()
   11.28 +            var newAccount = verifiableAccount ?? VerifiableAccount()
   11.29  
   11.30              newAccount.verifiableAccountDelegate = self
   11.31              newAccount.address = accountName
   11.32 @@ -137,7 +137,7 @@
   11.33              newAccount.transportSMTP = smtpTransport
   11.34              newAccount.trustedImapServer = false
   11.35  
   11.36 -            verificationService = newAccount
   11.37 +            verifiableAccount = newAccount
   11.38              verifyAccount(model: newAccount)
   11.39          }
   11.40      }
   11.41 @@ -147,7 +147,7 @@
   11.42      /// - Parameter model: account data
   11.43      /// - Throws: AccountVerificationError
   11.44      func verifyAccount(model: VerifiableAccountProtocol?) {
   11.45 -        if let imapServer = verificationService?.serverIMAP {
   11.46 +        if let imapServer = verifiableAccount?.serverIMAP {
   11.47              qualifyServerService.delegate = self
   11.48              qualifyServerService.qualify(serverName: imapServer)
   11.49          } else {
   11.50 @@ -156,12 +156,13 @@
   11.51      }
   11.52  
   11.53      func accountHasBeenQualified(trusted: Bool) {
   11.54 -        guard var theVerificationService = verificationService else {
   11.55 +        guard var theVerificationService = verifiableAccount else {
   11.56              Log.shared.errorAndCrash("no VerificationService")
   11.57              return
   11.58          }
   11.59  
   11.60          theVerificationService.trustedImapServer = trusted
   11.61 +
   11.62          do {
   11.63              try theVerificationService.verify()
   11.64          } catch {
   11.65 @@ -222,25 +223,17 @@
   11.66  
   11.67  extension LoginViewModel: VerifiableAccountDelegate {
   11.68      func informAccountVerificationResultDelegate(error: Error?) {
   11.69 -        guard let theService = verificationService else {
   11.70 -            Log.shared.error(
   11.71 -                "Lost the verificationService, was about to inform the delegate")
   11.72 -            if let err = error {
   11.73 -                Log.shared.log("%@", err.localizedDescription)
   11.74 -            }
   11.75 -            return
   11.76 -        }
   11.77          if let imapError = error as? ImapSyncError {
   11.78              accountVerificationResultDelegate?.didVerify(
   11.79 -                result: .imapError(imapError), accountInput: theService)
   11.80 +                result: .imapError(imapError))
   11.81          } else if let smtpError = error as? SmtpSendError {
   11.82              accountVerificationResultDelegate?.didVerify(
   11.83 -                result: .smtpError(smtpError), accountInput: theService)
   11.84 +                result: .smtpError(smtpError))
   11.85          } else {
   11.86              if let theError = error {
   11.87                  Log.shared.errorAndCrash("%@", theError.localizedDescription)
   11.88              } else {
   11.89 -                accountVerificationResultDelegate?.didVerify(result: .ok, accountInput: theService)
   11.90 +                accountVerificationResultDelegate?.didVerify(result: .ok)
   11.91              }
   11.92          }
   11.93      }
   11.94 @@ -249,7 +242,7 @@
   11.95          switch result {
   11.96          case .success(()):
   11.97              do {
   11.98 -                try verificationService?.save()
   11.99 +                try verifiableAccount?.save()
  11.100                  informAccountVerificationResultDelegate(error: nil)
  11.101                  mySelfer?.startMySelf()
  11.102              } catch {
    12.1 --- a/pEpForiOS/UI/ManualLogin/ImapSetup/IMAPSettingsTableViewController.swift	Thu May 09 17:41:47 2019 +0200
    12.2 +++ b/pEpForiOS/UI/ManualLogin/ImapSetup/IMAPSettingsTableViewController.swift	Fri May 17 14:07:44 2019 +0200
    12.3 @@ -32,7 +32,9 @@
    12.4  
    12.5      let viewWidthAligner = ViewWidthsAligner()
    12.6  
    12.7 -    var model: VerifiableAccountProtocol!
    12.8 +    /// - Note: This VC doesn't have a view model yet, so this is used for the model.
    12.9 +    var model: VerifiableAccountProtocol?
   12.10 +
   12.11      var fields = [UITextField]()
   12.12      var responder = 0
   12.13  
   12.14 @@ -59,13 +61,15 @@
   12.15  
   12.16      override func viewDidAppear(_ animated: Bool) {
   12.17          super.viewDidAppear(animated)
   12.18 -        firstResponder(model.serverIMAP == nil)
   12.19 +        firstResponder(model?.serverIMAP == nil)
   12.20      }
   12.21  
   12.22      private func updateView() {
   12.23 -        serverValue.text = model.serverIMAP
   12.24 -        portValue.text = String(model.portIMAP)
   12.25 -        transportSecurity.setTitle(model.transportIMAP.localizedString(), for: UIControl.State())
   12.26 +        serverValue.text = model?.serverIMAP
   12.27 +        if let thePort = model?.portIMAP {
   12.28 +            portValue.text = String(thePort)
   12.29 +        }
   12.30 +        transportSecurity.setTitle(model?.transportIMAP.localizedString(), for: UIControl.State())
   12.31      }
   12.32  
   12.33      @IBAction func alertWithSecurityValues(_ sender: UIButton) {
   12.34 @@ -76,7 +80,7 @@
   12.35                                         comment: "UI alert message for transport protocol"),
   12.36              preferredStyle: .actionSheet)
   12.37          let block: (ConnectionTransport) -> () = { transport in
   12.38 -            self.model.transportIMAP = transport
   12.39 +            self.model?.transportIMAP = transport
   12.40              self.updateView()
   12.41          }
   12.42  
   12.43 @@ -98,13 +102,13 @@
   12.44      @IBAction func changePort(_ sender: UITextField) {
   12.45          if let text = portValue.text {
   12.46              if let port = UInt16(text) {
   12.47 -                model.portIMAP = port
   12.48 +                model?.portIMAP = port
   12.49              }
   12.50          }
   12.51      }
   12.52  
   12.53      @IBAction func changeServer(_ sender: UITextField) {
   12.54 -        model.serverIMAP = serverValue.text!
   12.55 +        model?.serverIMAP = serverValue.text
   12.56      }
   12.57  
   12.58      public func textFieldShouldReturn(_ textfield: UITextField) -> Bool {
   12.59 @@ -129,9 +133,13 @@
   12.60      public override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
   12.61          switch segueIdentifier(for: segue) {
   12.62          case .SMTPSettings:
   12.63 -            let destination = segue.destination as! SMTPSettingsTableViewController
   12.64 -            destination.appConfig = appConfig
   12.65 -            destination.model = model
   12.66 +            if let destination = segue.destination as? SMTPSettingsTableViewController {
   12.67 +                destination.appConfig = appConfig
   12.68 +                destination.model = model
   12.69 +            } else {
   12.70 +                Log.shared.errorAndCrash(
   12.71 +                    "Seque is .SMTPSettings, but controller is not a SMTPSettingsTableViewController")
   12.72 +            }
   12.73              break
   12.74          default:()
   12.75          }
    13.1 --- a/pEpForiOS/UI/ManualLogin/SMTPSetup/SMTPSettingsTableViewController.swift	Thu May 09 17:41:47 2019 +0200
    13.2 +++ b/pEpForiOS/UI/ManualLogin/SMTPSetup/SMTPSettingsTableViewController.swift	Fri May 17 14:07:44 2019 +0200
    13.3 @@ -21,7 +21,9 @@
    13.4      @IBOutlet weak var serverTitle: UILabel!
    13.5      @IBOutlet weak var portTitle: UILabel!
    13.6  
    13.7 -    var model: VerifiableAccountProtocol!
    13.8 +    /// - Note: This VC doesn't have a view model yet, so this is used for the model.
    13.9 +    var model: VerifiableAccountProtocol?
   13.10 +
   13.11      var fields = [UITextField]()
   13.12      var responder = 0
   13.13  
   13.14 @@ -48,7 +50,7 @@
   13.15  
   13.16      public override func viewDidAppear(_ animated: Bool) {
   13.17          super.viewDidAppear(animated)
   13.18 -        firstResponder(model.serverSMTP == nil)
   13.19 +        firstResponder(model?.serverSMTP == nil)
   13.20      }
   13.21  
   13.22      public override func viewDidLayoutSubviews() {
   13.23 @@ -59,9 +61,11 @@
   13.24      // MARK: - Working Bees
   13.25  
   13.26      private func updateView() {
   13.27 -        serverValue.text = model.serverSMTP
   13.28 -        portValue.text = String(model.portSMTP)
   13.29 -        transportSecurity.setTitle(model.transportSMTP.localizedString(), for: UIControl.State())
   13.30 +        serverValue.text = model?.serverSMTP
   13.31 +        if let thePort = model?.portSMTP {
   13.32 +            portValue.text = String(thePort)
   13.33 +        }
   13.34 +        transportSecurity.setTitle(model?.transportSMTP.localizedString(), for: UIControl.State())
   13.35  
   13.36          if isCurrentlyVerifying {
   13.37              activityIndicatorView.startAnimating()
   13.38 @@ -76,8 +80,8 @@
   13.39      /// - Throws: AccountVerificationError
   13.40      private func verifyAccount() throws {
   13.41          isCurrentlyVerifying =  true
   13.42 -        model.verifiableAccountDelegate = self
   13.43 -        try model.verify()
   13.44 +        model?.verifiableAccountDelegate = self
   13.45 +        try model?.verify()
   13.46      }
   13.47  
   13.48      private func informUser(about error: Error, title: String) {
   13.49 @@ -107,7 +111,7 @@
   13.50                                         comment: "UI alert message for transport protocol"),
   13.51              preferredStyle: .actionSheet)
   13.52          let block: (ConnectionTransport) -> () = { transport in
   13.53 -            self.model.transportSMTP = transport
   13.54 +            self.model?.transportSMTP = transport
   13.55              self.updateView()
   13.56          }
   13.57  
   13.58 @@ -127,13 +131,13 @@
   13.59      }
   13.60  
   13.61      @IBAction func changeServer(_ sender: UITextField) {
   13.62 -        model.serverSMTP = sender.text
   13.63 +        model?.serverSMTP = sender.text
   13.64      }
   13.65  
   13.66      @IBAction func changePort(_ sender: UITextField) {
   13.67          if let text = portValue.text {
   13.68              if let port = UInt16(text) {
   13.69 -                model.portSMTP = port
   13.70 +                model?.portSMTP = port
   13.71              }
   13.72          }
   13.73      }
   13.74 @@ -215,19 +219,37 @@
   13.75      func didEndVerification(result: Result<Void, Error>) {
   13.76          switch result {
   13.77          case .success(()):
   13.78 -                MessageModelUtil.performAndWait { [weak self] in
   13.79 -                    do {
   13.80 -                        try self?.model.save()
   13.81 -                    } catch {
   13.82 -                        Log.shared.errorAndCrash("%@", error.localizedDescription)
   13.83 -                    }
   13.84 +            MessageModelUtil.performAndWait { [weak self] in
   13.85 +                // Note: Currently, there is no way for the VC to disappear
   13.86 +                // before the verification has happened.
   13.87 +                guard let theSelf = self else {
   13.88 +                    Log.shared.lostMySelf()
   13.89 +                    return
   13.90                  }
   13.91 -                GCD.onMain() {
   13.92 -                    self.performSegue(withIdentifier: .backToEmailListSegue, sender: self)
   13.93 +
   13.94 +                do {
   13.95 +                    try theSelf.model?.save()
   13.96 +                } catch {
   13.97 +                    Log.shared.errorAndCrash("%@", error.localizedDescription)
   13.98 +                }
   13.99 +            }
  13.100 +            GCD.onMain() {  [weak self] in
  13.101 +                // Note: Currently, there is no way for the VC to disappear
  13.102 +                // before the verification has happened.
  13.103 +                guard let theSelf = self else {
  13.104 +                    Log.shared.lostMySelf()
  13.105 +                    return
  13.106 +                }
  13.107 +
  13.108 +                theSelf.isCurrentlyVerifying = false
  13.109 +                theSelf.performSegue(withIdentifier: .backToEmailListSegue, sender: theSelf)
  13.110              }
  13.111          case .failure(let error):
  13.112 -            GCD.onMain() {
  13.113 -                UIUtils.show(error: error, inViewController: self)
  13.114 +            GCD.onMain() { [weak self] in
  13.115 +                if let theSelf = self {
  13.116 +                    theSelf.isCurrentlyVerifying = false
  13.117 +                    UIUtils.show(error: error, inViewController: theSelf)
  13.118 +                }
  13.119              }
  13.120          }
  13.121      }
    14.1 --- a/pEpForiOS/UI/Settings/Setting/AccountSettings/AccountSettingsTableViewController.swift	Thu May 09 17:41:47 2019 +0200
    14.2 +++ b/pEpForiOS/UI/Settings/Setting/AccountSettings/AccountSettingsTableViewController.swift	Fri May 17 14:07:44 2019 +0200
    14.3 @@ -27,6 +27,9 @@
    14.4      @IBOutlet weak var passwordTableViewCell: UITableViewCell!
    14.5      @IBOutlet weak var oauth2TableViewCell: UITableViewCell!
    14.6      @IBOutlet weak var oauth2ActivityIndicator: UIActivityIndicatorView!
    14.7 +    @IBOutlet weak var doneButton: UIBarButtonItem!
    14.8 +
    14.9 +
   14.10      private let spinner: UIActivityIndicatorView = {
   14.11          let createe = UIActivityIndicatorView()
   14.12          createe.hidesWhenStopped = true
   14.13 @@ -48,7 +51,7 @@
   14.14       should trigger the reauthorization.
   14.15       */
   14.16      var oauth2ReauthIndexPath: IndexPath?
   14.17 -    
   14.18 +
   14.19       override func viewDidLoad() {
   14.20          super.viewDidLoad()
   14.21          configureView()
   14.22 @@ -245,7 +248,7 @@
   14.23                  password = nil
   14.24              }
   14.25  
   14.26 -            showSpinner()
   14.27 +            showSpinnerAndDisableUI()
   14.28              viewModel?.update(loginName: validated.loginName, name: validated.accountName,
   14.29                                password: password, imap: imap, smtp: smtp)
   14.30  
   14.31 @@ -305,10 +308,9 @@
   14.32  // MARK: - AccountVerificationResultDelegate
   14.33  
   14.34  extension AccountSettingsTableViewController: AccountVerificationResultDelegate {
   14.35 -    func didVerify(result: AccountVerificationResult,
   14.36 -                   accountInput: VerifiableAccountProtocol?) {
   14.37 +    func didVerify(result: AccountVerificationResult) {
   14.38          GCD.onMain() {
   14.39 -            self.hideSpinner()
   14.40 +            self.hideSpinnerAndEnableUI()
   14.41              switch result {
   14.42              case .ok:
   14.43                  self.navigationController?.popViewController(animated: true)
   14.44 @@ -346,7 +348,11 @@
   14.45  // MARK: - SPINNER
   14.46  
   14.47  extension AccountSettingsTableViewController {
   14.48 -    private func showSpinner() {
   14.49 +    /// Shows the spinner and disables UI parts that could lead to
   14.50 +    /// launching another verification while one is already in process.
   14.51 +    private func showSpinnerAndDisableUI() {
   14.52 +        doneButton.isEnabled = false
   14.53 +
   14.54          spinner.center =
   14.55              CGPoint(x: tableView.frame.width / 2,
   14.56                      y:
   14.57 @@ -357,7 +363,9 @@
   14.58          spinner.startAnimating()
   14.59      }
   14.60  
   14.61 -    private func hideSpinner() {
   14.62 +    /// Hides the spinner and enables all UI elements again.
   14.63 +    private func hideSpinnerAndEnableUI() {
   14.64 +        doneButton.isEnabled = true
   14.65          tableView.isUserInteractionEnabled = true
   14.66          spinner.stopAnimating()
   14.67      }
    15.1 --- a/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift	Thu May 09 17:41:47 2019 +0200
    15.2 +++ b/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift	Fri May 17 14:07:44 2019 +0200
    15.3 @@ -44,6 +44,10 @@
    15.4      public let svm = SecurityViewModel()
    15.5      public let isOAuth2: Bool
    15.6  
    15.7 +    /// Holding both the data of the current account in verification,
    15.8 +    /// and also the implementation of the verification.
    15.9 +    public var verifiableAccount: VerifiableAccountProtocol?
   15.10 +
   15.11      public init(account: Account) {
   15.12          // We are using a copy of the data here.
   15.13          // The outside world must not know changed settings until they have been verified.
   15.14 @@ -52,7 +56,18 @@
   15.15          self.loginName = account.server(with: .imap)?.credentials.loginName ?? ""
   15.16          self.name = account.user.userName ?? ""
   15.17  
   15.18 +        if let server = account.imapServer {
   15.19 +            self.originalPassword = server.credentials.password
   15.20 +            self.imapServer = ServerViewModel(
   15.21 +                address: server.address,
   15.22 +                port: "\(server.port)",
   15.23 +                transport: server.transport?.asString())
   15.24 +        } else {
   15.25 +            self.imapServer = ServerViewModel()
   15.26 +        }
   15.27 +
   15.28          if let server = account.smtpServer {
   15.29 +            self.originalPassword = self.originalPassword ?? server.credentials.password
   15.30              self.smtpServer = ServerViewModel(
   15.31                  address: server.address,
   15.32                  port: "\(server.port)",
   15.33 @@ -61,13 +76,15 @@
   15.34              self.smtpServer = ServerViewModel()
   15.35          }
   15.36  
   15.37 -        if let server = account.imapServer {
   15.38 -            self.imapServer = ServerViewModel(
   15.39 -                address: server.address,
   15.40 -                port: "\(server.port)",
   15.41 -                transport: server.transport?.asString())
   15.42 -        } else {
   15.43 -            self.imapServer = ServerViewModel()
   15.44 +        if isOAuth2 {
   15.45 +            if let payload = account.imapServer?.credentials.password ??
   15.46 +                account.smtpServer?.credentials.password,
   15.47 +                let token = OAuth2AccessToken.from(base64Encoded: payload)
   15.48 +                    as? OAuth2AccessTokenProtocol {
   15.49 +                self.accessToken = token
   15.50 +            } else {
   15.51 +                Log.shared.errorAndCrash("Supposed to do OAUTH2, but no existing token")
   15.52 +            }
   15.53          }
   15.54      }
   15.55  
   15.56 @@ -84,12 +101,18 @@
   15.57  
   15.58      weak var delegate: AccountVerificationResultDelegate?
   15.59  
   15.60 -    /// Holding both the data of the current account in verification,
   15.61 -    /// and also the implementation of the verification.
   15.62 -    private var verifiableAccount: VerifiableAccountProtocol?
   15.63 +    /// If the credentials have either an IMAP or SMTP password,
   15.64 +    /// it gets stored here.
   15.65 +    private var originalPassword: String?
   15.66  
   15.67 -    // Currently we assume imap and smtp servers exist already (update).
   15.68 -    // If we run into problems here modify to updateOrCreate.
   15.69 +    /// If there was OAUTH2 for this account, here is a current token.
   15.70 +    /// This trumps both the `originalPassword` and a password given by the user
   15.71 +    /// via the UI.
   15.72 +    /// - Note: For logins that require it, there must be an up-to-date token
   15.73 +    ///         for the verification be able to succeed.
   15.74 +    ///         It is extracted from the existing server credentials on `init`.
   15.75 +    private var accessToken: OAuth2AccessTokenProtocol?
   15.76 +
   15.77      func update(loginName: String, name: String, password: String? = nil, imap: ServerViewModel,
   15.78                  smtp: ServerViewModel) {
   15.79          var theVerifier = verifiableAccount ?? VerifiableAccount()
   15.80 @@ -98,15 +121,23 @@
   15.81          theVerifier.address = email
   15.82          theVerifier.userName = name
   15.83  
   15.84 -        // TODO: How to handle if the password got changed or not?
   15.85 -        theVerifier.password = password
   15.86 -
   15.87          if loginName != email {
   15.88              theVerifier.loginName = loginName
   15.89          }
   15.90  
   15.91          if isOAuth2 {
   15.92 -            // TODO: Set correct auth method, etc.
   15.93 +            if self.accessToken == nil {
   15.94 +                Log.shared.errorAndCrash("Have to do OAUTH2, but lacking current token")
   15.95 +            }
   15.96 +            theVerifier.authMethod = .saslXoauth2
   15.97 +            theVerifier.accessToken = accessToken
   15.98 +            // OAUTH2 trumps any password
   15.99 +            theVerifier.password = nil
  15.100 +        } else {
  15.101 +            theVerifier.password = originalPassword
  15.102 +            if password != nil {
  15.103 +                theVerifier.password = password
  15.104 +            }
  15.105          }
  15.106  
  15.107          // IMAP
  15.108 @@ -132,7 +163,7 @@
  15.109          do {
  15.110              try theVerifier.verify()
  15.111          } catch {
  15.112 -            delegate?.didVerify(result: .noImapConnectData, accountInput: theVerifier)
  15.113 +            delegate?.didVerify(result: .noImapConnectData)
  15.114          }
  15.115      }
  15.116  
  15.117 @@ -175,37 +206,7 @@
  15.118      }
  15.119  
  15.120      func updateToken(accessToken: OAuth2AccessTokenProtocol) {
  15.121 -        // TODO: What to do here? When does this get called?
  15.122 -        /*
  15.123 -        guard let imapServer = account.imapServer,
  15.124 -            let smtpServer = account.smtpServer else {
  15.125 -                return
  15.126 -        }
  15.127 -        let password = accessToken.persistBase64Encoded()
  15.128 -        imapServer.credentials.password = password
  15.129 -        smtpServer.credentials.password = password
  15.130 -         */
  15.131 -    }
  15.132 -}
  15.133 -
  15.134 -// MARK: - AccountVerificationServiceDelegate
  15.135 -
  15.136 -extension AccountSettingsViewModel: AccountVerificationServiceDelegate {
  15.137 -    public func verified(account: Account,
  15.138 -                  service: AccountVerificationServiceProtocol,
  15.139 -                  result: AccountVerificationResult) {
  15.140 -        if result == .ok {
  15.141 -            MessageModelUtil.performAndWait {
  15.142 -                account.save()
  15.143 -            }
  15.144 -        }
  15.145 -        GCD.onMainWait { [weak self] in
  15.146 -            guard let me = self else {
  15.147 -                Log.shared.errorAndCrash("Lost MySelf")
  15.148 -                return
  15.149 -            }
  15.150 -            me.delegate?.didVerify(result: result, accountInput: nil)
  15.151 -        }
  15.152 +        self.accessToken = accessToken
  15.153      }
  15.154  }
  15.155  
  15.156 @@ -217,16 +218,17 @@
  15.157          case .success(()):
  15.158              do {
  15.159                  try verifiableAccount?.save()
  15.160 +                delegate?.didVerify(result: .ok)
  15.161              } catch {
  15.162                  Log.shared.errorAndCrash("%@", error.localizedDescription)
  15.163              }
  15.164          case .failure(let error):
  15.165              if let imapError = error as? ImapSyncError {
  15.166                  delegate?.didVerify(
  15.167 -                    result: .imapError(imapError), accountInput: verifiableAccount)
  15.168 +                    result: .imapError(imapError))
  15.169              } else if let smtpError = error as? SmtpSendError {
  15.170                  delegate?.didVerify(
  15.171 -                    result: .smtpError(smtpError), accountInput: verifiableAccount)
  15.172 +                    result: .smtpError(smtpError))
  15.173              } else {
  15.174                  Log.shared.errorAndCrash("%@", error.localizedDescription)
  15.175              }
    16.1 --- a/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountVerificationResultDelegate.swift	Thu May 09 17:41:47 2019 +0200
    16.2 +++ b/pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountVerificationResultDelegate.swift	Fri May 17 14:07:44 2019 +0200
    16.3 @@ -11,5 +11,5 @@
    16.4  import MessageModel
    16.5  
    16.6  protocol AccountVerificationResultDelegate: class {
    16.7 -    func didVerify(result: AccountVerificationResult, accountInput: VerifiableAccountProtocol?)
    16.8 +    func didVerify(result: AccountVerificationResult)
    16.9  }
    17.1 --- a/pEpForiOS/public.xcconfig	Thu May 09 17:41:47 2019 +0200
    17.2 +++ b/pEpForiOS/public.xcconfig	Fri May 17 14:07:44 2019 +0200
    17.3 @@ -6,5 +6,5 @@
    17.4  //  Copyright © 2018 p≡p Security S.A. All rights reserved.
    17.5  //
    17.6  
    17.7 -#include "secret.xcconfig"
    17.8 +#include "../pEp_for_iOS_intern/secret.xcconfig"
    17.9  
    18.1 --- a/pEpForiOSTests/AccountVerificationServiceTests.swift	Thu May 09 17:41:47 2019 +0200
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,114 +0,0 @@
    18.4 -//
    18.5 -//  AccountVerificationServiceTests.swift
    18.6 -//  pEpForiOS
    18.7 -//
    18.8 -//  Created by Dirk Zimmermann on 24.05.17.
    18.9 -//  Copyright © 2017 p≡p Security S.A. All rights reserved.
   18.10 -//
   18.11 -
   18.12 -import XCTest
   18.13 -
   18.14 -@testable import MessageModel
   18.15 -@testable import pEpForiOS
   18.16 -
   18.17 -class AccountVerificationTestDelegate: AccountVerificationServiceDelegate {
   18.18 -    let expVerified: XCTestExpectation?
   18.19 -    var verificationResult: AccountVerificationResult?
   18.20 -    var verifiedAccount: Account?
   18.21 -
   18.22 -    init(expVerified: XCTestExpectation? = nil) {
   18.23 -        self.expVerified = expVerified
   18.24 -    }
   18.25 -
   18.26 -    func verified(account: Account, service: AccountVerificationServiceProtocol,
   18.27 -                  result: AccountVerificationResult) {
   18.28 -        verifiedAccount = account
   18.29 -        verificationResult = result
   18.30 -        expVerified?.fulfill()
   18.31 -    }
   18.32 -}
   18.33 -
   18.34 -class AccountVerificationServiceTests: XCTestCase {
   18.35 -    var persistentSetup: PersistentSetup!
   18.36 -
   18.37 -    override func setUp() {
   18.38 -        persistentSetup = PersistentSetup()
   18.39 -    }
   18.40 -    
   18.41 -    override func tearDown() {
   18.42 -        persistentSetup = nil
   18.43 -    }
   18.44 -
   18.45 -    func testDirectlySuccess() {
   18.46 -        testVerification(account: SecretTestData().createVerifiableAccount(),
   18.47 -                         expectedResult: AccountVerificationResult.ok,
   18.48 -                         testDirectly: true)
   18.49 -    }
   18.50 -
   18.51 -    func testDirectlyImapFailure() {
   18.52 -        testVerification(
   18.53 -            account: SecretTestData().createImapTimeOutAccount(),
   18.54 -            expectedResult: AccountVerificationResult.imapError(
   18.55 -                .connectionTimedOut("connectionTimedOut(_:notification:)")),
   18.56 -            testDirectly: true)
   18.57 -    }
   18.58 -
   18.59 -    func testDirectlySmtpFailure() {
   18.60 -        testVerification(
   18.61 -            account: SecretTestData().createSmtpTimeOutAccount(),
   18.62 -            expectedResult: AccountVerificationResult.smtpError(
   18.63 -                .connectionTimedOut("connectionTimedOut(_:theNotification:)")),
   18.64 -            testDirectly: true)
   18.65 -    }
   18.66 -
   18.67 -    func testVerificationServiceSuccess() {
   18.68 -        testVerification(account: SecretTestData().createVerifiableAccount(),
   18.69 -                         expectedResult: AccountVerificationResult.ok,
   18.70 -                         testDirectly: false)
   18.71 -    }
   18.72 -
   18.73 -    func testVerificationServiceImapFailures() {
   18.74 -        testVerification(
   18.75 -            account: SecretTestData().createImapTimeOutAccount(),
   18.76 -            expectedResult: AccountVerificationResult.imapError(
   18.77 -                .connectionTimedOut("connectionTimedOut(_:notification:)")),
   18.78 -            testDirectly: false)
   18.79 -    }
   18.80 -
   18.81 -    func testVerificationServiceSmtpFailures() {
   18.82 -        testVerification(
   18.83 -            account: SecretTestData().createSmtpTimeOutAccount(),
   18.84 -            expectedResult: AccountVerificationResult.smtpError(
   18.85 -                .connectionTimedOut("connectionTimedOut(_:theNotification:)")),
   18.86 -            testDirectly: false)
   18.87 -    }
   18.88 -
   18.89 -    // MARK: HELPER
   18.90 -
   18.91 -    func testVerification(account: Account, expectedResult: AccountVerificationResult,
   18.92 -                          testDirectly: Bool) {
   18.93 -        account.save()
   18.94 -
   18.95 -        let expVerified = expectation(description: "account verified")
   18.96 -        let delegate = AccountVerificationTestDelegate(expVerified: expVerified)
   18.97 -
   18.98 -        let asService = AccountVerificationService()
   18.99 -        let verificationService = VerificationService(parentName: #function)
  18.100 -
  18.101 -        if testDirectly {
  18.102 -            asService.delegate = delegate
  18.103 -            asService.verify(account: account)
  18.104 -        } else {
  18.105 -            verificationService.requestVerification(account: account, delegate: delegate)
  18.106 -        }
  18.107 -
  18.108 -        waitForExpectations(timeout: TestUtil.waitTime, handler: { error in
  18.109 -            XCTAssertNil(error)
  18.110 -            guard let result = delegate.verificationResult else {
  18.111 -                XCTFail()
  18.112 -                return
  18.113 -            }
  18.114 -            XCTAssertEqual(result, expectedResult)
  18.115 -        })
  18.116 -    }
  18.117 -}
    19.1 --- a/pEpForiOSTests/Models/Folder/FolderViewModelTest.swift	Thu May 09 17:41:47 2019 +0200
    19.2 +++ b/pEpForiOSTests/Models/Folder/FolderViewModelTest.swift	Fri May 17 14:07:44 2019 +0200
    19.3 @@ -99,11 +99,4 @@
    19.4          CdAccount.deleteAll()
    19.5          viewmodel = FolderViewModel(withFoldersIn: nil, includeUnifiedInbox: withUnifiedInbox)
    19.6      }
    19.7 -    
    19.8 -    class VerificationServiceMock: VerificationServiceProtocol {
    19.9 -        func requestVerification(account: Account, delegate: AccountVerificationServiceDelegate) {
   19.10 -            
   19.11 -        }
   19.12 -    }
   19.13 -
   19.14  }
    20.1 --- a/pEpForiOSTests/Models/LoginViewModelTests.swift	Thu May 09 17:41:47 2019 +0200
    20.2 +++ b/pEpForiOSTests/Models/LoginViewModelTests.swift	Fri May 17 14:07:44 2019 +0200
    20.3 @@ -25,7 +25,7 @@
    20.4  }
    20.5  
    20.6  class LoginViewModelTests: CoreDataDrivenTestBase {
    20.7 -    class TestVerificationService: VerifiableAccountProtocol {
    20.8 +    class TestVerifiableAccount: VerifiableAccountProtocol {
    20.9          let accountSettings: TestDataBase.AccountSettings
   20.10          let expLookedUp: XCTestExpectation
   20.11  
   20.12 @@ -49,6 +49,10 @@
   20.13          var trustedImapServer: Bool = false
   20.14          var verifiableAccountDelegate: VerifiableAccountDelegate?
   20.15  
   20.16 +        let isValidName = false
   20.17 +
   20.18 +        let isValidUser = false
   20.19 +
   20.20          func verify() throws {
   20.21              XCTAssertEqual(address, accountSettings.idAddress)
   20.22  
   20.23 @@ -105,9 +109,9 @@
   20.24  //        }
   20.25  
   20.26          let expLookedUp = expectation(description: "expLookedUp")
   20.27 -        let verificationService =
   20.28 -            TestVerificationService(accountSettings: accountSettings, expLookedUp: expLookedUp)
   20.29 -        let vm = LoginViewModel(verificationService: verificationService)
   20.30 +        let verifiableAccount =
   20.31 +            TestVerifiableAccount(accountSettings: accountSettings, expLookedUp: expLookedUp)
   20.32 +        let vm = LoginViewModel(verifiableAccount: verifiableAccount)
   20.33          let errorHandler = ErrorHandler()
   20.34          vm.loginViewModelLoginErrorDelegate = errorHandler
   20.35          vm.login(accountName: accountSettings.idAddress,
    21.1 --- a/pEpForiOSTests/Models/Settings/AccountSettingsViewModelTest.swift	Thu May 09 17:41:47 2019 +0200
    21.2 +++ b/pEpForiOSTests/Models/Settings/AccountSettingsViewModelTest.swift	Fri May 17 14:07:44 2019 +0200
    21.3 @@ -63,15 +63,17 @@
    21.4      }
    21.5  
    21.6      func testUpdate() {
    21.7 -        let address = "fakeAddress"
    21.8 +        let address = "localhost"
    21.9          let login = "fakelogin"
   21.10          let name = "fakeName"
   21.11          let password = "fakePassword"
   21.12 +        let portString = "1"
   21.13 +        let portInt = UInt16(portString)!
   21.14  
   21.15          setUpViewModel()
   21.16  
   21.17          let server = AccountSettingsViewModel.ServerViewModel(address: address,
   21.18 -                                                              port: "123",
   21.19 +                                                              port: portString,
   21.20                                                                transport: "StartTls")
   21.21  
   21.22          let verifyExpectation =
   21.23 @@ -89,24 +91,18 @@
   21.24  
   21.25          waitForExpectations(timeout: UnitTestUtils.asyncWaitTime)
   21.26  
   21.27 -        // TODO: What to test here?
   21.28 -        /*
   21.29 -        let smtp = viewModel.account.smtpServer
   21.30 -        let imap = viewModel.account.imapServer
   21.31 +        guard let verifier = viewModel.verifiableAccount else {
   21.32 +            XCTFail()
   21.33 +            return
   21.34 +        }
   21.35  
   21.36 -        XCTAssertEqual(smtp?.credentials.loginName, login)
   21.37 -        XCTAssertEqual(smtp?.credentials.password, password)
   21.38 -        XCTAssertEqual(imap?.credentials.loginName, login)
   21.39 -        XCTAssertEqual(imap?.credentials.password, password)
   21.40 -
   21.41 -        XCTAssertEqual(imap?.address, address)
   21.42 -        XCTAssertEqual(imap?.port, 123)
   21.43 -        XCTAssertEqual(imap?.transport, .startTls)
   21.44 -
   21.45 -        XCTAssertEqual(smtp?.address, address)
   21.46 -        XCTAssertEqual(smtp?.port, 123)
   21.47 -        XCTAssertEqual(smtp?.transport, .startTls)
   21.48 -         */
   21.49 +        XCTAssertEqual(verifier.loginName, login)
   21.50 +        XCTAssertEqual(verifier.password, password)
   21.51 +        XCTAssertEqual(verifier.serverIMAP, address)
   21.52 +        XCTAssertEqual(verifier.serverSMTP, address)
   21.53 +        XCTAssertEqual(verifier.portIMAP, portInt)
   21.54 +        XCTAssertEqual(verifier.portSMTP, portInt)
   21.55 +        XCTAssertNil(verifier.accessToken)
   21.56      }
   21.57  
   21.58      public func testSectionIsValid() {
   21.59 @@ -133,9 +129,7 @@
   21.60          delegate.expectationDidVerifyCalled = verifyExpectation
   21.61          viewModel.delegate = delegate
   21.62  
   21.63 -        viewModel.verified(account: account,
   21.64 -                           service: AccountVerificationService(),
   21.65 -                           result: .ok)
   21.66 +        viewModel.didEndVerification(result: .success(()))
   21.67  
   21.68          waitForExpectations(timeout: UnitTestUtils.waitTime)
   21.69      }
   21.70 @@ -152,7 +146,7 @@
   21.71      var expectationDidVerifyCalled: XCTestExpectation?
   21.72      var error: Error? = nil
   21.73  
   21.74 -    func didVerify(result: AccountVerificationResult, accountInput: VerifiableAccountProtocol?) {
   21.75 +    func didVerify(result: AccountVerificationResult) {
   21.76          switch result {
   21.77          case .ok:
   21.78              self.error = nil
    22.1 --- a/pEpForiOSTests/Service/VerifiableAccountTest.swift	Thu May 09 17:41:47 2019 +0200
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,162 +0,0 @@
    22.4 -//
    22.5 -//  VerifiableAccountTest.swift
    22.6 -//  pEpForiOSTests
    22.7 -//
    22.8 -//  Created by Dirk Zimmermann on 16.04.19.
    22.9 -//  Copyright © 2019 p≡p Security S.A. All rights reserved.
   22.10 -//
   22.11 -
   22.12 -import XCTest
   22.13 -
   22.14 -import MessageModel
   22.15 -@testable import pEpForiOS
   22.16 -
   22.17 -class VerifiableAccountTest: XCTestCase {
   22.18 -    func testBasicSuccess() {
   22.19 -        let verifier = VerifiableAccount()
   22.20 -        var verifierType: VerifiableAccountProtocol = verifier
   22.21 -        SecretTestData().populateWorkingAccount(
   22.22 -            verifiableAccount: &verifierType)
   22.23 -        let expDidVerify = expectation(description: "expDidVerify")
   22.24 -        let delegate = VerifiableAccountTestDelegate(expDidVerify: expDidVerify)
   22.25 -        try! check(verifier: &verifierType, delegate: delegate)
   22.26 -        wait(for: [expDidVerify], timeout: TestUtil.waitTime)
   22.27 -
   22.28 -        guard let theResult = delegate.result else {
   22.29 -            XCTFail()
   22.30 -            return
   22.31 -        }
   22.32 -        switch theResult {
   22.33 -        case .success(()):
   22.34 -            break
   22.35 -        case .failure(_):
   22.36 -            XCTFail()
   22.37 -        }
   22.38 -    }
   22.39 -
   22.40 -    func testFailingValidation() {
   22.41 -        let (exceptionOnVerify, exceptionOnSave) = checkFailingValidation() {
   22.42 -            var newOne = $0
   22.43 -            newOne.address = nil
   22.44 -            return newOne
   22.45 -        }
   22.46 -        XCTAssertTrue(exceptionOnVerify)
   22.47 -        XCTAssertTrue(exceptionOnSave)
   22.48 -    }
   22.49 -
   22.50 -    func testBasicFailingVerification() {
   22.51 -        let result = checkBasicVerification() { v in
   22.52 -            var verifiable = v
   22.53 -
   22.54 -            // This should make it fail quickly
   22.55 -            verifiable.serverIMAP = "localhost"
   22.56 -            verifiable.portIMAP = 5
   22.57 -            verifiable.serverSMTP = "localhost"
   22.58 -            verifiable.portSMTP = 5
   22.59 -
   22.60 -            return verifiable
   22.61 -        }
   22.62 -        switch result {
   22.63 -        case .success(_):
   22.64 -            XCTFail()
   22.65 -        case .failure(_):
   22.66 -            break
   22.67 -        }
   22.68 -    }
   22.69 -
   22.70 -    func testBasicFailingVerificationWithWrongPassword() {
   22.71 -        let result = checkBasicVerification() { v in
   22.72 -            var verifiable = v
   22.73 -
   22.74 -            verifiable.password = "xxxxxxxxxx"
   22.75 -
   22.76 -            return verifiable
   22.77 -        }
   22.78 -        switch result {
   22.79 -        case .success(_):
   22.80 -            XCTFail()
   22.81 -        case .failure(_):
   22.82 -            break
   22.83 -        }
   22.84 -    }
   22.85 -
   22.86 -    // MARK: Helpers
   22.87 -
   22.88 -    /// Tries `verify()` and `save()` on the given `VerifiableAccountProtocol`.
   22.89 -    /// - Returns: A tuple of Bool denoting if `verify()` and `save()` threw exceptions.
   22.90 -    func checkFailingValidation(
   22.91 -        modifier: (VerifiableAccountProtocol) -> VerifiableAccountProtocol) -> (Bool, Bool) {
   22.92 -        let verifier = VerifiableAccount()
   22.93 -        var verifierType: VerifiableAccountProtocol = verifier
   22.94 -        SecretTestData().populateWorkingAccount(
   22.95 -            verifiableAccount: &verifierType)
   22.96 -
   22.97 -        // Invalidate it
   22.98 -        var verifierToBeUsed = modifier(verifierType)
   22.99 -
  22.100 -        var exceptionHit1 = false
  22.101 -        do {
  22.102 -            try check(verifier: &verifierToBeUsed, delegate: nil)
  22.103 -        } catch {
  22.104 -            exceptionHit1 = true
  22.105 -        }
  22.106 -
  22.107 -        var exceptionHit2 = false
  22.108 -        do {
  22.109 -            try check(verifier: &verifierToBeUsed, delegate: nil)
  22.110 -        } catch {
  22.111 -            exceptionHit2 = true
  22.112 -        }
  22.113 -
  22.114 -        return (exceptionHit1, exceptionHit2)
  22.115 -    }
  22.116 -
  22.117 -    func check(verifier: inout VerifiableAccountProtocol,
  22.118 -               delegate: VerifiableAccountDelegate?) throws {
  22.119 -        verifier.verifiableAccountDelegate = delegate
  22.120 -        try verifier.verify()
  22.121 -    }
  22.122 -
  22.123 -    enum TestError: Error {
  22.124 -        case noResult
  22.125 -    }
  22.126 -
  22.127 -    /// Expects a failure, lets caller modify the `VerifiableAccountProtocol`.
  22.128 -    func checkBasicVerification(
  22.129 -        modifier: (VerifiableAccountProtocol) -> VerifiableAccountProtocol)
  22.130 -        -> Result<Void, Error> {
  22.131 -            let verifier = VerifiableAccount()
  22.132 -            var verifiable: VerifiableAccountProtocol = verifier
  22.133 -            SecretTestData().populateWorkingAccount(
  22.134 -                verifiableAccount: &verifiable)
  22.135 -
  22.136 -            verifiable = modifier(verifiable)
  22.137 -
  22.138 -            let expDidVerify = expectation(description: "expDidVerify")
  22.139 -            let delegate = VerifiableAccountTestDelegate(expDidVerify: expDidVerify)
  22.140 -            try! check(verifier: &verifiable, delegate: delegate)
  22.141 -            wait(for: [expDidVerify], timeout: TestUtil.waitTime)
  22.142 -
  22.143 -            guard let result = delegate.result else {
  22.144 -                XCTFail()
  22.145 -                return .failure(TestError.noResult)
  22.146 -            }
  22.147 -
  22.148 -            return result
  22.149 -    }
  22.150 -}
  22.151 -
  22.152 -class VerifiableAccountTestDelegate: VerifiableAccountDelegate {
  22.153 -    var result: Result<Void, Error>?
  22.154 -
  22.155 -    let expDidVerify: XCTestExpectation
  22.156 -
  22.157 -    init(expDidVerify: XCTestExpectation) {
  22.158 -        self.expDidVerify = expDidVerify
  22.159 -    }
  22.160 -
  22.161 -    func didEndVerification(result: Result<Void, Error>) {
  22.162 -        self.result = result
  22.163 -        expDidVerify.fulfill()
  22.164 -    }
  22.165 -}
    23.1 --- a/pEpForiOSTests/TestUtils/TestDataBase.swift	Thu May 09 17:41:47 2019 +0200
    23.2 +++ b/pEpForiOSTests/TestUtils/TestDataBase.swift	Fri May 17 14:07:44 2019 +0200
    23.3 @@ -13,6 +13,15 @@
    23.4  import PEPObjCAdapterFramework
    23.5  import PantomimeFramework
    23.6  
    23.7 +/// Base class for test data.
    23.8 +/// - Note:
    23.9 +///   1. This class is used both in MessageModel and the app,
   23.10 +///      so it's _duplicated code_ for the testing targets.
   23.11 +///   2. Make sure that, in your SecretTestData, you override:
   23.12 +///      * `populateAccounts` if you don't use the greenmail local server for testing,
   23.13 +///        or you want to test against other servers for various reasons.
   23.14 +///      * `populateVerifiableAccounts` in order to provide verifiable servers, to test
   23.15 +///        the verification parts.
   23.16  class TestDataBase {
   23.17      struct AccountSettings {
   23.18          var accountName: String?
   23.19 @@ -170,6 +179,7 @@
   23.20          /// Transfers the account data into a `VerifiableAccountProtocol`
   23.21          /// that you then can verify the acconut data with.
   23.22          func populate(verifiableAccount: inout VerifiableAccountProtocol) {
   23.23 +            verifiableAccount.userName = accountName
   23.24              verifiableAccount.address = idAddress
   23.25              verifiableAccount.loginName = imapLoginName
   23.26              verifiableAccount.accessToken = nil
   23.27 @@ -214,6 +224,32 @@
   23.28          addLocalTestAccount(userName: "test003")
   23.29      }
   23.30  
   23.31 +    /**
   23.32 +     Accounts needed for testing LAS, that is they need to be registered
   23.33 +     in the LAS DB or provide (correct) DNS SRV for IMAP and SMTP.
   23.34 +     - Note: Override this in your SecretTestData to something that's working.
   23.35 +     */
   23.36 +    func populateVerifiableAccounts() {
   23.37 +        append(verifiableAccountSettings: AccountSettings(
   23.38 +            accountName: "Whatever_you_want",
   23.39 +            idAddress: "whatever_you_want@yahoo.com",
   23.40 +            idUserName: "whatever_you_want@yahoo.com",
   23.41 +
   23.42 +            imapServerAddress: "imap.mail.yahoo.com",
   23.43 +            imapServerType: Server.ServerType.imap,
   23.44 +            imapServerTransport: Server.Transport.tls,
   23.45 +            imapServerPort: 993,
   23.46 +
   23.47 +            smtpServerAddress: "smtp.mail.yahoo.com",
   23.48 +            smtpServerType: Server.ServerType.smtp,
   23.49 +            smtpServerTransport: Server.Transport.tls,
   23.50 +            smtpServerPort: 465,
   23.51 +
   23.52 +            password: "whatever_you_want"))
   23.53 +
   23.54 +        fatalError("Abstract method. Must be overridden")
   23.55 +    }
   23.56 +
   23.57      private func addLocalTestAccount(userName: String) {
   23.58          let address = "\(userName)@localhost"
   23.59          append(accountSettings: AccountSettings(
   23.60 @@ -237,31 +273,6 @@
   23.61      }
   23.62  
   23.63      /**
   23.64 -     Accounts needed for testing LAS, that is they need to be registered
   23.65 -     in the LAS DB or provide (correct) DNS SRV for IMAP and SMTP.
   23.66 -     */
   23.67 -    func populateVerifiableAccounts() {
   23.68 -        append(verifiableAccountSettings: AccountSettings(
   23.69 -            accountName: "Whatever_you_want",
   23.70 -            idAddress: "whatever_you_want@yahoo.com",
   23.71 -            idUserName: "whatever_you_want@yahoo.com",
   23.72 -
   23.73 -            imapServerAddress: "imap.mail.yahoo.com",
   23.74 -            imapServerType: Server.ServerType.imap,
   23.75 -            imapServerTransport: Server.Transport.tls,
   23.76 -            imapServerPort: 993,
   23.77 -
   23.78 -            smtpServerAddress: "smtp.mail.yahoo.com",
   23.79 -            smtpServerType: Server.ServerType.smtp,
   23.80 -            smtpServerTransport: Server.Transport.tls,
   23.81 -            smtpServerPort: 465,
   23.82 -
   23.83 -            password: "whatever_you_want"))
   23.84 -
   23.85 -        fatalError("Abstract method. Must be overridden")
   23.86 -    }
   23.87 -
   23.88 -    /**
   23.89       - Returns: A valid `CdAccount`.
   23.90       */
   23.91      func createWorkingCdAccount(number: Int = 0) -> CdAccount {
   23.92 @@ -390,8 +401,8 @@
   23.93          return createImapTimeOutAccountSettings().account()
   23.94      }
   23.95  
   23.96 -    func populateWorkingAccount(number: Int = 0,
   23.97 -                                verifiableAccount: inout VerifiableAccountProtocol) {
   23.98 +    func populateVerifiableAccount(number: Int = 0,
   23.99 +                                   verifiableAccount: inout VerifiableAccountProtocol) {
  23.100          createVerifiableAccountSettings(number: number).populate(
  23.101              verifiableAccount: &verifiableAccount)
  23.102      }
    24.1 --- a/pEpForiOSUITests/NewAccountSetupUITest.swift	Thu May 09 17:41:47 2019 +0200
    24.2 +++ b/pEpForiOSUITests/NewAccountSetupUITest.swift	Fri May 17 14:07:44 2019 +0200
    24.3 @@ -25,7 +25,7 @@
    24.4  
    24.5          dismissInitialSystemAlerts()
    24.6  
    24.7 -        let account = SecretUITestData.workingAccount1
    24.8 +        let account = secretTestData().workingAccount1
    24.9          newAccountSetup(account: account)
   24.10          waitForever()
   24.11      }
   24.12 @@ -35,7 +35,7 @@
   24.13  
   24.14          dismissInitialSystemAlerts()
   24.15  
   24.16 -        let account = SecretUITestData.workingAccount2
   24.17 +        let account = secretTestData().workingAccount2
   24.18          newAccountSetup(account: account)
   24.19          waitForever()
   24.20      }
   24.21 @@ -43,14 +43,14 @@
   24.22      func testAdditionalAccount() {
   24.23          app().launch()
   24.24          addAccount()
   24.25 -        let account = SecretUITestData.workingAccount3
   24.26 +        let account = secretTestData().workingAccount3
   24.27          newAccountSetup(account: account)
   24.28          waitForever()
   24.29      }
   24.30  
   24.31      func testAdditionalManualAccount() {
   24.32          app().launch()
   24.33 -        addAdditionalManual(account: SecretUITestData.manualAccount)
   24.34 +        addAdditionalManual(account: secretTestData().manualAccount)
   24.35      }
   24.36  
   24.37      func testAutoAccountPlusManual() {
   24.38 @@ -58,10 +58,10 @@
   24.39  
   24.40          dismissInitialSystemAlerts()
   24.41  
   24.42 -        let account1 = SecretUITestData.workingAccount1
   24.43 +        let account1 = secretTestData().workingAccount1
   24.44          newAccountSetup(account: account1)
   24.45  
   24.46 -        addAdditionalManual(account: SecretUITestData.manualAccount)
   24.47 +        addAdditionalManual(account: secretTestData().manualAccount)
   24.48      }
   24.49  
   24.50      func testTwoInitialAccounts() {
   24.51 @@ -69,12 +69,12 @@
   24.52  
   24.53          dismissInitialSystemAlerts()
   24.54  
   24.55 -        let account1 = SecretUITestData.workingAccount1
   24.56 +        let account1 = secretTestData().workingAccount1
   24.57          newAccountSetup(account: account1)
   24.58  
   24.59          addAccount()
   24.60  
   24.61 -        let account2 = SecretUITestData.workingAccount2
   24.62 +        let account2 = secretTestData().workingAccount2
   24.63          newAccountSetup(account: account2)
   24.64          waitForever()
   24.65      }
   24.66 @@ -86,7 +86,36 @@
   24.67  
   24.68          dismissInitialSystemAlerts()
   24.69  
   24.70 -        let account = SecretUITestData.manualAccount
   24.71 +        var account = secretTestData().workingAccount1
   24.72 +
   24.73 +        // Wrong password should prevent the automatic login
   24.74 +        let correctPassword = account.password
   24.75 +        account.password += "ShouldNotWork"
   24.76 +
   24.77 +        newAccountSetup(account: account)
   24.78 +
   24.79 +        switchToManualConfig()
   24.80 +
   24.81 +        // Use correct password for the manual setup
   24.82 +        account.password = correctPassword
   24.83 +
   24.84 +        manualNewAccountSetup(account)
   24.85 +
   24.86 +        waitForever()
   24.87 +    }
   24.88 +
   24.89 +    func testNewAccountSetupManualThatFails() {
   24.90 +        let theApp = app()
   24.91 +
   24.92 +        theApp.launch()
   24.93 +
   24.94 +        dismissInitialSystemAlerts()
   24.95 +
   24.96 +        var account = secretTestData().workingAccount1
   24.97 +
   24.98 +        // Make sure this account will fails, both in auto and manual modes
   24.99 +        account.password += "ShouldNotWork"
  24.100 +
  24.101          newAccountSetup(account: account)
  24.102  
  24.103          switchToManualConfig()
  24.104 @@ -101,7 +130,7 @@
  24.105  
  24.106          dismissInitialSystemAlerts()
  24.107  
  24.108 -        let account = SecretUITestData.gmailOAuth2Account
  24.109 +        let account = secretTestData().gmailOAuth2Account
  24.110          newAccountSetup(account: account, enterPassword: false)
  24.111          waitForever()
  24.112      }
  24.113 @@ -111,7 +140,7 @@
  24.114  
  24.115          dismissInitialSystemAlerts()
  24.116  
  24.117 -        let account = SecretUITestData.yahooOAuth2Account
  24.118 +        let account = secretTestData().yahooOAuth2Account
  24.119          newAccountSetup(account: account, enterPassword: false)
  24.120          waitForever()
  24.121      }
  24.122 @@ -124,6 +153,10 @@
  24.123          return app
  24.124      }
  24.125  
  24.126 +    func secretTestData() -> UITestDataProtocol {
  24.127 +        return SecretUITestData()
  24.128 +    }
  24.129 +
  24.130      /*
  24.131       Use if you want to wait forever. May be useful for debugging.
  24.132       */
  24.133 @@ -151,7 +184,7 @@
  24.134  
  24.135          tf = tablesQuery.cells.secureTextFields["password"]
  24.136          tf.tap()
  24.137 -        typeTextIfEmpty(textField: tf, text: account.password)
  24.138 +        tf.typeText(account.password)
  24.139  
  24.140          theApp.navigationBars.buttons["Next"].tap()
  24.141  
    25.1 --- a/pEpForiOSUITests/UITestDataProtocol.swift	Thu May 09 17:41:47 2019 +0200
    25.2 +++ b/pEpForiOSUITests/UITestDataProtocol.swift	Fri May 17 14:07:44 2019 +0200
    25.3 @@ -9,10 +9,11 @@
    25.4  import Foundation
    25.5  
    25.6  protocol UITestDataProtocol {
    25.7 -    static var workingAccount1: UIAccount { get }
    25.8 -    static var workingAccount2: UIAccount  { get }
    25.9 -    static var workingYahooAccount: UIAccount { get }
   25.10 -    static var gmailOAuth2Account: UIAccount { get }
   25.11 -    static var yahooOAuth2Account: UIAccount { get }
   25.12 -    static var manualAccount: UIAccount { get }
   25.13 +    var workingAccount1: UIAccount { get }
   25.14 +    var workingAccount2: UIAccount  { get }
   25.15 +    var workingAccount3: UIAccount  { get }
   25.16 +    var workingYahooAccount: UIAccount { get }
   25.17 +    var gmailOAuth2Account: UIAccount { get }
   25.18 +    var yahooOAuth2Account: UIAccount { get }
   25.19 +    var manualAccount: UIAccount { get }
   25.20  }