Ensure client secret is deleted when the user signs out.

This commit is contained in:
Benoit Marty
2024-01-16 14:34:06 +01:00
parent 504ff46f1b
commit fcb84016ca
4 changed files with 24 additions and 11 deletions

View File

@@ -29,9 +29,4 @@ interface PushClientSecret {
* Return null if not found.
*/
suspend fun getUserIdFromSecret(clientSecret: String): SessionId?
/**
* To call when the user signs out.
*/
suspend fun resetSecretForUser(userId: SessionId)
}

View File

@@ -49,6 +49,7 @@ dependencies {
testImplementation(libs.coroutines.test)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.services.appnavstate.test)
testImplementation(projects.libraries.sessionStorage.test)
androidTestImplementation(libs.coroutines.test)
androidTestImplementation(libs.test.core)

View File

@@ -22,13 +22,20 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretFactory
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
import javax.inject.Inject
@ContributesBinding(AppScope::class)
@ContributesBinding(AppScope::class, boundType = PushClientSecret::class)
class PushClientSecretImpl @Inject constructor(
private val pushClientSecretFactory: PushClientSecretFactory,
private val pushClientSecretStore: PushClientSecretStore,
) : PushClientSecret {
private val sessionObserver: SessionObserver,
) : PushClientSecret, SessionListener {
init {
observeSessions()
}
override suspend fun getSecretForUser(userId: SessionId): String {
val existingSecret = pushClientSecretStore.getSecret(userId)
if (existingSecret != null) {
@@ -43,7 +50,16 @@ class PushClientSecretImpl @Inject constructor(
return pushClientSecretStore.getUserIdFromSecret(clientSecret)
}
override suspend fun resetSecretForUser(userId: SessionId) {
pushClientSecretStore.resetSecret(userId)
private fun observeSessions() {
sessionObserver.addListener(this)
}
override suspend fun onSessionCreated(userId: String) {
// Nothing to do
}
override suspend fun onSessionDeleted(userId: String) {
// Delete the secret
pushClientSecretStore.resetSecret(SessionId(userId))
}
}

View File

@@ -18,6 +18,7 @@ package io.element.android.libraries.pushstore.impl.clientsecret
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -31,7 +32,7 @@ internal class PushClientSecretImplTest {
fun test() = runTest {
val factory = FakePushClientSecretFactory()
val store = InMemoryPushClientSecretStore()
val sut = PushClientSecretImpl(factory, store)
val sut = PushClientSecretImpl(factory, store, NoOpSessionObserver())
val secret0 = factory.getSecretForUser(0)
val secret1 = factory.getSecretForUser(1)
@@ -56,7 +57,7 @@ internal class PushClientSecretImplTest {
assertThat(sut.getUserIdFromSecret(A_UNKNOWN_SECRET)).isNull()
// User signs out
sut.resetSecretForUser(A_USER_ID_0)
sut.onSessionDeleted(A_USER_ID_0.value)
assertThat(store.getSecrets()).hasSize(1)
// Create a new secret after reset
assertThat(sut.getSecretForUser(A_USER_ID_0)).isEqualTo(secret2)