Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09d7dcc3 authored by Abhishek Aggarwal's avatar Abhishek Aggarwal
Browse files

refactor(auth): remove test-only login constructors and explicitize google bootstrap paths

parent a364c3dd
Loading
Loading
Loading
Loading
+43 −102
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import com.aurora.gplayapi.data.models.AuthData
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.apps.data.NetworkRetryPolicy
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.login.api.PlayStoreAuthValidator
import foundation.e.apps.data.login.api.PlayStoreBootstrapCredentials
import foundation.e.apps.data.login.api.PlayStoreLoginBootstrapper
import foundation.e.apps.data.login.core.StoreActivationPolicy
@@ -37,7 +36,6 @@ import foundation.e.apps.domain.auth.AuthStore
import foundation.e.apps.domain.auth.PersistedLoginIntent
import foundation.e.apps.domain.auth.PlayStoreLoginMode
import foundation.e.apps.domain.preferences.SessionRepository
import foundation.e.apps.domain.source.SourceSelectionRepository
import timber.log.Timber
import java.util.Locale
import javax.inject.Inject
@@ -68,80 +66,6 @@ class PlayStoreAuthenticator @Inject constructor(
    private val playStoreStoredAuthPolicy: PlayStoreStoredAuthPolicy,
) : StoreAuthenticator, PlayStoreLoginBootstrapper {

    constructor(
        @ApplicationContext context: Context,
        sessionRepository: SessionRepository,
        playStoreAuthStore: PlayStoreAuthStore,
        sourceSelectionRepository: SourceSelectionRepository,
        authDataCache: AuthDataCache,
        googleLoginManager: GoogleLoginManager,
        microgLoginManager: MicrogLoginManager,
        anonymousLoginManager: AnonymousLoginManager,
        aasTokenConverter: OauthToAasTokenConverter,
        userProfileFetcher: UserProfileFetcher,
        successfulLoginNotifier: SuccessfulLoginNotifier,
        networkRetryPolicy: NetworkRetryPolicy,
        playStoreAuthValidator: PlayStoreAuthValidator,
    ) : this(
        context = context,
        sessionRepository = sessionRepository,
        playStoreAuthStore = playStoreAuthStore,
        storeActivationPolicy = StoreActivationPolicy(
            sessionRepository = sessionRepository,
            sourceSelectionRepository = sourceSelectionRepository,
        ),
        authDataCache = authDataCache,
        googleLoginManager = googleLoginManager,
        microgLoginManager = microgLoginManager,
        anonymousLoginManager = anonymousLoginManager,
        aasTokenConverter = aasTokenConverter,
        userProfileFetcher = userProfileFetcher,
        successfulLoginNotifier = successfulLoginNotifier,
        networkRetryPolicy = networkRetryPolicy,
        playStoreStoredAuthPolicy = PlayStoreStoredAuthPolicy(
            playStoreAuthStore = playStoreAuthStore,
            playStoreAuthValidator = playStoreAuthValidator,
        ),
    )

    constructor(
        @ApplicationContext context: Context,
        sessionRepository: SessionRepository,
        playStoreAuthStore: PlayStoreAuthStore,
        sourceSelectionRepository: SourceSelectionRepository,
        authDataCache: AuthDataCache,
        googleLoginManager: GoogleLoginManager,
        microgLoginManager: MicrogLoginManager,
        anonymousLoginManager: AnonymousLoginManager,
        aasTokenConverter: OauthToAasTokenConverter,
        userProfileFetcher: UserProfileFetcher,
        successfulLoginNotifier: SuccessfulLoginNotifier,
        networkRetryPolicy: NetworkRetryPolicy,
        playStoreAuthValidator: PlayStoreAuthValidator,
        monotonicClockMs: () -> Long,
    ) : this(
        context = context,
        sessionRepository = sessionRepository,
        playStoreAuthStore = playStoreAuthStore,
        storeActivationPolicy = StoreActivationPolicy(
            sessionRepository = sessionRepository,
            sourceSelectionRepository = sourceSelectionRepository,
        ),
        authDataCache = authDataCache,
        googleLoginManager = googleLoginManager,
        microgLoginManager = microgLoginManager,
        anonymousLoginManager = anonymousLoginManager,
        aasTokenConverter = aasTokenConverter,
        userProfileFetcher = userProfileFetcher,
        successfulLoginNotifier = successfulLoginNotifier,
        networkRetryPolicy = networkRetryPolicy,
        playStoreStoredAuthPolicy = PlayStoreStoredAuthPolicy(
            playStoreAuthStore = playStoreAuthStore,
            playStoreAuthValidator = playStoreAuthValidator,
            monotonicClockMs = monotonicClockMs,
        ),
    )

    override val storeType: AuthStore = AuthStore.PLAY_STORE
    private val locale: Locale
        get() = context.resources.configuration.locales[0]
@@ -254,9 +178,9 @@ class PlayStoreAuthenticator @Inject constructor(
        val oauthToken = playStoreAuthStore.awaitOauthToken()
        val aasTokenResponse = aasTokenConverter.convert(email, oauthToken)
        return if (aasTokenResponse.isSuccess()) {
            loginWithAasTokenFromConversion(aasTokenResponse.data.orEmpty())
            loginWithPersistedAasTokenFromConversion(aasTokenResponse.data.orEmpty())
        } else {
            loginWithOauthToken(aasTokenResponse, oauthToken)
            loginWithPersistedOauthToken(aasTokenResponse, oauthToken)
        }
    }

@@ -268,15 +192,15 @@ class PlayStoreAuthenticator @Inject constructor(
            oauthToken = credentials.oauthToken,
        )
        return if (aasTokenResponse.isSuccess()) {
            loginWithAasTokenFromConversion(
            loginWithExplicitAasTokenFromConversion(
                aasToken = aasTokenResponse.data.orEmpty(),
                email = credentials.email,
            )
        } else {
            loginWithOauthToken(
            loginWithExplicitOauthToken(
                aasTokenResponse = aasTokenResponse,
                oauthToken = credentials.oauthToken,
                email = credentials.email,
                oauthToken = credentials.oauthToken,
            )
        }
    }
@@ -302,19 +226,26 @@ class PlayStoreAuthenticator @Inject constructor(
        return formatLoginResult(sessionForGoogle().login())
    }

    private suspend fun loginWithAasTokenFromConversion(
    private suspend fun loginWithPersistedAasTokenFromConversion(
        aasToken: String,
        email: String? = null,
    ): ResultSupreme<AuthData?> {
        if (aasToken.isBlank()) {
            return ResultSupreme.Error("Fetched AAS Token is blank")
        }

        return if (email == null) {
        playStoreAuthStore.saveAasToken(aasToken)
            loginWithAasToken()
        } else {
            formatLoginResult(
        return loginWithAasToken()
    }

    private suspend fun loginWithExplicitAasTokenFromConversion(
        aasToken: String,
        email: String,
    ): ResultSupreme<AuthData?> {
        if (aasToken.isBlank()) {
            return ResultSupreme.Error("Fetched AAS Token is blank")
        }

        return formatLoginResult(
            ResultSupreme.Success(
                googleLoginManager.login(
                    email = email,
@@ -324,18 +255,28 @@ class PlayStoreAuthenticator @Inject constructor(
            )
        )
    }

    private suspend fun loginWithPersistedOauthToken(
        aasTokenResponse: ResultSupreme<String>,
        oauthToken: String,
    ): ResultSupreme<AuthData?> {
        val fallbackAuth = googleLoginManager.loginWithOauthToken(oauthToken)
        return replicateOauthFallback(aasTokenResponse, fallbackAuth)
    }

    private suspend fun loginWithOauthToken(
    private suspend fun loginWithExplicitOauthToken(
        aasTokenResponse: ResultSupreme<String>,
        email: String,
        oauthToken: String,
        email: String? = null,
    ): ResultSupreme<AuthData?> {
        val fallbackAuth = if (email == null) {
            googleLoginManager.loginWithOauthToken(oauthToken)
        } else {
            googleLoginManager.loginWithOauthToken(email, oauthToken)
        val fallbackAuth = googleLoginManager.loginWithOauthToken(email, oauthToken)
        return replicateOauthFallback(aasTokenResponse, fallbackAuth)
    }

    private fun replicateOauthFallback(
        aasTokenResponse: ResultSupreme<String>,
        fallbackAuth: AuthData?,
    ): ResultSupreme<AuthData?> {
        return if (fallbackAuth != null) {
            ResultSupreme.Success<AuthData?>(authDataCache.formatAuthData(fallbackAuth))
        } else {
+0 −33
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ package foundation.e.apps.data.login.repository
import com.aurora.gplayapi.data.models.AuthData
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.login.api.PlayStoreAuthManager
import foundation.e.apps.data.login.api.PlayStoreAuthValidator
import foundation.e.apps.data.login.api.StoreAuthCoordinator
import foundation.e.apps.data.login.core.StoreAuthResult
import foundation.e.apps.data.login.core.StoreAuthenticator
@@ -48,38 +47,6 @@ class AuthenticatorRepository @Inject constructor(
) : PlayStoreAuthManager, StoreAuthCoordinator {
    private val validatedAuthMutex = Mutex()

    constructor(
        authenticators: List<StoreAuthenticator>,
        sessionRepository: SessionRepository,
        playStoreAuthStore: PlayStoreAuthStore,
        playStoreAuthValidator: PlayStoreAuthValidator,
    ) : this(
        authenticators = authenticators,
        sessionRepository = sessionRepository,
        playStoreAuthStore = playStoreAuthStore,
        playStoreStoredAuthPolicy = PlayStoreStoredAuthPolicy(
            playStoreAuthStore = playStoreAuthStore,
            playStoreAuthValidator = playStoreAuthValidator,
        ),
    )

    constructor(
        authenticators: List<StoreAuthenticator>,
        sessionRepository: SessionRepository,
        playStoreAuthStore: PlayStoreAuthStore,
        playStoreAuthValidator: PlayStoreAuthValidator,
        monotonicClockMs: () -> Long,
    ) : this(
        authenticators = authenticators,
        sessionRepository = sessionRepository,
        playStoreAuthStore = playStoreAuthStore,
        playStoreStoredAuthPolicy = PlayStoreStoredAuthPolicy(
            playStoreAuthStore = playStoreAuthStore,
            playStoreAuthValidator = playStoreAuthValidator,
            monotonicClockMs = monotonicClockMs,
        ),
    )

    override suspend fun requireValidatedPlayStoreAuth(): AuthData {
        val result = getValidatedAuthData()
        val authData = result.data
+81 −21
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import foundation.e.apps.data.NetworkRetryPolicy
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.login.api.PlayStoreAuthValidationResult
import foundation.e.apps.data.login.api.PlayStoreAuthValidator
import foundation.e.apps.data.login.core.StoreActivationPolicy
import foundation.e.apps.data.login.core.StoreAuthResult
import foundation.e.apps.data.login.microg.MicrogLoginManager
import foundation.e.apps.data.preference.PlayStoreAuthStore
@@ -45,6 +46,46 @@ class PlayStoreAuthenticatorTest {

    private fun applicationContext(): Context = ApplicationProvider.getApplicationContext()

    private fun playStoreAuthenticator(
        context: Context = applicationContext(),
        sessionRepository: SessionRepository,
        playStoreAuthStore: PlayStoreAuthStore,
        sourceSelectionRepository: SourceSelectionRepository = sourceSelectionRepository(),
        authDataCache: AuthDataCache,
        googleLoginManager: GoogleLoginManager,
        microgLoginManager: MicrogLoginManager,
        anonymousLoginManager: AnonymousLoginManager,
        aasTokenConverter: OauthToAasTokenConverter,
        userProfileFetcher: UserProfileFetcher,
        successfulLoginNotifier: SuccessfulLoginNotifier,
        networkRetryPolicy: NetworkRetryPolicy,
        playStoreAuthValidator: PlayStoreAuthValidator,
        monotonicClockMs: (() -> Long)? = null,
    ): PlayStoreAuthenticator {
        return PlayStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = playStoreAuthStore,
            storeActivationPolicy = StoreActivationPolicy(
                sessionRepository = sessionRepository,
                sourceSelectionRepository = sourceSelectionRepository,
            ),
            authDataCache = authDataCache,
            googleLoginManager = googleLoginManager,
            microgLoginManager = microgLoginManager,
            anonymousLoginManager = anonymousLoginManager,
            aasTokenConverter = aasTokenConverter,
            userProfileFetcher = userProfileFetcher,
            successfulLoginNotifier = successfulLoginNotifier,
            networkRetryPolicy = networkRetryPolicy,
            playStoreStoredAuthPolicy = createPlayStoreStoredAuthPolicy(
                playStoreAuthStore = playStoreAuthStore,
                playStoreAuthValidator = playStoreAuthValidator,
                monotonicClockMs = monotonicClockMs,
            ),
        )
    }

    private fun sourceSelectionRepository(
        isPlayStoreSelected: Boolean = true,
    ): SourceSelectionRepository {
@@ -78,7 +119,7 @@ class PlayStoreAuthenticatorTest {
        val aasTokenConverter = mockk<OauthToAasTokenConverter>()
        val userProfileFetcher = mockk<UserProfileFetcher>()

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -108,7 +149,7 @@ class PlayStoreAuthenticatorTest {

    @Test
    fun isStoreActive_awaitsPersistedLoginIntent() = runTest {
        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = FakeSessionRepository(
                initialLoginIntent = PersistedLoginIntent.NONE,
@@ -133,7 +174,7 @@ class PlayStoreAuthenticatorTest {

    @Test
    fun isStoreActive_allowsAnonymousPlayLoginWithoutPersistedAuthData() = runTest {
        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = FakeSessionRepository(
                initialLoginIntent = PersistedLoginIntent.PLAY_ANONYMOUS,
@@ -156,7 +197,7 @@ class PlayStoreAuthenticatorTest {

    @Test
    fun isStoreActive_returnsFalseWhenPlayStoreIsDeselected() = runTest {
        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = FakeSessionRepository(
                initialLoginIntent = PersistedLoginIntent.PLAY_ANONYMOUS,
@@ -179,7 +220,7 @@ class PlayStoreAuthenticatorTest {

    @Test
    fun isStoreActive_returnsFalseForNoGoogleUserEvenWhenPlayStoreIsSelected() = runTest {
        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = FakeSessionRepository(
                initialLoginIntent = PersistedLoginIntent.OPEN_SOURCE,
@@ -209,7 +250,7 @@ class PlayStoreAuthenticatorTest {
        val authData = AuthData(email = "anon@example.com", isAnonymous = true)
        coEvery { anonymousLoginManager.login() } returns authData

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = sessionRepository,
            playStoreAuthStore = mockk(relaxed = true),
@@ -244,7 +285,7 @@ class PlayStoreAuthenticatorTest {
        val authData = AuthData(email = "google@example.com")
        coEvery { googleLoginManager.login() } returns authData

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -279,7 +320,7 @@ class PlayStoreAuthenticatorTest {
        val authData = AuthData(email = "microg@example.com")
        coEvery { microgLoginManager.login() } returns authData

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -319,7 +360,7 @@ class PlayStoreAuthenticatorTest {
        val authData = AuthData(email = "anon@example.com", isAnonymous = true)
        coEvery { anonymousLoginManager.login() } returns authData

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -363,7 +404,7 @@ class PlayStoreAuthenticatorTest {

        coEvery { anonymousLoginManager.login() } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -407,7 +448,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { googleLoginManager.login() } returns authData
        coEvery { userProfileFetcher.fetch(authData) } returns profile

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -455,7 +496,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { googleLoginManager.login() } returns authData
        coEvery { userProfileFetcher.fetch(any()) } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -497,7 +538,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { googleLoginManager.login() } returns authData
        coEvery { userProfileFetcher.fetch(any()) } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -544,7 +585,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { googleLoginManager.loginWithOauthToken("oauth-token") } returns authData
        coEvery { userProfileFetcher.fetch(any()) } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -588,7 +629,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { microgLoginManager.login() } returns authData
        coEvery { userProfileFetcher.fetch(any()) } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -631,7 +672,7 @@ class PlayStoreAuthenticatorTest {
        coEvery { microgLoginManager.login() } returns authData
        coEvery { userProfileFetcher.fetch(any()) } returns null

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -666,7 +707,7 @@ class PlayStoreAuthenticatorTest {
        val anonymousLoginManager = mockk<AnonymousLoginManager>()
        val successfulLoginNotifier = FakeSuccessfulLoginNotifier()

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = applicationContext(),
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -705,7 +746,7 @@ class PlayStoreAuthenticatorTest {
        val anonymousLoginManager = mockk<AnonymousLoginManager>()
        coEvery { anonymousLoginManager.login() } returns freshAuth

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -741,7 +782,7 @@ class PlayStoreAuthenticatorTest {
        )
        val anonymousLoginManager = mockk<AnonymousLoginManager>()

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -789,7 +830,7 @@ class PlayStoreAuthenticatorTest {
        val validator = FakePlayStoreAuthValidator()
        var nowMs = 1_000L

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -833,7 +874,7 @@ class PlayStoreAuthenticatorTest {
        val validator = FakePlayStoreAuthValidator()
        var nowMs = 1_000L

        val authenticator = PlayStoreAuthenticator(
        val authenticator = playStoreAuthenticator(
            context = context,
            sessionRepository = sessionRepository,
            playStoreAuthStore = sessionRepository,
@@ -939,6 +980,25 @@ class PlayStoreAuthenticatorTest {

    private fun alwaysValidAuthValidator(): PlayStoreAuthValidator = FakePlayStoreAuthValidator()

    private fun createPlayStoreStoredAuthPolicy(
        playStoreAuthStore: PlayStoreAuthStore,
        playStoreAuthValidator: PlayStoreAuthValidator,
        monotonicClockMs: (() -> Long)? = null,
    ): PlayStoreStoredAuthPolicy {
        return if (monotonicClockMs == null) {
            PlayStoreStoredAuthPolicy(
                playStoreAuthStore = playStoreAuthStore,
                playStoreAuthValidator = playStoreAuthValidator,
            )
        } else {
            PlayStoreStoredAuthPolicy(
                playStoreAuthStore = playStoreAuthStore,
                playStoreAuthValidator = playStoreAuthValidator,
                monotonicClockMs = monotonicClockMs,
            )
        }
    }

    private class FakePlayStoreAuthValidator(
        private val validateBlock: suspend (AuthData) -> PlayStoreAuthValidationResult = {
            PlayStoreAuthValidationResult.Valid
+52 −14

File changed.

Preview size limit exceeded, changes collapsed.