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