// // LoginViewController.swift // GMERemittance // // Created by gme_2 on 07/09/2018. //Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved. // import UIKit import Localize_Swift import LocalAuthentication var passwordRegex = #"^(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$&*])(?=.*[a-z]).{8,24}$"# class LoginViewController: UIViewController { struct StringConstants { let headerTitle = "login_title_text".localized() let userIdTitle = "userid_placeholder_text".localized() let userIdPlaceholder = "userid_placeholder_text".localized() let passwordTitle = "enter_login_password_text".localized() let passwordPlaceholder = "enter_login_password_text".localized() let forgotPasswordText = "forgot_password_text".localized() let newToGmeText = "new_to_gme_text".localized() let registerHereText = "login_register_here_text".localized() let loginText = "login_text".localized() let fingerPrintText = "tap_to_login_using_finger_text".localized() } // MARK: IBOutlets @IBOutlet weak var userNameTextField: ValidationTextField! @IBOutlet weak var passwordTextField: ValidationTextField! // views @IBOutlet weak var newToGmeLabel: UILabel! @IBOutlet weak var registerHereButton: UIButton! @IBOutlet weak var forgotPasswordButton: UIButton! @IBOutlet weak var loginButton: UIButton! @IBOutlet weak var backButton: UIImageView! { didSet { let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tappedView)) backButton.addGestureRecognizer(tapGestureRecognizer) backButton.isUserInteractionEnabled = true } } @IBOutlet weak var headerTitle: UILabel! @IBOutlet weak var passwordToggleButon: UIButton! @IBOutlet weak var fingerprintLogin: UIButton! @IBOutlet weak var biometricStackView: UIStackView! var encryptedPassword : String? { didSet { guard let email = self.userNameTextField.text, let pw = self.encryptedPassword, email != "", pw != "" else {return} self.login(UIButton()) } } // MARK: Properties var presenter: LoginModuleInterface? private var isFirst = true private var validDic = [ "id": false, "pw": false ] private var isValid = false { didSet { //loginButton.isEnabled = isValid loginButton.isEnabled = true // loginButton.backgroundColor = isValid ? .themeRed : .themeText loginButton.backgroundColor = isValid ? .themeRed : .themeRed } } // MARK: VC's Life cycle override func viewDidLoad() { super.viewDidLoad() self.setup() configureLanguage() } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if isFirst { userNameTextField.text = KeyChain.shared.get(key: .id) isFirst = false self.userNameTextField.sendActions(for: .editingChanged) } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) self.navigationItem.title = "" } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) #if DEBUG if self.userNameTextField.text == "" { DebugManager.shared.setTestAccount(target: self) { (id, pw) in self.userNameTextField.text = id self.passwordTextField.text = pw self.userNameTextField.sendActions(for: .editingChanged) self.passwordTextField.sendActions(for: .editingChanged) } } #endif } // MARK: IBActions @IBAction func forgotPassword(_ sender: UIButton) { self.presenter?.forgotPassword() } @IBAction func showPasswordToggle(_ sender: UIButton) { passwordTextField.isSecureTextEntry = !passwordTextField.isSecureTextEntry passwordTextField.isSecureTextEntry ? passwordToggleButon.setImage(UIImage(named: "Show"), for: .normal) : passwordToggleButon.setImage(UIImage(named: "Hide"), for: .normal) } @IBAction func register(_ sender: UIButton) { self.presenter?.register() } @IBAction func login(_ sender: UIButton) { let username = self.userNameTextField.text ?? "" let password = self.passwordTextField.text ?? self.encryptedPassword ?? "" self.presenter?.login(userName: username, encryptedPassword: password) } @IBAction func fingerprintLogin(_ sender: UIButton) { self.authenticate() } // MARK: Other Functions private func setup() { // all setup should be done here let isBio = KeyChain.shared.get(key: .biometricAuth) == "1" ? true : false if isBio { self.biometricStackView.isHidden = false } else { self.biometricStackView.isHidden = true } setupColor() userNameTextField.delegate = self passwordTextField.delegate = self userNameTextField.returnKeyType = .next userNameTextField.validCondition = { !$0.isEmpty } userNameTextField.addTarget(self, action: #selector(editingChanged(_:)), for: .editingChanged) passwordTextField.validCondition = { !$0.isEmpty && $0.validateRegex(regex: passwordRegex)} passwordTextField.errorMessage = "password_error_text".localized() passwordTextField.isSecureTextEntry = true passwordTextField.addTarget(self, action: #selector(editingChanged(_:)), for: .editingChanged) loginButton.layer.cornerRadius = 6 } @objc func tappedView(){ self.navigationController?.popViewController(animated: true) } @objc private func editingChanged(_ textField: ValidationTextField) { switch textField { case userNameTextField: userNameTextField.filterForUserIDFormat() validDic["id"] = userNameTextField.isValid case passwordTextField: validDic["pw"] = passwordTextField.isValid default: () } isValid = validDic.allSatisfy { $0.value } } private func configureLanguage() { userNameTextField.titleText = StringConstants().userIdTitle userNameTextField.placeholder = StringConstants().userIdPlaceholder passwordTextField.titleText = StringConstants().passwordTitle passwordTextField.placeholder = StringConstants().passwordPlaceholder forgotPasswordButton.setTitle(StringConstants().forgotPasswordText, for: .normal) newToGmeLabel.text = StringConstants().newToGmeText registerHereButton.setTitle(StringConstants().registerHereText, for: .normal) loginButton.setTitle(StringConstants().loginText, for: .normal) fingerprintLogin.setTitle(StringConstants().fingerPrintText, for: .normal) headerTitle.text = StringConstants().headerTitle } func setupColor() { } private func authenticate() { guard let email = KeyChain.shared.get(key: .id), let typedEmail = self.userNameTextField.text, let isUseBiometricAuth = KeyChain.shared.get(key: .biometricAuth), email == typedEmail, isUseBiometricAuth == "1" else { self.encryptedPassword = self.passwordTextField.text return } BiometricAuthenticationWireframe().openWithDelegate(on: self, delegate: self) } } // MARK: LoginViewInterface extension LoginViewController: LoginViewInterface { func show(error: String) { self.alert(type: .error, message: error) } func showLoading() { self.showProgressHud() } func hideLoading() { self.hideProgressHud() } } // MARK: - UITextFieldDelegate extension LoginViewController: UITextFieldDelegate { func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { return true } func textFieldShouldReturn(_ textField: UITextField) -> Bool { if textField == userNameTextField { self.authenticate() } return false } } // MARK: - BiometricAuthenticationViewControllerDelegate extension LoginViewController: BiometricAuthenticationViewControllerDelegate { func viewController( _ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel, authenticationButton button: UIButton ) { titleLabel.text = "Please enter authentication information for login" button.setTitle("login_text".localized(), for: .normal) } func didComplete(_ viewController: BiometricAuthenticationViewController) { viewController.dismiss(animated: true) { self.encryptedPassword = KeyChain.shared.get(key: .password) self.login(UIButton()) } } func viewController( _ viewController: BiometricAuthenticationViewController, didFailWithError error: BiometricAuthenticationError, errorMessage: String? ) { DispatchQueue.main.async {[weak self] in guard let _ = self else {return} switch error { case .userFallback, .biometryNotAvailable, .authenticationFailed: viewController.dismiss(animated: true, completion: nil) case .notBeConfigured, .biometryNotEnrolled: viewController.alert(type: .error, message: error.message, title: "Alert") { viewController.dismiss(animated: true, completion: nil) } default: viewController.dismiss(animated: true, completion: nil) } } } func doSelectLocalAuthenticationPolicy( _ viewController: BiometricAuthenticationViewController ) -> BiometricAuthenticationPolicy { return .deviceOwnerAuthenticationWithBiometrics } }