diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 7cd04a801..3692d5049 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -94,7 +94,7 @@ 9F6EE17B2598F9FA0059BA51 /* Gmail+Backup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6EE17A2598F9FA0059BA51 /* Gmail+Backup.swift */; }; 9F716308234FC73E0031645E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9F71630A234FC73E0031645E /* Localizable.strings */; }; 9F7920F52667CEF100DA3D80 /* PassPraseSaveable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7920F42667CEF100DA3D80 /* PassPraseSaveable.swift */; }; - 9F79228826696B0200DA3D80 /* PassPhraseStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F79228726696B0200DA3D80 /* PassPhraseStorage.swift */; }; + 9F79228826696B0200DA3D80 /* PassPhraseService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F79228726696B0200DA3D80 /* PassPhraseService.swift */; }; 9F79229426696B9300DA3D80 /* KeyDataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F79229326696B9300DA3D80 /* KeyDataStorage.swift */; }; 9F7E5137267AA51B00CE37C3 /* AlertsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7E5136267AA51B00CE37C3 /* AlertsFactory.swift */; }; 9F8220D526336626004B2009 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8220D426336626004B2009 /* Logger.swift */; }; @@ -139,11 +139,11 @@ 9FC4116526811861004C0A69 /* BackupServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4163EC266574CB00106194 /* BackupServiceMock.swift */; }; 9FC4116B2681186D004C0A69 /* KeyMethodsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FA0157926565B7800CBBA05 /* KeyMethodsTest.swift */; }; 9FC41171268118A7004C0A69 /* PassPhraseStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBA2266EB95300F3BF5D /* PassPhraseStorageTests.swift */; }; - 9FC41177268118AD004C0A69 /* LocalPassPhraseStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBC8266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift */; }; - 9FC4117D268118AE004C0A69 /* EncryptedPassPhraseStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBCF266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift */; }; + 9FC4117D268118AE004C0A69 /* PassPhraseStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBCF266EBE1D00F3BF5D /* PassPhraseStorageMock.swift */; }; 9FC41183268118B1004C0A69 /* EmailProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBC1266EBE0100F3BF5D /* EmailProviderMock.swift */; }; 9FC4120926811D00004C0A69 /* PromiseExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC411892681191D004C0A69 /* PromiseExtensions.swift */; }; - 9FC7EAB3266A404D00F3BF5D /* PassPhrase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EAB2266A404D00F3BF5D /* PassPhrase.swift */; }; + 9FC413182683C492004C0A69 /* InMemoryPassPhraseStorageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC413172683C491004C0A69 /* InMemoryPassPhraseStorageTest.swift */; }; + 9FC7EAB3266A404D00F3BF5D /* PassPhraseObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EAB2266A404D00F3BF5D /* PassPhraseObject.swift */; }; 9FC7EB76266EB67B00F3BF5D /* EncryptedStorageProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EB75266EB67B00F3BF5D /* EncryptedStorageProtocols.swift */; }; 9FC7EBAA266EBD3700F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC7EBA9266EBD3700F3BF5D /* InMemoryPassPhraseStorage.swift */; }; 9FD364862381EFCB00657302 /* SetupManuallyEnterPassPhraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD364852381EFCB00657302 /* SetupManuallyEnterPassPhraseViewController.swift */; }; @@ -485,7 +485,7 @@ 9F71630B234FC7500031645E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; 9F72E866263ECE2A0039CF81 /* Trace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trace.swift; sourceTree = ""; }; 9F7920F42667CEF100DA3D80 /* PassPraseSaveable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPraseSaveable.swift; sourceTree = ""; }; - 9F79228726696B0200DA3D80 /* PassPhraseStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassPhraseStorage.swift; sourceTree = ""; }; + 9F79228726696B0200DA3D80 /* PassPhraseService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassPhraseService.swift; sourceTree = ""; }; 9F79229326696B9300DA3D80 /* KeyDataStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyDataStorage.swift; sourceTree = ""; }; 9F7E5136267AA51B00CE37C3 /* AlertsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertsFactory.swift; sourceTree = ""; }; 9F8220D426336626004B2009 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; @@ -523,13 +523,13 @@ 9FC411342595EA94001180A8 /* Imap+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Imap+Search.swift"; sourceTree = ""; }; 9FC4114B25961CEA001180A8 /* MailServiceProviderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailServiceProviderType.swift; sourceTree = ""; }; 9FC411892681191D004C0A69 /* PromiseExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromiseExtensions.swift; sourceTree = ""; }; - 9FC7EAB2266A404D00F3BF5D /* PassPhrase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhrase.swift; sourceTree = ""; }; + 9FC413172683C491004C0A69 /* InMemoryPassPhraseStorageTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InMemoryPassPhraseStorageTest.swift; sourceTree = ""; }; + 9FC7EAB2266A404D00F3BF5D /* PassPhraseObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseObject.swift; sourceTree = ""; }; 9FC7EB75266EB67B00F3BF5D /* EncryptedStorageProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedStorageProtocols.swift; sourceTree = ""; }; 9FC7EBA2266EB95300F3BF5D /* PassPhraseStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseStorageTests.swift; sourceTree = ""; }; 9FC7EBA9266EBD3700F3BF5D /* InMemoryPassPhraseStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InMemoryPassPhraseStorage.swift; sourceTree = ""; }; 9FC7EBC1266EBE0100F3BF5D /* EmailProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailProviderMock.swift; sourceTree = ""; }; - 9FC7EBC8266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalPassPhraseStorageMock.swift; sourceTree = ""; }; - 9FC7EBCF266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedPassPhraseStorageMock.swift; sourceTree = ""; }; + 9FC7EBCF266EBE1D00F3BF5D /* PassPhraseStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassPhraseStorageMock.swift; sourceTree = ""; }; 9FD22A19230FD781005067A6 /* NavigationBarItemsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarItemsView.swift; sourceTree = ""; }; 9FD22A1B230FE7D0005067A6 /* Then.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Then.swift; sourceTree = ""; }; 9FD22A1E230FEFC6005067A6 /* NavigationBarActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarActionButton.swift; sourceTree = ""; }; @@ -1190,7 +1190,7 @@ isa = PBXGroup; children = ( 9F79229326696B9300DA3D80 /* KeyDataStorage.swift */, - 9F79228726696B0200DA3D80 /* PassPhraseStorage.swift */, + 9F79228726696B0200DA3D80 /* PassPhraseService.swift */, 9FC7EBA9266EBD3700F3BF5D /* InMemoryPassPhraseStorage.swift */, D2891AC124C59EFA008918E3 /* KeyService.swift */, ); @@ -1247,9 +1247,9 @@ isa = PBXGroup; children = ( 9FC7EBA2266EB95300F3BF5D /* PassPhraseStorageTests.swift */, - 9FC7EBC8266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift */, 9FC7EBC1266EBE0100F3BF5D /* EmailProviderMock.swift */, - 9FC7EBCF266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift */, + 9FC7EBCF266EBE1D00F3BF5D /* PassPhraseStorageMock.swift */, + 9FC413172683C491004C0A69 /* InMemoryPassPhraseStorageTest.swift */, ); path = PassPhraseStorageTests; sourceTree = ""; @@ -1492,7 +1492,7 @@ D212D36324C1AC4800035991 /* KeyId.swift */, D212D35C24C1AACF00035991 /* PrvKeyInfo.swift */, D2E26F6B24F25B1F00612AF1 /* KeyAlgo.swift */, - 9FC7EAB2266A404D00F3BF5D /* PassPhrase.swift */, + 9FC7EAB2266A404D00F3BF5D /* PassPhraseObject.swift */, ); path = Models; sourceTree = ""; @@ -2307,14 +2307,14 @@ 9FC41183268118B1004C0A69 /* EmailProviderMock.swift in Sources */, 9F976490267E11880058419D /* ImapHelperTest.swift in Sources */, 9FC4116526811861004C0A69 /* BackupServiceMock.swift in Sources */, + 9FC413182683C492004C0A69 /* InMemoryPassPhraseStorageTest.swift in Sources */, 9F9764C5267E14AB0058419D /* GeneralConstantsTest.swift in Sources */, 9F976507267E165D0058419D /* ZBase32EncodingTests.swift in Sources */, - 9FC4117D268118AE004C0A69 /* EncryptedPassPhraseStorageMock.swift in Sources */, + 9FC4117D268118AE004C0A69 /* PassPhraseStorageMock.swift in Sources */, 9F97650E267E16620058419D /* WKDURLsConstructorTests.swift in Sources */, 9F976585267E194F0058419D /* FlowCryptCoreTests.swift in Sources */, 9FC4116B2681186D004C0A69 /* KeyMethodsTest.swift in Sources */, 9F97653D267E17C90058419D /* LocalStorageTests.swift in Sources */, - 9FC41177268118AD004C0A69 /* LocalPassPhraseStorageMock.swift in Sources */, 9F9764F4267E15CC0058419D /* ExtensionTests.swift in Sources */, 9F976556267E186D0058419D /* DomainRulesTests.swift in Sources */, 9FC41171268118A7004C0A69 /* PassPhraseStorageTests.swift in Sources */, @@ -2410,7 +2410,7 @@ D20D3C672520AB1000D4AA9A /* BackupViewController.swift in Sources */, D2E26F6324F1698100612AF1 /* ContactsListViewController.swift in Sources */, 9F53CB7B2555E1E300C0157A /* GmailService+folders.swift in Sources */, - 9F79228826696B0200DA3D80 /* PassPhraseStorage.swift in Sources */, + 9F79228826696B0200DA3D80 /* PassPhraseService.swift in Sources */, D2E26F6624F169B400612AF1 /* ContactsListDecorator.swift in Sources */, D2FF6968243115F9007182F0 /* EmailProviderViewDecorator.swift in Sources */, 9F589F0D238C7A9B007FD759 /* LocalStorage.swift in Sources */, @@ -2466,7 +2466,7 @@ D29AFFF92409767F00C1387D /* GoogleContactsResponse.swift in Sources */, 9F003D6125E1B4ED00EB38C0 /* TrashFolderProvider.swift in Sources */, 9FF0671025520D7100FCC9E6 /* MessageGateway.swift in Sources */, - 9FC7EAB3266A404D00F3BF5D /* PassPhrase.swift in Sources */, + 9FC7EAB3266A404D00F3BF5D /* PassPhraseObject.swift in Sources */, 9F31AB8C23298B3F00CF87EA /* Imap+retry.swift in Sources */, 9F79229426696B9300DA3D80 /* KeyDataStorage.swift in Sources */, 9F82D352256D74FA0069A702 /* InboxViewControllerContainer.swift in Sources */, diff --git a/FlowCrypt/Controllers/Msg/MessageViewController.swift b/FlowCrypt/Controllers/Msg/MessageViewController.swift index f1a30549c..bdc18b863 100644 --- a/FlowCrypt/Controllers/Msg/MessageViewController.swift +++ b/FlowCrypt/Controllers/Msg/MessageViewController.swift @@ -56,17 +56,12 @@ final class MessageViewController: TableNodeViewController { private let messageOperationsProvider: MessageOperationsProvider private let trashFolderProvider: TrashFolderProviderType private var processedMessage: ProcessedMessage = .empty - private let passPhraseStorage: PassPhraseStorageType init( messageService: MessageService = MessageService(), messageOperationsProvider: MessageOperationsProvider = MailProvider.shared.messageOperationsProvider, decorator: MessageViewDecorator = MessageViewDecorator(dateFormatter: DateFormatter()), trashFolderProvider: TrashFolderProviderType = TrashFolderProvider(), - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ), input: MessageViewController.Input, completion: MsgViewControllerCompletion? ) { @@ -76,7 +71,6 @@ final class MessageViewController: TableNodeViewController { self.decorator = decorator self.trashFolderProvider = trashFolderProvider self.onCompletion = completion - self.passPhraseStorage = passPhraseStorage super.init(node: TableNode()) } diff --git a/FlowCrypt/Controllers/Setup/PassPraseSaveable.swift b/FlowCrypt/Controllers/Setup/PassPraseSaveable.swift index 0b8f4e18b..187be7eec 100644 --- a/FlowCrypt/Controllers/Setup/PassPraseSaveable.swift +++ b/FlowCrypt/Controllers/Setup/PassPraseSaveable.swift @@ -14,7 +14,7 @@ protocol PassPhraseSaveable { var saveLocallyNode: CellNode { get } var saveInMemoryNode: CellNode { get } - var passPhraseStorage: PassPhraseStorageType { get } + var passPhraseService: PassPhraseServiceType { get } func handleSelectedPassPhraseOption() func showPassPhraseErrorAlert() diff --git a/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift b/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift index 9c6772f94..70fe1f718 100644 --- a/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupBackupsViewController.swift @@ -18,7 +18,7 @@ final class SetupBackupsViewController: TableNodeViewController, PassPhraseSavea private let user: UserId private let fetchedEncryptedKeys: [KeyDetails] private let keyStorage: KeyStorageType - let passPhraseStorage: PassPhraseStorageType + let passPhraseService: PassPhraseServiceType private var passPhrase: String? private lazy var logger = Logger.nested(in: Self.self, with: .setup) @@ -42,10 +42,7 @@ final class SetupBackupsViewController: TableNodeViewController, PassPhraseSavea core: Core = Core.shared, keyMethods: KeyMethodsType = KeyMethods(), user: UserId, - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ) + passPhraseService: PassPhraseServiceType = PassPhraseService() ) { self.fetchedEncryptedKeys = fetchedEncryptedKeys self.router = router @@ -54,7 +51,7 @@ final class SetupBackupsViewController: TableNodeViewController, PassPhraseSavea self.core = core self.keyMethods = keyMethods self.user = user - self.passPhraseStorage = passPhraseStorage + self.passPhraseService = passPhraseService super.init(node: TableNode()) } @@ -140,7 +137,7 @@ extension SetupBackupsViewController { PassPhrase(value: passPhrase, longid: $0.longid) } .forEach { - passPhraseStorage.savePassPhrase(with: $0, inStorage: shouldSaveLocally) + passPhraseService.savePassPhrase(with: $0, inStorage: shouldSaveLocally) } // save keys diff --git a/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift b/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift index ce6fc10ec..c255ae242 100644 --- a/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupGenerateKeyViewController.swift @@ -36,7 +36,7 @@ final class SetupGenerateKeyViewController: TableNodeViewController, PassPhraseS private let storage: DataServiceType private let keyStorage: KeyStorageType private let attester: AttesterApiType - let passPhraseStorage: PassPhraseStorageType + let passPhraseService: PassPhraseServiceType var shouldSaveLocally = true { didSet { @@ -62,10 +62,7 @@ final class SetupGenerateKeyViewController: TableNodeViewController, PassPhraseS storage: DataServiceType = DataService.shared, keyStorage: KeyStorageType = KeyDataStorage(), attester: AttesterApiType = AttesterApi(), - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ) + passPhraseService: PassPhraseServiceType = PassPhraseService() ) { self.user = user self.core = core @@ -75,7 +72,7 @@ final class SetupGenerateKeyViewController: TableNodeViewController, PassPhraseS self.storage = storage self.attester = attester self.keyStorage = keyStorage - self.passPhraseStorage = passPhraseStorage + self.passPhraseService = passPhraseService super.init(node: TableNode()) } @@ -149,7 +146,7 @@ extension SetupGenerateKeyViewController { let passPhrase = PassPhrase(value: passPhrase, longid: encryptedPrv.key.longid) self.keyStorage.addKeys(keyDetails: [encryptedPrv.key], source: .generated) - self.passPhraseStorage.savePassPhrase(with: passPhrase, inStorage: self.shouldSaveLocally) + self.passPhraseService.savePassPhrase(with: passPhrase, inStorage: self.shouldSaveLocally) let updateKey = self.attester.updateKey( email: userId.email, diff --git a/FlowCrypt/Controllers/Setup/SetupManuallyEnterPassPhraseViewController.swift b/FlowCrypt/Controllers/Setup/SetupManuallyEnterPassPhraseViewController.swift index 9f77d5553..fb8ab5fb4 100644 --- a/FlowCrypt/Controllers/Setup/SetupManuallyEnterPassPhraseViewController.swift +++ b/FlowCrypt/Controllers/Setup/SetupManuallyEnterPassPhraseViewController.swift @@ -25,7 +25,7 @@ final class SetupManuallyEnterPassPhraseViewController: TableNodeViewController, private let keysStorage: KeyStorageType private let keyService: KeyServiceType private let router: GlobalRouterType - let passPhraseStorage: PassPhraseStorageType + let passPhraseService: PassPhraseServiceType private var passPhrase: String? @@ -46,10 +46,7 @@ final class SetupManuallyEnterPassPhraseViewController: TableNodeViewController, keysService: KeyStorageType = KeyDataStorage(), router: GlobalRouterType = GlobalRouter(), keyService: KeyServiceType = KeyService(), - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ), + passPhraseService: PassPhraseServiceType = PassPhraseService(), email: String, fetchedKeys: [KeyDetails] ) { @@ -60,7 +57,7 @@ final class SetupManuallyEnterPassPhraseViewController: TableNodeViewController, self.keysStorage = keysService self.router = router self.keyService = keyService - self.passPhraseStorage = passPhraseStorage + self.passPhraseService = passPhraseService super.init(node: TableNode()) } @@ -247,7 +244,7 @@ extension SetupManuallyEnterPassPhraseViewController { PassPhrase(value: passPhrase, longid: $0.longid) } .forEach { - passPhraseStorage.updatePassPhrase(with: $0, inStorage: shouldSaveLocally) + passPhraseService.updatePassPhrase(with: $0, inStorage: shouldSaveLocally) } newKeysToAdd @@ -255,7 +252,7 @@ extension SetupManuallyEnterPassPhraseViewController { PassPhrase(value: passPhrase, longid: $0.longid) } .forEach { - passPhraseStorage.savePassPhrase(with: $0, inStorage: shouldSaveLocally) + passPhraseService.savePassPhrase(with: $0, inStorage: shouldSaveLocally) } hideSpinner() diff --git a/FlowCrypt/Core/Models/PassPhrase.swift b/FlowCrypt/Core/Models/PassPhraseObject.swift similarity index 78% rename from FlowCrypt/Core/Models/PassPhrase.swift rename to FlowCrypt/Core/Models/PassPhraseObject.swift index 963929e9d..768efa269 100644 --- a/FlowCrypt/Core/Models/PassPhrase.swift +++ b/FlowCrypt/Core/Models/PassPhraseObject.swift @@ -9,24 +9,6 @@ import Foundation import RealmSwift -// Should be operated in app -struct PassPhrase: Codable, Hashable, Equatable { - let value: String - let longid: String - - init(value: String, longid: String) { - self.value = value - self.longid = longid - } -} - -extension PassPhrase { - init(object: PassPhraseObject) { - self.value = object.value - self.longid = object.longid - } -} - /// PassPhrase object to store in Realm final class PassPhraseObject: Object { @objc dynamic var longid: String = "" @@ -42,8 +24,17 @@ final class PassPhraseObject: Object { } } +// MARK: - Convenience extension PassPhraseObject { convenience init(_ passPhrase: PassPhrase) { self.init(longid: passPhrase.longid, value: passPhrase.value) } } + +extension PassPhrase { + init(object: PassPhraseObject) { + self.value = object.value + self.longid = object.longid + self.date = nil + } +} diff --git a/FlowCrypt/Functionality/DataManager/DataService.swift b/FlowCrypt/Functionality/DataManager/DataService.swift index c98224b40..1fb7355be 100644 --- a/FlowCrypt/Functionality/DataManager/DataService.swift +++ b/FlowCrypt/Functionality/DataManager/DataService.swift @@ -10,6 +10,10 @@ import Foundation import Promises import RealmSwift +protocol EmailProviderType { + var email: String? { get } +} + protocol DataServiceType: EmailProviderType { // data var email: String? { get } diff --git a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift index 6759af52f..564b747e1 100644 --- a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift +++ b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift @@ -190,27 +190,27 @@ extension EncryptedStorage { } // MARK: - PassPhrase -extension EncryptedStorage: EncryptedPassPhraseStorage { - func addPassPhrase(object: PassPhraseObject) { +extension EncryptedStorage: PassPhraseStorageType { + func save(passPhrase: PassPhrase) { try! storage.write { - storage.add(object) + storage.add(PassPhraseObject(passPhrase)) } } - func updatePassPhrase(object: PassPhraseObject) { + func update(passPhrase: PassPhrase) { try! storage.write { - storage.add(object, update: .all) + storage.add(PassPhraseObject(passPhrase), update: .all) } } - func removePassPhrase(object: PassPhraseObject) { + func remove(passPhrase: PassPhrase) { try! storage.write { - storage.delete(object) + storage.delete(PassPhraseObject(passPhrase)) } } - func getPassPhrases() -> [PassPhraseObject] { - Array(storage.objects(PassPhraseObject.self)) + func getPassPhrases() -> [PassPhrase] { + Array(storage.objects(PassPhraseObject.self)).map(PassPhrase.init) } } diff --git a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorageProtocols.swift b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorageProtocols.swift index 44ec94c44..7c717c823 100644 --- a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorageProtocols.swift +++ b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorageProtocols.swift @@ -14,11 +14,3 @@ protocol KeyStorageType { func publicKey() -> String? func keysInfo() -> [KeyInfo] } - -protocol EncryptedPassPhraseStorage { - func addPassPhrase(object: PassPhraseObject) - func updatePassPhrase(object: PassPhraseObject) - func getPassPhrases() -> [PassPhraseObject] - func removePassPhrase(object: PassPhraseObject) - func keysInfo() -> [KeyInfo] -} diff --git a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift index 9e97fd622..c1b5d6970 100644 --- a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift +++ b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift @@ -48,22 +48,19 @@ enum MessageServiceError: Error { final class MessageService { private let messageProvider: MessageProvider private let keyService: KeyServiceType - private let passPhraseStorage: PassPhraseStorageType + private let passPhraseService: PassPhraseServiceType private let core: Core init( messageProvider: MessageProvider = MailProvider.shared.messageProvider, keyService: KeyServiceType = KeyService(), core: Core = Core.shared, - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ) + passPhraseService: PassPhraseServiceType = PassPhraseService() ) { self.messageProvider = messageProvider self.keyService = keyService self.core = core - self.passPhraseStorage = passPhraseStorage + self.passPhraseService = passPhraseService } func validateMessage(rawMimeData: Data, with passPhrase: String) -> Promise { @@ -94,7 +91,7 @@ final class MessageService { } else { keys .map { PassPhrase(value: passPhrase, longid: $0.longid) } - .forEach { self.passPhraseStorage.savePassPhrase(with: $0, inStorage: false) } + .forEach { self.passPhraseService.savePassPhrase(with: $0, inStorage: false) } let processedMessage = self.processMessage(rawMimeData: rawMimeData, with: decrypted) diff --git a/FlowCrypt/Functionality/Services/Key Services/InMemoryPassPhraseStorage.swift b/FlowCrypt/Functionality/Services/Key Services/InMemoryPassPhraseStorage.swift index a18ef8291..2157a606f 100644 --- a/FlowCrypt/Functionality/Services/Key Services/InMemoryPassPhraseStorage.swift +++ b/FlowCrypt/Functionality/Services/Key Services/InMemoryPassPhraseStorage.swift @@ -8,38 +8,86 @@ import UIKit -protocol InMemoryPassPhraseStorageType { - var passPhrases: Set { get } - func save(passPhrase: InMemoryPassPhrase) - func removePassPhrases(with objects: [InMemoryPassPhrase]) -} +final class InMemoryPassPhraseStorage: PassPhraseStorageType { + private lazy var logger = Logger.nested(Self.self) + + let timeoutInSeconds: Int + let calendar = Calendar.current + let passPhraseProvider: InMemoryPassPhraseProviderType + + init( + passPhraseProvider: InMemoryPassPhraseProviderType = InMemoryPassPhraseProvider.shared, + timeoutInSeconds: Int = 4*60*60 // 4 hours + ) { + self.passPhraseProvider = passPhraseProvider + self.timeoutInSeconds = timeoutInSeconds + } + + func save(passPhrase: PassPhrase) { + let passPhraseToSave = passPhrase.withUpdatedDate() + passPhraseProvider.save(passPhrase: passPhraseToSave) + } + + func update(passPhrase: PassPhrase) { + let passPhraseToSave = passPhrase.withUpdatedDate() + passPhraseProvider.save(passPhrase: passPhraseToSave) + } + + func remove(passPhrase: PassPhrase) { + passPhraseProvider.removePassPhrases(with: passPhrase) + } + + func getPassPhrases() -> [PassPhrase] { + passPhraseProvider.passPhrases + .compactMap { passPhrase -> PassPhrase? in + guard let dateToCompare = passPhrase.date else { + logger.logError("Date should not be nil") + return nil + } + + let components = calendar.dateComponents( + [.second], + from: dateToCompare, + to: Date() + ) -struct InMemoryPassPhrase: Codable, Hashable, Equatable { - let passPhrase: PassPhrase - let date: Date + let timePassed = components.second ?? 0 - static func == (lhs: Self, rhs: Self) -> Bool { - lhs.passPhrase.longid == rhs.passPhrase.longid + let isPassPhraseValid = timePassed < timeoutInSeconds + + if isPassPhraseValid { + return passPhrase + } else { + return nil + } + } } } -final class InMemoryPassPhraseStorage: InMemoryPassPhraseStorageType { - static let shared: InMemoryPassPhraseStorage = InMemoryPassPhraseStorage() +// MARK: - Convenience - private(set) var passPhrases: Set = [] +protocol InMemoryPassPhraseProviderType { + var passPhrases: Set { get } + func save(passPhrase: PassPhrase) + func removePassPhrases(with objects: PassPhrase) +} + +/// - Warning: - should be shared instance +final class InMemoryPassPhraseProvider: InMemoryPassPhraseProviderType { + static let shared: InMemoryPassPhraseProvider = InMemoryPassPhraseProvider() + + private(set) var passPhrases: Set = [] private init() { } - func save(passPhrase: InMemoryPassPhrase) { + func save(passPhrase: PassPhrase) { passPhrases.insert(passPhrase) } - func removePassPhrases(with objects: [InMemoryPassPhrase]) { - objects.forEach { - if passPhrases.contains($0) { - passPhrases.remove($0) - } + func removePassPhrases(with objects: PassPhrase) { + if passPhrases.contains(objects) { + passPhrases.remove(objects) } } } diff --git a/FlowCrypt/Functionality/Services/Key Services/KeyDataStorage.swift b/FlowCrypt/Functionality/Services/Key Services/KeyDataStorage.swift index 39d0b7c6a..aca0ef9b7 100644 --- a/FlowCrypt/Functionality/Services/Key Services/KeyDataStorage.swift +++ b/FlowCrypt/Functionality/Services/Key Services/KeyDataStorage.swift @@ -10,17 +10,11 @@ import Foundation final class KeyDataStorage { private let encryptedStorage: EncryptedStorageType - private let passPhraseStorage: PassPhraseStorageType init( - encryptedStorage: EncryptedStorageType = EncryptedStorage(), - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ) + encryptedStorage: EncryptedStorageType = EncryptedStorage() ) { self.encryptedStorage = encryptedStorage - self.passPhraseStorage = passPhraseStorage } } diff --git a/FlowCrypt/Functionality/Services/Key Services/KeyService.swift b/FlowCrypt/Functionality/Services/Key Services/KeyService.swift index 55cacba32..e8855bcb8 100644 --- a/FlowCrypt/Functionality/Services/Key Services/KeyService.swift +++ b/FlowCrypt/Functionality/Services/Key Services/KeyService.swift @@ -20,19 +20,16 @@ enum KeyServiceError: Error { final class KeyService: KeyServiceType { let coreService: Core = .shared let storage: KeyStorageType - let passPhraseStorage: PassPhraseStorageType + let passPhraseService: PassPhraseServiceType let currentUserEmail: () -> (String?) init( storage: KeyStorageType = KeyDataStorage(), - passPhraseStorage: PassPhraseStorageType = PassPhraseStorage( - storage: EncryptedStorage(), - emailProvider: DataService.shared - ), + passPhraseService: PassPhraseServiceType = PassPhraseService(), currentUserEmail: @autoclosure @escaping () -> (String?) = DataService.shared.email ) { self.storage = storage - self.passPhraseStorage = passPhraseStorage + self.passPhraseService = passPhraseService self.currentUserEmail = currentUserEmail } @@ -63,7 +60,7 @@ final class KeyService: KeyServiceType { let keysInfo = storage.keysInfo() .filter { $0.account.contains(email) } - let storedPassPhrases = passPhraseStorage.getPassPhrases() + let storedPassPhrases = passPhraseService.getPassPhrases() guard keysInfo.isNotEmpty else { return .failure(.emptyKeys) diff --git a/FlowCrypt/Functionality/Services/Key Services/PassPhraseService.swift b/FlowCrypt/Functionality/Services/Key Services/PassPhraseService.swift new file mode 100644 index 000000000..ad5579356 --- /dev/null +++ b/FlowCrypt/Functionality/Services/Key Services/PassPhraseService.swift @@ -0,0 +1,97 @@ +// +// PassPhraseStorageService.swift +// FlowCrypt +// +// Created by Anton Kharchevskyi on 02.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import UIKit + +// MARK: - Data Object +struct PassPhrase: Codable, Hashable, Equatable { + let value: String + let longid: String + let date: Date? + + init(value: String, longid: String, date: Date? = nil) { + self.value = value + self.longid = longid + self.date = date + } + + func withUpdatedDate() -> PassPhrase { + PassPhrase(value: self.value, longid: self.longid, date: Date()) + } + + static func == (lhs: PassPhrase, rhs: PassPhrase) -> Bool { + lhs.longid == rhs.longid + } + + func hash(into hasher: inout Hasher) { + hasher.combine(longid) + } +} + +// MARK: - Pass Phrase Storage +protocol PassPhraseStorageType { + func save(passPhrase: PassPhrase) + func update(passPhrase: PassPhrase) + func remove(passPhrase: PassPhrase) + + func getPassPhrases() -> [PassPhrase] +} + +// MARK: - PassPhraseService +protocol PassPhraseServiceType { + func getPassPhrases() -> [PassPhrase] + func savePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) + func updatePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) +} + +final class PassPhraseService: PassPhraseServiceType { + private lazy var logger = Logger.nested(Self.self) + + let currentUserEmail: String? + let encryptedStorage: PassPhraseStorageType + let inMemoryStorage: PassPhraseStorageType + + init( + encryptedStorage: PassPhraseStorageType = EncryptedStorage(), + localStorage: PassPhraseStorageType = InMemoryPassPhraseStorage(), + emailProvider: EmailProviderType = DataService.shared + ) { + self.encryptedStorage = encryptedStorage + self.inMemoryStorage = localStorage + self.currentUserEmail = emailProvider.email + } + + func savePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) { + if inStorage { + logger.logInfo("Save to storage \(passPhrase.longid)") + encryptedStorage.save(passPhrase: passPhrase) + } else { + logger.logInfo("Save in memory \(passPhrase.longid)") + + inMemoryStorage.save(passPhrase: passPhrase) + + let alreadySaved = encryptedStorage.getPassPhrases() + + if alreadySaved.contains(where: { $0.longid == passPhrase.longid }) { + encryptedStorage.remove(passPhrase: passPhrase) + } + } + } + + func updatePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) { + if inStorage { + encryptedStorage.update(passPhrase: passPhrase) + } else { + inMemoryStorage.save(passPhrase: passPhrase) + } + } + + func getPassPhrases() -> [PassPhrase] { + encryptedStorage.getPassPhrases() + inMemoryStorage.getPassPhrases() + } +} diff --git a/FlowCrypt/Functionality/Services/Key Services/PassPhraseStorage.swift b/FlowCrypt/Functionality/Services/Key Services/PassPhraseStorage.swift deleted file mode 100644 index 498e75a6a..000000000 --- a/FlowCrypt/Functionality/Services/Key Services/PassPhraseStorage.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// PassPhraseStorageService.swift -// FlowCrypt -// -// Created by Anton Kharchevskyi on 02.06.2021. -// Copyright © 2021 FlowCrypt Limited. All rights reserved. -// - -import UIKit - -protocol PassPhraseStorageType { - func getPassPhrases() -> [PassPhrase] - func savePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) - func updatePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) -} - -protocol EmailProviderType { - var email: String? { get } -} - -final class PassPhraseStorage: PassPhraseStorageType { - private lazy var logger = Logger.nested(Self.self) - - let currentUserEmail: String? - let encryptedStorage: EncryptedPassPhraseStorage - let inMemoryStorage: InMemoryPassPhraseStorageType - let timeoutInSeconds: Int - - init( - storage: EncryptedPassPhraseStorage, - localStorage: InMemoryPassPhraseStorageType = InMemoryPassPhraseStorage.shared, - timeoutInSeconds: Int = 4*60*60, // 4 hours - emailProvider: EmailProviderType, - isHours: Bool = true - ) { - self.encryptedStorage = storage - self.inMemoryStorage = localStorage - self.timeoutInSeconds = timeoutInSeconds - self.currentUserEmail = emailProvider.email - } - - func savePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) { - if inStorage { - logger.logInfo("Save to storage \(passPhrase.longid)") - encryptedStorage.addPassPhrase(object: PassPhraseObject(passPhrase)) - } else { - logger.logInfo("Save locally \(passPhrase.longid)") - - let inMemoryPassPhrase = InMemoryPassPhrase(passPhrase: passPhrase, date: Date()) - inMemoryStorage.save(passPhrase: inMemoryPassPhrase) - - let alreadySaved = encryptedStorage.getPassPhrases() - - if alreadySaved.contains(where: { $0.longid == passPhrase.longid }) { - encryptedStorage.removePassPhrase(object: PassPhraseObject(passPhrase)) - } - } - } - - func updatePassPhrase(with passPhrase: PassPhrase, inStorage: Bool) { - if inStorage { - encryptedStorage.updatePassPhrase(object: PassPhraseObject(passPhrase)) - } else { - let updated = InMemoryPassPhrase(passPhrase: passPhrase, date: Date()) - inMemoryStorage.save(passPhrase: updated) - } - } - - func getPassPhrases() -> [PassPhrase] { - let dbPassPhrases = encryptedStorage.getPassPhrases() - .map(PassPhrase.init) - - logger.logInfo("dbPassPhrases \(dbPassPhrases.count)") - - let calendar = Calendar.current - - var validPassPhrases: [PassPhrase] = [] - var invalidPassPhrases: [InMemoryPassPhrase] = [] - - inMemoryStorage.passPhrases - .forEach { localPassPhrases in - let components = calendar.dateComponents( - [.second], - from: localPassPhrases.date, - to: Date() - ) - - let timePassed = components.second ?? 0 - - let isPassPhraseValid = timePassed < timeoutInSeconds - - if isPassPhraseValid { - validPassPhrases.append(localPassPhrases.passPhrase) - } else { - invalidPassPhrases.append(localPassPhrases) - } - - let message = "pass phrase is \(isPassPhraseValid ? "valid" : "invalid") \(localPassPhrases.passPhrase.longid)" - self.logger.logInfo(message) - } - - inMemoryStorage.removePassPhrases(with: invalidPassPhrases) - - logger.logInfo("validPassPhrases \(validPassPhrases.count)") - return dbPassPhrases + validPassPhrases - } -} diff --git a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/EncryptedPassPhraseStorageMock.swift b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/EncryptedPassPhraseStorageMock.swift deleted file mode 100644 index 6ca85f621..000000000 --- a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/EncryptedPassPhraseStorageMock.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// EncryptedPassPhraseStorageMock.swift -// FlowCryptTests -// -// Created by Anton Kharchevskyi on 07.06.2021. -// Copyright © 2021 FlowCrypt Limited. All rights reserved. -// - -import Foundation -@testable import FlowCrypt - -class EncryptedPassPhraseStorageMock: EncryptedPassPhraseStorage { - func addPassPhrase(object: PassPhraseObject) { - - } - - func updatePassPhrase(object: PassPhraseObject) { - - } - - var getPassPhrasesResult: () -> ([PassPhraseObject]) = { - [PassPhraseObject(longid: "longid", value: "value")] - } - func getPassPhrases() -> [PassPhraseObject] { - getPassPhrasesResult() - } - - var isRemovePassPhraseResult: ((PassPhraseObject) -> ())? - func removePassPhrase(object: PassPhraseObject) { - isRemovePassPhraseResult?(object) - } - - var keysInfoResult: () -> ([KeyInfo]) = { [] } - func keysInfo() -> [KeyInfo] { - keysInfoResult() - } -} diff --git a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/InMemoryPassPhraseStorageTest.swift b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/InMemoryPassPhraseStorageTest.swift new file mode 100644 index 000000000..89b803995 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/InMemoryPassPhraseStorageTest.swift @@ -0,0 +1,82 @@ +// +// InMemoryPassPhraseStorageTest.swift +// FlowCryptAppTests +// +// Created by Anton Kharchevskyi on 23.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest +@testable import FlowCrypt + +class InMemoryPassPhraseStorageTest: XCTestCase { + var sut: InMemoryPassPhraseStorage! + var passPhraseProvider: InMemoryPassPhraseProviderType! + var timeoutInSeconds: Int! + + override func setUp() { + passPhraseProvider = InMemoryPassPhraseProviderMock() + timeoutInSeconds = 2 + sut = .init( + passPhraseProvider: passPhraseProvider, + timeoutInSeconds: timeoutInSeconds + ) + } + + func testSavePassPhrase() { + let pass = PassPhrase(value: "A", longid: "1") + sut.save(passPhrase: pass) + passPhraseProvider.passPhrases.forEach { + XCTAssertNotNil($0.date) + } + } + + func testUpdatePassPhrase() { + let pass = PassPhrase(value: "A", longid: "1") + sut.update(passPhrase: pass) + passPhraseProvider.passPhrases.forEach { + XCTAssertNotNil($0.date) + } + } + + func testRemovePassPhrase() { + let pass = PassPhrase(value: "A", longid: "1") + sut.save(passPhrase: pass) + sut.remove(passPhrase: pass) + XCTAssertTrue(passPhraseProvider.passPhrases.isEmpty) + } + + func testGetPassPhrases() { + XCTAssertTrue(sut.getPassPhrases().isEmpty) + + let pass = PassPhrase(value: "A", longid: "1") + sut.save(passPhrase: pass) + XCTAssertTrue(sut.getPassPhrases().count == 1) + XCTAssertTrue(sut.getPassPhrases().contains(where: { $0.longid == "1"})) + XCTAssertTrue(sut.getPassPhrases().filter { $0.date == nil }.isEmpty) + } + + func testExpiredPassPhrases() { + XCTAssertTrue(sut.getPassPhrases().isEmpty) + + let pass = PassPhrase(value: "A", longid: "1") + sut.save(passPhrase: pass) + sleep(3) + XCTAssertTrue(sut.getPassPhrases().isEmpty) + } +} + + +class InMemoryPassPhraseProviderMock: InMemoryPassPhraseProviderType { + var passPhrases: Set = [] + + func save(passPhrase: PassPhrase) { + passPhrases.insert(passPhrase) + } + + func removePassPhrases(with objects: PassPhrase) { + if passPhrases.contains(objects) { + passPhrases.remove(objects) + } + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/LocalPassPhraseStorageMock.swift b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/LocalPassPhraseStorageMock.swift deleted file mode 100644 index 5a784fa94..000000000 --- a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/LocalPassPhraseStorageMock.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// LocalPassPhraseStorageMock.swift -// FlowCryptTests -// -// Created by Anton Kharchevskyi on 07.06.2021. -// Copyright © 2021 FlowCrypt Limited. All rights reserved. -// - -import Foundation -@testable import FlowCrypt - -class LocalPassPhraseStorageMock: InMemoryPassPhraseStorageType { - var passPhrases: Set = [] - - var isSaveCalled = false - func save(passPhrase: InMemoryPassPhrase) { - isSaveCalled = true - passPhrases.insert(passPhrase) - - print("^^ \(passPhrases)") - } - - func removePassPhrases(with objects: [InMemoryPassPhrase]) { - objects.forEach { - passPhrases.remove($0) - } - } -} diff --git a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageMock.swift b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageMock.swift new file mode 100644 index 000000000..ae9a98620 --- /dev/null +++ b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageMock.swift @@ -0,0 +1,38 @@ +// +// EncryptedPassPhraseStorageMock.swift +// FlowCryptTests +// +// Created by Anton Kharchevskyi on 07.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +@testable import FlowCrypt + +class PassPhraseStorageMock: PassPhraseStorageType { + + var saveResult: ((PassPhrase) -> ())? + func save(passPhrase: PassPhrase) { + saveResult?(passPhrase) + } + + var updateResult: ((PassPhrase) -> ())? + func update(passPhrase: PassPhrase) { + updateResult?(passPhrase) + } + + var isRemovePassPhraseResult: ((PassPhrase) -> ())? + func remove(passPhrase: PassPhrase) { + isRemovePassPhraseResult?(passPhrase) + } + + var getPassPhrasesResult: () -> ([PassPhrase]) = { + [ + PassPhrase(value: "a", longid: "1"), + PassPhrase(value: "2", longid: "2") + ] + } + func getPassPhrases() -> [PassPhrase] { + getPassPhrasesResult() + } +} diff --git a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageTests.swift b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageTests.swift index d18f4fd8a..361c7a186 100644 --- a/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageTests.swift +++ b/FlowCryptAppTests/Functionallity/Services/PassPhraseStorageTests/PassPhraseStorageTests.swift @@ -11,30 +11,28 @@ import XCTest class PassPhraseStorageTests: XCTestCase { - var sut: PassPhraseStorage! - var storage: EncryptedPassPhraseStorageMock! + var sut: PassPhraseService! + var encryptedStorage: PassPhraseStorageMock! + var inMemoryStorage: PassPhraseStorageMock! var emailProvider: EmailProviderMock! - var localStorage: LocalPassPhraseStorageMock! override func setUp() { - storage = EncryptedPassPhraseStorageMock() emailProvider = EmailProviderMock() - localStorage = LocalPassPhraseStorageMock() - - sut = PassPhraseStorage( - storage: storage, - localStorage: localStorage, - timeoutInSeconds: 2, - emailProvider: emailProvider, - isHours: false + encryptedStorage = PassPhraseStorageMock() + inMemoryStorage = PassPhraseStorageMock() + + sut = PassPhraseService( + encryptedStorage: encryptedStorage, + localStorage: inMemoryStorage, + emailProvider: emailProvider ) } func testGetPassPhrasesWhenEmpty() { // no pass phrases in storage - storage.getPassPhrasesResult = { [] } + encryptedStorage.getPassPhrasesResult = { [] } // no pass phrases in localStorage - localStorage.passPhrases = [] + inMemoryStorage.getPassPhrasesResult = { [] } let result = sut.getPassPhrases() @@ -42,24 +40,24 @@ class PassPhraseStorageTests: XCTestCase { } func testGetValidPassPhraseFromStorage() { - let passPhrase1 = PassPhraseObject( - longid: "A123", - value: "some" + let passPhrase1 = PassPhrase( + value: "some", + longid: "A123" ) - let passPhrase2 = PassPhraseObject( - longid: "A123", - value: "some" + let passPhrase2 = PassPhrase( + value: "some", + longid: "A123" ) - storage.getPassPhrasesResult = { [passPhrase1] } + encryptedStorage.getPassPhrasesResult = { [passPhrase1] } // no pass phrases in localStorage - localStorage.passPhrases = [] + inMemoryStorage.getPassPhrasesResult = { [] } var result = sut.getPassPhrases() XCTAssertTrue(result.count == 1) - storage.getPassPhrasesResult = { + encryptedStorage.getPassPhrasesResult = { [passPhrase1, passPhrase2] } @@ -69,16 +67,15 @@ class PassPhraseStorageTests: XCTestCase { } func testGetValidPassPhraseInLocalStorage() { - storage.getPassPhrasesResult = { [] } + encryptedStorage.getPassPhrasesResult = { [] } let savedDate = Date() - let localPassPhrase = InMemoryPassPhrase( - passPhrase: PassPhrase( - value: "value", - longid: "longid"), + let localPassPhrase = PassPhrase( + value: "value", + longid: "longid", date: savedDate ) - localStorage.passPhrases = [localPassPhrase] + inMemoryStorage.getPassPhrasesResult = { [localPassPhrase] } // current timeout = 2 sleep(1) @@ -87,48 +84,28 @@ class PassPhraseStorageTests: XCTestCase { XCTAssertTrue(result.isNotEmpty) } - func testGetExpiredPassPhraseInLocalStorage() { - storage.getPassPhrasesResult = { [] } - - let savedDate = Date() - let localPassPhrase = InMemoryPassPhrase( - passPhrase: PassPhrase( - value: "value", - longid: "longid"), - date: savedDate - ) - localStorage.passPhrases = [localPassPhrase] - - // current timeout = 2 - sleep(3) - - let result = sut.getPassPhrases() - XCTAssertTrue(result.isEmpty) - } - func testBothStorageContainsValidPassPhrase() { - let passPhrase1 = PassPhraseObject( - longid: "A123", - value: "some" + let passPhrase1 = PassPhrase( + value: "some", + longid: "A123" ) - let passPhrase2 = PassPhraseObject( - longid: "A123", - value: "some" + let passPhrase2 = PassPhrase( + value: "some", + longid: "A123" ) - storage.getPassPhrasesResult = { + encryptedStorage.getPassPhrasesResult = { [passPhrase1, passPhrase2] } let savedDate = Date() - let localPassPhrase = InMemoryPassPhrase( - passPhrase: PassPhrase( - value: "value", - longid: "longid"), + let localPassPhrase = PassPhrase( + value: "value", + longid: "longid", date: savedDate ) - localStorage.passPhrases = [localPassPhrase] + inMemoryStorage.getPassPhrasesResult = { [localPassPhrase] } let result = sut.getPassPhrases() XCTAssertTrue(result.count == 3) @@ -142,15 +119,15 @@ class PassPhraseStorageTests: XCTestCase { expectation.isInverted = true // encrypted storage contains pass phrase which should be saved locally - storage.getPassPhrasesResult = { + encryptedStorage.getPassPhrasesResult = { [ - PassPhraseObject(longid: "12345", value: "pass") + PassPhrase(value: "pass", longid: "12345") ] } // encrypted storage should not contains pass phrase which user decide to save locally - storage.isRemovePassPhraseResult = { passPhraseToRemove in + encryptedStorage.isRemovePassPhraseResult = { passPhraseToRemove in if passPhraseToRemove.longid == "12345" { expectation.fulfill() } @@ -158,7 +135,7 @@ class PassPhraseStorageTests: XCTestCase { sut.savePassPhrase(with: passPhraseToSave, inStorage: true) - XCTAssertFalse(localStorage.isSaveCalled) + XCTAssertFalse(inMemoryStorage.saveResult != nil ) wait(for: [expectation], timeout: 0.1, enforceOrder: false) } @@ -170,25 +147,19 @@ class PassPhraseStorageTests: XCTestCase { expectation.isInverted = true // encrypted storage is empty - storage.getPassPhrasesResult = { [ ] } + encryptedStorage.getPassPhrasesResult = { [ ] } - storage.isRemovePassPhraseResult = { _ in + encryptedStorage.isRemovePassPhraseResult = { _ in expectation.fulfill() } sut.savePassPhrase(with: passPhraseToSave, inStorage: true) - XCTAssertFalse(localStorage.isSaveCalled) + XCTAssertFalse(inMemoryStorage.saveResult != nil ) wait(for: [expectation], timeout: 0.1, enforceOrder: false) } - - func testSavePassPhraseInMemory() { - let passPhraseToSave = PassPhrase(value: "pass", longid: "12345") - sut.savePassPhrase(with: passPhraseToSave, inStorage: false) - XCTAssertTrue(localStorage.isSaveCalled) - } } extension KeyInfo {