mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Improve biometric lock security and hide it on tv
This commit is contained in:
parent
638cc4fee9
commit
6f1b0d297c
6 changed files with 84 additions and 34 deletions
|
@ -154,7 +154,7 @@ repositories {
|
|||
dependencies {
|
||||
// Testing
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
testImplementation("org.json:json:20231013")
|
||||
testImplementation("org.json:json:20240303")
|
||||
androidTestImplementation("androidx.test:core")
|
||||
implementation("androidx.test.ext:junit-ktx:1.1.5")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
|
@ -163,10 +163,10 @@ dependencies {
|
|||
// Android Core & Lifecycle
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.6")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
|
||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0")
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.6")
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
|
||||
|
||||
// Design & UI
|
||||
implementation("jp.wasabeef:glide-transformations:4.3.0")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.lagradost.cloudstream3
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
@ -62,9 +63,11 @@ import com.lagradost.cloudstream3.APIHolder.apis
|
|||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.initAll
|
||||
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.context
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.activity
|
||||
import com.lagradost.cloudstream3.CommonActivity.loadThemes
|
||||
import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent
|
||||
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||
|
@ -135,6 +138,7 @@ import com.lagradost.cloudstream3.utils.BackupUtils.backup
|
|||
import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.deviceHasPasswordPinLock
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.isAuthEnabled
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.startBiometricAuthentication
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
|
@ -1226,10 +1230,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu
|
|||
changeStatusBarState(isEmulatorSettings())
|
||||
|
||||
/** Biometric stuff for users without accounts **/
|
||||
val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_key), false)
|
||||
val noAccounts = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false) || accounts.count() <= 1
|
||||
|
||||
if (isTruePhone() && authEnabled && noAccounts) {
|
||||
if (isTruePhone() && isAuthEnabled(this) && noAccounts) {
|
||||
if (deviceHasPasswordPinLock(this)) {
|
||||
startBiometricAuthentication(this, R.string.biometric_authentication_title, false)
|
||||
|
||||
|
@ -1787,6 +1790,14 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricAu
|
|||
binding?.navHostFragment?.isInvisible = false
|
||||
}
|
||||
|
||||
override fun onAuthenticationError() {
|
||||
try {
|
||||
finish()
|
||||
}
|
||||
catch (e:Exception) {
|
||||
print(e)
|
||||
}
|
||||
}
|
||||
private var backPressedCallback: OnBackPressedCallback? = null
|
||||
|
||||
private fun attachBackPressedCallback() {
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueP
|
|||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.deviceHasPasswordPinLock
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.isAuthEnabled
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.startBiometricAuthentication
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.accounts
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.selectedKeyIndex
|
||||
|
@ -46,7 +47,6 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet
|
|||
)
|
||||
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val authEnabled = settingsManager.getBoolean(getString(R.string.biometric_key), false)
|
||||
val skipStartup = settingsManager.getBoolean(getString(R.string.skip_startup_account_select_key), false
|
||||
) || accounts.count() <= 1
|
||||
|
||||
|
@ -54,7 +54,7 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet
|
|||
|
||||
fun askBiometricAuth() {
|
||||
|
||||
if (isTruePhone() && authEnabled) {
|
||||
if (isTruePhone() && isAuthEnabled(this)) {
|
||||
if (deviceHasPasswordPinLock(this)) {
|
||||
startBiometricAuthentication(
|
||||
this,
|
||||
|
@ -187,4 +187,8 @@ class AccountSelectActivity : AppCompatActivity(), BiometricAuthenticator.Biomet
|
|||
override fun onAuthenticationSuccess() {
|
||||
Log.i(BiometricAuthenticator.TAG,"Authentication successful in AccountSelectActivity")
|
||||
}
|
||||
|
||||
override fun onAuthenticationError() {
|
||||
finish()
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import androidx.core.view.isVisible
|
|||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
||||
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||
|
@ -30,19 +31,22 @@ import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
|||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTruePhone
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setToolBarScrollFlags
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator
|
||||
import com.lagradost.cloudstream3.utils.BiometricAuthenticator.isAuthEnabled
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialogText
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||
|
||||
class SettingsAccount : PreferenceFragmentCompat() {
|
||||
class SettingsAccount : PreferenceFragmentCompat(),BiometricAuthenticator.BiometricAuthCallback {
|
||||
companion object {
|
||||
/** Used by nginx plugin too */
|
||||
fun showLoginInfo(
|
||||
|
@ -250,6 +254,31 @@ class SettingsAccount : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateAuthPreference(enabled: Boolean) {
|
||||
val biometricKey = getString(R.string.biometric_key)
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(context ?: requireContext()).edit()
|
||||
.putBoolean(biometricKey, enabled).apply()
|
||||
findPreference<SwitchPreferenceCompat>(biometricKey)?.isChecked = enabled
|
||||
}
|
||||
|
||||
override fun onAuthenticationError() {
|
||||
updateAuthPreference(!isAuthEnabled(context ?: requireContext()))
|
||||
}
|
||||
|
||||
override fun onAuthenticationSuccess() {
|
||||
if (isAuthEnabled(context?: return)) {
|
||||
updateAuthPreference(true)
|
||||
BackupUtils.backup(activity)
|
||||
activity?.showBottomDialogText(
|
||||
getString(R.string.biometric_setting),
|
||||
getString(R.string.biometric_warning).html()
|
||||
) { onDialogDismissedEvent }
|
||||
} else {
|
||||
updateAuthPreference(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setUpToolbar(R.string.category_account)
|
||||
|
@ -260,23 +289,27 @@ class SettingsAccount : PreferenceFragmentCompat() {
|
|||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
hideKeyboard()
|
||||
setPreferencesFromResource(R.xml.settings_account, rootKey)
|
||||
// hide preference on tvs and emulators
|
||||
if (!isTruePhone()) {
|
||||
getPref(R.string.biometric_key)?.isVisible = false
|
||||
}
|
||||
|
||||
getPref(R.string.biometric_key)?.setOnPreferenceClickListener {
|
||||
val authEnabled = PreferenceManager.getDefaultSharedPreferences(
|
||||
context ?: return@setOnPreferenceClickListener false
|
||||
)
|
||||
.getBoolean(getString(R.string.biometric_key), false)
|
||||
val ctx = context ?: return@setOnPreferenceClickListener false
|
||||
|
||||
if (authEnabled) {
|
||||
BackupUtils.backup(activity)
|
||||
val title = activity?.getString(R.string.biometric_setting)
|
||||
val warning = activity?.getString(R.string.biometric_warning)
|
||||
activity?.showBottomDialogText(
|
||||
title as String,
|
||||
warning.html()
|
||||
) { onDialogDismissedEvent }
|
||||
if (BiometricAuthenticator.deviceHasPasswordPinLock(ctx)) {
|
||||
BiometricAuthenticator.startBiometricAuthentication(
|
||||
activity?: requireActivity(),
|
||||
R.string.biometric_authentication_title,
|
||||
false
|
||||
)
|
||||
BiometricAuthenticator.promptInfo?.let {
|
||||
BiometricAuthenticator.authCallback = this
|
||||
BiometricAuthenticator.biometricPrompt?.authenticate(it)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
val syncApis =
|
||||
|
|
|
@ -12,7 +12,9 @@ import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
|
|||
import androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.getString
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.R
|
||||
|
||||
|
@ -21,7 +23,6 @@ object BiometricAuthenticator {
|
|||
private const val MAX_FAILED_ATTEMPTS = 3
|
||||
private var failedAttempts = 0
|
||||
const val TAG = "cs3Auth"
|
||||
|
||||
private var biometricManager: BiometricManager? = null
|
||||
var biometricPrompt: BiometricPrompt? = null
|
||||
var promptInfo: BiometricPrompt.PromptInfo? = null
|
||||
|
@ -42,15 +43,8 @@ object BiometricAuthenticator {
|
|||
super.onAuthenticationError(errorCode, errString)
|
||||
showToast("$errString")
|
||||
Log.e(TAG, "$errorCode")
|
||||
failedAttempts++
|
||||
|
||||
if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
|
||||
failedAttempts = 0
|
||||
activity.finish()
|
||||
} else {
|
||||
failedAttempts = 0
|
||||
activity.finish()
|
||||
}
|
||||
authCallback?.onAuthenticationError()
|
||||
//activity.finish()
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||
|
@ -153,7 +147,7 @@ object BiometricAuthenticator {
|
|||
// function to start authentication in any fragment or activity
|
||||
fun startBiometricAuthentication(activity: Activity, title: Int, setDeviceCred: Boolean) {
|
||||
initializeBiometrics(activity)
|
||||
|
||||
authCallback = activity as? BiometricAuthCallback
|
||||
if (isBiometricHardWareAvailable()) {
|
||||
authCallback = activity as? BiometricAuthCallback
|
||||
authenticationDialog(activity, title, setDeviceCred)
|
||||
|
@ -171,7 +165,15 @@ object BiometricAuthenticator {
|
|||
}
|
||||
}
|
||||
|
||||
fun isAuthEnabled(ctx: Context):Boolean {
|
||||
return ctx.let {
|
||||
PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||
.getBoolean(getString(ctx, R.string.biometric_key), false)
|
||||
}
|
||||
}
|
||||
|
||||
interface BiometricAuthCallback {
|
||||
fun onAuthenticationSuccess()
|
||||
fun onAuthenticationError()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@
|
|||
<string name="search">Search</string>
|
||||
<string name="library">Library</string>
|
||||
<string name="category_account">Accounts and Security</string>
|
||||
<string name="category_updates">Updates and backup</string>
|
||||
<string name="category_updates">Updates and Backup</string>
|
||||
<string name="settings_info">Info</string>
|
||||
<string name="advanced_search">Advanced Search</string>
|
||||
<string name="advanced_search_des">Gives you the search results separated by provider</string>
|
||||
|
@ -611,7 +611,7 @@
|
|||
<string name="tracks">Tracks</string>
|
||||
<string name="audio_tracks">Audio tracks</string>
|
||||
<string name="video_tracks">Video tracks</string>
|
||||
<string name="apply_on_restart">Apply on Restart</string>
|
||||
<string name="apply_on_restart">Restart the app to see changes.</string>
|
||||
<string name="restart">Restart</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="safe_mode_title">Safe mode on</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue