Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions app/src/main/java/com/getcode/util/AccountAuthenticator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.getcode.util
import android.accounts.*
import android.content.Context
import android.os.Bundle
import androidx.core.os.bundleOf
import com.getcode.utils.trace


Expand Down Expand Up @@ -66,13 +67,21 @@ class AccountAuthenticator(
return Bundle()
}

override fun getAuthTokenLabel(arg0: String): String? = null
override fun getAuthTokenLabel(arg0: String): String? {
return "entropy"
}

@Throws(NetworkErrorException::class)
override fun hasFeatures(
arg0: AccountAuthenticatorResponse, arg1: Account,
arg2: Array<String>
): Bundle? = null
): Bundle {
// This call is used to query whether the Authenticator supports
// specific features. We don't expect to get called, so we always
// return false (no) for any queries.
val result = bundleOf(AccountManager.KEY_BOOLEAN_RESULT to false)
return result
}

@Throws(NetworkErrorException::class)
override fun updateCredentials(
Expand Down
61 changes: 30 additions & 31 deletions app/src/main/java/com/getcode/util/AccountUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package com.getcode.util
import android.accounts.Account
import android.accounts.AccountManager
import android.accounts.AuthenticatorException
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import androidx.core.os.bundleOf
import com.getcode.BuildConfig
import com.getcode.utils.TraceType
import com.getcode.utils.trace
Expand All @@ -23,14 +22,20 @@ import kotlin.coroutines.resume


object AccountUtils {
private const val acctType = BuildConfig.APPLICATION_ID

fun addAccount(context: Context, name: String, password: String, token: String) {
val am: AccountManager = AccountManager.get(context)
val a = Account(name, acctType)

am.addAccountExplicitly(a, password, Bundle())
am.setAuthToken(a, acctType, token)
private const val ACCOUNT_TYPE = BuildConfig.APPLICATION_ID

fun addAccount(
context: Context,
name: String,
password: String,
token: String
) {
val accountManager: AccountManager = AccountManager.get(context)
val account = Account(name, ACCOUNT_TYPE)

val data = bundleOf(AccountManager.KEY_AUTH_TOKEN_LABEL to "entropy")
accountManager.addAccountExplicitly(account, password, data)
accountManager.setAuthToken(account, ACCOUNT_TYPE, token)
}

suspend fun removeAccounts(context: Context): @NonNull Single<Boolean> {
Expand Down Expand Up @@ -63,54 +68,48 @@ object AccountUtils {

private suspend fun getAccountNoActivity(
context: Context
) : Pair<String?, Account?>? = suspendCancellableCoroutine { cont ->
): Pair<String?, Account?>? = suspendCancellableCoroutine { cont ->
trace("getAuthToken", type = TraceType.Silent)
val am: AccountManager = AccountManager.get(context)
val accountthing = am.accounts.getOrNull(0)
if (accountthing == null) {
val account = am.accounts.getOrNull(0)
if (account == null) {
trace("no associated account found", type = TraceType.Error)
cont.resume(null to null)
return@suspendCancellableCoroutine
}
val start = Clock.System.now()
am.getAuthToken(
accountthing, acctType, null, false,
account, ACCOUNT_TYPE, null, false,
{ future ->
try {
val bundle = future?.result
val authToken = bundle?.getString(AccountManager.KEY_AUTHTOKEN)
val accountName = bundle?.getString(AccountManager.KEY_ACCOUNT_NAME)
val account: Account? = getAccount(context, accountName)

val end = Clock.System.now()
trace("auth token fetch took ${end.toEpochMilliseconds() - start.toEpochMilliseconds()} ms")

cont.resume(authToken.orEmpty() to account)

if (null == account && authToken != null) {
addAccount(context, accountName.orEmpty(), "", authToken)
}
cont.resume(authToken.orEmpty() to account)
} catch (e: AuthenticatorException) {
e.printStackTrace()
trace(message = "failed to read account", error = e, type = TraceType.Error)
cont.resume(null to null)
}
}, handler
)
}


suspend fun getToken(context: Context): String? {
return getAccountNoActivity(context)?.first
}

private fun getAccount(context: Context?, accountName: String?): Account? {
val accountManager = AccountManager.get(context)
val accounts = accountManager.getAccountsByType(acctType)
for (account in accounts) {
if (account.name.equals(accountName, ignoreCase = true)) {
return account
val account = accountManager.accounts.firstOrNull()
if (account != null) {
val token = runCatching { accountManager.peekAuthToken(account, ACCOUNT_TYPE) }
.getOrNull()?.takeIf { it.isNotEmpty() }

if (token != null) {
return token
}
}
return null

return getAccountNoActivity(context)?.first
}
}