pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift
author Dirk Zimmermann <dz@pep.security>
Thu, 28 May 2020 17:02:51 +0200
branchIOS-2259
changeset 13612 ae8aa97b45dc
parent 12373 5ae49930a3fc
child 13571 37ec7511313f
permissions -rw-r--r--
IOS-2259 Comment in test
     1 //
     2 //  AccountSettingsViewModel.swift
     3 //  pEpForiOS
     4 //
     5 //  Created by Xavier Algarra on 13/06/2017.
     6 //  Copyright © 2017 p≡p Security S.A. All rights reserved.
     7 //
     8 
     9 import Foundation
    10 import MessageModel
    11 import pEpIOSToolbox
    12 
    13 protocol AccountSettingsViewModelDelegate: class {
    14     func showErrorAlert(error: Error)
    15     func undoPEPSyncToggle()
    16     func showLoadingView()
    17     func hideLoadingView()
    18 }
    19 
    20 final class AccountSettingsViewModel {
    21     let isOAuth2: Bool
    22 
    23     var account: Account
    24     var count: Int { return headers.count }
    25 
    26     weak var delegate: AccountSettingsViewModelDelegate?
    27 
    28     private let headers = [NSLocalizedString("Account",
    29                                              comment: "Account settings"),
    30                            NSLocalizedString("IMAP Settings",
    31                                              comment: "Account settings title IMAP"),
    32                            NSLocalizedString("SMTP Settings",
    33                                              comment: "Account settings title SMTP")]
    34 
    35     /// If there was OAUTH2 for this account, here is a current token.
    36     /// This trumps both the `originalPassword` and a password given by the user
    37     /// via the UI.
    38     /// - Note: For logins that require it, there must be an up-to-date token
    39     ///         for the verification be able to succeed.
    40     ///         It is extracted from the existing server credentials on `init`.
    41     private var accessToken: OAuth2AccessTokenProtocol?
    42     private(set) var pEpSync: Bool
    43 
    44     private enum AccountSettingsError: Error, LocalizedError {
    45         case accountNotFound, failToModifyAccountPEPSync
    46 
    47         var errorDescription: String? {
    48             switch self {
    49             case .accountNotFound, .failToModifyAccountPEPSync:
    50                 return NSLocalizedString("Something went wrong, please try again later", comment: "AccountSettings viewModel: no account error")
    51             }
    52         }
    53     }
    54 
    55     subscript(section: Int) -> String {
    56         get {
    57             assert(sectionIsValid(section: section), "Section out of range")
    58             return headers[section]
    59         }
    60     }
    61 
    62     init(account: Account) {
    63         // We are using a copy of the data here.
    64         // The outside world must not know changed settings until they have been verified.
    65         isOAuth2 = account.imapServer?.authMethod == AuthMethod.saslXoauth2.rawValue
    66         self.account = account
    67 
    68         pEpSync = (try? account.isKeySyncEnabled()) ?? false
    69     }
    70     
    71     public func rowShouldBeHidden(indexPath: IndexPath) -> Bool {
    72         if indexPath.section == 0 && indexPath.row == 3 {
    73             if account.imapServer?.credentials.clientCertificate != nil {
    74                 return false
    75             }
    76             return true
    77         }
    78         return false
    79     }
    80     
    81     public func clientCertificateViewModel() -> ClientCertificateManagementViewModel {
    82         let viewModel = ClientCertificateManagementViewModel(account: account)
    83         return viewModel
    84     }
    85     
    86     public func certificateInfo() -> String {
    87         
    88         guard let certificate = account.imapServer?.credentials.clientCertificate else {
    89             return ""
    90         }
    91         let name = certificate.label ?? "--"
    92         let date = certificate.date?.fullString() ?? ""
    93         let separator = NSLocalizedString("Exp. date:", comment: "spearator string bewtween name and date")
    94         return "\(name), \(separator) \(date)"
    95     }
    96 
    97     public func handleResetIdentity() {
    98         delegate?.showLoadingView()
    99         account.resetKeys() { [weak self] result in
   100             guard let me = self else {
   101                 Log.shared.lostMySelf()
   102                 return
   103             }
   104             switch result {
   105             case .success():
   106                 me.delegate?.hideLoadingView()
   107             case .failure(let error):
   108                 me.delegate?.hideLoadingView()
   109                 me.delegate?.showErrorAlert(error: error)
   110                 Log.shared.errorAndCrash("Fail to reset identity, with error %@ ",
   111                                          error.localizedDescription)
   112             }
   113         }
   114     }
   115 
   116     public func pEpSync(enable: Bool) {
   117         do {
   118             try account.setKeySyncEnabled(enable: enable)
   119         } catch {
   120             delegate?.undoPEPSyncToggle()
   121             delegate?.showErrorAlert(error: AccountSettingsError.failToModifyAccountPEPSync)
   122         }
   123     }
   124 
   125     public func updateToken(accessToken: OAuth2AccessTokenProtocol) {
   126         self.accessToken = accessToken
   127     }
   128 
   129     public func isPEPSyncSwitchGreyedOut() -> Bool {
   130         return KeySyncUtil.isInDeviceGroup
   131     }
   132 }
   133 
   134 // MARK: - Private
   135 
   136 extension AccountSettingsViewModel {
   137     private func sectionIsValid(section: Int) -> Bool {
   138         return section >= 0 && section < headers.count
   139     }
   140 }