diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt index 7f7bdb2a..c72b9aa9 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt @@ -24,9 +24,7 @@ open class LandingActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val authenticationType = authenticationService.getAuthenticationType() - - if (authenticationType == AuthenticationType.None) { + if (authenticationService.authenticationType == AuthenticationType.None) { launchActivity(MainActivity::class.java) } else { diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt index 779bbf5d..27d84312 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt @@ -2,6 +2,7 @@ package net.dankito.banking.ui.android.activities import android.os.Bundle import android.view.View +import android.widget.Toast import kotlinx.android.synthetic.main.activity_login.* import net.dankito.banking.ui.android.MainActivity import net.dankito.banking.ui.android.R @@ -48,8 +49,11 @@ open class LoginActivity : BaseActivity() { protected open fun checkEnteredPasswordAndLogIn() { - if (authenticationService.isCorrectUserPassword(edtxtLoginPassword.text)) { - logIn() + val enteredPassword = edtxtLoginPassword.text + + if (authenticationService.isCorrectUserPassword(enteredPassword)) { + authenticationService.userLoggedInWithPassword(enteredPassword) + navigateToMainActivity() } else { Toast.makeText(this, R.string.activity_login_incorrect_password_entered, Toast.LENGTH_SHORT).show() @@ -57,10 +61,11 @@ open class LoginActivity : BaseActivity() { } protected open fun biometricAuthenticationSuccessful() { - logIn() + authenticationService.userLoggedInWithBiometricAuthentication() + navigateToMainActivity() } - protected open fun logIn() { + protected open fun navigateToMainActivity() { navigateToActivity(MainActivity::class.java) } diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt index 104570cd..56c7ef7e 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt @@ -1,14 +1,16 @@ package net.dankito.banking.ui.android.authentication +import net.dankito.banking.persistence.IBankingPersistence import net.dankito.banking.util.ISerializer import net.dankito.utils.multiplatform.File import org.slf4j.LoggerFactory open class AuthenticationService( - protected val biometricAuthenticationService: IBiometricAuthenticationService, - protected val dataFolder: File, - protected val serializer: ISerializer + protected open val biometricAuthenticationService: IBiometricAuthenticationService, + protected open val persistence: IBankingPersistence, + protected open val dataFolder: File, + protected open val serializer: ISerializer ) { companion object { @@ -29,11 +31,40 @@ open class AuthenticationService( init { authenticationType = loadAuthenticationType() + + if (authenticationType == AuthenticationType.None) { + val authenticationSettings = loadAuthenticationSettings() + + if (authenticationSettings == null) { // first app run -> create a default password + removeAppProtection() + } + else { + openDatabase(authenticationSettings) + } + } } + open fun userLoggedInWithBiometricAuthentication() { + loadAuthenticationSettings()?.let { + openDatabase(it) + } + } + + open fun userLoggedInWithPassword(enteredPassword: String) { + openDatabase(enteredPassword) + } + + protected open fun openDatabase(authenticationSettings: AuthenticationSettings) { + openDatabase(authenticationSettings.userPassword) + } + + protected open fun openDatabase(password: String?) { + persistence.decryptData(password) + } + open fun setAuthenticationMethodToBiometric() { - if (saveUserPasswordIfChanged(null)) { + if (saveNewUserPassword(generateRandomPassword())) { if (saveAuthenticationType(AuthenticationType.Biometric)) { authenticationType = AuthenticationType.Biometric } @@ -41,7 +72,7 @@ open class AuthenticationService( } open fun setAuthenticationMethodToPassword(newPassword: String) { - if (saveUserPasswordIfChanged(newPassword)) { + if (saveNewUserPassword(newPassword)) { if (saveAuthenticationType(AuthenticationType.Password)) { authenticationType = AuthenticationType.Password } @@ -49,7 +80,7 @@ open class AuthenticationService( } open fun removeAppProtection() { - if (saveUserPasswordIfChanged(null)) { + if (saveNewUserPassword(generateRandomPassword())) { if (saveAuthenticationType(AuthenticationType.None)) { authenticationType = AuthenticationType.None } @@ -103,16 +134,22 @@ open class AuthenticationService( } - protected open fun saveUserPasswordIfChanged(userPassword: String?): Boolean { + protected open fun saveNewUserPassword(newPassword: String?): Boolean { val settings = loadOrCreateDefaultAuthenticationSettings() + val currentPassword = settings.userPassword - if (settings.userPassword != userPassword) { - settings.userPassword = userPassword + if (currentPassword != newPassword) { + settings.userPassword = newPassword - return saveAuthenticationSettings(settings) + if (saveAuthenticationSettings(settings)) { + persistence.changePassword(currentPassword, newPassword) // TODO: actually this is bad. If changing password fails then password is saved in AuthenticationSettings but DB has a different password + return true + } + + return false } - return false + return true } protected open fun loadOrCreateDefaultAuthenticationSettings(): AuthenticationSettings { @@ -151,4 +188,20 @@ open class AuthenticationService( return false } + + open fun generateRandomPassword(): String { + return generateRandomPassword(30) + } + + open fun generateRandomPassword(passwordLength: Int): String { + val dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789§±!@#$%^&*-_=+;:|/?.>,<" + + val passwordBuilder = StringBuilder() + IntRange(0, passwordLength).forEach { + passwordBuilder.append(dictionary.random()) + } + + return passwordBuilder.toString() + } + } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt new file mode 100644 index 00000000..a3feb220 --- /dev/null +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt @@ -0,0 +1,6 @@ +package net.dankito.banking.ui.android.authentication + + +open class AuthenticationSettings( + var userPassword: String? = null +) \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt index ae316795..578613a1 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt @@ -1,12 +1,12 @@ package net.dankito.banking.ui.android.authentication -enum class AuthenticationType { +enum class AuthenticationType(internal val rawValue: Int) { - None, + None(3), - Password, + Password(7), - Biometric + Biometric(9) } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt index fe0c739b..46ba6ecb 100644 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt +++ b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt @@ -89,8 +89,9 @@ class BankingModule(private val applicationContext: Context) { @Provides @Singleton - fun provideAuthenticationService(biometricAuthenticationService: IBiometricAuthenticationService, @Named(DataFolderKey) dataFolder: File, serializer: ISerializer) : AuthenticationService { - return AuthenticationService(biometricAuthenticationService, dataFolder, serializer) + fun provideAuthenticationService(biometricAuthenticationService: IBiometricAuthenticationService, persistence: IBankingPersistence, + @Named(DataFolderKey) dataFolder: File, serializer: ISerializer) : AuthenticationService { + return AuthenticationService(biometricAuthenticationService, persistence, dataFolder, serializer) } @Provides