You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

300 lines
10 KiB

//
// 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
}
}