pEpForiOS/UI/Settings/Setting/AccountSettings/ViewModel/AccountSettingsViewModel.swift
author Dirk Zimmermann <dz@pep.security>
Wed, 24 Apr 2019 12:43:18 +0200
branchIOS-1542
changeset 8354 1b6ad54afb11
parent 8353 304abe625eac
child 8356 01f05d350fc9
permissions -rw-r--r--
IOS-1542 AccountSettingsViewModel: Get rid of the account copy.
andreas@3697
     1
//
andreas@3697
     2
//  AccountSettingsViewModel.swift
andreas@3697
     3
//  pEpForiOS
andreas@3697
     4
//
andreas@3697
     5
//  Created by Xavier Algarra on 13/06/2017.
andreas@3697
     6
//  Copyright © 2017 p≡p Security S.A. All rights reserved.
andreas@3697
     7
//
andreas@3697
     8
andreas@3697
     9
import Foundation
andreas@3697
    10
import MessageModel
xavier@7644
    11
import pEpIOSToolbox
andreas@3697
    12
andreas@3697
    13
public class AccountSettingsViewModel {
andreas@3697
    14
    public struct ServerViewModel {
andreas@3697
    15
        var address: String?
andreas@3697
    16
        var port: String?
andreas@3697
    17
        var transport: String?
andreas@3697
    18
    }
andreas@3697
    19
andreas@3697
    20
    public struct SecurityViewModel {
andreas@3697
    21
        var options = Server.Transport.toArray()
andreas@3697
    22
        var size : Int {
andreas@3697
    23
            get {
andreas@3697
    24
                return options.count
andreas@3697
    25
            }
andreas@3697
    26
        }
andreas@3697
    27
andreas@3697
    28
        subscript(option: Int) -> String {
andreas@3697
    29
            get {
andreas@3697
    30
                return options[option].asString()
andreas@3697
    31
            }
andreas@3697
    32
        }
andreas@3697
    33
    }
andreas@3697
    34
andreas@3697
    35
    private let headers = [
andreas@3697
    36
        NSLocalizedString("Account", comment: "Account settings"),
andreas@3697
    37
        NSLocalizedString("IMAP Settings", comment: "Account settings title IMAP"),
andreas@3697
    38
        NSLocalizedString("SMTP Settings", comment: "Account settings title SMTP")
andreas@3697
    39
    ]
andreas@3697
    40
    private var controlWord = "noRealPassword"
andreas@3697
    41
andreas@3697
    42
    public let svm = SecurityViewModel()
dirk@4019
    43
    public let isOAuth2: Bool
andreas@3697
    44
andreas@3697
    45
    public init(account: Account) {
dz@8354
    46
        // We are using a copy of the data here.
dz@8354
    47
        // The outside world must not know changed settings until they have been verified.
dirk@4019
    48
        isOAuth2 = account.server(with: .imap)?.authMethod == AuthMethod.saslXoauth2.rawValue
dz@8354
    49
        self.email = account.user.address
dz@8354
    50
        self.loginName = account.server(with: .imap)?.credentials.loginName ?? ""
dz@8354
    51
        self.name = account.user.userName ?? ""
andreas@3697
    52
dz@8354
    53
        if let server = account.smtpServer {
dz@8354
    54
            self.smtpServer = ServerViewModel(
dz@8354
    55
                address: server.address,
dz@8354
    56
                port: "\(server.port)",
dz@8354
    57
                transport: server.transport?.asString())
dz@8354
    58
        } else {
dz@8354
    59
            self.smtpServer = ServerViewModel()
dz@8354
    60
        }
dz@8354
    61
dz@8354
    62
        if let server = account.imapServer {
dz@8354
    63
            self.imapServer = ServerViewModel(
dz@8354
    64
                address: server.address,
dz@8354
    65
                port: "\(server.port)",
dz@8354
    66
                transport: server.transport?.asString())
dz@8354
    67
        } else {
dz@8354
    68
            self.imapServer = ServerViewModel()
andreas@3697
    69
        }
andreas@3697
    70
    }
andreas@3697
    71
dz@8354
    72
    var email: String
dz@8354
    73
dz@8353
    74
    /// - Note: The email model is based on the assumption that imap.loginName == smtp.loginName
dz@8354
    75
    var loginName: String
andreas@3697
    76
dz@8354
    77
    var name: String
andreas@3697
    78
dz@8354
    79
    var smtpServer: ServerViewModel
andreas@3697
    80
dz@8354
    81
    var imapServer: ServerViewModel
andreas@3697
    82
agp@8142
    83
    var verificationService: VerificationService?
andreas@3697
    84
    weak var delegate: AccountVerificationResultDelegate?
andreas@3697
    85
dz@8354
    86
    // Currently we assume imap and smtp servers exist already (update).
dz@8354
    87
    // If we run into problems here modify to updateOrCreate.
andreas@3697
    88
    func update(loginName: String, name: String, password: String? = nil, imap: ServerViewModel,
andreas@3697
    89
                smtp: ServerViewModel) {
dz@8354
    90
        // TODO: Implement
dz@8354
    91
        /*
andreas@3697
    92
        guard let serverImap = account.imapServer,
andreas@3697
    93
            let serverSmtp = account.smtpServer else {
dz@7517
    94
                Logger.frontendLogger.errorAndCrash("Account misses imap or smtp server.")
andreas@3697
    95
                return
andreas@3697
    96
        }
andreas@3697
    97
        let pass : String?
andreas@3697
    98
        if let p = password {
andreas@3697
    99
            pass = p
andreas@3697
   100
        } else {
andreas@3697
   101
            pass = serverImap.credentials.password
andreas@3697
   102
        }
andreas@3697
   103
        guard let editedServerImap = server(from: imap, serverType: .imap,
andreas@3697
   104
                                            loginName: loginName,
andreas@3697
   105
                                            password: pass,
andreas@3697
   106
                                            key: serverImap.credentials.key),
andreas@3697
   107
            let editedServerSmtp = server(from: smtp,
andreas@3697
   108
                                          serverType: .smtp,
andreas@3697
   109
                                          loginName: loginName,
andreas@3697
   110
                                          password: pass,
andreas@3697
   111
                                          key: serverSmtp.credentials.key)
andreas@3697
   112
            else {
dz@7517
   113
                Logger.frontendLogger.errorAndCrash("Invalid input.")
andreas@3697
   114
                return
andreas@3697
   115
        }
andreas@3697
   116
andreas@3697
   117
        serverImap.updateValues(with: editedServerImap)
andreas@3697
   118
        serverSmtp.updateValues(with: editedServerSmtp)
andreas@3697
   119
andreas@3697
   120
        self.account.user.userName = name
andreas@3697
   121
agp@8142
   122
        guard let verificationService = verificationService else {
agp@8142
   123
            Logger.frontendLogger.errorAndCrash("no VerificationService")
andreas@3697
   124
            return
andreas@3697
   125
        }
agp@8142
   126
        verificationService.requestVerification(account: account, delegate: self)
dz@8354
   127
         */
andreas@3697
   128
    }
andreas@3697
   129
andreas@3697
   130
    func sectionIsValid(section: Int) -> Bool {
borja@6875
   131
        return section >= 0 && section < headers.count
andreas@3697
   132
    }
andreas@3697
   133
andreas@3697
   134
    var count: Int {
andreas@3697
   135
        get {
andreas@3697
   136
            return headers.count
andreas@3697
   137
        }
andreas@3697
   138
    }
andreas@3697
   139
andreas@3697
   140
    subscript(section: Int) -> String {
andreas@3697
   141
        get {
andreas@3697
   142
            assert(sectionIsValid(section: section), "Section out of range")
andreas@3697
   143
            return headers[section]
andreas@3697
   144
        }
andreas@3697
   145
    }
andreas@3697
   146
andreas@3697
   147
    private func server(from viewModel:ServerViewModel, serverType:Server.ServerType,
andreas@3697
   148
                        loginName: String, password: String?, key: String? = nil) -> Server? {
andreas@3697
   149
        guard let viewModelPort = viewModel.port,
andreas@3697
   150
            let port = UInt16(viewModelPort),
andreas@3697
   151
            let address = viewModel.address else {
dz@7517
   152
                Logger.frontendLogger.errorAndCrash("viewModel misses required data.")
andreas@3697
   153
                return nil
andreas@3697
   154
        }
andreas@5601
   155
        let transport = Server.Transport(fromString: viewModel.transport)
andreas@3697
   156
andreas@3697
   157
        let credentials = ServerCredentials.create(loginName: loginName, key: key)
andreas@3697
   158
        if password != nil && password != "" {
andreas@3697
   159
            credentials.password = password
andreas@3697
   160
        }
andreas@3697
   161
andreas@3697
   162
        let server = Server.create(serverType: serverType, port: port, address: address,
andreas@3697
   163
                                   transport: transport, credentials: credentials)
andreas@3697
   164
andreas@3697
   165
        return server
andreas@3697
   166
    }
andreas@3697
   167
dirk@4052
   168
    func updateToken(accessToken: OAuth2AccessTokenProtocol) {
dz@8354
   169
        // TODO: What to do here? When does this get called?
dz@8354
   170
        /*
dirk@4053
   171
        guard let imapServer = account.imapServer,
dirk@4053
   172
            let smtpServer = account.smtpServer else {
dirk@4053
   173
                return
dirk@4052
   174
        }
dirk@4053
   175
        let password = accessToken.persistBase64Encoded()
dirk@4053
   176
        imapServer.credentials.password = password
dirk@4053
   177
        smtpServer.credentials.password = password
dz@8354
   178
         */
dirk@4052
   179
    }
andreas@3697
   180
}
andreas@3697
   181
andreas@5601
   182
// MARK: - AccountVerificationServiceDelegate
andreas@5601
   183
andreas@3697
   184
extension AccountSettingsViewModel: AccountVerificationServiceDelegate {
dz@7999
   185
    public func verified(account: Account,
andreas@5601
   186
                  service: AccountVerificationServiceProtocol,
andreas@3697
   187
                  result: AccountVerificationResult) {
andreas@5601
   188
        if result == .ok {
dz@7914
   189
            MessageModelUtil.performAndWait {
andreas@5601
   190
                account.save()
andreas@5601
   191
            }
andreas@5601
   192
        }
andreas@5601
   193
        GCD.onMainWait { [weak self] in
andreas@5601
   194
            guard let me = self else {
dz@7517
   195
                Logger.frontendLogger.lostMySelf()
andreas@5601
   196
                return
andreas@5601
   197
            }
andreas@5601
   198
            me.delegate?.didVerify(result: result, accountInput: nil)
andreas@3697
   199
        }
andreas@3697
   200
    }
andreas@3697
   201
}