Improve API, to avoid ignoring errors

This commit is contained in:
Benoit Marty 2024-05-06 23:06:25 +02:00 committed by Benoit Marty
parent d88ef8769e
commit a65c290dd3
18 changed files with 143 additions and 107 deletions

View file

@ -18,55 +18,18 @@ package io.element.android.libraries.pushproviders.unifiedpush
import android.content.Context
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.pushproviders.api.Distributor
import io.element.android.libraries.pushproviders.api.PusherSubscriber
import org.unifiedpush.android.connector.UnifiedPush
import javax.inject.Inject
class RegisterUnifiedPushUseCase @Inject constructor(
@ApplicationContext private val context: Context,
private val pusherSubscriber: PusherSubscriber,
private val unifiedPushStore: UnifiedPushStore,
) {
sealed interface RegisterUnifiedPushResult {
data object Success : RegisterUnifiedPushResult
data object NeedToAskUserForDistributor : RegisterUnifiedPushResult
data object Error : RegisterUnifiedPushResult
}
suspend fun execute(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String): RegisterUnifiedPushResult {
val distributorValue = distributor.value
if (distributorValue.isNotEmpty()) {
saveAndRegisterApp(distributorValue, clientSecret)
val endpoint = unifiedPushStore.getEndpoint(clientSecret) ?: return RegisterUnifiedPushResult.Error
val gateway = unifiedPushStore.getPushGateway(clientSecret) ?: return RegisterUnifiedPushResult.Error
pusherSubscriber.registerPusher(matrixClient, endpoint, gateway)
return RegisterUnifiedPushResult.Success
}
// TODO Below should never happen?
if (UnifiedPush.getDistributor(context).isNotEmpty()) {
registerApp(clientSecret)
return RegisterUnifiedPushResult.Success
}
val distributors = UnifiedPush.getDistributors(context)
return if (distributors.size == 1) {
saveAndRegisterApp(distributors.first(), clientSecret)
RegisterUnifiedPushResult.Success
} else {
RegisterUnifiedPushResult.NeedToAskUserForDistributor
}
}
private fun saveAndRegisterApp(distributor: String, clientSecret: String) {
UnifiedPush.saveDistributor(context, distributor)
registerApp(clientSecret)
}
private fun registerApp(clientSecret: String) {
fun execute(distributor: Distributor, clientSecret: String): Result<Unit> {
UnifiedPush.saveDistributor(context, distributor.value)
// This will trigger the callback
// VectorUnifiedPushMessagingReceiver.onNewEndpoint
UnifiedPush.registerApp(context = context, instance = clientSecret)
return Result.success(Unit)
}
}

View file

@ -16,6 +16,7 @@
package io.element.android.libraries.pushproviders.unifiedpush
import io.element.android.libraries.core.extensions.flatMap
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.pushproviders.api.PusherSubscriber
@ -35,18 +36,25 @@ class UnifiedPushNewGatewayHandler @Inject constructor(
private val pushClientSecret: PushClientSecret,
private val matrixAuthenticationService: MatrixAuthenticationService,
) {
suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String) {
suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String): Result<Unit> {
// Register the pusher for the session with this client secret, if is it using UnifiedPush.
val userId = pushClientSecret.getUserIdFromSecret(clientSecret) ?: return Unit.also {
val userId = pushClientSecret.getUserIdFromSecret(clientSecret) ?: return Result.failure<Unit>(
IllegalStateException("Unable to retrieve session")
).also {
Timber.w("Unable to retrieve session")
}
val userDataStore = userPushStoreFactory.getOrCreate(userId)
if (userDataStore.getPushProviderName() == UnifiedPushConfig.NAME) {
matrixAuthenticationService.restoreSession(userId).getOrNull()?.use { client ->
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
}
return if (userDataStore.getPushProviderName() == UnifiedPushConfig.NAME) {
matrixAuthenticationService
.restoreSession(userId)
.flatMap { client ->
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
}
} else {
Timber.tag(loggerTag.value).d("This session is not using UnifiedPush pusher")
Result.failure(
IllegalStateException("This session is not using UnifiedPush pusher")
)
}
}
}

View file

@ -58,10 +58,12 @@ class UnifiedPushProvider @Inject constructor(
return unifiedPushDistributorProvider.getDistributors()
}
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor) {
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor): Result<Unit> {
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
registerUnifiedPushUseCase.execute(matrixClient, distributor, clientSecret)
unifiedPushStore.setDistributorValue(matrixClient.sessionId, distributor.value)
return registerUnifiedPushUseCase.execute(distributor, clientSecret)
.onSuccess {
unifiedPushStore.setDistributorValue(matrixClient.sessionId, distributor.value)
}
}
override suspend fun getCurrentDistributor(matrixClient: MatrixClient): Distributor? {
@ -69,9 +71,9 @@ class UnifiedPushProvider @Inject constructor(
return getDistributors().find { it.value == distributorValue }
}
override suspend fun unregister(matrixClient: MatrixClient) {
override suspend fun unregister(matrixClient: MatrixClient): Result<Unit> {
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
unRegisterUnifiedPushUseCase.execute(matrixClient, clientSecret)
return unRegisterUnifiedPushUseCase.execute(matrixClient, clientSecret)
}
override suspend fun getCurrentUserPushConfig(): CurrentUserPushConfig? {

View file

@ -21,7 +21,6 @@ import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.pushproviders.api.PusherSubscriber
import org.unifiedpush.android.connector.UnifiedPush
import timber.log.Timber
import javax.inject.Inject
class UnregisterUnifiedPushUseCase @Inject constructor(
@ -29,18 +28,17 @@ class UnregisterUnifiedPushUseCase @Inject constructor(
private val unifiedPushStore: UnifiedPushStore,
private val pusherSubscriber: PusherSubscriber,
) {
suspend fun execute(matrixClient: MatrixClient, clientSecret: String) {
suspend fun execute(matrixClient: MatrixClient, clientSecret: String): Result<Unit> {
val endpoint = unifiedPushStore.getEndpoint(clientSecret)
val gateway = unifiedPushStore.getPushGateway(clientSecret)
if (endpoint != null && gateway != null) {
try {
pusherSubscriber.unregisterPusher(matrixClient, endpoint, gateway)
} catch (e: Exception) {
Timber.d(e, "Probably unregistering a non existing pusher")
}
if (endpoint == null || gateway == null) {
return Result.failure(IllegalStateException("No endpoint or gateway found for client secret"))
}
unifiedPushStore.storeUpEndpoint(null, clientSecret)
unifiedPushStore.storePushGateway(null, clientSecret)
UnifiedPush.unregisterApp(context)
return pusherSubscriber.unregisterPusher(matrixClient, endpoint, gateway)
.onSuccess {
unifiedPushStore.storeUpEndpoint(null, clientSecret)
unifiedPushStore.storePushGateway(null, clientSecret)
UnifiedPush.unregisterApp(context)
}
}
}

View file

@ -73,12 +73,17 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
// If the endpoint has changed
// or the gateway has changed
if (unifiedPushStore.getEndpoint(instance) != endpoint) {
unifiedPushStore.storeUpEndpoint(endpoint, instance)
coroutineScope.launch {
val gateway = unifiedPushGatewayResolver.getGateway(endpoint)
unifiedPushStore.storePushGateway(gateway, instance)
gateway?.let { pushGateway ->
newGatewayHandler.handle(endpoint, pushGateway, instance)
.onFailure {
Timber.tag(loggerTag.value).e("Failed to handle new gateway")
}
.onSuccess {
unifiedPushStore.storeUpEndpoint(endpoint, instance)
}
}
}
} else {