auth: lets keep an eye on microG bundle uninstall
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Aurora OSS
|
||||||
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
* SPDX-FileCopyrightText: 2025 The Calyx Institute
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
@@ -8,7 +9,10 @@ package com.aurora.store.compose.navigation
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.activity.compose.LocalActivity
|
import androidx.activity.compose.LocalActivity
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.compose.LifecycleEventEffect
|
||||||
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
||||||
import androidx.navigation.NavDeepLinkBuilder
|
import androidx.navigation.NavDeepLinkBuilder
|
||||||
import androidx.navigation3.runtime.NavKey
|
import androidx.navigation3.runtime.NavKey
|
||||||
@@ -16,6 +20,10 @@ import androidx.navigation3.runtime.entryProvider
|
|||||||
import androidx.navigation3.runtime.rememberNavBackStack
|
import androidx.navigation3.runtime.rememberNavBackStack
|
||||||
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
||||||
import androidx.navigation3.ui.NavDisplay
|
import androidx.navigation3.ui.NavDisplay
|
||||||
|
import com.aurora.Constants.PACKAGE_NAME_GMS
|
||||||
|
import com.aurora.extensions.toast
|
||||||
|
import com.aurora.store.AuroraApp
|
||||||
|
import com.aurora.store.ComposeActivity
|
||||||
import com.aurora.store.MainActivity
|
import com.aurora.store.MainActivity
|
||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.compose.ui.about.AboutScreen
|
import com.aurora.store.compose.ui.about.AboutScreen
|
||||||
@@ -33,6 +41,11 @@ import com.aurora.store.compose.ui.onboarding.OnboardingScreen
|
|||||||
import com.aurora.store.compose.ui.preferences.installation.InstallerScreen
|
import com.aurora.store.compose.ui.preferences.installation.InstallerScreen
|
||||||
import com.aurora.store.compose.ui.search.SearchScreen
|
import com.aurora.store.compose.ui.search.SearchScreen
|
||||||
import com.aurora.store.compose.ui.spoof.SpoofScreen
|
import com.aurora.store.compose.ui.spoof.SpoofScreen
|
||||||
|
import com.aurora.store.data.event.InstallerEvent
|
||||||
|
import com.aurora.store.data.model.AccountType
|
||||||
|
import com.aurora.store.data.providers.AccountProvider
|
||||||
|
import com.aurora.store.util.PackageUtil
|
||||||
|
import com.aurora.store.util.Preferences
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigation display for compose screens
|
* Navigation display for compose screens
|
||||||
@@ -58,6 +71,36 @@ fun NavDisplay(startDestination: NavKey) {
|
|||||||
if (backstack.size == 1) activity?.finish() else backstack.removeLastOrNull()
|
if (backstack.size == 1) activity?.finish() else backstack.removeLastOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
fun isMicroGAuthInvalidated(): Boolean =
|
||||||
|
Preferences.getBoolean(context, Preferences.PREFERENCE_AUTH_VIA_MICROG, false) &&
|
||||||
|
AccountProvider.getAccountType(context) == AccountType.GOOGLE &&
|
||||||
|
!PackageUtil.hasSupportedMicroGVariant(context)
|
||||||
|
|
||||||
|
fun handleMicroGRemoved() {
|
||||||
|
context.toast(R.string.microg_removed_auth_warning)
|
||||||
|
AccountProvider.logout(context)
|
||||||
|
val intent = Intent(context, ComposeActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
}
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check every time the screen resumes in case microG was removed while Aurora was in background.
|
||||||
|
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
|
||||||
|
if (isMicroGAuthInvalidated()) handleMicroGRemoved()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also react immediately if the GMS package is uninstalled while Aurora is in the foreground.
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
AuroraApp.events.installerEvent.collect { event ->
|
||||||
|
if (event is InstallerEvent.Uninstalled && event.packageName == PACKAGE_NAME_GMS) {
|
||||||
|
if (isMicroGAuthInvalidated()) handleMicroGRemoved()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NavDisplay(
|
NavDisplay(
|
||||||
backStack = backstack,
|
backStack = backstack,
|
||||||
entryDecorators = listOf(
|
entryDecorators = listOf(
|
||||||
|
|||||||
@@ -80,5 +80,6 @@ object AccountProvider {
|
|||||||
Preferences.remove(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
Preferences.remove(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
||||||
Preferences.remove(context, Constants.ACCOUNT_AAS_PLAIN)
|
Preferences.remove(context, Constants.ACCOUNT_AAS_PLAIN)
|
||||||
Preferences.remove(context, Constants.ACCOUNT_AUTH_PLAIN)
|
Preferences.remove(context, Constants.ACCOUNT_AUTH_PLAIN)
|
||||||
|
Preferences.remove(context, Preferences.PREFERENCE_AUTH_VIA_MICROG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ object Preferences {
|
|||||||
const val PREFERENCE_PROXY_INFO = "PREFERENCE_PROXY_INFO"
|
const val PREFERENCE_PROXY_INFO = "PREFERENCE_PROXY_INFO"
|
||||||
|
|
||||||
const val PREFERENCE_MICROG_AUTH = "PREFERENCE_MICROG_AUTH"
|
const val PREFERENCE_MICROG_AUTH = "PREFERENCE_MICROG_AUTH"
|
||||||
|
const val PREFERENCE_AUTH_VIA_MICROG = "PREFERENCE_AUTH_VIA_MICROG"
|
||||||
|
|
||||||
const val PREFERENCE_DISPENSER_URLS = "PREFERENCE_DISPENSER_URLS"
|
const val PREFERENCE_DISPENSER_URLS = "PREFERENCE_DISPENSER_URLS"
|
||||||
const val PREFERENCE_VENDING_VERSION = "PREFERENCE_VENDING_VERSION"
|
const val PREFERENCE_VENDING_VERSION = "PREFERENCE_VENDING_VERSION"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.aurora.store.data.model.AuthState
|
|||||||
import com.aurora.store.data.providers.AccountProvider
|
import com.aurora.store.data.providers.AccountProvider
|
||||||
import com.aurora.store.data.providers.AuthProvider
|
import com.aurora.store.data.providers.AuthProvider
|
||||||
import com.aurora.store.util.AC2DMTask
|
import com.aurora.store.util.AC2DMTask
|
||||||
|
import com.aurora.store.util.PackageUtil
|
||||||
import com.aurora.store.util.Preferences
|
import com.aurora.store.util.Preferences
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
@@ -171,13 +172,26 @@ class AuthViewModel @Inject constructor(
|
|||||||
_authState.value = AuthState.Verifying
|
_authState.value = AuthState.Verifying
|
||||||
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
||||||
authProvider.saveAuthData(authData)
|
authProvider.saveAuthData(authData)
|
||||||
|
val tokenType =
|
||||||
|
if (authData.aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS
|
||||||
AccountProvider.login(
|
AccountProvider.login(
|
||||||
context,
|
context,
|
||||||
authData.email,
|
authData.email,
|
||||||
authData.aasToken.ifBlank { authData.authToken },
|
authData.aasToken.ifBlank {
|
||||||
if (authData.aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS,
|
authData.authToken
|
||||||
|
},
|
||||||
|
tokenType,
|
||||||
accountType
|
accountType
|
||||||
)
|
)
|
||||||
|
// Record whether this Google session relies on microG's AccountManager so we
|
||||||
|
// can warn the user if microG is later uninstalled.
|
||||||
|
Preferences.putBoolean(
|
||||||
|
context,
|
||||||
|
Preferences.PREFERENCE_AUTH_VIA_MICROG,
|
||||||
|
accountType == AccountType.GOOGLE &&
|
||||||
|
tokenType == AuthHelper.Token.AUTH &&
|
||||||
|
PackageUtil.hasSupportedMicroGVariant(context)
|
||||||
|
)
|
||||||
_authState.value = AuthState.SignedIn
|
_authState.value = AuthState.SignedIn
|
||||||
} else {
|
} else {
|
||||||
authProvider.removeAuthData(context)
|
authProvider.removeAuthData(context)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.aurora.extensions.TAG
|
|||||||
import com.aurora.extensions.requiresGMS
|
import com.aurora.extensions.requiresGMS
|
||||||
import com.aurora.gplayapi.data.models.App
|
import com.aurora.gplayapi.data.models.App
|
||||||
import com.aurora.gplayapi.data.models.Review
|
import com.aurora.gplayapi.data.models.Review
|
||||||
|
import com.aurora.gplayapi.data.models.datasafety.Report as DataSafetyReport
|
||||||
import com.aurora.gplayapi.data.models.details.TestingProgramStatus
|
import com.aurora.gplayapi.data.models.details.TestingProgramStatus
|
||||||
import com.aurora.gplayapi.helpers.AppDetailsHelper
|
import com.aurora.gplayapi.helpers.AppDetailsHelper
|
||||||
import com.aurora.gplayapi.helpers.ReviewsHelper
|
import com.aurora.gplayapi.helpers.ReviewsHelper
|
||||||
@@ -41,6 +42,7 @@ import com.aurora.store.util.Preferences
|
|||||||
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED
|
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
@@ -54,8 +56,6 @@ import kotlinx.coroutines.flow.stateIn
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import javax.inject.Inject
|
|
||||||
import com.aurora.gplayapi.data.models.datasafety.Report as DataSafetyReport
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class AppDetailsViewModel @Inject constructor(
|
class AppDetailsViewModel @Inject constructor(
|
||||||
|
|||||||
@@ -392,6 +392,7 @@
|
|||||||
<string name="native_installer_desc">Best suited for devices running below Android 4.4</string>
|
<string name="native_installer_desc">Best suited for devices running below Android 4.4</string>
|
||||||
<string name="services_installer_subtitle">Installer for background installations</string>
|
<string name="services_installer_subtitle">Installer for background installations</string>
|
||||||
<string name="services_installer_desc">Requires Aurora Services to be installed as a privileged-system app</string>
|
<string name="services_installer_desc">Requires Aurora Services to be installed as a privileged-system app</string>
|
||||||
|
<string name="microg_removed_auth_warning">microG is no longer installed. Run setup again to keep things working smoothly.</string>
|
||||||
<string name="microg_installer_subtitle">Requires microG companion app to be installed</string>
|
<string name="microg_installer_subtitle">Requires microG companion app to be installed</string>
|
||||||
<string name="microg_installer_desc">Helps you bypass App Integrity (installer only) check</string>
|
<string name="microg_installer_desc">Helps you bypass App Integrity (installer only) check</string>
|
||||||
<string name="am_installer_subtitle">Full-featured open source package manager</string>
|
<string name="am_installer_subtitle">Full-featured open source package manager</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user