GitNex-Android-App/app/src/main/java/org/mian/gitnex/activities/SettingsSecurityActivity.java

280 lines
9.8 KiB
Java
Raw Normal View History

package org.mian.gitnex.activities;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.Bundle;
import androidx.biometric.BiometricManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsSecurityBinding;
import org.mian.gitnex.helpers.AppDatabaseSettings;
Don't use TinyDB as cache (#1034) Do not use TinyDB as a cache or a way to send data between activities. ### How is this working Instead of saving everything into the TinyDB, I created three `Context`s (a `RepositoryContext`, an `IssueContext` and an `AccountContext`). All are used to store things like API or database values/models and additional data, e.g. the `RepositoryContext` also contains information about the current filter state of a repository (issues, pull requests, releases/tags and milestones). These are sent using `Intent`s and `Bundle`s between activities and fragments. Changing a field (e.g. filter state) in any fragment changes it also for the whole repository (or at least it should do so). Due to the size of the changes (after https://codeberg.org/gitnex/GitNex/commit/c9172f85efafd9f25739fdd8385e1904b711ea41, Git says `154 files changed, 3318 insertions(+), 3835 deletions(-)`) **I highly recommend you to create a beta/pre release before releasing a stable version**. Additional changes: * after logging out, the account remains in the account list (with a note) and you can log in again (you can't switch to this account) * repositories and organizations are clickable on user profiles * deleted two unused classes Once finished, hopefully * closes #354 * replaces #897 * fixes #947 * closes #1001 * closes #1015 * marks #876 and #578 as `Wontfix` since they are not necessary at this point * and all the other TinyDB issues Co-authored-by: qwerty287 <ndev@web.de> Co-authored-by: M M Arif <mmarif@noreply.codeberg.org> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1034 Reviewed-by: 6543 <6543@noreply.codeberg.org> Co-authored-by: qwerty287 <qwerty287@noreply.codeberg.org> Co-committed-by: qwerty287 <qwerty287@noreply.codeberg.org>
2022-03-13 03:59:13 +01:00
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.SnackBar;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
/**
* @author M M Arif
*/
public class SettingsSecurityActivity extends BaseActivity {
private static String[] cacheSizeDataList;
private static int cacheSizeDataSelectedChoice;
private static String[] cacheSizeImagesList;
private static int cacheSizeImagesSelectedChoice;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivitySettingsSecurityBinding activitySettingsSecurityBinding =
ActivitySettingsSecurityBinding.inflate(getLayoutInflater());
setContentView(activitySettingsSecurityBinding.getRoot());
activitySettingsSecurityBinding.topAppBar.setNavigationOnClickListener(v -> finish());
cacheSizeDataList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeImagesList = getResources().getStringArray(R.array.cacheSizeList);
cacheSizeDataSelectedChoice =
Integer.parseInt(
AppDatabaseSettings.getSettingsValue(
ctx, AppDatabaseSettings.APP_DATA_CACHE_KEY));
cacheSizeImagesSelectedChoice =
Integer.parseInt(
AppDatabaseSettings.getSettingsValue(
ctx, AppDatabaseSettings.APP_IMAGES_CACHE_KEY));
activitySettingsSecurityBinding.cacheSizeDataSelected.setText(
cacheSizeDataList[cacheSizeDataSelectedChoice]);
activitySettingsSecurityBinding.cacheSizeImagesSelected.setText(
cacheSizeImagesList[cacheSizeImagesSelectedChoice]);
activitySettingsSecurityBinding.switchBiometric.setChecked(
Boolean.parseBoolean(
AppDatabaseSettings.getSettingsValue(
ctx, AppDatabaseSettings.APP_BIOMETRIC_KEY)));
// biometric switcher
activitySettingsSecurityBinding.switchBiometric.setOnCheckedChangeListener(
(buttonView, isChecked) -> {
if (isChecked) {
BiometricManager biometricManager = BiometricManager.from(ctx);
KeyguardManager keyguardManager =
(KeyguardManager) ctx.getSystemService(Context.KEYGUARD_SERVICE);
if (!keyguardManager.isDeviceSecure()) {
switch (biometricManager.canAuthenticate(
BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
case BiometricManager.BIOMETRIC_SUCCESS:
AppDatabaseSettings.updateSettingsValue(
ctx, "true", AppDatabaseSettings.APP_BIOMETRIC_KEY);
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
break;
case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
case BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
case BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED:
case BiometricManager.BIOMETRIC_STATUS_UNKNOWN:
AppDatabaseSettings.updateSettingsValue(
ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.biometricNotSupported));
break;
case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
AppDatabaseSettings.updateSettingsValue(
ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
SnackBar.error(
ctx,
findViewById(android.R.id.content),
getString(R.string.biometricNotAvailable));
break;
case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
AppDatabaseSettings.updateSettingsValue(
ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY);
activitySettingsSecurityBinding.switchBiometric.setChecked(
false);
SnackBar.info(
ctx,
findViewById(android.R.id.content),
getString(R.string.enrollBiometric));
break;
}
} else {
AppDatabaseSettings.updateSettingsValue(
ctx, "true", AppDatabaseSettings.APP_BIOMETRIC_KEY);
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
}
} else {
AppDatabaseSettings.updateSettingsValue(
ctx, "false", AppDatabaseSettings.APP_BIOMETRIC_KEY);
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
}
});
activitySettingsSecurityBinding.biometricFrame.setOnClickListener(
v ->
activitySettingsSecurityBinding.switchBiometric.setChecked(
!activitySettingsSecurityBinding.switchBiometric.isChecked()));
// clear cache setter
File cacheDir = appCtx.getCacheDir();
activitySettingsSecurityBinding.clearCacheSelected.setText(
FileUtils.byteCountToDisplaySize((int) FileUtils.sizeOfDirectory(cacheDir)));
// clear cache
activitySettingsSecurityBinding.clearCacheSelectionFrame.setOnClickListener(
v1 -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
.setTitle(R.string.clearCacheDialogHeader)
.setMessage(
getResources()
.getString(R.string.clearCacheDialogMessage))
.setNeutralButton(
R.string.cancelButton,
(dialog, which) -> dialog.dismiss())
.setPositiveButton(
R.string.menuDeleteText,
(dialog, which) -> {
try {
FileUtils.deleteDirectory(cacheDir);
FileUtils.forceMkdir(cacheDir);
this.recreate();
this.overridePendingTransition(0, 0);
} catch (IOException e) {
// Log.e("SettingsSecurity", e.toString());
}
});
materialAlertDialogBuilder.create().show();
});
// cache size images selection dialog
activitySettingsSecurityBinding.cacheSizeImagesSelectionFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
.setTitle(R.string.cacheSizeImagesDialogHeader)
.setCancelable(cacheSizeImagesSelectedChoice != -1)
.setSingleChoiceItems(
cacheSizeImagesList,
cacheSizeImagesSelectedChoice,
(dialogInterfaceTheme, i) -> {
cacheSizeImagesSelectedChoice = i;
activitySettingsSecurityBinding
.cacheSizeImagesSelected.setText(
cacheSizeImagesList[i]);
AppDatabaseSettings.updateSettingsValue(
ctx,
cacheSizeImagesList[i],
AppDatabaseSettings
.APP_IMAGES_CACHE_SIZE_KEY);
AppDatabaseSettings.updateSettingsValue(
ctx,
String.valueOf(i),
AppDatabaseSettings.APP_IMAGES_CACHE_KEY);
dialogInterfaceTheme.dismiss();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
// cache size data selection dialog
activitySettingsSecurityBinding.cacheSizeDataSelectionFrame.setOnClickListener(
view -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
.setTitle(R.string.cacheSizeDataDialogHeader)
.setCancelable(cacheSizeDataSelectedChoice != -1)
.setSingleChoiceItems(
cacheSizeDataList,
cacheSizeDataSelectedChoice,
(dialogInterfaceTheme, i) -> {
cacheSizeDataSelectedChoice = i;
activitySettingsSecurityBinding
.cacheSizeDataSelected.setText(
cacheSizeDataList[i]);
AppDatabaseSettings.updateSettingsValue(
ctx,
cacheSizeDataList[i],
AppDatabaseSettings
.APP_DATA_CACHE_SIZE_KEY);
AppDatabaseSettings.updateSettingsValue(
ctx,
String.valueOf(i),
AppDatabaseSettings.APP_DATA_CACHE_KEY);
dialogInterfaceTheme.dismiss();
SnackBar.success(
ctx,
findViewById(android.R.id.content),
getString(R.string.settingsSave));
});
materialAlertDialogBuilder.create().show();
});
// certs deletion
activitySettingsSecurityBinding.certsFrame.setOnClickListener(
v1 -> {
MaterialAlertDialogBuilder materialAlertDialogBuilder =
new MaterialAlertDialogBuilder(ctx)
.setTitle(R.string.settingsCertsPopupTitle)
.setMessage(
getResources()
.getString(R.string.settingsCertsPopupMessage))
.setNeutralButton(
R.string.cancelButton,
(dialog, which) -> dialog.dismiss())
.setPositiveButton(
R.string.menuDeleteText,
(dialog, which) -> {
appCtx.getSharedPreferences(
MemorizingTrustManager
.KEYSTORE_NAME,
Context.MODE_PRIVATE)
.edit()
.remove(MemorizingTrustManager.KEYSTORE_KEY)
.apply();
AppUtil.logout(this);
});
materialAlertDialogBuilder.create().show();
});
}
}