mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-14 14:02:49 +00:00
Add ability to enable PIN keyboard
Review fixes Fix line
This commit is contained in:
parent
57ef52d6ff
commit
0c0e8c0d66
6 changed files with 107 additions and 9 deletions
|
@ -168,6 +168,10 @@ public class Preferences {
|
|||
return _prefs.getString("pref_backups_error", null);
|
||||
}
|
||||
|
||||
public boolean isPinKeyboardEnabled() {
|
||||
return _prefs.getBoolean("pref_pin_keyboard", false);
|
||||
}
|
||||
|
||||
public boolean isTimeSyncWarningEnabled() {
|
||||
return _prefs.getBoolean("pref_warn_time_sync", true);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Intent;
|
|||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -59,6 +60,8 @@ public class AuthActivity extends AegisActivity {
|
|||
private BiometricSlot _bioSlot;
|
||||
private BiometricPrompt _bioPrompt;
|
||||
|
||||
private int _failedUnlockAttempts;
|
||||
|
||||
// the first time this activity is resumed after creation, it's possible to inhibit showing the
|
||||
// biometric prompt by setting 'inhibitBioPrompt' to false through the intent
|
||||
private boolean _inhibitBioPrompt;
|
||||
|
@ -83,6 +86,10 @@ public class AuthActivity extends AegisActivity {
|
|||
return false;
|
||||
});
|
||||
|
||||
if (_prefs.isPinKeyboardEnabled()) {
|
||||
_textPassword.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
|
||||
}
|
||||
|
||||
Intent intent = getIntent();
|
||||
_inhibitBioPrompt = savedInstanceState == null ? !intent.getBooleanExtra("_inhibitBioPrompt", true) : savedInstanceState.getBoolean("_inhibitBioPrompt");
|
||||
_cancelAction = (CancelAction) intent.getSerializableExtra("cancelAction");
|
||||
|
@ -253,6 +260,9 @@ public class AuthActivity extends AegisActivity {
|
|||
}
|
||||
|
||||
public BiometricPrompt showBiometricPrompt() {
|
||||
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(_textPassword.getWindowToken(), 0);
|
||||
|
||||
Cipher cipher;
|
||||
try {
|
||||
cipher = _bioSlot.createDecryptCipher(_bioKey);
|
||||
|
@ -301,6 +311,21 @@ public class AuthActivity extends AegisActivity {
|
|||
finish();
|
||||
}
|
||||
|
||||
private void onInvalidPassword() {
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(AuthActivity.this)
|
||||
.setTitle(getString(R.string.unlock_vault_error))
|
||||
.setMessage(getString(R.string.unlock_vault_error_description))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> selectPassword())
|
||||
.create());
|
||||
|
||||
_failedUnlockAttempts ++;
|
||||
|
||||
if (_failedUnlockAttempts >= 3) {
|
||||
_textPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
private class PasswordDerivationListener implements PasswordSlotDecryptTask.Callback {
|
||||
@Override
|
||||
public void onTaskFinished(PasswordSlotDecryptTask.Result result) {
|
||||
|
@ -316,12 +341,7 @@ public class AuthActivity extends AegisActivity {
|
|||
|
||||
finish(result.getKey(), result.isSlotRepaired());
|
||||
} else {
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(AuthActivity.this)
|
||||
.setTitle(getString(R.string.unlock_vault_error))
|
||||
.setMessage(getString(R.string.unlock_vault_error_description))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> selectPassword())
|
||||
.create());
|
||||
onInvalidPassword();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ public class Dialogs {
|
|||
showSecureDialog(dialog);
|
||||
}
|
||||
|
||||
private static void showTextInputDialog(Context context, @StringRes int titleId, @StringRes int messageId, @StringRes int hintId, TextInputListener listener, boolean isSecret) {
|
||||
private static void showTextInputDialog(Context context, @StringRes int titleId, @StringRes int messageId, @StringRes int hintId, TextInputListener listener, DialogInterface.OnDismissListener dismissListener, boolean isSecret) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.dialog_text_input, null);
|
||||
EditText input = view.findViewById(R.id.text_input);
|
||||
if (isSecret) {
|
||||
|
@ -198,6 +198,11 @@ public class Dialogs {
|
|||
char[] text = EditTextHelper.getEditTextChars(input);
|
||||
listener.onTextInputResult(text);
|
||||
});
|
||||
|
||||
if (dismissListener != null) {
|
||||
builder.setOnDismissListener(dismissListener);
|
||||
}
|
||||
|
||||
if (messageId != 0) {
|
||||
builder.setMessage(messageId);
|
||||
}
|
||||
|
@ -207,7 +212,7 @@ public class Dialogs {
|
|||
}
|
||||
|
||||
private static void showTextInputDialog(Context context, @StringRes int titleId, @StringRes int hintId, TextInputListener listener, boolean isSecret) {
|
||||
showTextInputDialog(context, titleId, 0, hintId, listener, isSecret);
|
||||
showTextInputDialog(context, titleId, 0, hintId, listener, null, isSecret);
|
||||
}
|
||||
|
||||
public static void showTextInputDialog(Context context, @StringRes int titleId, @StringRes int hintId, TextInputListener listener) {
|
||||
|
@ -219,7 +224,11 @@ public class Dialogs {
|
|||
}
|
||||
|
||||
public static void showPasswordInputDialog(Context context, @StringRes int messageId, TextInputListener listener) {
|
||||
showTextInputDialog(context, R.string.set_password, messageId, R.string.password, listener, true);
|
||||
showTextInputDialog(context, R.string.set_password, messageId, R.string.password, listener, null, true);
|
||||
}
|
||||
|
||||
public static void showPasswordInputDialog(Context context, @StringRes int setPasswordMessageId, @StringRes int messageId, TextInputListener listener, DialogInterface.OnDismissListener dismissListener) {
|
||||
showTextInputDialog(context, setPasswordMessageId, messageId, R.string.password, listener, dismissListener, true);
|
||||
}
|
||||
|
||||
public static void showNumberPickerDialog(Activity activity, NumberInputListener listener) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import com.beemdevelopment.aegis.importers.DatabaseImporterException;
|
|||
import com.beemdevelopment.aegis.services.NotificationService;
|
||||
import com.beemdevelopment.aegis.ui.models.ImportEntry;
|
||||
import com.beemdevelopment.aegis.ui.preferences.SwitchPreference;
|
||||
import com.beemdevelopment.aegis.ui.tasks.PasswordSlotDecryptTask;
|
||||
import com.beemdevelopment.aegis.util.UUIDMap;
|
||||
import com.beemdevelopment.aegis.vault.VaultBackupManager;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
|
@ -63,6 +64,8 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import static android.text.TextUtils.isDigitsOnly;
|
||||
|
||||
public class PreferencesFragment extends PreferenceFragmentCompat {
|
||||
// activity request codes
|
||||
private static final int CODE_IMPORT = 0;
|
||||
|
@ -90,6 +93,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
private Preference _slotsPreference;
|
||||
private Preference _groupsPreference;
|
||||
private Preference _passwordReminderPreference;
|
||||
private SwitchPreferenceCompat _pinKeyboardPreference;
|
||||
private SwitchPreferenceCompat _backupsPreference;
|
||||
private Preference _backupsLocationPreference;
|
||||
private Preference _backupsTriggerPreference;
|
||||
|
@ -370,6 +374,32 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
});
|
||||
|
||||
_pinKeyboardPreference = findPreference("pref_pin_keyboard");
|
||||
_pinKeyboardPreference.setOnPreferenceChangeListener((preference, o) -> {
|
||||
if ((boolean)o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Dialogs.showPasswordInputDialog(getActivity(), R.string.set_password_confirm, R.string.pin_keyboard_description, password -> {
|
||||
if (isDigitsOnly(new String(password))) {
|
||||
List<PasswordSlot> slots = _vault.getCredentials().getSlots().findAll(PasswordSlot.class);
|
||||
PasswordSlotDecryptTask.Params params = new PasswordSlotDecryptTask.Params(slots, password);
|
||||
new PasswordSlotDecryptTask(getActivity(), new PasswordConfirmationListener()).execute(params);
|
||||
} else {
|
||||
setPinKeyboardPreference(false);
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.pin_keyboard_error)
|
||||
.setMessage(R.string.pin_keyboard_error_description)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create());
|
||||
}
|
||||
}, dialog -> {
|
||||
setPinKeyboardPreference(false);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
_groupsPreference = findPreference("pref_groups");
|
||||
_groupsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
|
@ -767,6 +797,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
_biometricsPreference.setVisible(encrypted);
|
||||
_slotsPreference.setEnabled(encrypted);
|
||||
_autoLockPreference.setVisible(encrypted);
|
||||
_pinKeyboardPreference.setVisible(encrypted);
|
||||
|
||||
if (encrypted) {
|
||||
SlotList slots = _vault.getCredentials().getSlots();
|
||||
|
@ -810,6 +841,10 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
startActivityForResult(intent, CODE_BACKUPS);
|
||||
}
|
||||
|
||||
private void setPinKeyboardPreference(boolean enable) {
|
||||
_pinKeyboardPreference.setChecked(enable);
|
||||
}
|
||||
|
||||
private class SetPasswordListener implements Dialogs.SlotListener {
|
||||
@Override
|
||||
public void onSlotResult(Slot slot, Cipher cipher) {
|
||||
|
@ -895,4 +930,21 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
Dialogs.showErrorDialog(getContext(), R.string.encryption_set_password_error, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class PasswordConfirmationListener implements PasswordSlotDecryptTask.Callback {
|
||||
@Override
|
||||
public void onTaskFinished(PasswordSlotDecryptTask.Result result) {
|
||||
if (result != null) {
|
||||
setPinKeyboardPreference(true);
|
||||
} else {
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.pin_keyboard_error)
|
||||
.setMessage(R.string.invalid_password)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create());
|
||||
setPinKeyboardPreference(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue