Create the methods to ask for the current Security Lock before showing the BrainKey.

This commit is contained in:
Severiano Jaramillo 2019-02-14 13:41:27 -06:00
parent f3c85e8875
commit b4965d8a01
3 changed files with 80 additions and 41 deletions

View file

@ -16,15 +16,19 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
companion object { companion object {
/** Used to denote that the user is in the step of creating the preferred security lock option */ /** Used to denote that the user is in the step of creating the preferred security lock option */
const val SECURITY_LOG_STEP_CREATE = 1 const val STEP_SECURITY_LOCK_CREATE = 1
/** Used to denote that the user is in the step of confirming the newly created security lock option */ /** Used to denote that the user is in the step of confirming the newly created security lock option */
private const val SECURITY_LOG_STEP_CONFIRM = 2 private const val STEP_SECURITY_LOCK_CONFIRM = 2
/** Used to denote that the user is in the step of verifying the current security lock option, to give /** Used to denote that the user is in the step of verifying the current security lock option, to give
* permission to do a security constrained action like sending a transaction or trying to change the * permission to do a security constrained action like sending a transaction or trying to change the
* current security lock option */ * current security lock option */
const val SECURITY_LOG_STEP_VERIFY = 3 const val STEP_SECURITY_LOCK_VERIFY = 3
/** Used to let the dialog know if the user wants to create a new PIN/Pattern or just verify its correctness
* to get access to security constrained actions */
const val KEY_STEP_SECURITY_LOCK = "key_step_security_lock"
/** The calling fragment can be calling this dialog to unlock many different things, this variable helps to /** The calling fragment can be calling this dialog to unlock many different things, this variable helps to
* keep track of what action the calling fragment wants to achieve */ * keep track of what action the calling fragment wants to achieve */
@ -40,6 +44,10 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
/** Callback used to notify the parent that a PIN/Pattern has been entered successfully */ /** Callback used to notify the parent that a PIN/Pattern has been entered successfully */
protected var mCallback: OnPINPatternEnteredListener? = null protected var mCallback: OnPINPatternEnteredListener? = null
/** Keeps track of the current step, can be create, confirm of verify */
protected var currentStep: Int = 1
/** Used so the calling object knows what was the intention to ask for the Security Lock */
protected var actionIdentifier: Int = 0 protected var actionIdentifier: Int = 0
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */ /** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
@ -56,6 +64,8 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
currentEncryptedPINPattern = PreferenceManager.getDefaultSharedPreferences(context) currentEncryptedPINPattern = PreferenceManager.getDefaultSharedPreferences(context)
.getString(Constants.KEY_ENCRYPTED_PIN, "")?.trim() .getString(Constants.KEY_ENCRYPTED_PIN, "")?.trim()
currentStep = arguments?.getInt(KEY_STEP_SECURITY_LOCK) ?: 0
actionIdentifier = arguments?.getInt(KEY_ACTION_IDENTIFIER) ?: 0 actionIdentifier = arguments?.getInt(KEY_ACTION_IDENTIFIER) ?: 0
} }

View file

@ -33,12 +33,16 @@ class PINSecurityLockDialog : BaseSecurityLockDialog() {
var handled = false var handled = false
if (actionId == EditorInfo.IME_ACTION_GO) { if (actionId == EditorInfo.IME_ACTION_GO) {
val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim() val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim()
if (encryptedPIN == currentEncryptedPINPattern) {
// PIN is correct, proceed if (currentStep == STEP_SECURITY_LOCK_VERIFY) {
dismiss() // The user just wants to verify the current encrypted PIN/Pattern
mCallback?.onPINPatternEntered(actionIdentifier) if (encryptedPIN == currentEncryptedPINPattern) {
} else { // PIN is correct, proceed
tilPIN.error = "Wrong PIN" dismiss()
mCallback?.onPINPatternEntered(actionIdentifier)
} else {
tilPIN.error = "Wrong PIN"
}
} }
handled = true handled = true

View file

@ -43,6 +43,7 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
private const val TAG = "SettingsFragment" private const val TAG = "SettingsFragment"
private const val ACTION_CHANGE_SECURITY_LOCK = 1 private const val ACTION_CHANGE_SECURITY_LOCK = 1
private const val ACTION_SHOW_BRAINKEY = 2
} }
private var mDisposables = CompositeDisposable() private var mDisposables = CompositeDisposable()
@ -74,8 +75,6 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
initNightModeSwitch() initNightModeSwitch()
btnViewBrainKey.setOnClickListener { getBrainkey(it) }
tvNetworkStatus.setOnClickListener { v -> tvNetworkStatus.setOnClickListener { v ->
if (mNetworkService != null) { if (mNetworkService != null) {
// PublishSubject used to announce full node latencies updates // PublishSubject used to announce full node latencies updates
@ -109,6 +108,11 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
// 1 -> Pattern // 1 -> Pattern
// 2 -> None // 2 -> None
btnViewBrainKey.setOnClickListener {
if (!verifySecurityLock(securityLockSelected, ACTION_SHOW_BRAINKEY))
getBrainkey()
}
tvSecurityLockSelected.text = resources.getStringArray(R.array.security_lock_options)[securityLockSelected] tvSecurityLockSelected.text = resources.getStringArray(R.array.security_lock_options)[securityLockSelected]
tvSecurityLock.setOnClickListener { onSecurityLockTextSelected(securityLockSelected) } tvSecurityLock.setOnClickListener { onSecurityLockTextSelected(securityLockSelected) }
@ -213,26 +217,46 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
} }
private fun onSecurityLockTextSelected(securityLockSelected: Int) { private fun onSecurityLockTextSelected(securityLockSelected: Int) {
when (securityLockSelected) { if (!verifySecurityLock(securityLockSelected, ACTION_CHANGE_SECURITY_LOCK))
showChooseSecurityLockDialog()
}
/**
* Encapsulated the logic required to do actions possibly locked by the Security Lock. If PIN/Pattern is selected
* then it prompts for it.
*
* @param securityLockSelected Current Security Lock option selected
* @param actionIdentifier Identifier used to know why a verify security lock was launched
* @return true if the action was handled, false otherwise
*/
private fun verifySecurityLock(securityLockSelected: Int, actionIdentifier: Int): Boolean {
return when (securityLockSelected) {
0 /* PIN */ -> { 0 /* PIN */ -> {
val pinFrag = PINSecurityLockDialog() val pinFrag = PINSecurityLockDialog()
val args = Bundle() val args = Bundle()
args.putInt(BaseSecurityLockDialog.KEY_ACTION_IDENTIFIER, ACTION_CHANGE_SECURITY_LOCK) args.putInt(BaseSecurityLockDialog.KEY_STEP_SECURITY_LOCK,
BaseSecurityLockDialog.STEP_SECURITY_LOCK_VERIFY)
args.putInt(BaseSecurityLockDialog.KEY_ACTION_IDENTIFIER, actionIdentifier)
pinFrag.arguments = args pinFrag.arguments = args
pinFrag.show(childFragmentManager, "pin_security_lock_tag") pinFrag.show(childFragmentManager, "pin_security_lock_tag")
true
} }
1 /* Pattern */ -> { 1 /* Pattern */ -> {
true
} }
else -> { /* None */ else -> { /* None */
false
} }
} }
} }
override fun onPINPatternEntered(actionIdentifier: Int) { override fun onPINPatternEntered(actionIdentifier: Int) {
if (actionIdentifier == ACTION_CHANGE_SECURITY_LOCK) if (actionIdentifier == ACTION_CHANGE_SECURITY_LOCK) {
showChooseSecurityLockDialog() showChooseSecurityLockDialog()
} else if (actionIdentifier == ACTION_SHOW_BRAINKEY) {
getBrainkey()
}
} }
override fun onPINPatternChanged() { override fun onPINPatternChanged() {
@ -249,9 +273,6 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
listItems(R.array.security_lock_options) {dialog, index, text -> listItems(R.array.security_lock_options) {dialog, index, text ->
dialog.context.toast("$text selected!") dialog.context.toast("$text selected!")
} }
cancelable(false)
cancelOnTouchOutside(false)
negativeButton(android.R.string.cancel)
} }
} }
} }
@ -260,37 +281,41 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
* Obtains the brainKey from the authorities db table for the current user account and if it is not null it passes * Obtains the brainKey from the authorities db table for the current user account and if it is not null it passes
* the brainKey to a method to show it in a nice MaterialDialog * the brainKey to a method to show it in a nice MaterialDialog
*/ */
private fun getBrainkey(view: View) { private fun getBrainkey() {
val userId = PreferenceManager.getDefaultSharedPreferences(view.context) context?.let {
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: "" val userId = PreferenceManager.getDefaultSharedPreferences(it)
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
val authorityRepository = AuthorityRepository(view.context) val authorityRepository = AuthorityRepository(it)
mDisposables.add(authorityRepository.get(userId) mDisposables.add(authorityRepository.get(userId)
.subscribeOn(Schedulers.computation()) .subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe { authority -> .subscribe { authority ->
if (authority != null) { if (authority != null) {
val plainBrainKey = CryptoUtils.decrypt(view.context, authority.encryptedBrainKey) val plainBrainKey = CryptoUtils.decrypt(it, authority.encryptedBrainKey)
val plainSequenceNumber = CryptoUtils.decrypt(view.context, authority.encryptedSequenceNumber) val plainSequenceNumber = CryptoUtils.decrypt(it, authority.encryptedSequenceNumber)
val sequenceNumber = Integer.parseInt(plainSequenceNumber) val sequenceNumber = Integer.parseInt(plainSequenceNumber)
val brainKey = BrainKey(plainBrainKey, sequenceNumber) val brainKey = BrainKey(plainBrainKey, sequenceNumber)
showBrainKeyDialog(view, brainKey) showBrainKeyDialog(brainKey)
}
} }
} )
) }
} }
/** /**
* Shows the plain brainkey in a dialog so that the user can view and Copy it. * Shows the plain brainkey in a dialog so that the user can view and Copy it.
*/ */
private fun showBrainKeyDialog(view: View, brainKey: BrainKey) { private fun showBrainKeyDialog(brainKey: BrainKey) {
MaterialDialog(view.context).show { context?.let { context ->
title(text = "BrainKey") MaterialDialog(context).show {
message(text = brainKey.brainKey) title(text = "BrainKey")
customView(R.layout.dialog_copy_brainkey) message(text = brainKey.brainKey)
cancelable(false) customView(R.layout.dialog_copy_brainkey)
positiveButton(R.string.button__copied) { it.dismiss() } cancelable(false)
positiveButton(R.string.button__copied) { it.dismiss() }
}
} }
} }