Make PushData.clientSecret mandatory.
Also do not restore the last session as a fallback, it can lead to error in a multi account context, or even when a ghost pusher send a Push.
This commit is contained in:
committed by
Benoit Marty
parent
807b066520
commit
b9df8f969a
@@ -16,7 +16,6 @@ import io.element.android.features.call.api.ElementCallEntryPoint
|
|||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
|
||||||
import io.element.android.libraries.matrix.api.exception.NotificationResolverException
|
import io.element.android.libraries.matrix.api.exception.NotificationResolverException
|
||||||
import io.element.android.libraries.push.impl.history.PushHistoryService
|
import io.element.android.libraries.push.impl.history.PushHistoryService
|
||||||
import io.element.android.libraries.push.impl.history.onDiagnosticPush
|
import io.element.android.libraries.push.impl.history.onDiagnosticPush
|
||||||
@@ -58,7 +57,6 @@ class DefaultPushHandler(
|
|||||||
private val userPushStoreFactory: UserPushStoreFactory,
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
private val pushClientSecret: PushClientSecret,
|
private val pushClientSecret: PushClientSecret,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
|
||||||
private val diagnosticPushHandler: DiagnosticPushHandler,
|
private val diagnosticPushHandler: DiagnosticPushHandler,
|
||||||
private val elementCallEntryPoint: ElementCallEntryPoint,
|
private val elementCallEntryPoint: ElementCallEntryPoint,
|
||||||
private val notificationChannels: NotificationChannels,
|
private val notificationChannels: NotificationChannels,
|
||||||
@@ -241,32 +239,15 @@ class DefaultPushHandler(
|
|||||||
} else {
|
} else {
|
||||||
Timber.tag(loggerTag.value).d("## handleInternal()")
|
Timber.tag(loggerTag.value).d("## handleInternal()")
|
||||||
}
|
}
|
||||||
val clientSecret = pushData.clientSecret
|
// Get userId from client secret
|
||||||
// clientSecret should not be null. If this happens, restore default session
|
val userId = pushClientSecret.getUserIdFromSecret(pushData.clientSecret)
|
||||||
var reason = if (clientSecret == null) "No client secret" else ""
|
|
||||||
val userId = clientSecret?.let {
|
|
||||||
// Get userId from client secret
|
|
||||||
pushClientSecret.getUserIdFromSecret(clientSecret).also {
|
|
||||||
if (it == null) {
|
|
||||||
reason = "Unable to get userId from client secret"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?: run {
|
|
||||||
matrixAuthenticationService.getLatestSessionId().also {
|
|
||||||
if (it == null) {
|
|
||||||
if (reason.isNotEmpty()) reason += " - "
|
|
||||||
reason += "Unable to get latest sessionId"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
Timber.w("Unable to get a session")
|
Timber.w("Unable to get userId from client secret")
|
||||||
pushHistoryService.onUnableToRetrieveSession(
|
pushHistoryService.onUnableToRetrieveSession(
|
||||||
providerInfo = providerInfo,
|
providerInfo = providerInfo,
|
||||||
eventId = pushData.eventId,
|
eventId = pushData.eventId,
|
||||||
roomId = pushData.roomId,
|
roomId = pushData.roomId,
|
||||||
reason = reason,
|
reason = "Unable to get userId from client secret",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import com.google.common.truth.Truth.assertThat
|
|||||||
import io.element.android.features.call.api.CallType
|
import io.element.android.features.call.api.CallType
|
||||||
import io.element.android.features.call.test.FakeElementCallEntryPoint
|
import io.element.android.features.call.test.FakeElementCallEntryPoint
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
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.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
@@ -28,7 +27,6 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
|
|||||||
import io.element.android.libraries.matrix.test.A_SECRET
|
import io.element.android.libraries.matrix.test.A_SECRET
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
|
||||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||||
import io.element.android.libraries.push.impl.history.FakePushHistoryService
|
import io.element.android.libraries.push.impl.history.FakePushHistoryService
|
||||||
import io.element.android.libraries.push.impl.history.PushHistoryService
|
import io.element.android.libraries.push.impl.history.PushHistoryService
|
||||||
@@ -181,7 +179,7 @@ class DefaultPushHandlerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when PushData is received, but client secret is not known, fallback the latest session`() =
|
fun `when PushData is received, but client secret is not known, nothing happen`() =
|
||||||
runTest {
|
runTest {
|
||||||
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
||||||
val notifiableEventResult =
|
val notifiableEventResult =
|
||||||
@@ -207,58 +205,6 @@ class DefaultPushHandlerTest {
|
|||||||
pushClientSecret = FakePushClientSecret(
|
pushClientSecret = FakePushClientSecret(
|
||||||
getUserIdFromSecretResult = { null }
|
getUserIdFromSecretResult = { null }
|
||||||
),
|
),
|
||||||
matrixAuthenticationService = FakeMatrixAuthenticationService().apply {
|
|
||||||
getLatestSessionIdLambda = { A_USER_ID }
|
|
||||||
},
|
|
||||||
incrementPushCounterResult = incrementPushCounterResult,
|
|
||||||
pushHistoryService = pushHistoryService,
|
|
||||||
)
|
|
||||||
defaultPushHandler.handle(aPushData, A_PUSHER_INFO)
|
|
||||||
|
|
||||||
advanceTimeBy(300.milliseconds)
|
|
||||||
|
|
||||||
incrementPushCounterResult.assertions()
|
|
||||||
.isCalledOnce()
|
|
||||||
notifiableEventResult.assertions()
|
|
||||||
.isCalledOnce()
|
|
||||||
.with(value(A_USER_ID), any())
|
|
||||||
onNotifiableEventsReceived.assertions()
|
|
||||||
.isCalledOnce()
|
|
||||||
.with(value(listOf(aNotifiableMessageEvent)))
|
|
||||||
onPushReceivedResult.assertions()
|
|
||||||
.isCalledOnce()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `when PushData is received, but client secret is not known, and there is no latest session, nothing happen`() =
|
|
||||||
runTest {
|
|
||||||
val aNotifiableMessageEvent = aNotifiableMessageEvent()
|
|
||||||
val notifiableEventResult =
|
|
||||||
lambdaRecorder<SessionId, List<NotificationEventRequest>, Result<Map<NotificationEventRequest, Result<ResolvedPushEvent>>>> { _, _ ->
|
|
||||||
val request = NotificationEventRequest(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID, A_PUSHER_INFO)
|
|
||||||
Result.success(mapOf(request to Result.success(ResolvedPushEvent.Event(aNotifiableMessageEvent))))
|
|
||||||
}
|
|
||||||
val onNotifiableEventsReceived = lambdaRecorder<List<NotifiableEvent>, Unit> {}
|
|
||||||
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
|
||||||
val aPushData = PushData(
|
|
||||||
eventId = AN_EVENT_ID,
|
|
||||||
roomId = A_ROOM_ID,
|
|
||||||
unread = 0,
|
|
||||||
clientSecret = A_SECRET,
|
|
||||||
)
|
|
||||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
|
||||||
val pushHistoryService = FakePushHistoryService(
|
|
||||||
onPushReceivedResult = onPushReceivedResult,
|
|
||||||
)
|
|
||||||
val defaultPushHandler = createDefaultPushHandler(
|
|
||||||
onNotifiableEventsReceived = onNotifiableEventsReceived,
|
|
||||||
notifiableEventsResult = notifiableEventResult,
|
|
||||||
pushClientSecret = FakePushClientSecret(
|
|
||||||
getUserIdFromSecretResult = { null }
|
|
||||||
),
|
|
||||||
matrixAuthenticationService = FakeMatrixAuthenticationService().apply {
|
|
||||||
getLatestSessionIdLambda = { null }
|
|
||||||
},
|
|
||||||
incrementPushCounterResult = incrementPushCounterResult,
|
incrementPushCounterResult = incrementPushCounterResult,
|
||||||
pushHistoryService = pushHistoryService,
|
pushHistoryService = pushHistoryService,
|
||||||
)
|
)
|
||||||
@@ -655,8 +601,8 @@ class DefaultPushHandlerTest {
|
|||||||
var receivedFallbackEvent = false
|
var receivedFallbackEvent = false
|
||||||
val onPushReceivedResult =
|
val onPushReceivedResult =
|
||||||
lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, isResolved, _, comment ->
|
lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, isResolved, _, comment ->
|
||||||
receivedFallbackEvent = !isResolved && comment == "Unable to resolve event: ${aNotifiableFallbackEvent.cause}"
|
receivedFallbackEvent = !isResolved && comment == "Unable to resolve event: ${aNotifiableFallbackEvent.cause}"
|
||||||
}
|
}
|
||||||
val pushHistoryService = FakePushHistoryService(
|
val pushHistoryService = FakePushHistoryService(
|
||||||
onPushReceivedResult = onPushReceivedResult,
|
onPushReceivedResult = onPushReceivedResult,
|
||||||
)
|
)
|
||||||
@@ -694,7 +640,6 @@ class DefaultPushHandlerTest {
|
|||||||
userPushStore: UserPushStore = FakeUserPushStore(),
|
userPushStore: UserPushStore = FakeUserPushStore(),
|
||||||
pushClientSecret: PushClientSecret = FakePushClientSecret(),
|
pushClientSecret: PushClientSecret = FakePushClientSecret(),
|
||||||
buildMeta: BuildMeta = aBuildMeta(),
|
buildMeta: BuildMeta = aBuildMeta(),
|
||||||
matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(),
|
|
||||||
diagnosticPushHandler: DiagnosticPushHandler = DiagnosticPushHandler(),
|
diagnosticPushHandler: DiagnosticPushHandler = DiagnosticPushHandler(),
|
||||||
elementCallEntryPoint: FakeElementCallEntryPoint = FakeElementCallEntryPoint(),
|
elementCallEntryPoint: FakeElementCallEntryPoint = FakeElementCallEntryPoint(),
|
||||||
notificationChannels: FakeNotificationChannels = FakeNotificationChannels(),
|
notificationChannels: FakeNotificationChannels = FakeNotificationChannels(),
|
||||||
@@ -712,7 +657,6 @@ class DefaultPushHandlerTest {
|
|||||||
userPushStoreFactory = FakeUserPushStoreFactory { userPushStore },
|
userPushStoreFactory = FakeUserPushStoreFactory { userPushStore },
|
||||||
pushClientSecret = pushClientSecret,
|
pushClientSecret = pushClientSecret,
|
||||||
buildMeta = buildMeta,
|
buildMeta = buildMeta,
|
||||||
matrixAuthenticationService = matrixAuthenticationService,
|
|
||||||
diagnosticPushHandler = diagnosticPushHandler,
|
diagnosticPushHandler = diagnosticPushHandler,
|
||||||
elementCallEntryPoint = elementCallEntryPoint,
|
elementCallEntryPoint = elementCallEntryPoint,
|
||||||
notificationChannels = notificationChannels,
|
notificationChannels = notificationChannels,
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ data class PushData(
|
|||||||
val eventId: EventId,
|
val eventId: EventId,
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val unread: Int?,
|
val unread: Int?,
|
||||||
val clientSecret: String?,
|
val clientSecret: String,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -34,10 +34,11 @@ data class PushDataFirebase(
|
|||||||
fun PushDataFirebase.toPushData(): PushData? {
|
fun PushDataFirebase.toPushData(): PushData? {
|
||||||
val safeEventId = eventId?.let(::EventId) ?: return null
|
val safeEventId = eventId?.let(::EventId) ?: return null
|
||||||
val safeRoomId = roomId?.let(::RoomId) ?: return null
|
val safeRoomId = roomId?.let(::RoomId) ?: return null
|
||||||
|
val safeClientSecret = clientSecret ?: return null
|
||||||
return PushData(
|
return PushData(
|
||||||
eventId = safeEventId,
|
eventId = safeEventId,
|
||||||
roomId = safeRoomId,
|
roomId = safeRoomId,
|
||||||
unread = unread,
|
unread = unread,
|
||||||
clientSecret = clientSecret,
|
clientSecret = safeClientSecret,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ class FirebasePushParserTest {
|
|||||||
assertThrowsInDebug { pushParser.parse(FIREBASE_PUSH_DATA.mutate("event_id", "")) }
|
assertThrowsInDebug { pushParser.parse(FIREBASE_PUSH_DATA.mutate("event_id", "")) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test empty client secret`() {
|
||||||
|
val pushParser = FirebasePushParser()
|
||||||
|
assertThat(pushParser.parse(FIREBASE_PUSH_DATA.mutate("cs", null))).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test invalid eventId`() {
|
fun `test invalid eventId`() {
|
||||||
val pushParser = FirebasePushParser()
|
val pushParser = FirebasePushParser()
|
||||||
|
|||||||
Reference in New Issue
Block a user