UnifiedPush WIP
This commit is contained in:
parent
95bafe4059
commit
80268156b5
28 changed files with 155 additions and 171 deletions
|
|
@ -20,7 +20,7 @@ import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
||||||
import io.element.android.libraries.push.providers.api.Distributor
|
import io.element.android.libraries.push.providers.api.Distributor
|
||||||
import io.element.android.libraries.push.providers.api.PushProvider
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
|
@ -31,7 +31,6 @@ import javax.inject.Inject
|
||||||
class DefaultPushService @Inject constructor(
|
class DefaultPushService @Inject constructor(
|
||||||
private val notificationDrawerManager: NotificationDrawerManager,
|
private val notificationDrawerManager: NotificationDrawerManager,
|
||||||
private val pushersManager: PushersManager,
|
private val pushersManager: PushersManager,
|
||||||
private val pushClientSecret: PushClientSecret,
|
|
||||||
private val userPushStoreFactory: UserPushStoreFactory,
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
private val pushProviders: Set<@JvmSuppressWildcards PushProvider>,
|
private val pushProviders: Set<@JvmSuppressWildcards PushProvider>,
|
||||||
) : PushService {
|
) : PushService {
|
||||||
|
|
@ -47,16 +46,13 @@ class DefaultPushService @Inject constructor(
|
||||||
* Get current push provider, compare with provided one, then unregister and register if different, and store change
|
* Get current push provider, compare with provided one, then unregister and register if different, and store change
|
||||||
*/
|
*/
|
||||||
override suspend fun registerWith(matrixClient: MatrixClient, pushProvider: PushProvider, distributor: Distributor) {
|
override suspend fun registerWith(matrixClient: MatrixClient, pushProvider: PushProvider, distributor: Distributor) {
|
||||||
val userPushStore = userPushStoreFactory.create(matrixClient.sessionId.value)
|
val userPushStore = userPushStoreFactory.create(matrixClient.sessionId)
|
||||||
val currentPushProviderName = userPushStore.getPushProviderName()
|
val currentPushProviderName = userPushStore.getPushProviderName()
|
||||||
if (currentPushProviderName != pushProvider.name) {
|
if (currentPushProviderName != pushProvider.name) {
|
||||||
// Unregister previous one if any
|
// Unregister previous one if any
|
||||||
pushProviders.find { it.name == currentPushProviderName }?.unregister(matrixClient)
|
pushProviders.find { it.name == currentPushProviderName }?.unregister(matrixClient)
|
||||||
}
|
}
|
||||||
|
pushProvider.registerWith(matrixClient, distributor)
|
||||||
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
|
|
||||||
pushProvider.registerWith(matrixClient, distributor, clientSecret)
|
|
||||||
|
|
||||||
// Store new value
|
// Store new value
|
||||||
userPushStore.setPushProviderName(pushProvider.name)
|
userPushStore.setPushProviderName(pushProvider.name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
|
import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
|
||||||
import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import io.element.android.libraries.push.impl.config.PushConfig
|
import io.element.android.libraries.push.impl.config.PushConfig
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
||||||
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
||||||
|
|
@ -79,7 +79,7 @@ class PushersManager @Inject constructor(
|
||||||
* Register a pusher to the server if not done yet.
|
* Register a pusher to the server if not done yet.
|
||||||
*/
|
*/
|
||||||
override suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
|
override suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
|
||||||
val userDataStore = userPushStoreFactory.create(matrixClient.sessionId.value)
|
val userDataStore = userPushStoreFactory.create(matrixClient.sessionId)
|
||||||
if (userDataStore.getCurrentRegisteredPushKey() == pushKey) {
|
if (userDataStore.getCurrentRegisteredPushKey() == pushKey) {
|
||||||
Timber.tag(loggerTag.value).d("Unnecessary to register again the same pusher")
|
Timber.tag(loggerTag.value).d("Unnecessary to register again the same pusher")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.push.api.store.PushDataStore
|
import io.element.android.libraries.push.api.store.PushDataStore
|
||||||
import io.element.android.libraries.push.impl.PushersManager
|
import io.element.android.libraries.push.impl.PushersManager
|
||||||
import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
||||||
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
|
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
|
||||||
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ interface PushProvider {
|
||||||
/**
|
/**
|
||||||
* Register the pusher to the homeserver
|
* Register the pusher to the homeserver
|
||||||
*/
|
*/
|
||||||
suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String)
|
suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregister the pusher
|
* Unregister the pusher
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.asSessionId
|
||||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||||
|
|
@ -41,15 +41,17 @@ class FirebaseNewTokenHandler @Inject constructor(
|
||||||
suspend fun handle(firebaseToken: String) {
|
suspend fun handle(firebaseToken: String) {
|
||||||
firebaseStore.storeFcmToken(firebaseToken)
|
firebaseStore.storeFcmToken(firebaseToken)
|
||||||
// Register the pusher for all the sessions
|
// Register the pusher for all the sessions
|
||||||
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
sessionStore.getAllSessions().toUserList()
|
||||||
val userDataStore = userPushStoreFactory.create(userId)
|
.map { it.asSessionId() }
|
||||||
if (userDataStore.getPushProviderName() == FirebaseConfig.name) {
|
.forEach { userId ->
|
||||||
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
val userDataStore = userPushStoreFactory.create(userId)
|
||||||
pusherSubscriber.registerPusher(client, firebaseToken, FirebaseConfig.pusher_http_url)
|
if (userDataStore.getPushProviderName() == FirebaseConfig.name) {
|
||||||
|
matrixAuthenticationService.restoreSession(userId).getOrNull()?.use { client ->
|
||||||
|
pusherSubscriber.registerPusher(client, firebaseToken, FirebaseConfig.pusher_http_url)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.push.providers.api.Distributor
|
import io.element.android.libraries.push.providers.api.Distributor
|
||||||
import io.element.android.libraries.push.providers.api.PushProvider
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ class FirebasePushProvider @Inject constructor(
|
||||||
private val firebaseStore: FirebaseStore,
|
private val firebaseStore: FirebaseStore,
|
||||||
private val firebaseTroubleshooter: FirebaseTroubleshooter,
|
private val firebaseTroubleshooter: FirebaseTroubleshooter,
|
||||||
private val pusherSubscriber: PusherSubscriber,
|
private val pusherSubscriber: PusherSubscriber,
|
||||||
|
private val pushClientSecret: PushClientSecret,
|
||||||
) : PushProvider {
|
) : PushProvider {
|
||||||
override val index = FirebaseConfig.index
|
override val index = FirebaseConfig.index
|
||||||
override val name = FirebaseConfig.name
|
override val name = FirebaseConfig.name
|
||||||
|
|
@ -38,7 +40,7 @@ class FirebasePushProvider @Inject constructor(
|
||||||
return listOf(Distributor("Firebase", "Firebase"))
|
return listOf(Distributor("Firebase", "Firebase"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String) {
|
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor) {
|
||||||
val pushKey = firebaseStore.getFcmToken() ?: return Unit.also {
|
val pushKey = firebaseStore.getFcmToken() ?: return Unit.also {
|
||||||
Timber.tag(loggerTag.value).w("Unable to register pusher, Firebase token is not known.")
|
Timber.tag(loggerTag.value).w("Unable to register pusher, Firebase token is not known.")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ class RegisterUnifiedPushUseCase @Inject constructor(
|
||||||
val distributorValue = distributor.value
|
val distributorValue = distributor.value
|
||||||
if (distributorValue.isNotEmpty()) {
|
if (distributorValue.isNotEmpty()) {
|
||||||
saveAndRegisterApp(distributorValue, clientSecret)
|
saveAndRegisterApp(distributorValue, clientSecret)
|
||||||
val endpoint = unifiedPushStore.getEndpoint() ?: return RegisterUnifiedPushResult.Error
|
val endpoint = unifiedPushStore.getEndpoint(clientSecret) ?: return RegisterUnifiedPushResult.Error
|
||||||
val gateway = unifiedPushStore.getPushGateway() ?: return RegisterUnifiedPushResult.Error
|
val gateway = unifiedPushStore.getPushGateway(clientSecret) ?: return RegisterUnifiedPushResult.Error
|
||||||
pusherSubscriber.registerPusher(matrixClient, endpoint, gateway)
|
pusherSubscriber.registerPusher(matrixClient, endpoint, gateway)
|
||||||
return RegisterUnifiedPushResult.Success
|
return RegisterUnifiedPushResult.Success
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
|
import io.element.android.libraries.network.RetrofitFactory
|
||||||
|
import io.element.android.libraries.push.providers.unifiedpush.network.UnifiedPushApi
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.net.URL
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class UnifiedPushGatewayResolver @Inject constructor(
|
||||||
|
private val retrofitFactory: RetrofitFactory,
|
||||||
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
|
) {
|
||||||
|
suspend fun getGateway(endpoint: String): String? {
|
||||||
|
val gateway = UnifiedPushConfig.default_push_gateway_http_url
|
||||||
|
val url = URL(endpoint)
|
||||||
|
val custom = "${url.protocol}://${url.host}/_matrix/push/v1/notify"
|
||||||
|
Timber.i("Testing $custom")
|
||||||
|
try {
|
||||||
|
return withContext(coroutineDispatchers.io) {
|
||||||
|
val api = retrofitFactory.create("${url.protocol}://${url.host}")
|
||||||
|
.create(UnifiedPushApi::class.java)
|
||||||
|
try {
|
||||||
|
val discoveryResponse = api.discover()
|
||||||
|
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
||||||
|
Timber.d("Using custom gateway")
|
||||||
|
return@withContext custom
|
||||||
|
}
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Timber.tag("UnifiedPushHelper").e(throwable)
|
||||||
|
}
|
||||||
|
return@withContext gateway
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
Timber.d(e, "Cannot try custom gateway")
|
||||||
|
}
|
||||||
|
return gateway
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.libraries.push.providers.unifiedpush
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|
||||||
import io.element.android.libraries.core.data.tryOrNull
|
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
|
||||||
import io.element.android.libraries.network.RetrofitFactory
|
|
||||||
import io.element.android.libraries.push.providers.unifiedpush.network.UnifiedPushApi
|
|
||||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.net.URL
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class UnifiedPushHelper @Inject constructor(
|
|
||||||
@ApplicationContext private val context: Context,
|
|
||||||
private val unifiedPushStore: UnifiedPushStore,
|
|
||||||
private val stringProvider: StringProvider,
|
|
||||||
private val retrofitFactory: RetrofitFactory,
|
|
||||||
private val coroutineDispatchers: CoroutineDispatchers,
|
|
||||||
) {
|
|
||||||
suspend fun storeCustomOrDefaultGateway(endpoint: String) {
|
|
||||||
val gateway = UnifiedPushConfig.default_push_gateway_http_url
|
|
||||||
val parsed = URL(endpoint)
|
|
||||||
val custom = "${parsed.protocol}://${parsed.host}/_matrix/push/v1/notify"
|
|
||||||
Timber.i("Testing $custom")
|
|
||||||
try {
|
|
||||||
withContext(coroutineDispatchers.io) {
|
|
||||||
val api = retrofitFactory.create("${parsed.protocol}://${parsed.host}")
|
|
||||||
.create(UnifiedPushApi::class.java)
|
|
||||||
tryOrNull { api.discover() }
|
|
||||||
?.let { discoveryResponse ->
|
|
||||||
if (discoveryResponse.unifiedpush.gateway == "matrix") {
|
|
||||||
Timber.d("Using custom gateway")
|
|
||||||
unifiedPushStore.storePushGateway(custom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
Timber.d(e, "Cannot try custom gateway")
|
|
||||||
}
|
|
||||||
unifiedPushStore.storePushGateway(gateway)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isEmbeddedDistributor() = false
|
|
||||||
|
|
||||||
fun getPrivacyFriendlyUpEndpoint(): String? {
|
|
||||||
val endpoint = getEndpointOrToken()
|
|
||||||
if (endpoint.isNullOrEmpty()) return null
|
|
||||||
if (isEmbeddedDistributor()) {
|
|
||||||
return endpoint
|
|
||||||
}
|
|
||||||
return try {
|
|
||||||
val parsed = URL(endpoint)
|
|
||||||
"${parsed.protocol}://${parsed.host}/***"
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Timber.e(e, "Error parsing unifiedpush endpoint")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getEndpointOrToken(): String? {
|
|
||||||
// TODO
|
|
||||||
return if (isEmbeddedDistributor()) "" // fcmHelper.getFcmToken()
|
|
||||||
else unifiedPushStore.getEndpoint()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPushGateway(): String? {
|
|
||||||
return if (isEmbeddedDistributor()) "" // PushConfig.pusher_http_url
|
|
||||||
else unifiedPushStore.getPushGateway()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -18,11 +18,9 @@ package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
|
||||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import io.element.android.libraries.sessionstorage.api.toUserList
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -33,21 +31,22 @@ private val loggerTag = LoggerTag("UnifiedPushNewGatewayHandler")
|
||||||
*/
|
*/
|
||||||
class UnifiedPushNewGatewayHandler @Inject constructor(
|
class UnifiedPushNewGatewayHandler @Inject constructor(
|
||||||
private val pusherSubscriber: PusherSubscriber,
|
private val pusherSubscriber: PusherSubscriber,
|
||||||
private val sessionStore: SessionStore,
|
|
||||||
private val userPushStoreFactory: UserPushStoreFactory,
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
|
private val pushClientSecret: PushClientSecret,
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||||
) {
|
) {
|
||||||
suspend fun handle(endpoint: String, pushGateway: String) {
|
suspend fun handle(endpoint: String, pushGateway: String, clientSecret: String) {
|
||||||
// Register the pusher for all the sessions which are using UnifiedPush.
|
// Register the pusher for the session with this client secret, if is it using UnifiedPush.
|
||||||
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
val userId = pushClientSecret.getUserIdFromSecret(clientSecret) ?: return Unit.also {
|
||||||
val userDataStore = userPushStoreFactory.create(userId)
|
Timber.w("Unable to retrieve session")
|
||||||
if (userDataStore.getPushProviderName() == UnifiedPushConfig.name) {
|
}
|
||||||
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
val userDataStore = userPushStoreFactory.create(userId)
|
||||||
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
|
if (userDataStore.getPushProviderName() == UnifiedPushConfig.name) {
|
||||||
}
|
matrixAuthenticationService.restoreSession(userId).getOrNull()?.use { client ->
|
||||||
} else {
|
pusherSubscriber.registerPusher(client, endpoint, pushGateway)
|
||||||
Timber.tag(loggerTag.value).d("This session is not using UnifiedPush pusher")
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Timber.tag(loggerTag.value).d("This session is not using UnifiedPush pusher")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.push.providers.api.Distributor
|
import io.element.android.libraries.push.providers.api.Distributor
|
||||||
import io.element.android.libraries.push.providers.api.PushProvider
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -29,6 +30,7 @@ class UnifiedPushProvider @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
private val registerUnifiedPushUseCase: RegisterUnifiedPushUseCase,
|
||||||
private val unRegisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
private val unRegisterUnifiedPushUseCase: UnregisterUnifiedPushUseCase,
|
||||||
|
private val pushClientSecret: PushClientSecret,
|
||||||
) : PushProvider {
|
) : PushProvider {
|
||||||
override val index = UnifiedPushConfig.index
|
override val index = UnifiedPushConfig.index
|
||||||
override val name = UnifiedPushConfig.name
|
override val name = UnifiedPushConfig.name
|
||||||
|
|
@ -45,12 +47,14 @@ class UnifiedPushProvider @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor, clientSecret: String) {
|
override suspend fun registerWith(matrixClient: MatrixClient, distributor: Distributor) {
|
||||||
|
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
|
||||||
registerUnifiedPushUseCase.execute(matrixClient, distributor, clientSecret)
|
registerUnifiedPushUseCase.execute(matrixClient, distributor, clientSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun unregister(matrixClient: MatrixClient) {
|
override suspend fun unregister(matrixClient: MatrixClient) {
|
||||||
unRegisterUnifiedPushUseCase.execute()
|
val clientSecret = pushClientSecret.getSecretForUser(matrixClient.sessionId)
|
||||||
|
unRegisterUnifiedPushUseCase.execute(clientSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun troubleshoot(): Result<Unit> {
|
override suspend fun troubleshoot(): Result<Unit> {
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,6 @@ import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.DefaultPreferences
|
import io.element.android.libraries.di.DefaultPreferences
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO EAx Store in BDD (for multisession).
|
|
||||||
*/
|
|
||||||
class UnifiedPushStore @Inject constructor(
|
class UnifiedPushStore @Inject constructor(
|
||||||
@ApplicationContext val context: Context,
|
@ApplicationContext val context: Context,
|
||||||
@DefaultPreferences private val defaultPrefs: SharedPreferences,
|
@DefaultPreferences private val defaultPrefs: SharedPreferences,
|
||||||
|
|
@ -35,8 +32,8 @@ class UnifiedPushStore @Inject constructor(
|
||||||
*
|
*
|
||||||
* @return the UnifiedPush Endpoint or null if not received
|
* @return the UnifiedPush Endpoint or null if not received
|
||||||
*/
|
*/
|
||||||
fun getEndpoint(): String? {
|
fun getEndpoint(clientSecret: String): String? {
|
||||||
return defaultPrefs.getString(PREFS_ENDPOINT_OR_TOKEN, null)
|
return defaultPrefs.getString(PREFS_ENDPOINT_OR_TOKEN + clientSecret, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -44,9 +41,9 @@ class UnifiedPushStore @Inject constructor(
|
||||||
*
|
*
|
||||||
* @param endpoint the endpoint to store
|
* @param endpoint the endpoint to store
|
||||||
*/
|
*/
|
||||||
fun storeUpEndpoint(endpoint: String?) {
|
fun storeUpEndpoint(endpoint: String?, clientSecret: String) {
|
||||||
defaultPrefs.edit {
|
defaultPrefs.edit {
|
||||||
putString(PREFS_ENDPOINT_OR_TOKEN, endpoint)
|
putString(PREFS_ENDPOINT_OR_TOKEN + clientSecret, endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,8 +52,8 @@ class UnifiedPushStore @Inject constructor(
|
||||||
*
|
*
|
||||||
* @return the Push Gateway or null if not defined
|
* @return the Push Gateway or null if not defined
|
||||||
*/
|
*/
|
||||||
fun getPushGateway(): String? {
|
fun getPushGateway(clientSecret: String): String? {
|
||||||
return defaultPrefs.getString(PREFS_PUSH_GATEWAY, null)
|
return defaultPrefs.getString(PREFS_PUSH_GATEWAY + clientSecret, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -64,9 +61,9 @@ class UnifiedPushStore @Inject constructor(
|
||||||
*
|
*
|
||||||
* @param gateway the push gateway to store
|
* @param gateway the push gateway to store
|
||||||
*/
|
*/
|
||||||
fun storePushGateway(gateway: String?) {
|
fun storePushGateway(gateway: String?, clientSecret: String) {
|
||||||
defaultPrefs.edit {
|
defaultPrefs.edit {
|
||||||
putString(PREFS_PUSH_GATEWAY, gateway)
|
putString(PREFS_PUSH_GATEWAY + clientSecret, gateway)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,22 +26,22 @@ class UnregisterUnifiedPushUseCase @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
//private val pushDataStore: PushDataStore,
|
//private val pushDataStore: PushDataStore,
|
||||||
private val unifiedPushStore: UnifiedPushStore,
|
private val unifiedPushStore: UnifiedPushStore,
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
private val unifiedPushGatewayResolver: UnifiedPushGatewayResolver,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun execute(/*pushersManager: PushersManager?*/) {
|
suspend fun execute(clientSecret: String /*pushersManager: PushersManager?*/) {
|
||||||
//val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
//val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||||
//pushDataStore.setFdroidSyncBackgroundMode(mode)
|
//pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||||
try {
|
try {
|
||||||
unifiedPushHelper.getEndpointOrToken()?.let {
|
unifiedPushStore.getEndpoint(clientSecret)?.let {
|
||||||
Timber.d("Removing $it")
|
Timber.d("Removing $it")
|
||||||
// TODO pushersManager?.unregisterPusher(it)
|
// TODO pushersManager?.unregisterPusher(it)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.d(e, "Probably unregistering a non existing pusher")
|
Timber.d(e, "Probably unregistering a non existing pusher")
|
||||||
}
|
}
|
||||||
unifiedPushStore.storeUpEndpoint(null)
|
unifiedPushStore.storeUpEndpoint(null, clientSecret)
|
||||||
unifiedPushStore.storePushGateway(null)
|
unifiedPushStore.storePushGateway(null, clientSecret)
|
||||||
UnifiedPush.unregisterApp(context)
|
UnifiedPush.unregisterApp(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import android.content.Intent
|
||||||
import io.element.android.libraries.architecture.bindings
|
import io.element.android.libraries.architecture.bindings
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.push.providers.api.PushHandler
|
import io.element.android.libraries.push.providers.api.PushHandler
|
||||||
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -33,13 +32,10 @@ private val loggerTag = LoggerTag("VectorUnifiedPushMessagingReceiver")
|
||||||
|
|
||||||
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
@Inject lateinit var pushParser: UnifiedPushParser
|
@Inject lateinit var pushParser: UnifiedPushParser
|
||||||
|
|
||||||
// @Inject lateinit var pushDataStore: PushDataStore
|
|
||||||
@Inject lateinit var pushHandler: PushHandler
|
@Inject lateinit var pushHandler: PushHandler
|
||||||
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
||||||
@Inject lateinit var unifiedPushStore: UnifiedPushStore
|
@Inject lateinit var unifiedPushStore: UnifiedPushStore
|
||||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
@Inject lateinit var unifiedPushGatewayResolver: UnifiedPushGatewayResolver
|
||||||
@Inject lateinit var pusherSubscriber: PusherSubscriber
|
|
||||||
@Inject lateinit var newGatewayHandler: UnifiedPushNewGatewayHandler
|
@Inject lateinit var newGatewayHandler: UnifiedPushNewGatewayHandler
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
private val coroutineScope = CoroutineScope(SupervisorJob())
|
||||||
|
|
@ -71,25 +67,23 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
/**
|
/**
|
||||||
* Called when a new endpoint is to be used for sending push messages.
|
* Called when a new endpoint is to be used for sending push messages.
|
||||||
* You should send the endpoint to your application server and sync for missing notifications.
|
* You should send the endpoint to your application server and sync for missing notifications.
|
||||||
* TODO use [instance] for multi-account
|
|
||||||
*/
|
*/
|
||||||
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||||
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
||||||
// If the endpoint has changed
|
// If the endpoint has changed
|
||||||
// or the gateway has changed
|
// or the gateway has changed
|
||||||
if (unifiedPushHelper.getEndpointOrToken() != endpoint) {
|
if (unifiedPushStore.getEndpoint(instance) != endpoint) {
|
||||||
unifiedPushStore.storeUpEndpoint(endpoint)
|
unifiedPushStore.storeUpEndpoint(endpoint, instance)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
unifiedPushHelper.storeCustomOrDefaultGateway(endpoint)
|
val gateway = unifiedPushGatewayResolver.getGateway(endpoint)
|
||||||
unifiedPushHelper.getPushGateway()?.let { pushGateway ->
|
unifiedPushStore.storePushGateway(gateway, instance)
|
||||||
newGatewayHandler.handle(endpoint, pushGateway)
|
gateway?.let { pushGateway ->
|
||||||
|
newGatewayHandler.handle(endpoint, pushGateway, instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.tag(loggerTag.value).i("onNewEndpoint: skipped")
|
Timber.tag(loggerTag.value).i("onNewEndpoint: skipped")
|
||||||
}
|
}
|
||||||
//val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
|
|
||||||
//pushDataStore.setFdroidSyncBackgroundMode(mode)
|
|
||||||
guardServiceStarter.stop()
|
guardServiceStarter.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,5 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,11 @@
|
||||||
|
|
||||||
package io.element.android.libraries.pushstore.api
|
package io.element.android.libraries.pushstore.api
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store data related to push about a user.
|
* Store data related to push about a user.
|
||||||
*/
|
*/
|
||||||
interface UserPushStoreFactory {
|
interface UserPushStoreFactory {
|
||||||
fun create(userId: String): UserPushStore
|
fun create(userId: SessionId): UserPushStore
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.api.clientsecret
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.api.clientsecret
|
||||||
|
|
||||||
interface PushClientSecretFactory {
|
interface PushClientSecretFactory {
|
||||||
fun create(): String
|
fun create(): String
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.api.clientsecret
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
||||||
|
|
@ -31,8 +31,17 @@ dependencies {
|
||||||
implementation(libs.dagger)
|
implementation(libs.dagger)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.core)
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
implementation(projects.libraries.pushstore.api)
|
implementation(projects.libraries.pushstore.api)
|
||||||
implementation(projects.libraries.sessionStorage.api)
|
implementation(projects.libraries.sessionStorage.api)
|
||||||
implementation(libs.androidx.corektx)
|
implementation(libs.androidx.corektx)
|
||||||
implementation(libs.androidx.datastore.preferences)
|
implementation(libs.androidx.datastore.preferences)
|
||||||
|
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.mockk)
|
||||||
|
testImplementation(libs.test.truth)
|
||||||
|
testImplementation(libs.test.turbine)
|
||||||
|
testImplementation(libs.coroutines.test)
|
||||||
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
testImplementation(projects.services.appnavstate.test)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.SingleIn
|
import io.element.android.libraries.di.SingleIn
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.matrix.api.core.asSessionId
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
||||||
|
|
@ -38,8 +40,8 @@ class DefaultUserPushStoreFactory @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can have only one class accessing a single data store, so keep a cache of them.
|
// We can have only one class accessing a single data store, so keep a cache of them.
|
||||||
private val cache = mutableMapOf<String, UserPushStore>()
|
private val cache = mutableMapOf<SessionId, UserPushStore>()
|
||||||
override fun create(userId: String): UserPushStore {
|
override fun create(userId: SessionId): UserPushStore {
|
||||||
return cache.getOrPut(userId) {
|
return cache.getOrPut(userId) {
|
||||||
UserPushStoreDataStore(
|
UserPushStoreDataStore(
|
||||||
context = context,
|
context = context,
|
||||||
|
|
@ -58,6 +60,6 @@ class DefaultUserPushStoreFactory @Inject constructor(
|
||||||
|
|
||||||
override suspend fun onSessionDeleted(userId: String) {
|
override suspend fun onSessionDeleted(userId: String) {
|
||||||
// Delete the store
|
// Delete the store
|
||||||
create(userId).reset()
|
create(userId.asSessionId()).reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ import kotlinx.coroutines.flow.first
|
||||||
*/
|
*/
|
||||||
class UserPushStoreDataStore(
|
class UserPushStoreDataStore(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
userId: String,
|
userId: SessionId,
|
||||||
) : UserPushStore {
|
) : UserPushStore {
|
||||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store_$userId")
|
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store_$userId")
|
||||||
private val pushProviderName = stringPreferencesKey("pushProviderName")
|
private val pushProviderName = stringPreferencesKey("pushProviderName")
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretFactory
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -14,11 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
@ContributesBinding(AppScope::class)
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
|
|
@ -27,6 +27,7 @@ import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.core.asSessionId
|
import io.element.android.libraries.matrix.api.core.asSessionId
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -14,7 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretFactory
|
||||||
|
|
||||||
private const val A_SECRET_PREFIX = "A_SECRET_"
|
private const val A_SECRET_PREFIX = "A_SECRET_"
|
||||||
|
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
|
||||||
|
|
||||||
class InMemoryPushClientSecretStore : PushClientSecretStore {
|
class InMemoryPushClientSecretStore : PushClientSecretStore {
|
||||||
private val secrets = mutableMapOf<SessionId, String>()
|
private val secrets = mutableMapOf<SessionId, String>()
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.clientsecret
|
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
Loading…
Add table
Add a link
Reference in a new issue