// // BiometricAuthenticationViewController.swift // GME Remit // // Created by InKwon Kim on 30/03/2019. //Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved. // import UIKit import LocalAuthentication enum BiometricAuthenticationPolicy { case deviceOwnerAuthentication case deviceOwnerAuthenticationWithBiometrics } enum BiometricAuthenticationError: Error { case authenticationFailed case userCancel case userFallback case biometryNotAvailable case biometryNotEnrolled case biometryLockout case notBeConfigured var message: String { let msg: String switch self { case .authenticationFailed: msg = "There was a problem verifying your identity." case .userCancel: msg = "You pressed cancel." case .userFallback: msg = "You pressed password." case .biometryNotAvailable: msg = "FaceID & TouchID is not available." case .biometryNotEnrolled: let path = "(Setting -> FaceID(TouchID) & Passcode" msg = "FaceID & TouchID is not set up.\nCheck your device setting.\n\(path)" case .biometryLockout: msg = "FaceID & TouchID is locked." default: msg = "FaceID & TouchID may not be configured" } return msg } } protocol BiometricAuthenticationViewControllerDelegate: class { func doSelectLocalAuthenticationPolicy( _ viewController: BiometricAuthenticationViewController ) -> BiometricAuthenticationPolicy func viewController( _ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel, authenticationButton button: UIButton ) func didComplete(_ viewController: BiometricAuthenticationViewController) func viewController( _ viewController: BiometricAuthenticationViewController, didFailWithError error: BiometricAuthenticationError, errorMessage: String? ) } extension BiometricAuthenticationViewControllerDelegate { func doSelectLocalAuthenticationPolicy( _ viewController: BiometricAuthenticationViewController ) -> BiometricAuthenticationPolicy { return .deviceOwnerAuthenticationWithBiometrics } } final class BiometricAuthenticationViewController: UIViewController, BiometricAuthenticationViewInterface { // MARK: Properties var presenter: BiometricAuthenticationModuleInterface? weak var delegate: BiometricAuthenticationViewControllerDelegate? private var isViewDidLoad = true private var buttonTitle: String = "bio_press_button_title_text".localized() { didSet { biometricAuthenticationImageButton.setTitle(buttonTitle, for: .normal) } } // MARK: IBOutlets @IBOutlet private weak var biometricAuthenticationImageButton: UIButton! @IBOutlet private weak var informationLabel: UILabel! @IBOutlet private weak var logoImageView: UIImageView! // MARK: VC's Life cycle override func viewDidLoad() { super.viewDidLoad() self.setup() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if self.isViewDidLoad { self.showAuthentication() self.isViewDidLoad = false } } // MARK: IBActions @IBAction private func authenticationButtonTouch(_ sender: Any) { self.showAuthentication() } // MARK: Other Functions private func setup() { // all setup should be done here self.setUI() self.delegate?.viewController( self, informationTitleLabel: self.informationLabel, authenticationButton: self.biometricAuthenticationImageButton ) } private func setUI() { logoImageView?.image = logoImageView.image?.withRenderingMode(.alwaysTemplate) logoImageView.tintColor = .themeWhiteRed biometricAuthenticationImageButton.layer.cornerRadius = 5 biometricAuthenticationImageButton.setTitle(buttonTitle, for: .normal) biometricAuthenticationImageButton.backgroundColor = .themeBlue } private func showAuthentication() { #if DEBUG DispatchQueue.main.async { self.delegate?.didComplete(self) } #else guard let isUseBiometricAuth = KeyChain.shared.get(key: .biometricAuth), isUseBiometricAuth == "1" else { let error = BiometricAuthenticationError.biometryNotAvailable self.delegate?.viewController( self, didFailWithError: error, errorMessage: error.message ) return } self.presenter?.showBiometricAuthentication() #endif } }