AuthProvider: Extract authData generation logic
* Partially revert 51c4beba8e
* Extract the AuthData generation logic to Authprovider and AccountProvider classes
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -47,10 +47,10 @@ object Constants {
|
|||||||
|
|
||||||
//ACCOUNTS
|
//ACCOUNTS
|
||||||
const val ACCOUNT_SIGNED_IN = "ACCOUNT_SIGNED_IN"
|
const val ACCOUNT_SIGNED_IN = "ACCOUNT_SIGNED_IN"
|
||||||
const val ACCOUNT_SIGNED_TIMESTAMP = "ACCOUNT_SIGNED_TIMESTAMP"
|
|
||||||
const val ACCOUNT_TYPE = "ACCOUNT_TYPE"
|
const val ACCOUNT_TYPE = "ACCOUNT_TYPE"
|
||||||
const val ACCOUNT_EMAIL_PLAIN = "ACCOUNT_EMAIL_PLAIN"
|
const val ACCOUNT_EMAIL_PLAIN = "ACCOUNT_EMAIL_PLAIN"
|
||||||
const val ACCOUNT_AAS_PLAIN = "ACCOUNT_AAS_PLAIN"
|
const val ACCOUNT_AAS_PLAIN = "ACCOUNT_AAS_PLAIN"
|
||||||
|
const val ACCOUNT_AUTH_PLAIN = "ACCOUNT_AUTH_PLAIN"
|
||||||
|
|
||||||
const val PAGE_TYPE = "PAGE_TYPE"
|
const val PAGE_TYPE = "PAGE_TYPE"
|
||||||
const val TOP_CHART_TYPE = "TOP_CHART_TYPE"
|
const val TOP_CHART_TYPE = "TOP_CHART_TYPE"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.aurora.store.data.providers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.aurora.Constants
|
import com.aurora.Constants
|
||||||
|
import com.aurora.gplayapi.helpers.AuthHelper
|
||||||
import com.aurora.store.data.model.AccountType
|
import com.aurora.store.data.model.AccountType
|
||||||
import com.aurora.store.util.Preferences
|
import com.aurora.store.util.Preferences
|
||||||
|
|
||||||
@@ -34,9 +35,49 @@ object AccountProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logout(context: Context) {
|
fun isLoggedIn(context: Context): Boolean {
|
||||||
Preferences.putBoolean(context, Constants.ACCOUNT_SIGNED_IN, false)
|
return Preferences.getBoolean(context, Constants.ACCOUNT_SIGNED_IN, false)
|
||||||
Preferences.putString(context, Constants.ACCOUNT_EMAIL_PLAIN, "")
|
|
||||||
Preferences.putString(context, Constants.ACCOUNT_AAS_PLAIN, "")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
fun getLoginEmail(context: Context): String? {
|
||||||
|
val email = Preferences.getString(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
||||||
|
return email.ifBlank { null }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLoginToken(context: Context): Pair<String, AuthHelper.Token>? {
|
||||||
|
val email = Preferences.getString(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
||||||
|
val aasToken = Preferences.getString(context, Constants.ACCOUNT_AAS_PLAIN)
|
||||||
|
val authToken = Preferences.getString(context, Constants.ACCOUNT_AUTH_PLAIN)
|
||||||
|
|
||||||
|
if (email.isBlank() && (aasToken.isBlank() || authToken.isBlank())) return null
|
||||||
|
|
||||||
|
val tokenType = if (aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS
|
||||||
|
return Pair(aasToken.ifBlank { authToken }, tokenType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun login(
|
||||||
|
context: Context,
|
||||||
|
email: String,
|
||||||
|
token: String,
|
||||||
|
tokenType: AuthHelper.Token,
|
||||||
|
accountType: AccountType
|
||||||
|
) {
|
||||||
|
Preferences.putBoolean(context, Constants.ACCOUNT_SIGNED_IN, true)
|
||||||
|
Preferences.putString(context, Constants.ACCOUNT_EMAIL_PLAIN, email)
|
||||||
|
Preferences.putString(context, Constants.ACCOUNT_TYPE, accountType.name)
|
||||||
|
|
||||||
|
if (tokenType == AuthHelper.Token.AAS) {
|
||||||
|
Preferences.putString(context, Constants.ACCOUNT_AAS_PLAIN, token)
|
||||||
|
} else {
|
||||||
|
Preferences.putString(context, Constants.ACCOUNT_AUTH_PLAIN, token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logout(context: Context) {
|
||||||
|
Preferences.remove(context, Constants.ACCOUNT_SIGNED_IN)
|
||||||
|
Preferences.remove(context, Constants.ACCOUNT_TYPE)
|
||||||
|
Preferences.remove(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
||||||
|
Preferences.remove(context, Constants.ACCOUNT_AAS_PLAIN)
|
||||||
|
Preferences.remove(context, Constants.ACCOUNT_AUTH_PLAIN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ package com.aurora.store.data.providers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.aurora.Constants
|
|
||||||
import com.aurora.Constants.ACCOUNT_SIGNED_IN
|
|
||||||
import com.aurora.gplayapi.data.models.AuthData
|
import com.aurora.gplayapi.data.models.AuthData
|
||||||
|
import com.aurora.gplayapi.data.models.PlayResponse
|
||||||
import com.aurora.gplayapi.helpers.AuthHelper
|
import com.aurora.gplayapi.helpers.AuthHelper
|
||||||
import com.aurora.gplayapi.helpers.AuthValidator
|
import com.aurora.gplayapi.helpers.AuthValidator
|
||||||
import com.aurora.gplayapi.network.IHttpClient
|
import com.aurora.gplayapi.network.IHttpClient
|
||||||
@@ -53,7 +52,27 @@ class AuthProvider @Inject constructor(
|
|||||||
|
|
||||||
private val TAG = AuthProvider::class.java.simpleName
|
private val TAG = AuthProvider::class.java.simpleName
|
||||||
|
|
||||||
val properties: Properties
|
val dispenserURL: String?
|
||||||
|
get() {
|
||||||
|
val dispensers = Preferences.getStringSet(context, PREFERENCE_DISPENSER_URLS)
|
||||||
|
return if (dispensers.isNotEmpty()) dispensers.random() else null
|
||||||
|
}
|
||||||
|
|
||||||
|
val authData: AuthData?
|
||||||
|
get() {
|
||||||
|
Log.i(TAG, "Loading saved AuthData")
|
||||||
|
val rawAuth: String = Preferences.getString(context, PREFERENCE_AUTH_DATA)
|
||||||
|
return if (rawAuth.isNotBlank()) {
|
||||||
|
gson.fromJson(rawAuth, AuthData::class.java)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isAnonymous: Boolean
|
||||||
|
get() = AccountProvider.getAccountType(context) == AccountType.ANONYMOUS
|
||||||
|
|
||||||
|
private val properties: Properties
|
||||||
get() {
|
get() {
|
||||||
val currentProperties = if (spoofProvider.isDeviceSpoofEnabled()) {
|
val currentProperties = if (spoofProvider.isDeviceSpoofEnabled()) {
|
||||||
spoofProvider.getSpoofDeviceProperties()
|
spoofProvider.getSpoofDeviceProperties()
|
||||||
@@ -63,41 +82,14 @@ class AuthProvider @Inject constructor(
|
|||||||
setVendingVersion(currentProperties)
|
setVendingVersion(currentProperties)
|
||||||
return currentProperties
|
return currentProperties
|
||||||
}
|
}
|
||||||
val locale: Locale
|
|
||||||
|
private val locale: Locale
|
||||||
get() = if (spoofProvider.isLocaleSpoofEnabled()) {
|
get() = if (spoofProvider.isLocaleSpoofEnabled()) {
|
||||||
spoofProvider.getSpoofLocale()
|
spoofProvider.getSpoofLocale()
|
||||||
} else {
|
} else {
|
||||||
Locale.getDefault()
|
Locale.getDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
val dispenserURL: String?
|
|
||||||
get() {
|
|
||||||
val dispensers = Preferences.getStringSet(context, PREFERENCE_DISPENSER_URLS)
|
|
||||||
return if (dispensers.isNotEmpty()) dispensers.random() else null
|
|
||||||
}
|
|
||||||
|
|
||||||
val authData: AuthData? get() = getSavedAuthData()
|
|
||||||
|
|
||||||
val isAnonymous: Boolean
|
|
||||||
get() {
|
|
||||||
val name = Preferences.getString(context, Constants.ACCOUNT_TYPE, AccountType.GOOGLE.name)
|
|
||||||
return AccountType.valueOf(name) == AccountType.ANONYMOUS
|
|
||||||
}
|
|
||||||
|
|
||||||
private val signedIn: Boolean
|
|
||||||
get() = Preferences.getBoolean(context, ACCOUNT_SIGNED_IN)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds and returns AuthData based on signed-in account type
|
|
||||||
*/
|
|
||||||
suspend fun getTmpAuthData(): AuthData? {
|
|
||||||
return when {
|
|
||||||
!signedIn -> null
|
|
||||||
!isAnonymous -> buildGoogleAuthData()
|
|
||||||
else -> buildAnonymousAuthData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether saved AuthData is valid or not
|
* Checks whether saved AuthData is valid or not
|
||||||
*/
|
*/
|
||||||
@@ -113,56 +105,79 @@ class AuthProvider @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSavedAuthData(): AuthData? {
|
/**
|
||||||
Log.i(TAG, "Loading saved AuthData")
|
* Builds [AuthData] for login using personal Google account
|
||||||
val rawAuth: String = Preferences.getString(context, PREFERENCE_AUTH_DATA)
|
* @param email E-mail ID
|
||||||
return if (rawAuth.isNotEmpty()) {
|
* @param token AAS or Auth token
|
||||||
gson.fromJson(rawAuth, AuthData::class.java)
|
* @param tokenType Type of the token, one from [AuthHelper.Token]
|
||||||
} else {
|
* @return Result encapsulating [AuthData] or exception
|
||||||
null
|
*/
|
||||||
}
|
suspend fun buildGoogleAuthData(
|
||||||
}
|
email: String,
|
||||||
|
token: String,
|
||||||
private suspend fun buildGoogleAuthData(): AuthData? {
|
tokenType: AuthHelper.Token
|
||||||
|
): Result<AuthData> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val email = Preferences.getString(context, Constants.ACCOUNT_EMAIL_PLAIN)
|
return@withContext Result.success(
|
||||||
val aasToken = Preferences.getString(context, Constants.ACCOUNT_AAS_PLAIN)
|
AuthHelper.build(
|
||||||
|
email = email,
|
||||||
return@withContext AuthHelper.build(
|
token = token,
|
||||||
email = email,
|
tokenType = tokenType,
|
||||||
token = aasToken,
|
properties = properties,
|
||||||
tokenType = AuthHelper.Token.AAS,
|
locale = locale,
|
||||||
properties = properties,
|
)
|
||||||
locale = locale
|
|
||||||
)
|
)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(TAG, "Failed to generate Session", exception)
|
Log.e(TAG, "Failed to generate Session", exception)
|
||||||
return@withContext null
|
return@withContext Result.failure(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun buildAnonymousAuthData(): AuthData? {
|
/**
|
||||||
|
* Builds [AuthData] for login using one of the dispensers
|
||||||
|
* @return Result encapsulating [AuthData] or exception
|
||||||
|
*/
|
||||||
|
suspend fun buildAnonymousAuthData(): Result<AuthData> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val playResponse = httpClient.getAuth(dispenserURL!!)
|
val playResponse = httpClient.getAuth(dispenserURL!!).also {
|
||||||
|
if (!it.isSuccessful) throwError(it, context)
|
||||||
|
}
|
||||||
|
|
||||||
val auth = gson.fromJson(String(playResponse.responseBytes), Auth::class.java)
|
val auth = gson.fromJson(String(playResponse.responseBytes), Auth::class.java)
|
||||||
return@withContext AuthHelper.build(
|
return@withContext Result.success(
|
||||||
email = auth.email,
|
AuthHelper.build(
|
||||||
token = auth.auth,
|
email = auth.email,
|
||||||
tokenType = AuthHelper.Token.AUTH,
|
token = auth.auth,
|
||||||
isAnonymous = true,
|
tokenType = AuthHelper.Token.AUTH,
|
||||||
properties = properties,
|
isAnonymous = true,
|
||||||
locale = locale
|
properties = properties,
|
||||||
|
locale = locale
|
||||||
|
)
|
||||||
)
|
)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(TAG, "Failed to generate AuthData", exception)
|
Log.e(TAG, "Failed to generate AuthData", exception)
|
||||||
return@withContext null
|
return@withContext Result.failure(exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves given [AuthData]
|
||||||
|
*/
|
||||||
|
fun saveAuthData(authData: AuthData) {
|
||||||
|
Preferences.putString(context, PREFERENCE_AUTH_DATA, gson.toJson(authData))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes saved [AuthData]
|
||||||
|
*/
|
||||||
|
fun removeAuthData(context: Context) {
|
||||||
|
Preferences.remove(context, PREFERENCE_AUTH_DATA)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setVendingVersion(currentProperties: Properties) {
|
private fun setVendingVersion(currentProperties: Properties) {
|
||||||
val vendingVersionIndex = Preferences.getInteger(context, PREFERENCE_VENDING_VERSION)
|
val vendingVersionIndex = Preferences.getInteger(context, PREFERENCE_VENDING_VERSION)
|
||||||
if (vendingVersionIndex > 0) {
|
if (vendingVersionIndex > 0) {
|
||||||
@@ -174,4 +189,27 @@ class AuthProvider @Inject constructor(
|
|||||||
currentProperties.setProperty("Vending.versionString", versionStrings[vendingVersionIndex])
|
currentProperties.setProperty("Vending.versionString", versionStrings[vendingVersionIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(Exception::class)
|
||||||
|
private fun throwError(playResponse: PlayResponse, context: Context) {
|
||||||
|
when (playResponse.code) {
|
||||||
|
400 -> throw Exception(context.getString(R.string.bad_request))
|
||||||
|
403 -> throw Exception(context.getString(R.string.access_denied_using_vpn))
|
||||||
|
404 -> throw Exception(context.getString(R.string.server_unreachable))
|
||||||
|
429 -> throw Exception(context.getString(R.string.login_rate_limited))
|
||||||
|
503 -> throw Exception(context.getString(R.string.server_maintenance))
|
||||||
|
else -> {
|
||||||
|
if (playResponse.errorString.isNotBlank()) {
|
||||||
|
throw Exception(playResponse.errorString)
|
||||||
|
} else {
|
||||||
|
throw Exception(
|
||||||
|
context.getString(
|
||||||
|
R.string.failed_generating_session,
|
||||||
|
playResponse.code
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,19 +121,13 @@ class UpdateWorker @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val authData = if (authProvider.isSavedAuthDataValid()) {
|
if (!authProvider.isSavedAuthDataValid()) {
|
||||||
authProvider.authData
|
|
||||||
} else {
|
|
||||||
authProvider.getTmpAuthData()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authData == null) {
|
|
||||||
Log.i(TAG, "AuthData is not valid, retrying later!")
|
Log.i(TAG, "AuthData is not valid, retrying later!")
|
||||||
return@withContext Result.retry()
|
return@withContext Result.retry()
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val updatesList = appUtil.checkUpdates(authData)
|
val updatesList = appUtil.checkUpdates()
|
||||||
.filter { it.hasValidCert }
|
.filter { it.hasValidCert }
|
||||||
.filterNot { it.isSelfUpdate() }
|
.filterNot { it.isSelfUpdate() }
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.util.Log
|
|||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import com.aurora.Constants
|
import com.aurora.Constants
|
||||||
import com.aurora.gplayapi.data.models.App
|
import com.aurora.gplayapi.data.models.App
|
||||||
import com.aurora.gplayapi.data.models.AuthData
|
|
||||||
import com.aurora.gplayapi.helpers.AppDetailsHelper
|
import com.aurora.gplayapi.helpers.AppDetailsHelper
|
||||||
import com.aurora.gplayapi.network.IHttpClient
|
import com.aurora.gplayapi.network.IHttpClient
|
||||||
import com.aurora.store.AuroraApp
|
import com.aurora.store.AuroraApp
|
||||||
@@ -58,10 +57,10 @@ class AppUtil @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkUpdates(tmpAuthData: AuthData? = null): List<Update> {
|
suspend fun checkUpdates(): List<Update> {
|
||||||
Log.i(TAG, "Checking for updates")
|
Log.i(TAG, "Checking for updates")
|
||||||
val packageInfoMap = PackageUtil.getPackageInfoMap(context)
|
val packageInfoMap = PackageUtil.getPackageInfoMap(context)
|
||||||
val appUpdatesList = getFilteredInstalledApps(tmpAuthData, packageInfoMap)
|
val appUpdatesList = getFilteredInstalledApps(packageInfoMap)
|
||||||
.filter {
|
.filter {
|
||||||
val packageInfo = packageInfoMap[it.packageName]
|
val packageInfo = packageInfoMap[it.packageName]
|
||||||
if (packageInfo != null) {
|
if (packageInfo != null) {
|
||||||
@@ -86,11 +85,10 @@ class AppUtil @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getFilteredInstalledApps(
|
suspend fun getFilteredInstalledApps(
|
||||||
tmpAuthData: AuthData? = null,
|
|
||||||
packageInfoMap: MutableMap<String, PackageInfo>? = null
|
packageInfoMap: MutableMap<String, PackageInfo>? = null
|
||||||
): List<App> {
|
): List<App> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
val appDetailsHelper = AppDetailsHelper(tmpAuthData?: authProvider.authData!!)
|
val appDetailsHelper = AppDetailsHelper(authProvider.authData!!)
|
||||||
.using(httpClient)
|
.using(httpClient)
|
||||||
|
|
||||||
(packageInfoMap ?: PackageUtil.getPackageInfoMap(context)).keys.let { packages ->
|
(packageInfoMap ?: PackageUtil.getPackageInfoMap(context)).keys.let { packages ->
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.aurora.gplayapi.helpers.AuthHelper
|
||||||
import com.aurora.store.AuroraApp
|
import com.aurora.store.AuroraApp
|
||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.data.event.AuthEvent
|
import com.aurora.store.data.event.AuthEvent
|
||||||
@@ -117,7 +118,7 @@ class GoogleFragment : BaseFragment<FragmentGoogleBinding>() {
|
|||||||
when (event) {
|
when (event) {
|
||||||
is AuthEvent.GoogleLogin -> {
|
is AuthEvent.GoogleLogin -> {
|
||||||
if (event.success) {
|
if (event.success) {
|
||||||
viewModel.buildGoogleAuthData(event.email, event.token)
|
viewModel.buildGoogleAuthData(event.email, event.token, AuthHelper.Token.AAS)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
|
|||||||
@@ -27,26 +27,20 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.aurora.Constants
|
import com.aurora.Constants
|
||||||
import com.aurora.gplayapi.data.models.AuthData
|
import com.aurora.gplayapi.data.models.AuthData
|
||||||
import com.aurora.gplayapi.data.models.PlayResponse
|
|
||||||
import com.aurora.gplayapi.helpers.AuthHelper
|
import com.aurora.gplayapi.helpers.AuthHelper
|
||||||
import com.aurora.gplayapi.network.IHttpClient
|
|
||||||
import com.aurora.store.AuroraApp
|
import com.aurora.store.AuroraApp
|
||||||
import com.aurora.store.R
|
import com.aurora.store.R
|
||||||
import com.aurora.store.data.event.AuthEvent
|
import com.aurora.store.data.event.AuthEvent
|
||||||
import com.aurora.store.data.model.AccountType
|
import com.aurora.store.data.model.AccountType
|
||||||
import com.aurora.store.data.model.Auth
|
|
||||||
import com.aurora.store.data.model.AuthState
|
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.Preferences
|
import com.aurora.store.util.Preferences
|
||||||
import com.aurora.store.util.Preferences.PREFERENCE_AUTH_DATA
|
|
||||||
import com.google.gson.Gson
|
|
||||||
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 kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.supervisorScope
|
|
||||||
import java.net.ConnectException
|
import java.net.ConnectException
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -56,8 +50,6 @@ import javax.inject.Inject
|
|||||||
class AuthViewModel @Inject constructor(
|
class AuthViewModel @Inject constructor(
|
||||||
val authProvider: AuthProvider,
|
val authProvider: AuthProvider,
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val gson: Gson,
|
|
||||||
private val httpClient: IHttpClient,
|
|
||||||
private val aC2DMTask: AC2DMTask
|
private val aC2DMTask: AC2DMTask
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
@@ -67,8 +59,7 @@ class AuthViewModel @Inject constructor(
|
|||||||
|
|
||||||
fun observe() {
|
fun observe() {
|
||||||
if (liveData.value != AuthState.Fetching) {
|
if (liveData.value != AuthState.Fetching) {
|
||||||
val signedIn = Preferences.getBoolean(context, Constants.ACCOUNT_SIGNED_IN)
|
if (AccountProvider.isLoggedIn(context)) {
|
||||||
if (signedIn) {
|
|
||||||
liveData.postValue(AuthState.Available)
|
liveData.postValue(AuthState.Available)
|
||||||
buildSavedAuthData()
|
buildSavedAuthData()
|
||||||
} else {
|
} else {
|
||||||
@@ -77,18 +68,14 @@ class AuthViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildGoogleAuthData(email: String, aasToken: String) {
|
fun buildGoogleAuthData(email: String, token: String, tokenType: AuthHelper.Token) {
|
||||||
liveData.postValue(AuthState.Fetching)
|
liveData.postValue(AuthState.Fetching)
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val authData = AuthHelper.build(
|
verifyAndSaveAuth(
|
||||||
email = email,
|
authProvider.buildGoogleAuthData(email, token, tokenType).getOrThrow(),
|
||||||
token = aasToken,
|
AccountType.GOOGLE
|
||||||
tokenType = AuthHelper.Token.AAS,
|
|
||||||
properties = authProvider.properties,
|
|
||||||
locale = authProvider.locale
|
|
||||||
)
|
)
|
||||||
verifyAndSaveAuth(authData, AccountType.GOOGLE)
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
liveData.postValue(
|
liveData.postValue(
|
||||||
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
||||||
@@ -102,28 +89,13 @@ class AuthViewModel @Inject constructor(
|
|||||||
liveData.postValue(AuthState.Fetching)
|
liveData.postValue(AuthState.Fetching)
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val playResponse = httpClient.getAuth(authProvider.dispenserURL!!)
|
verifyAndSaveAuth(
|
||||||
if (playResponse.isSuccessful) {
|
authProvider.buildAnonymousAuthData().getOrThrow(),
|
||||||
val tmpAuthData = gson.fromJson(
|
AccountType.ANONYMOUS
|
||||||
String(playResponse.responseBytes),
|
)
|
||||||
Auth::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
val authData = AuthHelper.build(
|
|
||||||
email = tmpAuthData.email,
|
|
||||||
token = tmpAuthData.auth,
|
|
||||||
tokenType = AuthHelper.Token.AUTH,
|
|
||||||
isAnonymous = true,
|
|
||||||
properties = authProvider.properties,
|
|
||||||
locale = authProvider.locale
|
|
||||||
)
|
|
||||||
verifyAndSaveAuth(authData, AccountType.ANONYMOUS)
|
|
||||||
} else {
|
|
||||||
throwError(playResponse, context)
|
|
||||||
}
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
liveData.postValue(AuthState.Failed(exception.message.toString()))
|
|
||||||
Log.e(TAG, "Failed to generate Session", exception)
|
Log.e(TAG, "Failed to generate Session", exception)
|
||||||
|
liveData.postValue(AuthState.Failed(exception.message.toString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,98 +127,54 @@ class AuthViewModel @Inject constructor(
|
|||||||
|
|
||||||
private fun buildSavedAuthData() {
|
private fun buildSavedAuthData() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
supervisorScope {
|
try {
|
||||||
try {
|
if (authProvider.isSavedAuthDataValid()) {
|
||||||
if (authProvider.isSavedAuthDataValid()) {
|
liveData.postValue(AuthState.Valid)
|
||||||
liveData.postValue(AuthState.Valid)
|
} else {
|
||||||
} else {
|
// Generate and validate new auth
|
||||||
//Generate and validate new auth
|
when (AccountProvider.getAccountType(context)) {
|
||||||
when (AccountProvider.getAccountType(context)) {
|
AccountType.GOOGLE -> {
|
||||||
AccountType.GOOGLE -> {
|
buildGoogleAuthData(
|
||||||
val email = Preferences.getString(
|
AccountProvider.getLoginEmail(context)!!,
|
||||||
context,
|
AccountProvider.getLoginToken(context)!!.first,
|
||||||
Constants.ACCOUNT_EMAIL_PLAIN
|
AccountProvider.getLoginToken(context)!!.second
|
||||||
)
|
)
|
||||||
val aasToken = Preferences.getString(
|
}
|
||||||
context,
|
|
||||||
Constants.ACCOUNT_AAS_PLAIN
|
|
||||||
)
|
|
||||||
buildGoogleAuthData(email, aasToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
AccountType.ANONYMOUS -> {
|
AccountType.ANONYMOUS -> {
|
||||||
buildAnonymousAuthData()
|
buildAnonymousAuthData()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
val error = when (e) {
|
|
||||||
is UnknownHostException -> {
|
|
||||||
context.getString(R.string.title_no_network)
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConnectException -> {
|
|
||||||
context.getString(R.string.server_unreachable)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
context.getString(R.string.bad_request)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liveData.postValue(AuthState.Failed(error))
|
|
||||||
}
|
}
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
val error = when (exception) {
|
||||||
|
is UnknownHostException -> context.getString(R.string.title_no_network)
|
||||||
|
is ConnectException -> context.getString(R.string.server_unreachable)
|
||||||
|
else -> context.getString(R.string.bad_request)
|
||||||
|
}
|
||||||
|
liveData.postValue(AuthState.Failed(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyAndSaveAuth(authData: AuthData, type: AccountType) {
|
private fun verifyAndSaveAuth(authData: AuthData, accountType: AccountType) {
|
||||||
liveData.postValue(AuthState.Verifying)
|
liveData.postValue(AuthState.Verifying)
|
||||||
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
if (authData.authToken.isNotEmpty() && authData.deviceConfigToken.isNotEmpty()) {
|
||||||
configAuthPref(authData, type, true)
|
authProvider.saveAuthData(authData)
|
||||||
|
AccountProvider.login(
|
||||||
|
context,
|
||||||
|
authData.email,
|
||||||
|
authData.aasToken.ifBlank { authData.authToken },
|
||||||
|
if (authData.aasToken.isBlank()) AuthHelper.Token.AUTH else AuthHelper.Token.AAS,
|
||||||
|
accountType
|
||||||
|
)
|
||||||
liveData.postValue(AuthState.SignedIn)
|
liveData.postValue(AuthState.SignedIn)
|
||||||
} else {
|
} else {
|
||||||
configAuthPref(authData, type, false)
|
authProvider.removeAuthData(context)
|
||||||
liveData.postValue(AuthState.SignedOut)
|
AccountProvider.logout(context)
|
||||||
|
|
||||||
liveData.postValue(
|
liveData.postValue(
|
||||||
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
AuthState.Failed(context.getString(R.string.failed_to_generate_session))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configAuthPref(authData: AuthData, type: AccountType, signedIn: Boolean) {
|
|
||||||
if (signedIn) {
|
|
||||||
//Save Auth Data
|
|
||||||
Preferences.putString(context, PREFERENCE_AUTH_DATA, gson.toJson(authData))
|
|
||||||
}
|
|
||||||
|
|
||||||
//Save Auth Type
|
|
||||||
Preferences.putString(context, Constants.ACCOUNT_TYPE, type.name)
|
|
||||||
|
|
||||||
//Save Auth Status
|
|
||||||
Preferences.putBoolean(context, Constants.ACCOUNT_SIGNED_IN, signedIn)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
private fun throwError(playResponse: PlayResponse, context: Context) {
|
|
||||||
when (playResponse.code) {
|
|
||||||
400 -> throw Exception(context.getString(R.string.bad_request))
|
|
||||||
403 -> throw Exception(context.getString(R.string.access_denied_using_vpn))
|
|
||||||
404 -> throw Exception(context.getString(R.string.server_unreachable))
|
|
||||||
429 -> throw Exception(context.getString(R.string.login_rate_limited))
|
|
||||||
503 -> throw Exception(context.getString(R.string.server_maintenance))
|
|
||||||
else -> {
|
|
||||||
if (playResponse.errorString.isNotBlank()) {
|
|
||||||
throw Exception(playResponse.errorString)
|
|
||||||
} else {
|
|
||||||
throw Exception(
|
|
||||||
context.getString(
|
|
||||||
R.string.failed_generating_session,
|
|
||||||
playResponse.code
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user