This commit is contained in:
Milos Kozak 2020-04-21 22:20:14 +02:00
commit 92ed678b6e
17 changed files with 164 additions and 36 deletions

View file

@ -322,7 +322,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
context?.let { context -> context?.let { context ->
if (preference != null) { if (preference != null) {
if (preference.key == resourceHelper.gs(R.string.key_master_password)) { if (preference.key == resourceHelper.gs(R.string.key_master_password)) {
passwordCheck.queryPassword(context, R.string.current_master_password, R.string.key_master_password, {
passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password) passwordCheck.setPassword(context, R.string.master_password, R.string.key_master_password)
})
return true return true
} }
if (preference.key == resourceHelper.gs(R.string.key_settings_password)) { if (preference.key == resourceHelper.gs(R.string.key_settings_password)) {

View file

@ -165,6 +165,7 @@ interface AppComponent : AndroidInjector<MainApp> {
fun injectSWButton(swButton: SWButton) fun injectSWButton(swButton: SWButton)
fun injectSWEditNumberWithUnits(swEditNumberWithUnits: SWEditNumberWithUnits) fun injectSWEditNumberWithUnits(swEditNumberWithUnits: SWEditNumberWithUnits)
fun injectSWEditString(swEditString: SWEditString) fun injectSWEditString(swEditString: SWEditString)
fun injectSWEditEncryptedPassword(swSWEditEncryptedPassword: SWEditEncryptedPassword)
fun injectSWEditUrl(swEditUrl: SWEditUrl) fun injectSWEditUrl(swEditUrl: SWEditUrl)
fun injectSWFragment(swFragment: SWFragment) fun injectSWFragment(swFragment: SWFragment)
fun injectSSWHtmlLink(swHtmlLink: SWHtmlLink) fun injectSSWHtmlLink(swHtmlLink: SWHtmlLink)

View file

@ -246,6 +246,7 @@ open class AppModule {
@ContributesAndroidInjector fun swButtonInjector(): SWButton @ContributesAndroidInjector fun swButtonInjector(): SWButton
@ContributesAndroidInjector fun swEditNumberWithUnitsInjector(): SWEditNumberWithUnits @ContributesAndroidInjector fun swEditNumberWithUnitsInjector(): SWEditNumberWithUnits
@ContributesAndroidInjector fun swEditStringInjector(): SWEditString @ContributesAndroidInjector fun swEditStringInjector(): SWEditString
@ContributesAndroidInjector fun swEditEncryptedPasswordInjector(): SWEditEncryptedPassword
@ContributesAndroidInjector fun swEditUrlInjector(): SWEditUrl @ContributesAndroidInjector fun swEditUrlInjector(): SWEditUrl
@ContributesAndroidInjector fun swFragmentInjector(): SWFragment @ContributesAndroidInjector fun swFragmentInjector(): SWFragment
@ContributesAndroidInjector fun swHtmlLinkInjector(): SWHtmlLink @ContributesAndroidInjector fun swHtmlLinkInjector(): SWHtmlLink

View file

@ -15,5 +15,6 @@ abstract class ReceiversModule {
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver @ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
@ContributesAndroidInjector abstract fun contributesNetworkChangeReceiver(): NetworkChangeReceiver @ContributesAndroidInjector abstract fun contributesNetworkChangeReceiver(): NetworkChangeReceiver
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver @ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver @ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
} }

View file

@ -382,6 +382,7 @@ public class LoopPlugin extends PluginBase {
if (lastRun == null) lastRun = new LastRun(); if (lastRun == null) lastRun = new LastRun();
lastRun.request = result; lastRun.request = result;
lastRun.constraintsProcessed = resultAfterConstraints; lastRun.constraintsProcessed = resultAfterConstraints;
lastRun.lastAPSRun = DateUtil.now();
lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.source = ((PluginBase) usedAPS).getName();
lastRun.tbrSetByPump = null; lastRun.tbrSetByPump = null;
lastRun.smbSetByPump = null; lastRun.smbSetByPump = null;

View file

@ -165,7 +165,7 @@ public class NSUpload {
Profile profile = profileFunction.getProfile(); Profile profile = profileFunction.getProfile();
String profileName = profileFunction.getProfileName(); String profileName = profileFunction.getProfileName();
if (profile == null || profileName == null) { if (profile == null) {
log.error("Profile is null. Skipping upload"); log.error("Profile is null. Skipping upload");
return; return;
} }

View file

@ -755,6 +755,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// ****** GRAPH ******* // ****** GRAPH *******
GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) {
overview_bggraph?: return@launch
val graphData = GraphData(injector, overview_bggraph, iobCobCalculatorPlugin) val graphData = GraphData(injector, overview_bggraph, iobCobCalculatorPlugin)
val secondaryGraphsData: ArrayList<GraphData> = ArrayList() val secondaryGraphsData: ArrayList<GraphData> = ArrayList()

View file

@ -29,7 +29,7 @@ class NetworkChangeReceiver : DaggerBroadcastReceiver() {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networks: Array<Network> = cm.allNetworks val networks: Array<Network> = cm.allNetworks
networks.forEach { networks.forEach {
val capabilities = cm.getNetworkCapabilities(it) val capabilities = cm.getNetworkCapabilities(it) ?: return@forEach
event.wifiConnected = event.wifiConnected || (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) event.wifiConnected = event.wifiConnected || (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
event.mobileConnected = event.mobileConnected || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) event.mobileConnected = event.mobileConnected || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)

View file

@ -33,6 +33,7 @@ import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.setupwizard.elements.* import info.nightscout.androidaps.setupwizard.elements.*
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.AndroidPermission import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.CryptoUtil
import info.nightscout.androidaps.utils.LocaleHelper.update import info.nightscout.androidaps.utils.LocaleHelper.update
import info.nightscout.androidaps.utils.extensions.isRunningTest import info.nightscout.androidaps.utils.extensions.isRunningTest
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
@ -60,7 +61,8 @@ class SWDefinition @Inject constructor(
private val nsProfilePlugin: NSProfilePlugin, private val nsProfilePlugin: NSProfilePlugin,
private val protectionCheck: ProtectionCheck, private val protectionCheck: ProtectionCheck,
private val importExportPrefs: ImportExportPrefs, private val importExportPrefs: ImportExportPrefs,
private val androidPermission: AndroidPermission private val androidPermission: AndroidPermission,
private val cryptoUtil: CryptoUtil
) { ) {
lateinit var activity: AppCompatActivity lateinit var activity: AppCompatActivity
@ -203,9 +205,18 @@ class SWDefinition @Inject constructor(
.add(SWInfotext(injector) .add(SWInfotext(injector)
.label(R.string.patient_name_summary)) .label(R.string.patient_name_summary))
.add(SWEditString(injector) .add(SWEditString(injector)
.validator(SWTextValidator { text: String -> text.length > 0 }) .validator(SWTextValidator(String::isNotEmpty))
.preferenceId(R.string.key_patient_name) .preferenceId(R.string.key_patient_name))
.updateDelay(5)) private val screenMasterPassword = SWScreen(injector, R.string.master_password)
.skippable(false)
.add(SWInfotext(injector)
.label(R.string.master_password))
.add(SWEditEncryptedPassword(injector, cryptoUtil)
.preferenceId(R.string.key_master_password))
.add(SWBreak(injector))
.add(SWInfotext(injector)
.label(R.string.master_password_summary))
.validator(SWValidator { !cryptoUtil.checkPassword("", sp.getString(R.string.key_master_password, "")) })
private val screenAge = SWScreen(injector, R.string.patientage) private val screenAge = SWScreen(injector, R.string.patientage)
.skippable(false) .skippable(false)
.add(SWBreak(injector)) .add(SWBreak(injector))
@ -393,6 +404,7 @@ class SWDefinition @Inject constructor(
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionBt) .add(screenPermissionBt)
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword)
.add(screenImport) .add(screenImport)
.add(screenUnits) .add(screenUnits)
.add(displaySettings) .add(displaySettings)
@ -420,6 +432,7 @@ class SWDefinition @Inject constructor(
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionBt) .add(screenPermissionBt)
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword)
.add(screenImport) .add(screenImport)
.add(screenUnits) .add(screenUnits)
.add(displaySettings) .add(displaySettings)
@ -442,6 +455,7 @@ class SWDefinition @Inject constructor(
.add(screenEula) .add(screenEula)
.add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization .add(if (isRunningTest()) null else screenPermissionBattery) // cannot mock ask battery optimization
.add(screenPermissionStore) .add(screenPermissionStore)
.add(screenMasterPassword)
.add(screenImport) .add(screenImport)
.add(screenUnits) .add(screenUnits)
.add(displaySettings) .add(displaySettings)

View file

@ -0,0 +1,82 @@
package info.nightscout.androidaps.setupwizard.elements
import android.graphics.Typeface
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.view.View
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.setupwizard.SWTextValidator
import info.nightscout.androidaps.utils.CryptoUtil
class SWEditEncryptedPassword(injector: HasAndroidInjector, private val cryptoUtil: CryptoUtil) : SWItem(injector, Type.STRING) {
private var validator: SWTextValidator = SWTextValidator(String::isNotEmpty)
private var updateDelay = 0L
override fun generateDialog(layout: LinearLayout) {
val context = layout.context
val l = TextView(context)
l.id = View.generateViewId()
label?.let { l.setText(it) }
l.setTypeface(l.typeface, Typeface.BOLD)
layout.addView(l)
val c = TextView(context)
c.id = View.generateViewId()
comment?.let { c.setText(it) }
c.setTypeface(c.typeface, Typeface.ITALIC)
layout.addView(c)
val editText = EditText(context)
editText.id = View.generateViewId()
editText.inputType = InputType.TYPE_CLASS_TEXT
editText.maxLines = 1
editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
layout.addView(editText)
val c2 = TextView(context)
c2.id = View.generateViewId()
c2.setText(R.string.confirm)
layout.addView(c2)
val editText2 = EditText(context)
editText2.id = View.generateViewId()
editText2.inputType = InputType.TYPE_CLASS_TEXT
editText2.maxLines = 1
editText2.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
layout.addView(editText2)
super.generateDialog(layout)
val watcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
sp.remove(preferenceId)
scheduleChange(updateDelay)
if (validator.isValid(editText.text.toString()) && validator.isValid(editText2.text.toString()) && editText.text.toString() == editText2.text.toString())
save(s.toString(), updateDelay)
}
override fun afterTextChanged(s: Editable) {}
}
editText.addTextChangedListener(watcher)
editText2.addTextChangedListener(watcher)
}
fun preferenceId(preferenceId: Int): SWEditEncryptedPassword {
this.preferenceId = preferenceId
return this
}
fun validator(validator: SWTextValidator): SWEditEncryptedPassword {
this.validator = validator
return this
}
override fun save(value: String, updateDelay: Long) {
sp.putString(preferenceId, cryptoUtil.hashPassword(value))
scheduleChange(updateDelay)
}
}

View file

@ -10,6 +10,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -20,7 +21,7 @@ open class SWItem(val injector: HasAndroidInjector, var type: Type) {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var sp: info.nightscout.androidaps.utils.sharedPreferences.SP @Inject lateinit var sp: SP
private val eventWorker = Executors.newSingleThreadScheduledExecutor() private val eventWorker = Executors.newSingleThreadScheduledExecutor()
private var scheduledEventPost: ScheduledFuture<*>? = null private var scheduledEventPost: ScheduledFuture<*>? = null
@ -55,7 +56,7 @@ open class SWItem(val injector: HasAndroidInjector, var type: Type) {
return this return this
} }
fun save(value: String, updateDelay: Long) { open fun save(value: String, updateDelay: Long) {
sp.putString(preferenceId, value) sp.putString(preferenceId, value)
scheduleChange(updateDelay) scheduleChange(updateDelay)
} }
@ -69,7 +70,7 @@ open class SWItem(val injector: HasAndroidInjector, var type: Type) {
open fun generateDialog(layout: LinearLayout) {} open fun generateDialog(layout: LinearLayout) {}
open fun processVisibility() {} open fun processVisibility() {}
private fun scheduleChange(updateDelay: Long) { fun scheduleChange(updateDelay: Long) {
class PostRunnable : Runnable { class PostRunnable : Runnable {
override fun run() { override fun run() {
aapsLogger.debug(LTag.CORE, "Firing EventPreferenceChange") aapsLogger.debug(LTag.CORE, "Firing EventPreferenceChange")

View file

@ -5,10 +5,11 @@ import androidx.biometric.BiometricPrompt
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.ToastUtils import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.extensions.runOnUiThread
import java.util.concurrent.Executors import java.util.concurrent.Executors
object BiometricCheck { object BiometricCheck {
fun biometricPrompt(activity: FragmentActivity, title: Int, ok: Runnable?, cancel: Runnable? = null, fail: Runnable? = null) { fun biometricPrompt(activity: FragmentActivity, title: Int, ok: Runnable?, cancel: Runnable? = null, fail: Runnable? = null, passwordCheck: PasswordCheck) {
val executor = Executors.newSingleThreadExecutor() val executor = Executors.newSingleThreadExecutor()
val biometricPrompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() { val biometricPrompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() {
@ -23,24 +24,31 @@ object BiometricCheck {
BiometricConstants.ERROR_LOCKOUT_PERMANENT, BiometricConstants.ERROR_LOCKOUT_PERMANENT,
BiometricConstants.ERROR_USER_CANCELED -> { BiometricConstants.ERROR_USER_CANCELED -> {
ToastUtils.showToastInUiThread(activity.baseContext, errString.toString()) ToastUtils.showToastInUiThread(activity.baseContext, errString.toString())
fail?.run() // fallback to master password
runOnUiThread(Runnable {
passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() })
})
} }
BiometricConstants.ERROR_NEGATIVE_BUTTON -> BiometricConstants.ERROR_NEGATIVE_BUTTON ->
cancel?.run() cancel?.run()
BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL -> BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL -> {
// call ok, because it's not possible to bypass it when biometrics is setup, hw not present and no pin set ToastUtils.showToastInUiThread(activity.baseContext, errString.toString())
ok?.run() // no pin set
// fallback to master password
runOnUiThread(Runnable {
passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() })
})
}
BiometricConstants.ERROR_NO_SPACE, BiometricConstants.ERROR_NO_SPACE,
BiometricConstants.ERROR_HW_UNAVAILABLE, BiometricConstants.ERROR_HW_UNAVAILABLE,
BiometricConstants.ERROR_HW_NOT_PRESENT, BiometricConstants.ERROR_HW_NOT_PRESENT,
BiometricConstants.ERROR_NO_BIOMETRICS -> BiometricConstants.ERROR_NO_BIOMETRICS ->
// call ok, because it's not possible to bypass it when biometrics fail runOnUiThread(Runnable {
// ok?.run() passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() })
// changed to fail as you can use PIN instead with setDeviceCredentialAllowed enabled })
fail?.run()
} }
} }
@ -60,8 +68,8 @@ object BiometricCheck {
val promptInfo = BiometricPrompt.PromptInfo.Builder() val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(activity.getString(title)) .setTitle(activity.getString(title))
.setDescription(activity.getString(R.string.biometric_title)) .setDescription(activity.getString(R.string.biometric_title))
// .setNegativeButtonText(activity.getString(R.string.cancel)) // not possible with setDeviceCredentialAllowed .setNegativeButtonText(activity.getString(R.string.cancel)) // not possible with setDeviceCredentialAllowed
.setDeviceCredentialAllowed(true) // .setDeviceCredentialAllowed(true) // setDeviceCredentialAllowed creates new activity when PIN is requested, activity.fragmentManager crash afterwards
.build() .build()
biometricPrompt.authenticate(promptInfo) biometricPrompt.authenticate(promptInfo)

View file

@ -16,12 +16,12 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
// since androidx.autofill.HintConstants are not available // since androidx.autofill.HintConstants are not available
val AUTOFILL_HINT_NEW_PASSWORD = "newPassword" const val AUTOFILL_HINT_NEW_PASSWORD = "newPassword"
@Singleton @Singleton
class PasswordCheck @Inject constructor( class PasswordCheck @Inject constructor(
val sp: SP, val sp: SP,
val cryptoUtil: CryptoUtil private val cryptoUtil: CryptoUtil
) { ) {
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
@ -36,7 +36,11 @@ class PasswordCheck @Inject constructor(
val alertDialogBuilder = AlertDialogHelper.Builder(context) val alertDialogBuilder = AlertDialogHelper.Builder(context)
alertDialogBuilder.setView(promptsView) alertDialogBuilder.setView(promptsView)
val userInput = promptsView.findViewById<View>(R.id.passwordprompt_pass) as EditText val userInput = promptsView.findViewById<View>(R.id.password_prompt_pass) as EditText
val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText
userInput2.visibility = View.GONE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val autoFillHintPasswordKind = context.getString(preference) val autoFillHintPasswordKind = context.getString(preference)
userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}") userInput.setAutofillHints(View.AUTOFILL_HINT_PASSWORD, "aaps_${autoFillHintPasswordKind}")
@ -69,7 +73,8 @@ class PasswordCheck @Inject constructor(
val alertDialogBuilder = AlertDialogHelper.Builder(context) val alertDialogBuilder = AlertDialogHelper.Builder(context)
alertDialogBuilder.setView(promptsView) alertDialogBuilder.setView(promptsView)
val userInput = promptsView.findViewById<View>(R.id.passwordprompt_pass) as EditText val userInput = promptsView.findViewById<View>(R.id.password_prompt_pass) as EditText
val userInput2 = promptsView.findViewById<View>(R.id.password_prompt_pass_confirm) as EditText
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val autoFillHintPasswordKind = context.getString(preference) val autoFillHintPasswordKind = context.getString(preference)
@ -82,7 +87,10 @@ class PasswordCheck @Inject constructor(
.setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key)) .setCustomTitle(AlertDialogHelper.buildCustomTitle(context, context.getString(labelId), R.drawable.ic_header_key))
.setPositiveButton(context.getString(R.string.ok)) { _, _ -> .setPositiveButton(context.getString(R.string.ok)) { _, _ ->
val enteredPassword = userInput.text.toString() val enteredPassword = userInput.text.toString()
if (enteredPassword.isNotEmpty()) { val enteredPassword2 = userInput2.text.toString()
if (enteredPassword != enteredPassword2) {
ToastUtils.errorToast(context, context.getString(R.string.passwords_dont_match))
} else if (enteredPassword.isNotEmpty()) {
sp.putString(preference, cryptoUtil.hashPassword(enteredPassword)) sp.putString(preference, cryptoUtil.hashPassword(enteredPassword))
ToastUtils.okToast(context, context.getString(R.string.password_set)) ToastUtils.okToast(context, context.getString(R.string.password_set))
ok?.invoke(enteredPassword) ok?.invoke(enteredPassword)

View file

@ -56,7 +56,7 @@ class ProtectionCheck @Inject constructor(
ProtectionType.NONE -> ProtectionType.NONE ->
ok?.run() ok?.run()
ProtectionType.BIOMETRIC -> ProtectionType.BIOMETRIC ->
BiometricCheck.biometricPrompt(activity, titleResourceIDs[protection.ordinal], ok, cancel, fail) BiometricCheck.biometricPrompt(activity, titleResourceIDs[protection.ordinal], ok, cancel, fail, passwordCheck)
ProtectionType.MASTER_PASSWORD -> ProtectionType.MASTER_PASSWORD ->
passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() }) passwordCheck.queryPassword(activity, R.string.master_password, R.string.key_master_password, { ok?.run() }, { cancel?.run() }, { fail?.run() })
ProtectionType.CUSTOM_PASSWORD -> ProtectionType.CUSTOM_PASSWORD ->

View file

@ -6,15 +6,20 @@
android:padding="10dp"> android:padding="10dp">
<EditText <EditText
android:id="@+id/passwordprompt_pass" android:id="@+id/password_prompt_pass"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/password_hint" android:hint="@string/password_hint"
android:inputType="textPassword" android:inputType="textPassword">
>
<requestFocus /> <requestFocus />
</EditText> </EditText>
<EditText
android:id="@+id/password_prompt_pass_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password_hint"
android:inputType="textPassword"/>
</LinearLayout> </LinearLayout>

View file

@ -34,7 +34,7 @@
<string name="objectives_smb_objective">Enabling additional features for daytime use, such as SMB</string> <string name="objectives_smb_objective">Enabling additional features for daytime use, such as SMB</string>
<string name="objectives_auto_objective">Enabling automation</string> <string name="objectives_auto_objective">Enabling automation</string>
<string name="objectives_smb_gate">You must read the wiki and rise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal</string> <string name="objectives_smb_gate">You must read the wiki and rise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal</string>
<string name="objectives_auto_gate">Read the wiki how automation works. Setup your first simple rules. Instead of action let AAPS display only notification. When you are sure automation is triggered at the right time replace notification by real action.</string> <string name="objectives_auto_gate">Read the docs how automation works. Setup your first simple rules. Instead of action let AAPS display only notification. When you are sure automation is triggered at the right time replace notification by real action. (https://androidaps.readthedocs.io/en/latest/EN/Usage/Automation.html)</string>
<string name="objectives_bgavailableinns">BG available in NS</string> <string name="objectives_bgavailableinns">BG available in NS</string>
<string name="objectives_pumpstatusavailableinns">Pump status available in NS</string> <string name="objectives_pumpstatusavailableinns">Pump status available in NS</string>
<string name="objectives_manualenacts">Manual enacts</string> <string name="objectives_manualenacts">Manual enacts</string>

View file

@ -1805,4 +1805,7 @@
<string name="key_graphconfig" translatable="false">graphconfig</string> <string name="key_graphconfig" translatable="false">graphconfig</string>
<string name="authorizationfailed">Authorization failed</string> <string name="authorizationfailed">Authorization failed</string>
<string name="overview_show_absinsulin">Absolute insulin</string> <string name="overview_show_absinsulin">Absolute insulin</string>
<string name="master_password_summary">Master password is used for backup encryption and to override security in application. Remember it or store on a safe place.</string>
<string name="passwords_dont_match">Passwords don\'t match</string>
<string name="current_master_password">Current master password</string>
</resources> </resources>