Create the methods to ask for the current Security Lock before showing the BrainKey.
This commit is contained in:
parent
f3c85e8875
commit
b4965d8a01
3 changed files with 80 additions and 41 deletions
|
@ -16,15 +16,19 @@ abstract class BaseSecurityLockDialog : DialogFragment() {
|
|||
|
||||
companion object {
|
||||
/** 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 */
|
||||
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
|
||||
* permission to do a security constrained action like sending a transaction or trying to change the
|
||||
* 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
|
||||
* 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 */
|
||||
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
|
||||
|
||||
/** 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)
|
||||
.getString(Constants.KEY_ENCRYPTED_PIN, "")?.trim()
|
||||
|
||||
currentStep = arguments?.getInt(KEY_STEP_SECURITY_LOCK) ?: 0
|
||||
|
||||
actionIdentifier = arguments?.getInt(KEY_ACTION_IDENTIFIER) ?: 0
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,16 @@ class PINSecurityLockDialog : BaseSecurityLockDialog() {
|
|||
var handled = false
|
||||
if (actionId == EditorInfo.IME_ACTION_GO) {
|
||||
val encryptedPIN = CryptoUtils.encrypt(v.context, v.text.toString()).trim()
|
||||
if (encryptedPIN == currentEncryptedPINPattern) {
|
||||
// PIN is correct, proceed
|
||||
dismiss()
|
||||
mCallback?.onPINPatternEntered(actionIdentifier)
|
||||
} else {
|
||||
tilPIN.error = "Wrong PIN"
|
||||
|
||||
if (currentStep == STEP_SECURITY_LOCK_VERIFY) {
|
||||
// The user just wants to verify the current encrypted PIN/Pattern
|
||||
if (encryptedPIN == currentEncryptedPINPattern) {
|
||||
// PIN is correct, proceed
|
||||
dismiss()
|
||||
mCallback?.onPINPatternEntered(actionIdentifier)
|
||||
} else {
|
||||
tilPIN.error = "Wrong PIN"
|
||||
}
|
||||
}
|
||||
|
||||
handled = true
|
||||
|
|
|
@ -43,6 +43,7 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
private const val TAG = "SettingsFragment"
|
||||
|
||||
private const val ACTION_CHANGE_SECURITY_LOCK = 1
|
||||
private const val ACTION_SHOW_BRAINKEY = 2
|
||||
}
|
||||
|
||||
private var mDisposables = CompositeDisposable()
|
||||
|
@ -74,8 +75,6 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
|
||||
initNightModeSwitch()
|
||||
|
||||
btnViewBrainKey.setOnClickListener { getBrainkey(it) }
|
||||
|
||||
tvNetworkStatus.setOnClickListener { v ->
|
||||
if (mNetworkService != null) {
|
||||
// PublishSubject used to announce full node latencies updates
|
||||
|
@ -109,6 +108,11 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
// 1 -> Pattern
|
||||
// 2 -> None
|
||||
|
||||
btnViewBrainKey.setOnClickListener {
|
||||
if (!verifySecurityLock(securityLockSelected, ACTION_SHOW_BRAINKEY))
|
||||
getBrainkey()
|
||||
}
|
||||
|
||||
tvSecurityLockSelected.text = resources.getStringArray(R.array.security_lock_options)[securityLockSelected]
|
||||
|
||||
tvSecurityLock.setOnClickListener { onSecurityLockTextSelected(securityLockSelected) }
|
||||
|
@ -213,26 +217,46 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
}
|
||||
|
||||
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 */ -> {
|
||||
val pinFrag = PINSecurityLockDialog()
|
||||
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.show(childFragmentManager, "pin_security_lock_tag")
|
||||
true
|
||||
}
|
||||
1 /* Pattern */ -> {
|
||||
|
||||
true
|
||||
}
|
||||
else -> { /* None */
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPINPatternEntered(actionIdentifier: Int) {
|
||||
if (actionIdentifier == ACTION_CHANGE_SECURITY_LOCK)
|
||||
if (actionIdentifier == ACTION_CHANGE_SECURITY_LOCK) {
|
||||
showChooseSecurityLockDialog()
|
||||
} else if (actionIdentifier == ACTION_SHOW_BRAINKEY) {
|
||||
getBrainkey()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPINPatternChanged() {
|
||||
|
@ -249,9 +273,6 @@ class SettingsFragment : Fragment(), ServiceConnection, BaseSecurityLockDialog.O
|
|||
listItems(R.array.security_lock_options) {dialog, index, text ->
|
||||
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
|
||||
* the brainKey to a method to show it in a nice MaterialDialog
|
||||
*/
|
||||
private fun getBrainkey(view: View) {
|
||||
val userId = PreferenceManager.getDefaultSharedPreferences(view.context)
|
||||
.getString(Constants.KEY_CURRENT_ACCOUNT_ID, "") ?: ""
|
||||
private fun getBrainkey() {
|
||||
context?.let {
|
||||
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)
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { authority ->
|
||||
if (authority != null) {
|
||||
val plainBrainKey = CryptoUtils.decrypt(view.context, authority.encryptedBrainKey)
|
||||
val plainSequenceNumber = CryptoUtils.decrypt(view.context, authority.encryptedSequenceNumber)
|
||||
val sequenceNumber = Integer.parseInt(plainSequenceNumber)
|
||||
val brainKey = BrainKey(plainBrainKey, sequenceNumber)
|
||||
showBrainKeyDialog(view, brainKey)
|
||||
mDisposables.add(authorityRepository.get(userId)
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { authority ->
|
||||
if (authority != null) {
|
||||
val plainBrainKey = CryptoUtils.decrypt(it, authority.encryptedBrainKey)
|
||||
val plainSequenceNumber = CryptoUtils.decrypt(it, authority.encryptedSequenceNumber)
|
||||
val sequenceNumber = Integer.parseInt(plainSequenceNumber)
|
||||
val brainKey = BrainKey(plainBrainKey, sequenceNumber)
|
||||
showBrainKeyDialog(brainKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the plain brainkey in a dialog so that the user can view and Copy it.
|
||||
*/
|
||||
private fun showBrainKeyDialog(view: View, brainKey: BrainKey) {
|
||||
MaterialDialog(view.context).show {
|
||||
title(text = "BrainKey")
|
||||
message(text = brainKey.brainKey)
|
||||
customView(R.layout.dialog_copy_brainkey)
|
||||
cancelable(false)
|
||||
positiveButton(R.string.button__copied) { it.dismiss() }
|
||||
private fun showBrainKeyDialog(brainKey: BrainKey) {
|
||||
context?.let { context ->
|
||||
MaterialDialog(context).show {
|
||||
title(text = "BrainKey")
|
||||
message(text = brainKey.brainKey)
|
||||
customView(R.layout.dialog_copy_brainkey)
|
||||
cancelable(false)
|
||||
positiveButton(R.string.button__copied) { it.dismiss() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue