From 68a9ef18e656e62653744161c4abca31ff7611f8 Mon Sep 17 00:00:00 2001 From: David Perez Date: Wed, 31 Jan 2024 16:16:50 -0600 Subject: [PATCH] BIT-1567: Do process auth requests if feature is disabled (#912) --- .../data/platform/manager/PushManagerImpl.kt | 24 ++++---- .../manager/di/PlatformManagerModule.kt | 2 + .../data/platform/manager/PushManagerTest.kt | 60 +++++++++++++++++-- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/PushManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/PushManagerImpl.kt index 5a91293962..93d39164d6 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/PushManagerImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/PushManagerImpl.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.platform.manager import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource +import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest import com.x8bit.bitwarden.data.platform.datasource.network.service.PushService import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager @@ -35,8 +36,10 @@ import javax.inject.Inject /** * Primary implementation of [PushManager]. */ +@Suppress("LongParameterList") class PushManagerImpl @Inject constructor( private val authDiskSource: AuthDiskSource, + private val settingsDiskSource: SettingsDiskSource, private val pushDiskSource: PushDiskSource, private val pushService: PushService, private val clock: Clock, @@ -118,20 +121,22 @@ class PushManagerImpl @Inject constructor( if (authDiskSource.uniqueAppId == notification.contextId) return - val userId = activeUserId + val userId = activeUserId ?: return when (val type = notification.notificationType) { NotificationType.AUTH_REQUEST, NotificationType.AUTH_REQUEST_RESPONSE, -> { - val payload: NotificationPayload.PasswordlessRequestNotification = - json.decodeFromJsonElement(notification.payload) - mutablePasswordlessRequestSharedFlow.tryEmit( - PasswordlessRequestData( - loginRequestId = payload.id, - userId = payload.userId, - ), - ) + if (settingsDiskSource.getApprovePasswordlessLoginsEnabled(userId) == true) { + val payload: NotificationPayload.PasswordlessRequestNotification = + json.decodeFromJsonElement(notification.payload) + mutablePasswordlessRequestSharedFlow.tryEmit( + PasswordlessRequestData( + loginRequestId = payload.id, + userId = payload.userId, + ), + ) + } } NotificationType.LOG_OUT -> { @@ -171,7 +176,6 @@ class PushManagerImpl @Inject constructor( NotificationType.SYNC_SETTINGS, NotificationType.SYNC_VAULT, -> { - if (userId == null) return mutableFullSyncSharedFlow.tryEmit(Unit) } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt index 50b8a289ea..9df738fdae 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/di/PlatformManagerModule.kt @@ -128,6 +128,7 @@ object PlatformManagerModule { @Singleton fun providePushManager( authDiskSource: AuthDiskSource, + settingsDiskSource: SettingsDiskSource, pushDiskSource: PushDiskSource, pushService: PushService, dispatcherManager: DispatcherManager, @@ -135,6 +136,7 @@ object PlatformManagerModule { json: Json, ): PushManager = PushManagerImpl( authDiskSource = authDiskSource, + settingsDiskSource = settingsDiskSource, pushDiskSource = pushDiskSource, pushService = pushService, dispatcherManager = dispatcherManager, diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/PushManagerTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/PushManagerTest.kt index 563e12e53b..64e5fe9dee 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/PushManagerTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/manager/PushManagerTest.kt @@ -9,6 +9,8 @@ import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager import com.x8bit.bitwarden.data.platform.base.FakeSharedPreferences import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSourceImpl +import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource +import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule import com.x8bit.bitwarden.data.platform.datasource.network.model.PushTokenRequest import com.x8bit.bitwarden.data.platform.datasource.network.service.PushService @@ -37,18 +39,19 @@ import java.time.Instant import java.time.ZoneOffset import java.time.ZonedDateTime import java.time.temporal.ChronoUnit -import java.util.TimeZone class PushManagerTest { private val clock = Clock.fixed( Instant.parse("2023-10-27T12:00:00Z"), - TimeZone.getTimeZone("UTC").toZoneId(), + ZoneOffset.UTC, ) private val dispatcherManager: DispatcherManager = FakeDispatcherManager() private val authDiskSource: AuthDiskSource = FakeAuthDiskSource() + private val settingsDiskSource: SettingsDiskSource = FakeSettingsDiskSource() + private val pushDiskSource: PushDiskSource = PushDiskSourceImpl(FakeSharedPreferences()) private val pushService: PushService = mockk() @@ -59,6 +62,7 @@ class PushManagerTest { fun setUp() { pushManager = PushManagerImpl( authDiskSource = authDiskSource, + settingsDiskSource = settingsDiskSource, pushDiskSource = pushDiskSource, pushService = pushService, dispatcherManager = dispatcherManager, @@ -69,14 +73,43 @@ class PushManagerTest { @Nested inner class PushNotificationHandling { + private val userId = "any user ID" + + @BeforeEach + fun setup() { + val account = mockk { + every { isLoggedIn } returns false + } + authDiskSource.userState = UserStateJson(userId, mapOf(userId to account)) + } + @Test fun `onMessageReceived invalid JSON does not crash`() { pushManager.onMessageReceived(INVALID_NOTIFICATION_JSON) } + @Suppress("MaxLineLength") @Test - fun `onMessageReceived auth request emits to passwordlessRequestFlow`() = + fun `onMessageReceived auth request emits to nothing when getApprovePasswordlessLoginsEnabled is not true`() = runTest { + settingsDiskSource.storeApprovePasswordlessLoginsEnabled( + userId = userId, + isApprovePasswordlessLoginsEnabled = false, + ) + pushManager.passwordlessRequestFlow.test { + pushManager.onMessageReceived(AUTH_REQUEST_NOTIFICATION_JSON) + expectNoEvents() + } + } + + @Suppress("MaxLineLength") + @Test + fun `onMessageReceived auth request emits to passwordlessRequestFlow when getApprovePasswordlessLoginsEnabled is true`() = + runTest { + settingsDiskSource.storeApprovePasswordlessLoginsEnabled( + userId = userId, + isApprovePasswordlessLoginsEnabled = true, + ) pushManager.passwordlessRequestFlow.test { pushManager.onMessageReceived(AUTH_REQUEST_NOTIFICATION_JSON) assertEquals( @@ -89,9 +122,28 @@ class PushManagerTest { } } + @Suppress("MaxLineLength") @Test - fun `onMessageReceived auth request response emits to passwordlessRequestFlow`() = + fun `onMessageReceived auth request response emits nothing when getApprovePasswordlessLoginsEnabled is not true`() = runTest { + settingsDiskSource.storeApprovePasswordlessLoginsEnabled( + userId = userId, + isApprovePasswordlessLoginsEnabled = false, + ) + pushManager.passwordlessRequestFlow.test { + pushManager.onMessageReceived(AUTH_REQUEST_RESPONSE_NOTIFICATION_JSON) + expectNoEvents() + } + } + + @Suppress("MaxLineLength") + @Test + fun `onMessageReceived auth request response emits to passwordlessRequestFlow when getApprovePasswordlessLoginsEnabled is true`() = + runTest { + settingsDiskSource.storeApprovePasswordlessLoginsEnabled( + userId = userId, + isApprovePasswordlessLoginsEnabled = true, + ) pushManager.passwordlessRequestFlow.test { pushManager.onMessageReceived(AUTH_REQUEST_RESPONSE_NOTIFICATION_JSON) assertEquals(