From 175fa8c11c9511ad333e7ff25ee0b2b742e0c739 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Fri, 18 Jun 2021 17:22:57 +0300 Subject: [PATCH 1/4] Added DomainRules Realm object; Added fetching of ClientConfig that includes organisational rules; Fetching org rules on AppStartup; --- FlowCrypt.xcodeproj/project.pbxproj | 34 +++++++-- .../Inbox/InboxViewController.swift | 15 +--- .../Encrypted Storage/EncryptedStorage.swift | 2 +- .../Functionality/Services/AppStartup.swift | 8 +++ .../Services/EnterpriseServerApi.swift | 45 ++++++++++++ .../DomainRulesProvider.swift | 41 +++++++++++ .../OrganisationalRulesService.swift | 66 +++++++++++++++++ .../OrganisationalRulesServiceError.swift | 15 ++++ FlowCrypt/Models/DomainRules.swift | 62 ++++++++++++++++ FlowCrypt/Models/OrganisationalRule.swift | 28 +------- .../Realm Models/DomainRulesObject.swift | 71 +++++++++++++++++++ 11 files changed, 342 insertions(+), 45 deletions(-) create mode 100644 FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift create mode 100644 FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift create mode 100644 FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesServiceError.swift create mode 100644 FlowCrypt/Models/DomainRules.swift create mode 100644 FlowCrypt/Models/Realm Models/DomainRulesObject.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 40c124992..636d693b6 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,17 +11,20 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; + 21489B78267CB42400BDE4AC /* DomainRulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */; }; + 21489B7A267CB4DF00BDE4AC /* DomainRulesObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */; }; + 21489B7C267CBA0E00BDE4AC /* DomainRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */; }; + 21489B80267CC39E00BDE4AC /* OrganisationalRulesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */; }; + 21489B83267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */; }; 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; }; 21C7DEFE26669CE100C44800 /* DateFormattingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */; }; 21C7DF0526697DA500C44800 /* PromiseKitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */; }; 21C7DF09266C0D8F00C44800 /* EnterpriseServerApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */; }; 21C7DF0B266C0E3600C44800 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0A266C0E3600C44800 /* Configuration.swift */; }; 21CE25E62650070300ADFF4B /* WKDURLsConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */; }; - 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B2226565B5D00691848 /* DomainRulesTests.swift */; }; 21EA3B2F26565B7400691848 /* domain_rules.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B2E26565B7400691848 /* domain_rules.json */; }; 21EA3B3626565B8100691848 /* domain_rules_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3526565B8100691848 /* domain_rules_empty.json */; }; 21EA3B3D26565B9800691848 /* domain_rules_partly_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3C26565B9800691848 /* domain_rules_partly_empty.json */; }; - 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B15265647C400691848 /* OrganisationalRule.swift */; }; 21EA3B592656611D00691848 /* OrganisationalRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B15265647C400691848 /* OrganisationalRule.swift */; }; 21EFF61F265A5C6700AB0B71 /* WKDURLsApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EFF61E265A5C6700AB0B71 /* WKDURLsApi.swift */; }; 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */; }; @@ -362,6 +365,11 @@ 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; 211392A4266511E6009202EC /* PubLookup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubLookup.swift; sourceTree = ""; }; + 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRulesProvider.swift; sourceTree = ""; }; + 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRulesObject.swift; sourceTree = ""; }; + 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRules.swift; sourceTree = ""; }; + 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesService.swift; sourceTree = ""; }; + 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceError.swift; sourceTree = ""; }; 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = ""; }; 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseKitExtension.swift; sourceTree = ""; }; 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterpriseServerApi.swift; sourceTree = ""; }; @@ -719,6 +727,7 @@ 9F0C3C132316E69300299985 /* User.swift */, 9F9AAFFC2383E216000A00F1 /* Document.swift */, 21EA3B15265647C400691848 /* OrganisationalRule.swift */, + 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */, ); path = Models; sourceTree = ""; @@ -743,6 +752,16 @@ path = SideMenu; sourceTree = ""; }; + 21489B81267CC3BC00BDE4AC /* Organisational Rules Service */ = { + isa = PBXGroup; + children = ( + 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */, + 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */, + 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */, + ); + path = "Organisational Rules Service"; + sourceTree = ""; + }; 21CE25D32650034500ADFF4B /* WKDURLs */ = { isa = PBXGroup; children = ( @@ -919,14 +938,15 @@ 9F31AB9F232C071700CF87EA /* GlobalRouter.swift */, 32DCAC088C8BFFFAF08853AC /* AttesterApi.swift */, 32DCAC9C0512037018F434A1 /* BackendApi.swift */, - 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */, 21EFF61E265A5C6700AB0B71 /* WKDURLsApi.swift */, + 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */, D274724024F97C5C006BA6EF /* CacheService.swift */, C132B9CA1EC2DE6400763715 /* GeneralConstants.swift */, 9FB22CFD25715DDF0026EE64 /* Key Services */, 9F41FA1C25372C2D003B970D /* Backup Services */, D227C0E4250538190070F805 /* Folders Services */, D27B911724EFE787002DF0A1 /* Contacts Services */, + 21489B81267CC3BC00BDE4AC /* Organisational Rules Service */, ); path = Services; sourceTree = ""; @@ -940,6 +960,7 @@ D274724324FD1932006BA6EF /* FolderObject.swift */, 04B4728B1ECE29D200B8266F /* KeyInfo.swift */, D2F41370243CC76E0066AFB5 /* SessionObject.swift */, + 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */, ); path = "Realm Models"; sourceTree = ""; @@ -2290,11 +2311,9 @@ D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, 9F1D5769263B540100477938 /* Logger.swift in Sources */, A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, - 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, - 21EA3B532656611C00691848 /* OrganisationalRule.swift in Sources */, A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, D212D36124C1AC0D00035991 /* KeyDetails.swift in Sources */, 9F6EE18C25A8AF970059BA51 /* GeneralConstants.swift in Sources */, @@ -2329,6 +2348,7 @@ 9FB22CE425715D3E0026EE64 /* GmailServiceErrorHandler.swift in Sources */, 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */, C132B9B41EC2DBD800763715 /* AppDelegate.swift in Sources */, + 21489B7C267CBA0E00BDE4AC /* DomainRules.swift in Sources */, 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */, 5A39F441239EF17F001F4607 /* LegalViewControllersProvider.swift in Sources */, 9F31AB91232993F500CF87EA /* Imap+session.swift in Sources */, @@ -2357,6 +2377,7 @@ D952B71D1ED0CB2500E5C02B /* MessageViewController.swift in Sources */, 5A39F42D239EC321001F4607 /* SettingsViewController.swift in Sources */, 5ADEDCBC23A4329000EC495E /* PublicKeyDetailViewController.swift in Sources */, + 21489B80267CC39E00BDE4AC /* OrganisationalRulesService.swift in Sources */, D28655932423B4EE0066F52E /* MyMenuViewDecorator.swift in Sources */, 04B4728D1ECE29D200B8266F /* KeyInfo.swift in Sources */, 9F3EF32F23B172D300FA0CEF /* SearchViewController.swift in Sources */, @@ -2426,6 +2447,7 @@ 9F9362192573D10E0009912F /* Imap+Message.swift in Sources */, 32DCA9C61ABB3234649B374E /* CoreHost.swift in Sources */, 9F41FA28253B75F4003B970D /* BackupSelectKeyViewController.swift in Sources */, + 21489B83267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift in Sources */, D2F6D1402435008500DB4065 /* SessionCredentialsProvider.swift in Sources */, 9F9ABC8723AC1EAA00D560E3 /* MessageContext.swift in Sources */, 9F0C3C102316DD5B00299985 /* GoogleUserService.swift in Sources */, @@ -2447,6 +2469,7 @@ 9F6EE1552597399D0059BA51 /* BackupProvider.swift in Sources */, 9FEED1D2230DAD1E00700F8E /* InboxViewModel.swift in Sources */, 32DCAF9DA9EC47798DF8BB73 /* SignInViewController.swift in Sources */, + 21489B78267CB42400BDE4AC /* DomainRulesProvider.swift in Sources */, 9FF0671C25520D9D00FCC9E6 /* MailProvider.swift in Sources */, 9FE743072347AA54005E2DBB /* MainNavigationController.swift in Sources */, 9F5C2A8B257E6C4900DE9B4B /* ImapError.swift in Sources */, @@ -2462,6 +2485,7 @@ D2E26F7024F266F300612AF1 /* ContactDetailViewController.swift in Sources */, 9FDF3656235A22DA00614596 /* AppReset.swift in Sources */, 5A39F43F239EE7D2001F4607 /* SegmentedViewController.swift in Sources */, + 21489B7A267CB4DF00BDE4AC /* DomainRulesObject.swift in Sources */, 5A5C234B23A042520015E705 /* WebViewController.swift in Sources */, 9F5C2A7E257E64D500DE9B4B /* MessageOperationsProvider.swift in Sources */, 32DCACF9C6FC4B9330C9B362 /* Imap+send.swift in Sources */, diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index 01936fbf4..905f59a40 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -51,7 +51,6 @@ final class InboxViewController: ASDKViewController { private let messageProvider: MessagesListProvider private let decorator: InboxViewDecoratorType - private let enterpriseServerApi: EnterpriseServerApiType private let refreshControl = UIRefreshControl() private let tableNode: ASTableNode private lazy var composeButton = ComposeButtonNode { [weak self] in @@ -64,13 +63,11 @@ final class InboxViewController: ASDKViewController { init( _ viewModel: InboxViewModel, messageProvider: MessagesListProvider = MailProvider.shared.messageListProvider, - decorator: InboxViewDecoratorType = InboxViewDecorator(), - enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi() + decorator: InboxViewDecoratorType = InboxViewDecorator() ) { self.viewModel = viewModel self.messageProvider = messageProvider self.decorator = decorator - self.enterpriseServerApi = enterpriseServerApi tableNode = TableNode() super.init(node: ASDisplayNode()) @@ -218,7 +215,7 @@ extension InboxViewController { // insert new messages let indexesToInsert = messageContext.messages .enumerated() - .map { (index, _) -> Int in + .map { index, _ -> Int in let indexInTableView = index + count return indexInTableView } @@ -245,14 +242,6 @@ extension InboxViewController { showAlert(error: error, message: "message_failed_load".localized) } } - - private func checkFES() { - enterpriseServerApi.getActiveFesUrlForCurrentUser() - .then(on: .main) { [weak self] urlString in - guard let urlString = urlString else { return } - self?.showToast("FES at \(urlString) not supported on iOS yet") - } - } } // MARK: - Action handlers diff --git a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift index 2941ef728..1f5ac3029 100644 --- a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift +++ b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift @@ -41,7 +41,7 @@ final class EncryptedStorage: EncryptedStorageType { var version: SchemaVersion { switch self { case .initial: - return SchemaVersion(appVersion: "0.2.0", dbSchemaVersion: 1) + return SchemaVersion(appVersion: "0.2.0", dbSchemaVersion: 2) } } } diff --git a/FlowCrypt/Functionality/Services/AppStartup.swift b/FlowCrypt/Functionality/Services/AppStartup.swift index cee8e4ce2..dfb8e20f0 100644 --- a/FlowCrypt/Functionality/Services/AppStartup.swift +++ b/FlowCrypt/Functionality/Services/AppStartup.swift @@ -22,6 +22,8 @@ struct AppStartup { self.setupCore() try self.setupMigrationIfNeeded() try self.setupSession() + // Fetching of org rules is being called async in purpose we don't need to wait until it's fetched + self.getUserOrgRulesIfNeeded() }.then(on: .main) { self.chooseView(for: window, session: session) }.catch(on: .main) { error in @@ -77,6 +79,12 @@ struct AppStartup { } } + private func getUserOrgRulesIfNeeded() { + if DataService.shared.isLoggedIn { + _ = OrganisationalRulesService().fetchOrganisationalRulesForCurrentUser() + } + } + private func makeUserIdForSetup(session: SessionType) -> UserId? { guard let currentUser = DataService.shared.currentUser else { return nil diff --git a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift index 861660669..e344e88ab 100644 --- a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift +++ b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift @@ -11,6 +11,9 @@ import Promises protocol EnterpriseServerApiType { func getActiveFesUrl(for email: String) -> Promise func getActiveFesUrlForCurrentUser() -> Promise + + func getDomainRules(for email: String) -> Promise + func getDomainRulesForCurrentUser() -> Promise } class EnterpriseServerApi: EnterpriseServerApiType { @@ -22,6 +25,14 @@ class EnterpriseServerApi: EnterpriseServerApiType { static let serviceNeededValue = "enterprise-server" } + private struct ClientConfiguration: Codable { + let domainRules: DomainRules + + private enum CodingKeys: String, CodingKey { + case domainRules = "clientConfiguration" + } + } + func getActiveFesUrlForCurrentUser() -> Promise { guard let email = DataService.shared.currentUser?.email else { return Promise { resolve, _ in @@ -59,4 +70,38 @@ class EnterpriseServerApi: EnterpriseServerApiType { .timeout(Constants.getActiveFesTimeout) .recoverFromTimeOut(result: nil) } + + func getDomainRules(for email: String) -> Promise { + Promise { resolve, _ in + guard let userDomain = email.recipientDomain, + !Configuration.publicEmailProviderDomains.contains(userDomain) else { + resolve(nil) + return + } + let request = URLRequest.urlRequest( + with: "https://fes.\(userDomain)/api/v1/client-configuration?domain=\(userDomain)", + method: .get, + body: nil + ) + let response = try? awaitPromise(URLSession.shared.call(request)) + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + + guard let safeReponse = response, + let domainRules = (try? decoder.decode(ClientConfiguration.self, from: safeReponse.data))?.domainRules else { + resolve(nil) + return + } + resolve(domainRules) + } + } + + func getDomainRulesForCurrentUser() -> Promise { + guard let email = DataService.shared.currentUser?.email else { + return Promise { resolve, _ in + resolve(nil) + } + } + return getDomainRules(for: email) + } } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift new file mode 100644 index 000000000..5ac638a49 --- /dev/null +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift @@ -0,0 +1,41 @@ +// +// DomainRulesProvider.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import Promises +import RealmSwift + +protocol DomainRulesProviderType { + func fetch() -> DomainRules? + func removeDomainRules() + func save(domainRules: DomainRules) +} + +struct DomainRulesProvider: CacheServiceType { + let storage: CacheStorage + let domainRulesCache: CacheService + + init(storage: @escaping @autoclosure CacheStorage) { + self.storage = storage + self.domainRulesCache = CacheService(storage: storage()) + } +} + +extension DomainRulesProvider: DomainRulesProviderType { + func fetch() -> DomainRules? { + DomainRules(domainRulesCache.getAllForActiveUser()?.first) + } + + func removeDomainRules() { + domainRulesCache.removeAllForActiveUser() + } + + func save(domainRules: DomainRules) { + domainRulesCache.save(DomainRulesObject(domainRules, user: EncryptedStorage().activeUser)) + } +} diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift new file mode 100644 index 000000000..5dae52ad4 --- /dev/null +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift @@ -0,0 +1,66 @@ +// +// OrganisationalRulesService.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import Promises + +protocol OrganisationalRulesServiceType { + func fetchOrganisationalRulesForCurrentUser() -> Promise + func fetchOrganisationalRules(for email: String) -> Promise +} + +final class OrganisationalRulesService { + + private let enterpriseServerApi: EnterpriseServerApiType + private let domainRulesProvider: DomainRulesProviderType + + init( + storage: @escaping @autoclosure CacheStorage = DataService.shared.storage, + enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi() + ) { + self.enterpriseServerApi = enterpriseServerApi + self.domainRulesProvider = DomainRulesProvider(storage: storage()) + } +} + +// MARK: - OrganisationalRulesServiceType +extension OrganisationalRulesService: OrganisationalRulesServiceType { + + func fetchOrganisationalRulesForCurrentUser() -> Promise { + guard let currentUser = DataService.shared.currentUser else { + return Promise { _, reject in + reject(OrganisationalRulesServiceError.noCurrentUser) + } + } + return fetchOrganisationalRules(for: currentUser.email) + } + + func fetchOrganisationalRules(for email: String) -> Promise { + Promise { [weak self] resolve, reject in + guard let self = self else { throw AppErr.nilSelf } + + guard let domainRulesResponse = try awaitPromise( + self.enterpriseServerApi.getDomainRules(for: email) + ) else { + reject(OrganisationalRulesServiceError.parse) + return + } + guard let organisationalRules = OrganisationalRules( + domainRules: domainRulesResponse, + email: email + ) else { + reject(OrganisationalRulesServiceError.emailFormat) + return + } + + self.domainRulesProvider.save(domainRules: domainRulesResponse) + + resolve(organisationalRules) + } + } +} diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesServiceError.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesServiceError.swift new file mode 100644 index 000000000..43ef64888 --- /dev/null +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesServiceError.swift @@ -0,0 +1,15 @@ +// +// OrganisationalRulesServiceError.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +enum OrganisationalRulesServiceError: Error { + case noCurrentUser + case parse + case emailFormat +} diff --git a/FlowCrypt/Models/DomainRules.swift b/FlowCrypt/Models/DomainRules.swift new file mode 100644 index 000000000..7f7786d86 --- /dev/null +++ b/FlowCrypt/Models/DomainRules.swift @@ -0,0 +1,62 @@ +// +// DomainRules.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +enum DomainRulesFlag: String, Codable { + + case noPRVBackup = "NO_PRV_BACKUP" + case noPRVCreate = "NO_PRV_CREATE" + case noKeyManagerPubLookup = "NO_KEY_MANAGER_PUB_LOOKUP" + case PRVAutoimportOrAutogen = "PRV_AUTOIMPORT_OR_AUTOGEN" + case passphraseQuietAutogen = "PASS_PHRASE_QUIET_AUTOGEN" + case enforceAttesterSubmit = "ENFORCE_ATTESTER_SUBMIT" + case noAttesterSubmit = "NO_ATTESTER_SUBMIT" + case useLegacyAttesterSubmit = "USE_LEGACY_ATTESTER_SUBMIT" + case defaultRememberPassphrase = "DEFAULT_REMEMBER_PASS_PHRASE" + case hideArmorMeta = "HIDE_ARMOR_META" +} + +struct DomainRules: Codable, Equatable { + + let flags: [DomainRulesFlag]? + let customKeyserverUrl: String? + let keyManagerUrl: String? + let disallowAttesterSearchForDomains: [String]? + let enforceKeygenAlgo: String? + let enforceKeygenExpireMonths: Int? +} + +// MARK: - Map from realm model +extension DomainRules { + init?(_ object: DomainRulesObject?) { + guard let unwrappedObject = object else { + return nil + } + + var decodedFlags: [String]? + if let flagsData = object?.flags { + decodedFlags = try? JSONDecoder().decode([String].self, from: flagsData) + } + + var decodedDisallowAttesterSearchForDomains: [String]? + if let disallowAttesterSearchForDomainsData = object?.disallowAttesterSearchForDomains { + decodedDisallowAttesterSearchForDomains = try? JSONDecoder() + .decode([String].self, from: disallowAttesterSearchForDomainsData) + } + + self.init( + flags: decodedFlags?.compactMap(DomainRulesFlag.init), + customKeyserverUrl: unwrappedObject.customKeyserverUrl, + keyManagerUrl: unwrappedObject.keyManagerUrl, + disallowAttesterSearchForDomains: decodedDisallowAttesterSearchForDomains, + enforceKeygenAlgo: unwrappedObject.enforceKeygenAlgo, + enforceKeygenExpireMonths: unwrappedObject.enforceKeygenExpireMonths + ) + } +} diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index 7321bd8ea..d6a47fb16 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -8,30 +8,6 @@ import Foundation -enum DomainRulesFlag: String, Codable { - - case noPRVBackup = "NO_PRV_BACKUP" - case noPRVCreate = "NO_PRV_CREATE" - case noKeyManagerPubLookup = "NO_KEY_MANAGER_PUB_LOOKUP" - case PRVAutoimportOrAutogen = "PRV_AUTOIMPORT_OR_AUTOGEN" - case passphraseQuietAutogen = "PASS_PHRASE_QUIET_AUTOGEN" - case enforceAttesterSubmit = "ENFORCE_ATTESTER_SUBMIT" - case noAttesterSubmit = "NO_ATTESTER_SUBMIT" - case useLegacyAttesterSubmit = "USE_LEGACY_ATTESTER_SUBMIT" - case defaultRememberPassphrase = "DEFAULT_REMEMBER_PASS_PHRASE" - case hideArmorMeta = "HIDE_ARMOR_META" -} - -struct DomainRules: Codable, Equatable { - - let flags: [DomainRulesFlag]? - let customKeyserverUrl: String? - let keyManagerUrl: String? - let disallowAttesterSearchForDomains: [String]? - let enforceKeygenAlgo: String? - let enforceKeygenExpireMonths: Int? -} - /// Organisational rules, set domain-wide, and delivered from FlowCrypt Backend /// These either enforce, alter or forbid various behavior to fit customer needs class OrganisationalRules { @@ -43,12 +19,12 @@ class OrganisationalRules { self.domainRules = domainRules self.domain = domain } - + init?(domainRules: DomainRules, email: String) { guard let recipientDomain = email.recipientDomain else { return nil } - + self.domain = recipientDomain self.domainRules = domainRules } diff --git a/FlowCrypt/Models/Realm Models/DomainRulesObject.swift b/FlowCrypt/Models/Realm Models/DomainRulesObject.swift new file mode 100644 index 000000000..6ec5d95a8 --- /dev/null +++ b/FlowCrypt/Models/Realm Models/DomainRulesObject.swift @@ -0,0 +1,71 @@ +// +// DomainRulesObject.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import RealmSwift + +final class DomainRulesObject: Object { + + @objc dynamic var flags: Data? + @objc dynamic var customKeyserverUrl: String? + @objc dynamic var keyManagerUrl: String? + @objc dynamic var disallowAttesterSearchForDomains: Data? + @objc dynamic var enforceKeygenAlgo: String? + @objc dynamic var enforceKeygenExpireMonths: Int = -1 + @objc dynamic var user: UserObject? + @objc dynamic var userEmail: String? + + convenience init( + flags: [String]?, + customKeyserverUrl: String?, + keyManagerUrl: String?, + disallowAttesterSearchForDomains: [String]?, + enforceKeygenAlgo: String?, + enforceKeygenExpireMonths: Int?, + user: UserObject? + ) { + self.init() + if let flags = flags { + self.flags = try? JSONEncoder().encode(flags) + } + self.customKeyserverUrl = customKeyserverUrl + self.keyManagerUrl = keyManagerUrl + if let disallowAttesterSearchForDomains = disallowAttesterSearchForDomains { + self.disallowAttesterSearchForDomains = try? JSONEncoder().encode(disallowAttesterSearchForDomains) + } + self.enforceKeygenAlgo = enforceKeygenAlgo + self.enforceKeygenExpireMonths = enforceKeygenExpireMonths ?? -1 + self.user = user + self.userEmail = user?.email + } + + convenience init( + _ domainRules: DomainRules, + user: UserObject? + ) { + self.init( + flags: domainRules.flags?.map(\.rawValue), + customKeyserverUrl: domainRules.customKeyserverUrl, + keyManagerUrl: domainRules.keyManagerUrl, + disallowAttesterSearchForDomains: domainRules.disallowAttesterSearchForDomains, + enforceKeygenAlgo: domainRules.enforceKeygenAlgo, + enforceKeygenExpireMonths: domainRules.enforceKeygenExpireMonths, + user: user + ) + } + + override class func primaryKey() -> String? { + "userEmail" + } +} + +extension DomainRulesObject: CachedObject { + var identifier: String { userEmail ?? "" } + + var activeUser: UserObject? { user } +} From ec105b4b800318b0bbeb1bc1bde055b420a12bc0 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Wed, 23 Jun 2021 18:02:16 +0300 Subject: [PATCH 2/4] Renamed DomainRules to ClientConfiguration --- FlowCrypt.xcodeproj/project.pbxproj | 25 +++++------ .../Inbox/InboxViewController.swift | 6 +-- .../Encrypted Storage/EncryptedStorage.swift | 2 +- .../Services/EnterpriseServerApi.swift | 30 +++++++------ .../ClientConfigurationProvider.swift | 41 +++++++++++++++++ .../DomainRulesProvider.swift | 41 ----------------- .../OrganisationalRulesService.swift | 12 ++--- ...nRules.swift => ClientConfiguration.swift} | 20 ++++----- FlowCrypt/Models/OrganisationalRule.swift | 44 +++++++++---------- ....swift => ClientConfigurationObject.swift} | 20 ++++----- 10 files changed, 122 insertions(+), 119 deletions(-) create mode 100644 FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift delete mode 100644 FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift rename FlowCrypt/Models/{DomainRules.swift => ClientConfiguration.swift} (78%) rename FlowCrypt/Models/Realm Models/{DomainRulesObject.swift => ClientConfigurationObject.swift} (72%) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 3d88173c9..6b376c138 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -11,9 +11,9 @@ 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; 211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; }; - 21489B78267CB42400BDE4AC /* DomainRulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */; }; - 21489B7A267CB4DF00BDE4AC /* DomainRulesObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */; }; - 21489B7C267CBA0E00BDE4AC /* DomainRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */; }; + 21489B78267CB42400BDE4AC /* ClientConfigurationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */; }; + 21489B7A267CB4DF00BDE4AC /* ClientConfigurationObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */; }; + 21489B7C267CBA0E00BDE4AC /* ClientConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7B267CBA0E00BDE4AC /* ClientConfiguration.swift */; }; 21489B80267CC39E00BDE4AC /* OrganisationalRulesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */; }; 21489B83267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */; }; 21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; }; @@ -388,9 +388,9 @@ 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; 211392A4266511E6009202EC /* PubLookup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubLookup.swift; sourceTree = ""; }; - 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRulesProvider.swift; sourceTree = ""; }; - 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRulesObject.swift; sourceTree = ""; }; - 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRules.swift; sourceTree = ""; }; + 21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationProvider.swift; sourceTree = ""; }; + 21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationObject.swift; sourceTree = ""; }; + 21489B7B267CBA0E00BDE4AC /* ClientConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfiguration.swift; sourceTree = ""; }; 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesService.swift; sourceTree = ""; }; 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceError.swift; sourceTree = ""; }; 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = ""; }; @@ -766,7 +766,7 @@ 9F0C3C132316E69300299985 /* User.swift */, 9F9AAFFC2383E216000A00F1 /* Document.swift */, 21EA3B15265647C400691848 /* OrganisationalRule.swift */, - 21489B7B267CBA0E00BDE4AC /* DomainRules.swift */, + 21489B7B267CBA0E00BDE4AC /* ClientConfiguration.swift */, ); path = Models; sourceTree = ""; @@ -794,7 +794,7 @@ 21489B81267CC3BC00BDE4AC /* Organisational Rules Service */ = { isa = PBXGroup; children = ( - 21489B77267CB42400BDE4AC /* DomainRulesProvider.swift */, + 21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */, 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */, 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */, ); @@ -1001,7 +1001,7 @@ D274724324FD1932006BA6EF /* FolderObject.swift */, 04B4728B1ECE29D200B8266F /* KeyInfo.swift */, D2F41370243CC76E0066AFB5 /* SessionObject.swift */, - 21489B79267CB4DF00BDE4AC /* DomainRulesObject.swift */, + 21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */, ); path = "Realm Models"; sourceTree = ""; @@ -2381,7 +2381,6 @@ 9FC7EBC9266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift in Sources */, A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, 9FC7EBB0266EBD4600F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */, - 21EA3B2326565B5D00691848 /* DomainRulesTests.swift in Sources */, 9F4164102665754A00106194 /* PromiseExtensions.swift in Sources */, 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, 9FC7EBA3266EB95300F3BF5D /* PassPhraseStorageTests.swift in Sources */, @@ -2426,7 +2425,7 @@ 9F4163E6266520B600106194 /* CommonNodesInputs.swift in Sources */, 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */, C132B9B41EC2DBD800763715 /* AppDelegate.swift in Sources */, - 21489B7C267CBA0E00BDE4AC /* DomainRules.swift in Sources */, + 21489B7C267CBA0E00BDE4AC /* ClientConfiguration.swift in Sources */, 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */, 5A39F441239EF17F001F4607 /* LegalViewControllersProvider.swift in Sources */, 9F31AB91232993F500CF87EA /* Imap+session.swift in Sources */, @@ -2555,7 +2554,7 @@ 9F6EE1552597399D0059BA51 /* BackupProvider.swift in Sources */, 9FEED1D2230DAD1E00700F8E /* InboxViewModel.swift in Sources */, 32DCAF9DA9EC47798DF8BB73 /* SignInViewController.swift in Sources */, - 21489B78267CB42400BDE4AC /* DomainRulesProvider.swift in Sources */, + 21489B78267CB42400BDE4AC /* ClientConfigurationProvider.swift in Sources */, 9FF0671C25520D9D00FCC9E6 /* MailProvider.swift in Sources */, 9FE743072347AA54005E2DBB /* MainNavigationController.swift in Sources */, 9F5C2A8B257E6C4900DE9B4B /* ImapError.swift in Sources */, @@ -2571,7 +2570,7 @@ D2E26F7024F266F300612AF1 /* ContactDetailViewController.swift in Sources */, 9FDF3656235A22DA00614596 /* AppReset.swift in Sources */, 5A39F43F239EE7D2001F4607 /* SegmentedViewController.swift in Sources */, - 21489B7A267CB4DF00BDE4AC /* DomainRulesObject.swift in Sources */, + 21489B7A267CB4DF00BDE4AC /* ClientConfigurationObject.swift in Sources */, 5A5C234B23A042520015E705 /* WebViewController.swift in Sources */, 9F5C2A7E257E64D500DE9B4B /* MessageOperationsProvider.swift in Sources */, 9FC7EB76266EB67B00F3BF5D /* EncryptedStorageProtocols.swift in Sources */, diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index 879ce9539..bdc5a6703 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -50,7 +50,7 @@ final class InboxViewController: ASDKViewController { private var state: State = .idle private let messageProvider: MessagesListProvider - private let decorator: InboxViewDecoratorType + private let decorator: InboxViewDecorator private let enterpriseServerApi: EnterpriseServerApiType private let refreshControl = UIRefreshControl() private let tableNode: ASTableNode @@ -64,12 +64,13 @@ final class InboxViewController: ASDKViewController { init( _ viewModel: InboxViewModel, messageProvider: MessagesListProvider = MailProvider.shared.messageListProvider, - decorator: InboxViewDecoratorType = InboxViewDecorator(), + decorator: InboxViewDecorator = InboxViewDecorator(), enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi() ) { self.viewModel = viewModel self.messageProvider = messageProvider self.decorator = decorator + self.enterpriseServerApi = enterpriseServerApi tableNode = TableNode() super.init(node: ASDisplayNode()) @@ -90,7 +91,6 @@ final class InboxViewController: ASDKViewController { setupUI() setupNavigationBar() fetchAndRenderEmails(nil) - checkFES() } override func viewWillAppear(_ animated: Bool) { diff --git a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift index ff2aae1fb..c3e124dd6 100644 --- a/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift +++ b/FlowCrypt/Functionality/DataManager/Encrypted Storage/EncryptedStorage.swift @@ -36,7 +36,7 @@ final class EncryptedStorage: EncryptedStorageType { var version: SchemaVersion { switch self { case .initial: - return SchemaVersion(appVersion: "0.2.0", dbSchemaVersion: 2) + return SchemaVersion(appVersion: "0.2.0", dbSchemaVersion: 4) } } } diff --git a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift index e344e88ab..6ebed76db 100644 --- a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift +++ b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift @@ -12,8 +12,8 @@ protocol EnterpriseServerApiType { func getActiveFesUrl(for email: String) -> Promise func getActiveFesUrlForCurrentUser() -> Promise - func getDomainRules(for email: String) -> Promise - func getDomainRulesForCurrentUser() -> Promise + func getClientConfiguration(for email: String) -> Promise + func getClientConfigurationForCurrentUser() -> Promise } class EnterpriseServerApi: EnterpriseServerApiType { @@ -25,11 +25,11 @@ class EnterpriseServerApi: EnterpriseServerApiType { static let serviceNeededValue = "enterprise-server" } - private struct ClientConfiguration: Codable { - let domainRules: DomainRules + private struct ClientConfigurationContainer: Codable { + let clientConfiguration: ClientConfiguration private enum CodingKeys: String, CodingKey { - case domainRules = "clientConfiguration" + case clientConfiguration = "clientConfiguration" } } @@ -71,9 +71,9 @@ class EnterpriseServerApi: EnterpriseServerApiType { .recoverFromTimeOut(result: nil) } - func getDomainRules(for email: String) -> Promise { - Promise { resolve, _ in - guard let userDomain = email.recipientDomain, + func getClientConfiguration(for email: String) -> Promise { + Promise { resolve, _ in + guard let userDomain = "name@flowcrypt.com".recipientDomain, !Configuration.publicEmailProviderDomains.contains(userDomain) else { resolve(nil) return @@ -88,20 +88,24 @@ class EnterpriseServerApi: EnterpriseServerApiType { decoder.keyDecodingStrategy = .convertFromSnakeCase guard let safeReponse = response, - let domainRules = (try? decoder.decode(ClientConfiguration.self, from: safeReponse.data))?.domainRules else { + let clientConfiguration = (try? decoder.decode( + ClientConfigurationContainer.self, + from: safeReponse.data + ))?.clientConfiguration + else { resolve(nil) return } - resolve(domainRules) + resolve(clientConfiguration) } } - func getDomainRulesForCurrentUser() -> Promise { + func getClientConfigurationForCurrentUser() -> Promise { guard let email = DataService.shared.currentUser?.email else { - return Promise { resolve, _ in + return Promise { resolve, _ in resolve(nil) } } - return getDomainRules(for: email) + return getClientConfiguration(for: email) } } diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift new file mode 100644 index 000000000..9f55d6942 --- /dev/null +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/ClientConfigurationProvider.swift @@ -0,0 +1,41 @@ +// +// ClientConfigurationProvider.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 18.06.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation +import Promises +import RealmSwift + +protocol ClientConfigurationProviderType { + func fetch() -> ClientConfiguration? + func removeClientConfiguration() + func save(clientConfiguration: ClientConfiguration) +} + +struct ClientConfigurationProvider: CacheServiceType { + let storage: CacheStorage + let clientConfigurationCache: CacheService + + init(storage: @escaping @autoclosure CacheStorage) { + self.storage = storage + self.clientConfigurationCache = CacheService(storage: storage()) + } +} + +extension ClientConfigurationProvider: ClientConfigurationProviderType { + func fetch() -> ClientConfiguration? { + ClientConfiguration(clientConfigurationCache.getAllForActiveUser()?.first) + } + + func removeClientConfiguration() { + clientConfigurationCache.removeAllForActiveUser() + } + + func save(clientConfiguration: ClientConfiguration) { + clientConfigurationCache.save(ClientConfigurationObject(clientConfiguration, user: EncryptedStorage().activeUser)) + } +} diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift deleted file mode 100644 index 5ac638a49..000000000 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/DomainRulesProvider.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// DomainRulesProvider.swift -// FlowCrypt -// -// Created by Yevhen Kyivskyi on 18.06.2021. -// Copyright © 2021 FlowCrypt Limited. All rights reserved. -// - -import Foundation -import Promises -import RealmSwift - -protocol DomainRulesProviderType { - func fetch() -> DomainRules? - func removeDomainRules() - func save(domainRules: DomainRules) -} - -struct DomainRulesProvider: CacheServiceType { - let storage: CacheStorage - let domainRulesCache: CacheService - - init(storage: @escaping @autoclosure CacheStorage) { - self.storage = storage - self.domainRulesCache = CacheService(storage: storage()) - } -} - -extension DomainRulesProvider: DomainRulesProviderType { - func fetch() -> DomainRules? { - DomainRules(domainRulesCache.getAllForActiveUser()?.first) - } - - func removeDomainRules() { - domainRulesCache.removeAllForActiveUser() - } - - func save(domainRules: DomainRules) { - domainRulesCache.save(DomainRulesObject(domainRules, user: EncryptedStorage().activeUser)) - } -} diff --git a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift index 5dae52ad4..20c0956e8 100644 --- a/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift +++ b/FlowCrypt/Functionality/Services/Organisational Rules Service/OrganisationalRulesService.swift @@ -17,14 +17,14 @@ protocol OrganisationalRulesServiceType { final class OrganisationalRulesService { private let enterpriseServerApi: EnterpriseServerApiType - private let domainRulesProvider: DomainRulesProviderType + private let clientConfigurationProvider: ClientConfigurationProviderType init( storage: @escaping @autoclosure CacheStorage = DataService.shared.storage, enterpriseServerApi: EnterpriseServerApiType = EnterpriseServerApi() ) { self.enterpriseServerApi = enterpriseServerApi - self.domainRulesProvider = DomainRulesProvider(storage: storage()) + self.clientConfigurationProvider = ClientConfigurationProvider(storage: storage()) } } @@ -44,21 +44,21 @@ extension OrganisationalRulesService: OrganisationalRulesServiceType { Promise { [weak self] resolve, reject in guard let self = self else { throw AppErr.nilSelf } - guard let domainRulesResponse = try awaitPromise( - self.enterpriseServerApi.getDomainRules(for: email) + guard let clientConfigurationResponse = try awaitPromise( + self.enterpriseServerApi.getClientConfiguration(for: email) ) else { reject(OrganisationalRulesServiceError.parse) return } guard let organisationalRules = OrganisationalRules( - domainRules: domainRulesResponse, + clientConfiguration: clientConfigurationResponse, email: email ) else { reject(OrganisationalRulesServiceError.emailFormat) return } - self.domainRulesProvider.save(domainRules: domainRulesResponse) + self.clientConfigurationProvider.save(clientConfiguration: clientConfigurationResponse) resolve(organisationalRules) } diff --git a/FlowCrypt/Models/DomainRules.swift b/FlowCrypt/Models/ClientConfiguration.swift similarity index 78% rename from FlowCrypt/Models/DomainRules.swift rename to FlowCrypt/Models/ClientConfiguration.swift index 7f7786d86..46b6e49c5 100644 --- a/FlowCrypt/Models/DomainRules.swift +++ b/FlowCrypt/Models/ClientConfiguration.swift @@ -1,5 +1,5 @@ // -// DomainRules.swift +// ClientConfiguration.swift // FlowCrypt // // Created by Yevhen Kyivskyi on 18.06.2021. @@ -8,12 +8,12 @@ import Foundation -enum DomainRulesFlag: String, Codable { +enum ClientConfigurationFlag: String, Codable { - case noPRVBackup = "NO_PRV_BACKUP" - case noPRVCreate = "NO_PRV_CREATE" + case noPrivateKeyBackup = "NO_PRV_BACKUP" + case noPrivateKeyCreate = "NO_PRV_CREATE" case noKeyManagerPubLookup = "NO_KEY_MANAGER_PUB_LOOKUP" - case PRVAutoimportOrAutogen = "PRV_AUTOIMPORT_OR_AUTOGEN" + case privateKeyAutoimportOrAutogen = "PRV_AUTOIMPORT_OR_AUTOGEN" case passphraseQuietAutogen = "PASS_PHRASE_QUIET_AUTOGEN" case enforceAttesterSubmit = "ENFORCE_ATTESTER_SUBMIT" case noAttesterSubmit = "NO_ATTESTER_SUBMIT" @@ -22,9 +22,9 @@ enum DomainRulesFlag: String, Codable { case hideArmorMeta = "HIDE_ARMOR_META" } -struct DomainRules: Codable, Equatable { +struct ClientConfiguration: Codable, Equatable { - let flags: [DomainRulesFlag]? + let flags: [ClientConfigurationFlag]? let customKeyserverUrl: String? let keyManagerUrl: String? let disallowAttesterSearchForDomains: [String]? @@ -33,8 +33,8 @@ struct DomainRules: Codable, Equatable { } // MARK: - Map from realm model -extension DomainRules { - init?(_ object: DomainRulesObject?) { +extension ClientConfiguration { + init?(_ object: ClientConfigurationObject?) { guard let unwrappedObject = object else { return nil } @@ -51,7 +51,7 @@ extension DomainRules { } self.init( - flags: decodedFlags?.compactMap(DomainRulesFlag.init), + flags: decodedFlags?.compactMap(ClientConfigurationFlag.init), customKeyserverUrl: unwrappedObject.customKeyserverUrl, keyManagerUrl: unwrappedObject.keyManagerUrl, disallowAttesterSearchForDomains: decodedDisallowAttesterSearchForDomains, diff --git a/FlowCrypt/Models/OrganisationalRule.swift b/FlowCrypt/Models/OrganisationalRule.swift index d6a47fb16..57b029675 100644 --- a/FlowCrypt/Models/OrganisationalRule.swift +++ b/FlowCrypt/Models/OrganisationalRule.swift @@ -12,86 +12,86 @@ import Foundation /// These either enforce, alter or forbid various behavior to fit customer needs class OrganisationalRules { - private let domainRules: DomainRules + private let clientConfiguration: ClientConfiguration let domain: String - init(domainRules: DomainRules, domain: String) { - self.domainRules = domainRules + init(clientConfiguration: ClientConfiguration, domain: String) { + self.clientConfiguration = clientConfiguration self.domain = domain } - init?(domainRules: DomainRules, email: String) { + init?(clientConfiguration: ClientConfiguration, email: String) { guard let recipientDomain = email.recipientDomain else { return nil } self.domain = recipientDomain - self.domainRules = domainRules + self.clientConfiguration = clientConfiguration } /// Internal company SKS-like public key server to trust above Attester var customSksPubkeyServer: String? { - domainRules.customKeyserverUrl + clientConfiguration.customKeyserverUrl } /// an internal org FlowCrypt Email Key Manager instance, can manage both public and private keys /// use this method when using for PRV sync var keyManagerUrlForPrivateKeys: String? { - domainRules.keyManagerUrl + clientConfiguration.keyManagerUrl } /// an internal org FlowCrypt Email Key Manager instance, can manage both public and private keys /// use this method when using for PUB sync var keyManagerUrlForPublicKeys: String? { - (domainRules.flags ?? []).contains(.noKeyManagerPubLookup) + (clientConfiguration.flags ?? []).contains(.noKeyManagerPubLookup) ? nil - : domainRules.keyManagerUrl + : clientConfiguration.keyManagerUrl } /// use when finding out if EKM is in use, to change functionality without actually neededing the EKM var isUsingKeyManager: Bool { - domainRules.keyManagerUrl != nil + clientConfiguration.keyManagerUrl != nil } /// Enforce a key algo for keygen, eg rsa2048,rsa4096,curve25519 var enforcedKeygenAlgo: String? { - domainRules.enforceKeygenAlgo + clientConfiguration.enforceKeygenAlgo } /// Some orgs want to have newly generated keys include self-signatures that expire some time in the future. var getEnforcedKeygenExpirationMonths: Int? { - domainRules.enforceKeygenExpireMonths + clientConfiguration.enforceKeygenExpireMonths } /// Some orgs expect 100% of their private keys to be imported from elsewhere (and forbid keygen in the extension) var canCreateKeys: Bool { - !(domainRules.flags ?? []).contains(.noPRVCreate) + !(clientConfiguration.flags ?? []).contains(.noPrivateKeyCreate) } /// Some orgs want to forbid backing up of public keys (such as inbox or other methods) var canBackupKeys: Bool { - !(domainRules.flags ?? []).contains(.noPRVBackup) + !(clientConfiguration.flags ?? []).contains(.noPrivateKeyBackup) } /// (normally, during setup, if a public key is submitted to Attester and there is /// a conflicting key already submitted, the issue will be skipped) /// Some orgs want to make sure that their public key gets submitted to attester and conflict errors are NOT ignored: var mustSubmitAttester: Bool { - (domainRules.flags ?? []).contains(.enforceAttesterSubmit) + (clientConfiguration.flags ?? []).contains(.enforceAttesterSubmit) } /// Normally, during setup, "remember pass phrase" is unchecked /// This option will cause "remember pass phrase" option to be checked by default /// This behavior is also enabled as a byproduct of PASS_PHRASE_QUIET_AUTOGEN var shouldRememberPassphraseByDefault: Bool { - (domainRules.flags ?? []).contains(.defaultRememberPassphrase) || mustAutogenPassPhraseQuietly + (clientConfiguration.flags ?? []).contains(.defaultRememberPassphrase) || mustAutogenPassPhraseQuietly } /// This is to be used for customers who run their own FlowCrypt Email Key Manager /// If a key can be found on FEKM, it will be auto imported /// If not, it will be autogenerated and stored there var mustAutoImportOrAutogenPrvWithKeyManager: Bool { - if !(domainRules.flags ?? []).contains(.PRVAutoimportOrAutogen) { + if !(clientConfiguration.flags ?? []).contains(.privateKeyAutoimportOrAutogen) { return false } @@ -107,29 +107,29 @@ class OrganisationalRules { /// The pass phrase will NOT be displayed to user, and it will never be asked of the user /// This creates the smoothest user experience, for organisations that use full-disk-encryption and don't need pass phrase protection var mustAutogenPassPhraseQuietly: Bool { - (domainRules.flags ?? []).contains(.passphraseQuietAutogen) + (clientConfiguration.flags ?? []).contains(.passphraseQuietAutogen) } /// Some orgs prefer to forbid publishing public keys publicly var canSubmitPubToAttester: Bool { - !(domainRules.flags ?? []).contains(.noAttesterSubmit) + !(clientConfiguration.flags ?? []).contains(.noAttesterSubmit) } /// Some orgs have a list of email domains where they do NOT want such emails to be looked up on public sources (such as Attester) /// This is because they already have other means to obtain public keys for these domains, such as from their own internal keyserver func canLookupThisRecipientOnAttester(recipient email: String) -> Bool { - !(domainRules.disallowAttesterSearchForDomains ?? []).contains(email.recipientDomain ?? "") + !(clientConfiguration.disallowAttesterSearchForDomains ?? []).contains(email.recipientDomain ?? "") } /// Some orgs use flows that are only implemented in POST /initial/legacy_submit and not in POST /pub/email@corp.co: /// -> enforcing that submitted keys match customer key server /// Until the newer endpoint is ready, this flag will point users in those orgs to the original endpoint var useLegacyAttesterSubmit: Bool { - (domainRules.flags ?? []).contains(.useLegacyAttesterSubmit) + (clientConfiguration.flags ?? []).contains(.useLegacyAttesterSubmit) } /// With this option, sent messages won't have any comment/version in armor, imported keys get imported without armor var shouldHideArmorMeta: Bool { - (domainRules.flags ?? []).contains(.hideArmorMeta) + (clientConfiguration.flags ?? []).contains(.hideArmorMeta) } } diff --git a/FlowCrypt/Models/Realm Models/DomainRulesObject.swift b/FlowCrypt/Models/Realm Models/ClientConfigurationObject.swift similarity index 72% rename from FlowCrypt/Models/Realm Models/DomainRulesObject.swift rename to FlowCrypt/Models/Realm Models/ClientConfigurationObject.swift index 6ec5d95a8..08d830006 100644 --- a/FlowCrypt/Models/Realm Models/DomainRulesObject.swift +++ b/FlowCrypt/Models/Realm Models/ClientConfigurationObject.swift @@ -1,5 +1,5 @@ // -// DomainRulesObject.swift +// ClientConfigurationObject.swift // FlowCrypt // // Created by Yevhen Kyivskyi on 18.06.2021. @@ -9,7 +9,7 @@ import Foundation import RealmSwift -final class DomainRulesObject: Object { +final class ClientConfigurationObject: Object { @objc dynamic var flags: Data? @objc dynamic var customKeyserverUrl: String? @@ -45,16 +45,16 @@ final class DomainRulesObject: Object { } convenience init( - _ domainRules: DomainRules, + _ clientConfiguration: ClientConfiguration, user: UserObject? ) { self.init( - flags: domainRules.flags?.map(\.rawValue), - customKeyserverUrl: domainRules.customKeyserverUrl, - keyManagerUrl: domainRules.keyManagerUrl, - disallowAttesterSearchForDomains: domainRules.disallowAttesterSearchForDomains, - enforceKeygenAlgo: domainRules.enforceKeygenAlgo, - enforceKeygenExpireMonths: domainRules.enforceKeygenExpireMonths, + flags: clientConfiguration.flags?.map(\.rawValue), + customKeyserverUrl: clientConfiguration.customKeyserverUrl, + keyManagerUrl: clientConfiguration.keyManagerUrl, + disallowAttesterSearchForDomains: clientConfiguration.disallowAttesterSearchForDomains, + enforceKeygenAlgo: clientConfiguration.enforceKeygenAlgo, + enforceKeygenExpireMonths: clientConfiguration.enforceKeygenExpireMonths, user: user ) } @@ -64,7 +64,7 @@ final class DomainRulesObject: Object { } } -extension DomainRulesObject: CachedObject { +extension ClientConfigurationObject: CachedObject { var identifier: String { userEmail ?? "" } var activeUser: UserObject? { user } From a49a73d8336fa08e304a255dab23fe47ae6a5ea3 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Wed, 23 Jun 2021 18:53:15 +0300 Subject: [PATCH 3/4] Rename DomainRules tests to ClientConfiguration --- FlowCrypt.xcodeproj/project.pbxproj | 86 ++++--------------- .../Message Provider/MessageService.swift | 2 +- ...s.swift => ClientConfigurationTests.swift} | 22 ++--- ...in_rules.json => client_configuraion.json} | 0 ...ty.json => client_configuraion_empty.json} | 0 ... => client_configuraion_partly_empty.json} | 0 6 files changed, 28 insertions(+), 82 deletions(-) rename FlowCryptAppTests/Models Parsing/{DomainRulesTests.swift => ClientConfigurationTests.swift} (76%) rename FlowCryptAppTests/Models Parsing/{domain_rules.json => client_configuraion.json} (100%) rename FlowCryptAppTests/Models Parsing/{domain_rules_empty.json => client_configuraion_empty.json} (100%) rename FlowCryptAppTests/Models Parsing/{domain_rules_partly_empty.json => client_configuraion_partly_empty.json} (100%) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index d3ee1a9dd..e00b462dc 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -22,9 +22,6 @@ 21C7DF09266C0D8F00C44800 /* EnterpriseServerApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */; }; 21C7DF0B266C0E3600C44800 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0A266C0E3600C44800 /* Configuration.swift */; }; 21CE25E62650070300ADFF4B /* WKDURLsConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */; }; - 21EA3B2F26565B7400691848 /* domain_rules.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B2E26565B7400691848 /* domain_rules.json */; }; - 21EA3B3626565B8100691848 /* domain_rules_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3526565B8100691848 /* domain_rules_empty.json */; }; - 21EA3B3D26565B9800691848 /* domain_rules_partly_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3C26565B9800691848 /* domain_rules_partly_empty.json */; }; 21EA3B592656611D00691848 /* OrganisationalRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B15265647C400691848 /* OrganisationalRule.swift */; }; 21EFF61F265A5C6700AB0B71 /* WKDURLsApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EFF61E265A5C6700AB0B71 /* WKDURLsApi.swift */; }; 21F836B62652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */; }; @@ -120,10 +117,10 @@ 9F976507267E165D0058419D /* ZBase32EncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */; }; 9F97650E267E16620058419D /* WKDURLsConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */; }; 9F97653D267E17C90058419D /* LocalStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F003D9D25EA910B00EB38C0 /* LocalStorageTests.swift */; }; - 9F976556267E186D0058419D /* DomainRulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B2226565B5D00691848 /* DomainRulesTests.swift */; }; - 9F976569267E18F30058419D /* domain_rules.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B2E26565B7400691848 /* domain_rules.json */; }; - 9F976576267E18F90058419D /* domain_rules_partly_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3C26565B9800691848 /* domain_rules_partly_empty.json */; }; - 9F97657D267E18FE0058419D /* domain_rules_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3526565B8100691848 /* domain_rules_empty.json */; }; + 9F976556267E186D0058419D /* ClientConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EA3B2226565B5D00691848 /* ClientConfigurationTests.swift */; }; + 9F976569267E18F30058419D /* client_configuraion.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B2E26565B7400691848 /* client_configuraion.json */; }; + 9F976576267E18F90058419D /* client_configuraion_partly_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3C26565B9800691848 /* client_configuraion_partly_empty.json */; }; + 9F97657D267E18FE0058419D /* client_configuraion_empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 21EA3B3526565B8100691848 /* client_configuraion_empty.json */; }; 9F976584267E194F0058419D /* TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3DAD60722E4588800F2C4CD /* TestData.swift */; }; 9F976585267E194F0058419D /* FlowCryptCoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3DAD5FD22E4574B00F2C4CD /* FlowCryptCoreTests.swift */; }; 9F976592267E19880058419D /* TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3DAD60722E4588800F2C4CD /* TestData.swift */; }; @@ -373,10 +370,10 @@ 21C7DF0A266C0E3600C44800 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsConstructor.swift; sourceTree = ""; }; 21EA3B15265647C400691848 /* OrganisationalRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRule.swift; sourceTree = ""; }; - 21EA3B2226565B5D00691848 /* DomainRulesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainRulesTests.swift; sourceTree = ""; }; - 21EA3B2E26565B7400691848 /* domain_rules.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = domain_rules.json; sourceTree = ""; }; - 21EA3B3526565B8100691848 /* domain_rules_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = domain_rules_empty.json; sourceTree = ""; }; - 21EA3B3C26565B9800691848 /* domain_rules_partly_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = domain_rules_partly_empty.json; sourceTree = ""; }; + 21EA3B2226565B5D00691848 /* ClientConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationTests.swift; sourceTree = ""; }; + 21EA3B2E26565B7400691848 /* client_configuraion.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = client_configuraion.json; sourceTree = ""; }; + 21EA3B3526565B8100691848 /* client_configuraion_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = client_configuraion_empty.json; sourceTree = ""; }; + 21EA3B3C26565B9800691848 /* client_configuraion_partly_empty.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = client_configuraion_partly_empty.json; sourceTree = ""; }; 21EFF61E265A5C6700AB0B71 /* WKDURLsApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsApi.swift; sourceTree = ""; }; 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExntensions+ZBase32Encoding.swift"; sourceTree = ""; }; 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZBase32EncodingTests.swift; sourceTree = ""; }; @@ -790,10 +787,10 @@ 21EA3B2126565B4100691848 /* Models Parsing */ = { isa = PBXGroup; children = ( - 21EA3B2226565B5D00691848 /* DomainRulesTests.swift */, - 21EA3B2E26565B7400691848 /* domain_rules.json */, - 21EA3B3C26565B9800691848 /* domain_rules_partly_empty.json */, - 21EA3B3526565B8100691848 /* domain_rules_empty.json */, + 21EA3B2226565B5D00691848 /* ClientConfigurationTests.swift */, + 21EA3B2E26565B7400691848 /* client_configuraion.json */, + 21EA3B3C26565B9800691848 /* client_configuraion_partly_empty.json */, + 21EA3B3526565B8100691848 /* client_configuraion_empty.json */, ); path = "Models Parsing"; sourceTree = ""; @@ -2015,9 +2012,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9F976569267E18F30058419D /* domain_rules.json in Resources */, - 9F976576267E18F90058419D /* domain_rules_partly_empty.json in Resources */, - 9F97657D267E18FE0058419D /* domain_rules_empty.json in Resources */, + 9F976569267E18F30058419D /* client_configuraion.json in Resources */, + 9F976576267E18F90058419D /* client_configuraion_partly_empty.json in Resources */, + 9F97657D267E18FE0058419D /* client_configuraion_empty.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2342,7 +2339,7 @@ 9F97653D267E17C90058419D /* LocalStorageTests.swift in Sources */, 9FC41177268118AD004C0A69 /* LocalPassPhraseStorageMock.swift in Sources */, 9F9764F4267E15CC0058419D /* ExtensionTests.swift in Sources */, - 9F976556267E186D0058419D /* DomainRulesTests.swift in Sources */, + 9F976556267E186D0058419D /* ClientConfigurationTests.swift in Sources */, 9FC41171268118A7004C0A69 /* PassPhraseStorageTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2365,57 +2362,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - A3DAD5F722E4574A00F2C4CD /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D2D27B7A248A874C007346FA /* BigIntExtension.swift in Sources */, - 9FC7EB7C266EB67D00F3BF5D /* EncryptedStorageProtocols.swift in Sources */, - 9F3EF32B23B16ADE00FA0CEF /* CommonExtensions.swift in Sources */, - 9FC7EBC2266EBE0100F3BF5D /* EmailProviderMock.swift in Sources */, - 9FC7EBD0266EBE1D00F3BF5D /* EncryptedPassPhraseStorageMock.swift in Sources */, - 9FA0157A26565B7800CBBA05 /* KeyMethodsTest.swift in Sources */, - A357699622EA2BC8009242C4 /* KeyInfo.swift in Sources */, - 9FC411902596229D001180A8 /* AppErr.swift in Sources */, - 9FC7EB69266EB64F00F3BF5D /* PassPhraseStorage.swift in Sources */, - D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, - 9F1D5769263B540100477938 /* Logger.swift in Sources */, - 9FC7EBC9266EBE0F00F3BF5D /* LocalPassPhraseStorageMock.swift in Sources */, - A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, - 9FC7EBB0266EBD4600F3BF5D /* InMemoryPassPhraseStorage.swift in Sources */, - 9F4164102665754A00106194 /* PromiseExtensions.swift in Sources */, - 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, - 9FC7EBA3266EB95300F3BF5D /* PassPhraseStorageTests.swift in Sources */, - 9F7920EE2666D32500DA3D80 /* BackupServiceType.swift in Sources */, - 9FC7EB6F266EB66200F3BF5D /* PassPhrase.swift in Sources */, - D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, - A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, - A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, - D212D36124C1AC0D00035991 /* KeyDetails.swift in Sources */, - 9F6EE18C25A8AF970059BA51 /* GeneralConstants.swift in Sources */, - A3DAD60A22E458C100F2C4CD /* CodableExntensions.swift in Sources */, - D254733424C597CD00DEE698 /* CoreTypesTest.swift in Sources */, - 9F003DA425EA928200EB38C0 /* LocalStorage.swift in Sources */, - 9F7DE8C6232029D000F10B3E /* CoreTypes.swift in Sources */, - 9F3EF32A23B15C9600FA0CEF /* ImapHelperTest.swift in Sources */, - 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, - D212D36524C1AC4800035991 /* KeyId.swift in Sources */, - 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, - 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, - 9F7920E32666D28400DA3D80 /* BackupServiceMock.swift in Sources */, - 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, - 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, - 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, - 9F3EF32823B15C8400FA0CEF /* ImapHelper.swift in Sources */, - 9F003D9E25EA910B00EB38C0 /* LocalStorageTests.swift in Sources */, - 9FA0158026565B9D00CBBA05 /* KeyMethods.swift in Sources */, - 32DCAF683D87EA6221F71335 /* SequenceExtensions.swift in Sources */, - 9F589F11238C7DDC007FD759 /* User.swift in Sources */, - 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */, - D2E26F6D24F263B600612AF1 /* KeyAlgo.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; C132B9AC1EC2DBD800763715 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; diff --git a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift index 9e97fd622..c68e247c7 100644 --- a/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift +++ b/FlowCrypt/Functionality/Mail Provider/Message Provider/MessageService.swift @@ -82,7 +82,7 @@ final class MessageService { isEmail: true ) - let isWrongPassPhraseError = decrypted.blocks.first(where: { (block) -> Bool in + let isWrongPassPhraseError = decrypted.blocks.first(where: { block -> Bool in guard let errorBlock = block.decryptErr, case .needPassphrase = errorBlock.error.type else { return false } diff --git a/FlowCryptAppTests/Models Parsing/DomainRulesTests.swift b/FlowCryptAppTests/Models Parsing/ClientConfigurationTests.swift similarity index 76% rename from FlowCryptAppTests/Models Parsing/DomainRulesTests.swift rename to FlowCryptAppTests/Models Parsing/ClientConfigurationTests.swift index 898edad9b..986d4066f 100644 --- a/FlowCryptAppTests/Models Parsing/DomainRulesTests.swift +++ b/FlowCryptAppTests/Models Parsing/ClientConfigurationTests.swift @@ -1,5 +1,5 @@ // -// DomainRulesTests.swift +// ClientConfigurationTests.swift // FlowCryptTests // // Created by Yevhen Kyivskyi on 20.05.2021. @@ -9,7 +9,7 @@ import XCTest @testable import FlowCrypt -class DomainRulesTests: XCTestCase { +class ClientConfigurationTests: XCTestCase { override func setUp() { // Put setup code here. This method is called before the invocation of each test method in the class. @@ -19,14 +19,14 @@ class DomainRulesTests: XCTestCase { // Put teardown code here. This method is called after the invocation of each test method in the class. } - func test_complete_domain_rules_json_parse() { - let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "domain_rules", ofType: "json")!) + func test_complete_client_configuraion_json_parse() { + let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "client_configuraion", ofType: "json")!) let data = try! Data(contentsOf: urlPath, options: .dataReadingMapped) let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase - let model = try? decoder.decode(DomainRules.self, from: data) + let model = try? decoder.decode(ClientConfiguration.self, from: data) XCTAssert(model?.flags != nil) XCTAssert(model?.customKeyserverUrl != nil) @@ -36,14 +36,14 @@ class DomainRulesTests: XCTestCase { XCTAssert(model?.enforceKeygenExpireMonths != nil) } - func test_partial_domain_rules_json_parse() { - let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "domain_rules_partly_empty", ofType: "json")!) + func test_partial_client_configuraion_json_parse() { + let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "client_configuraion_partly_empty", ofType: "json")!) let data = try! Data(contentsOf: urlPath, options: .dataReadingMapped) let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase - let model = try? decoder.decode(DomainRules.self, from: data) + let model = try? decoder.decode(ClientConfiguration.self, from: data) XCTAssert(model?.flags != nil) XCTAssert(model?.enforceKeygenAlgo != nil) @@ -54,14 +54,14 @@ class DomainRulesTests: XCTestCase { XCTAssert(model?.disallowAttesterSearchForDomains == nil) } - func test_empty_domain_rules_json_parse() { - let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "domain_rules_empty", ofType: "json")!) + func test_empty_client_configuraion_json_parse() { + let urlPath = URL(fileURLWithPath: Bundle(for: type(of: self)).path(forResource: "client_configuraion_empty", ofType: "json")!) let data = try! Data(contentsOf: urlPath, options: .dataReadingMapped) let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase - let model = try? decoder.decode(DomainRules.self, from: data) + let model = try? decoder.decode(ClientConfiguration.self, from: data) XCTAssert(model != nil) diff --git a/FlowCryptAppTests/Models Parsing/domain_rules.json b/FlowCryptAppTests/Models Parsing/client_configuraion.json similarity index 100% rename from FlowCryptAppTests/Models Parsing/domain_rules.json rename to FlowCryptAppTests/Models Parsing/client_configuraion.json diff --git a/FlowCryptAppTests/Models Parsing/domain_rules_empty.json b/FlowCryptAppTests/Models Parsing/client_configuraion_empty.json similarity index 100% rename from FlowCryptAppTests/Models Parsing/domain_rules_empty.json rename to FlowCryptAppTests/Models Parsing/client_configuraion_empty.json diff --git a/FlowCryptAppTests/Models Parsing/domain_rules_partly_empty.json b/FlowCryptAppTests/Models Parsing/client_configuraion_partly_empty.json similarity index 100% rename from FlowCryptAppTests/Models Parsing/domain_rules_partly_empty.json rename to FlowCryptAppTests/Models Parsing/client_configuraion_partly_empty.json From 85f5de61ffa29f841a711a864592df290896f679 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Thu, 24 Jun 2021 13:55:29 +0300 Subject: [PATCH 4/4] Removed tests data; --- FlowCrypt/Functionality/Services/EnterpriseServerApi.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift index 6ebed76db..d8df4c477 100644 --- a/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift +++ b/FlowCrypt/Functionality/Services/EnterpriseServerApi.swift @@ -73,7 +73,7 @@ class EnterpriseServerApi: EnterpriseServerApiType { func getClientConfiguration(for email: String) -> Promise { Promise { resolve, _ in - guard let userDomain = "name@flowcrypt.com".recipientDomain, + guard let userDomain = email.recipientDomain, !Configuration.publicEmailProviderDomains.contains(userDomain) else { resolve(nil) return