diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8565c30..c77a086 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ = emptyList() var fullName: String = "" diff --git a/app/src/main/java/sh/sar/basedbank/LockActivity.kt b/app/src/main/java/sh/sar/basedbank/LockActivity.kt index 481ee8d..8c7e01c 100644 --- a/app/src/main/java/sh/sar/basedbank/LockActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/LockActivity.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.withContext import sh.sar.basedbank.databinding.ActivityLockBinding import sh.sar.basedbank.ui.home.HomeActivity import sh.sar.basedbank.util.CredentialStore +import sh.sar.basedbank.BasedBankApp import javax.crypto.SecretKeyFactory import javax.crypto.spec.PBEKeySpec @@ -259,6 +260,7 @@ class LockActivity : AppCompatActivity() { } private fun proceed() { + (application as BasedBankApp).isUnlocked = true if (intent.getBooleanExtra(EXTRA_RESUME, false)) { finish() } else { diff --git a/app/src/main/java/sh/sar/basedbank/MainActivity.kt b/app/src/main/java/sh/sar/basedbank/MainActivity.kt index 9c1d59a..a2f464a 100644 --- a/app/src/main/java/sh/sar/basedbank/MainActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/MainActivity.kt @@ -7,11 +7,13 @@ import sh.sar.basedbank.ui.home.HomeActivity import sh.sar.basedbank.ui.login.LoginActivity import sh.sar.basedbank.ui.onboarding.OnboardingActivity import sh.sar.basedbank.util.CredentialStore +import sh.sar.basedbank.BasedBankApp class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val prefs = getSharedPreferences("prefs", MODE_PRIVATE) val onboardingDone = prefs.getBoolean("onboarding_done", false) val securitySet = prefs.getString("security_method", null) != null @@ -24,6 +26,11 @@ class MainActivity : AppCompatActivity() { securitySet -> LockActivity::class.java // proceed() → HomeActivity else -> HomeActivity::class.java } + // No lock screen configured — mark as unlocked so HomeActivity's guard passes + if (target == HomeActivity::class.java) { + (application as BasedBankApp).isUnlocked = true + } + startActivity(Intent(this, target)) finish() } diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt index c2191d1..e8fd174 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt @@ -118,6 +118,18 @@ class HomeActivity : AppCompatActivity() { isAppearanceLightStatusBars = isLight isAppearanceLightNavigationBars = isLight } + // Auth guard: HomeActivity must only be reachable after LockActivity or fresh login. + // Using loadSecurityHash() (EncryptedSharedPreferences) instead of plain prefs so + // a rooted device cannot bypass this by editing security_method in plain prefs. + val app = application as BasedBankApp + if (CredentialStore(this).loadSecurityHash() != null && !app.isUnlocked) { + startActivity( + android.content.Intent(this, sh.sar.basedbank.LockActivity::class.java) + ) + finish() + return + } + setSupportActionBar(binding.toolbar) toggle = ActionBarDrawerToggle( @@ -165,7 +177,6 @@ class HomeActivity : AppCompatActivity() { } // Load data - val app = application as BasedBankApp if (app.mibAccounts.isNotEmpty() || app.bmlAccounts.isNotEmpty() || app.fahipayAccounts.isNotEmpty()) { // Came from fresh manual login — accounts ready, rest fetched in background val merged = app.mibAccounts + app.bmlAccounts + app.fahipayAccounts diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/QrScannerActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/home/QrScannerActivity.kt index f8d6475..824c8c8 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/QrScannerActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/QrScannerActivity.kt @@ -37,8 +37,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import sh.sar.basedbank.BasedBankApp import sh.sar.basedbank.R import sh.sar.basedbank.databinding.ActivityQrScannerBinding +import sh.sar.basedbank.util.CredentialStore import java.util.concurrent.Executors class QrScannerActivity : AppCompatActivity() { @@ -95,6 +97,14 @@ class QrScannerActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + if (CredentialStore(this).loadSecurityHash() != null && + !(application as BasedBankApp).isUnlocked) { + startActivity(Intent(this, sh.sar.basedbank.LockActivity::class.java)) + finish() + return + } + WindowCompat.setDecorFitsSystemWindows(window, false) binding = ActivityQrScannerBinding.inflate(layoutInflater) setContentView(binding.root) diff --git a/app/src/main/java/sh/sar/basedbank/ui/login/CredentialsFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/login/CredentialsFragment.kt index 4e3cd5a..42d6398 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/login/CredentialsFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/login/CredentialsFragment.kt @@ -215,6 +215,7 @@ class CredentialsFragment : Fragment() { app.mibSessions[loginId] = flow.lastSession!! app.mibProfilesMap[loginId] = flow.lastProfiles app.mibLoginFlows[loginId] = flow + app.isUnlocked = true val intent = Intent(requireContext(), HomeActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) @@ -364,6 +365,7 @@ class CredentialsFragment : Fragment() { if (hasBusinessProfiles) { Toast.makeText(requireContext(), "Business profiles can be enabled in Settings → Logins", Toast.LENGTH_LONG).show() } + (requireActivity().application as BasedBankApp).isUnlocked = true val intent = Intent(requireContext(), HomeActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) @@ -496,6 +498,7 @@ class CredentialsFragment : Fragment() { app.fahipaySessions[loginId] = session app.fahipayAccounts = app.fahipayAccounts.filter { it.loginTag != loginTag } + listOf(account) app.accounts = app.accounts.filter { it.loginTag != loginTag } + listOf(account) + app.isUnlocked = true val intent = Intent(requireContext(), HomeActivity::class.java) intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) diff --git a/app/src/main/java/sh/sar/basedbank/ui/login/LoginActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/login/LoginActivity.kt index 1ac2926..4eb468e 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/login/LoginActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/login/LoginActivity.kt @@ -1,10 +1,14 @@ package sh.sar.basedbank.ui.login +import android.content.Intent import android.content.res.Configuration import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat +import sh.sar.basedbank.BasedBankApp +import sh.sar.basedbank.LockActivity import sh.sar.basedbank.databinding.ActivityLoginBinding +import sh.sar.basedbank.util.CredentialStore class LoginActivity : AppCompatActivity() { @@ -12,6 +16,16 @@ class LoginActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + // If security is configured and the user hasn't unlocked this session, + // they must authenticate first before being able to add more accounts. + val app = application as BasedBankApp + if (CredentialStore(this).loadSecurityHash() != null && !app.isUnlocked) { + startActivity(Intent(this, LockActivity::class.java)) + finish() + return + } + WindowCompat.setDecorFitsSystemWindows(window, false) binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) diff --git a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt index b8e86e7..b7f9318 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/onboarding/OnboardingActivity.kt @@ -13,9 +13,12 @@ import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayoutMediator +import sh.sar.basedbank.BasedBankApp +import sh.sar.basedbank.LockActivity import sh.sar.basedbank.R import sh.sar.basedbank.databinding.ActivityOnboardingBinding import sh.sar.basedbank.ui.login.LoginActivity +import sh.sar.basedbank.util.CredentialStore class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback { @@ -25,6 +28,15 @@ class OnboardingActivity : AppCompatActivity(), SecuritySetupFragment.Callback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + // If security is already configured, onboarding is complete. Redirect to lock screen + // to prevent overwriting an existing PIN/pattern via direct activity launch. + if (CredentialStore(this).loadSecurityHash() != null) { + startActivity(Intent(this, LockActivity::class.java)) + finish() + return + } + WindowCompat.setDecorFitsSystemWindows(window, false) binding = ActivityOnboardingBinding.inflate(layoutInflater) setContentView(binding.root)