Ensure authentication token is always sent when it exists (#193)
* Ensure auth token is sent if it is present * Allow using login token for other requests while API token is created * Update version code
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import com.android.build.api.dsl.ManagedVirtualDevice
|
||||
import java.io.FileInputStream
|
||||
import java.util.*
|
||||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
id("gq.kirmanak.mealient.application")
|
||||
@@ -17,8 +17,8 @@ plugins {
|
||||
android {
|
||||
defaultConfig {
|
||||
applicationId = "gq.kirmanak.mealient"
|
||||
versionCode = 33
|
||||
versionName = "0.4.4"
|
||||
versionCode = 34
|
||||
versionName = "0.4.5"
|
||||
testInstrumentationRunner = "gq.kirmanak.mealient.MealientTestRunner"
|
||||
testInstrumentationRunnerArguments += mapOf("clearPackageData" to "true")
|
||||
resourceConfigurations += listOf("en", "es", "ru", "fr", "nl", "pt", "de")
|
||||
|
||||
@@ -4,7 +4,6 @@ import gq.kirmanak.mealient.data.auth.AuthDataSource
|
||||
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.datasource.AuthenticationProvider
|
||||
import gq.kirmanak.mealient.datasource.SignOutHandler
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
@@ -14,7 +13,6 @@ class AuthRepoImpl @Inject constructor(
|
||||
private val authStorage: AuthStorage,
|
||||
private val authDataSource: AuthDataSource,
|
||||
private val logger: Logger,
|
||||
private val signOutHandler: SignOutHandler,
|
||||
private val credentialsLogRedactor: CredentialsLogRedactor,
|
||||
) : AuthRepo, AuthenticationProvider {
|
||||
|
||||
@@ -23,12 +21,14 @@ class AuthRepoImpl @Inject constructor(
|
||||
|
||||
override suspend fun authenticate(email: String, password: String) {
|
||||
logger.v { "authenticate() called" }
|
||||
|
||||
credentialsLogRedactor.set(email, password)
|
||||
val token = authDataSource.authenticate(email, password)
|
||||
credentialsLogRedactor.clear()
|
||||
authStorage.setAuthToken(token)
|
||||
|
||||
val apiToken = authDataSource.createApiToken(API_TOKEN_NAME)
|
||||
authStorage.setAuthToken(apiToken)
|
||||
credentialsLogRedactor.clear()
|
||||
}
|
||||
|
||||
override suspend fun getAuthToken(): String? = authStorage.getAuthToken()
|
||||
@@ -36,7 +36,6 @@ class AuthRepoImpl @Inject constructor(
|
||||
override suspend fun logout() {
|
||||
logger.v { "logout() called" }
|
||||
authStorage.setAuthToken(null)
|
||||
signOutHandler.signOut()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.SharedPreferences
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.edit
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.datasource.TokenChangeListener
|
||||
import gq.kirmanak.mealient.datastore.DataStoreModule.Companion.ENCRYPTED
|
||||
import gq.kirmanak.mealient.extensions.prefsChangeFlow
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
@@ -19,6 +20,7 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AuthStorageImpl @Inject constructor(
|
||||
@Named(ENCRYPTED) private val sharedPreferences: SharedPreferences,
|
||||
private val tokenChangeListener: TokenChangeListener,
|
||||
private val logger: Logger,
|
||||
) : AuthStorage {
|
||||
|
||||
@@ -28,7 +30,11 @@ class AuthStorageImpl @Inject constructor(
|
||||
.distinctUntilChanged()
|
||||
private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
|
||||
override suspend fun setAuthToken(authToken: String?) = putString(AUTH_TOKEN_KEY, authToken)
|
||||
override suspend fun setAuthToken(authToken: String?) {
|
||||
logger.v { "setAuthToken() called with: authToken = $authToken" }
|
||||
tokenChangeListener.onTokenChange()
|
||||
putString(AUTH_TOKEN_KEY, authToken)
|
||||
}
|
||||
|
||||
override suspend fun getAuthToken(): String? = getString(AUTH_TOKEN_KEY)
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class AuthenticationViewModel @Inject constructor(
|
||||
_uiState.value = OperationUiState.Progress()
|
||||
viewModelScope.launch {
|
||||
val result = runCatchingExceptCancel { authRepo.authenticate(email, password) }
|
||||
logger.d { "Authentication result = $result" }
|
||||
_uiState.value = OperationUiState.fromResult(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.google.common.truth.Truth.assertThat
|
||||
import gq.kirmanak.mealient.data.auth.AuthDataSource
|
||||
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.datasource.SignOutHandler
|
||||
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
|
||||
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_API_TOKEN
|
||||
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_PASSWORD
|
||||
@@ -31,9 +30,6 @@ class AuthRepoImplTest : BaseUnitTest() {
|
||||
@MockK(relaxUnitFun = true)
|
||||
lateinit var storage: AuthStorage
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
lateinit var signOutHandler: SignOutHandler
|
||||
|
||||
@RelaxedMockK
|
||||
lateinit var credentialsLogRedactor: CredentialsLogRedactor
|
||||
|
||||
@@ -46,7 +42,6 @@ class AuthRepoImplTest : BaseUnitTest() {
|
||||
authStorage = storage,
|
||||
authDataSource = dataSource,
|
||||
logger = logger,
|
||||
signOutHandler = signOutHandler,
|
||||
credentialsLogRedactor = credentialsLogRedactor,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.data.auth.impl.AuthStorageImpl.Companion.AUTH_TOKEN_KEY
|
||||
import gq.kirmanak.mealient.datasource.TokenChangeListener
|
||||
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_TOKEN
|
||||
import gq.kirmanak.mealient.test.HiltRobolectricTest
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
@@ -28,11 +30,14 @@ class AuthStorageImplTest : HiltRobolectricTest() {
|
||||
|
||||
lateinit var sharedPreferences: SharedPreferences
|
||||
|
||||
@MockK
|
||||
lateinit var tokenChangeListener: TokenChangeListener
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
sharedPreferences = context.getSharedPreferences("test", Context.MODE_PRIVATE)
|
||||
subject = AuthStorageImpl(sharedPreferences, logger)
|
||||
subject = AuthStorageImpl(sharedPreferences, tokenChangeListener, logger)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user