Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Create observer for legal hold state (WPB-5442) #2251

Merged
merged 3 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,12 @@ import com.wire.kalium.logic.feature.featureConfig.handler.SecondFactorPasswordC
import com.wire.kalium.logic.feature.featureConfig.handler.SelfDeletingMessagesConfigHandler
import com.wire.kalium.logic.feature.keypackage.KeyPackageManager
import com.wire.kalium.logic.feature.keypackage.KeyPackageManagerImpl
import com.wire.kalium.logic.feature.legalhold.LegalHoldRequestUseCase
import com.wire.kalium.logic.feature.legalhold.LegalHoldRequestUseCaseImpl
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldRequestUseCase
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldRequestUseCaseImpl
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldForSelfUserUseCase
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldForSelfUserUseCaseImpl
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldStateForUserUseCase
import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldStateForUserUseCaseImpl
import com.wire.kalium.logic.feature.message.AddSystemMessageToAllConversationsUseCase
import com.wire.kalium.logic.feature.message.AddSystemMessageToAllConversationsUseCaseImpl
import com.wire.kalium.logic.feature.message.EphemeralEventsNotificationManagerImpl
Expand Down Expand Up @@ -1322,6 +1326,12 @@ class UserSessionScope internal constructor(
userConfigRepository = userConfigRepository
)

val observeLegalHoldStateForUser: ObserveLegalHoldStateForUserUseCase
get() = ObserveLegalHoldStateForUserUseCaseImpl(clientRepository)

val observeLegalHoldForSelfUser: ObserveLegalHoldForSelfUserUseCase
get() = ObserveLegalHoldForSelfUserUseCaseImpl(userId, observeLegalHoldStateForUser)

private val fetchSelfClientsFromRemote: FetchSelfClientsFromRemoteUseCase
get() = FetchSelfClientsFromRemoteUseCaseImpl(
clientRepository = clientRepository,
Expand Down Expand Up @@ -1738,8 +1748,8 @@ class UserSessionScope internal constructor(
}
}

val legalHoldRequestUseCase: LegalHoldRequestUseCase
get() = LegalHoldRequestUseCaseImpl(
val observeLegalHoldRequestUseCase: ObserveLegalHoldRequestUseCase
get() = ObserveLegalHoldRequestUseCaseImpl(
userConfigRepository = userConfigRepository,
preKeyRepository = preKeyRepository
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.legalhold

import com.wire.kalium.logic.data.user.UserId
import kotlinx.coroutines.flow.Flow

/**
* Use case that allows to observe the legal hold state for the self user.
*/
interface ObserveLegalHoldForSelfUserUseCase {
suspend operator fun invoke(): Flow<LegalHoldState>
}

internal class ObserveLegalHoldForSelfUserUseCaseImpl internal constructor(
private val selfUserId: UserId,
private val observeLegalHoldStateForUser: ObserveLegalHoldStateForUserUseCase
) : ObserveLegalHoldForSelfUserUseCase {
override suspend fun invoke(): Flow<LegalHoldState> = observeLegalHoldStateForUser(
userId = selfUserId
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@ import kotlinx.coroutines.flow.map
/**
* Use case that observes the legal hold request.
*/
interface LegalHoldRequestUseCase {
operator fun invoke(): Flow<LegalHoldRequestObserverResult>
interface ObserveLegalHoldRequestUseCase {
operator fun invoke(): Flow<ObserveLegalHoldRequestUseCaseResult>
}

internal class LegalHoldRequestUseCaseImpl internal constructor(
internal class ObserveLegalHoldRequestUseCaseImpl internal constructor(
val userConfigRepository: UserConfigRepository,
val preKeyRepository: PreKeyRepository
) : LegalHoldRequestUseCase {
override fun invoke(): Flow<LegalHoldRequestObserverResult> =
) : ObserveLegalHoldRequestUseCase {
override fun invoke(): Flow<ObserveLegalHoldRequestUseCaseResult> =
userConfigRepository.observeLegalHoldRequest().map {
it.fold(
{ failure ->
if (failure is StorageFailure.DataNotFound) {
kaliumLogger.i("No legal hold request found")
LegalHoldRequestObserverResult.NoLegalHoldRequest
ObserveLegalHoldRequestUseCaseResult.NoObserveLegalHoldRequest
} else {
kaliumLogger.i("Legal hold request failure: $failure")
LegalHoldRequestObserverResult.Failure(failure)
ObserveLegalHoldRequestUseCaseResult.Failure(failure)
}
},
{ request ->
Expand All @@ -56,10 +56,10 @@ internal class LegalHoldRequestUseCaseImpl internal constructor(
result.fold(
{ failure ->
kaliumLogger.i("Legal hold request fingerprint failure: $failure")
LegalHoldRequestObserverResult.Failure(failure)
ObserveLegalHoldRequestUseCaseResult.Failure(failure)
},
{ fingerprint ->
LegalHoldRequestObserverResult.LegalHoldRequestAvailable(
ObserveLegalHoldRequestUseCaseResult.ObserveLegalHoldRequestAvailable(
fingerprint
)
}
Expand All @@ -69,13 +69,13 @@ internal class LegalHoldRequestUseCaseImpl internal constructor(
}
}

sealed class LegalHoldRequestObserverResult {
data class LegalHoldRequestAvailable(val fingerprint: ByteArray) : LegalHoldRequestObserverResult() {
sealed class ObserveLegalHoldRequestUseCaseResult {
data class ObserveLegalHoldRequestAvailable(val fingerprint: ByteArray) : ObserveLegalHoldRequestUseCaseResult() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false

other as LegalHoldRequestAvailable
other as ObserveLegalHoldRequestAvailable

return fingerprint.contentEquals(other.fingerprint)
}
Expand All @@ -85,6 +85,6 @@ sealed class LegalHoldRequestObserverResult {
}
}

data object NoLegalHoldRequest : LegalHoldRequestObserverResult()
data class Failure(val failure: CoreFailure) : LegalHoldRequestObserverResult()
data object NoObserveLegalHoldRequest : ObserveLegalHoldRequestUseCaseResult()
data class Failure(val failure: CoreFailure) : ObserveLegalHoldRequestUseCaseResult()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.legalhold

import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.client.DeviceType
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.functional.fold
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

/**
* Use case that allows to observe the legal hold state for a given user.
*/
interface ObserveLegalHoldStateForUserUseCase {
suspend operator fun invoke(userId: UserId): Flow<LegalHoldState>
}

internal class ObserveLegalHoldStateForUserUseCaseImpl internal constructor(
private val clientRepository: ClientRepository
) : ObserveLegalHoldStateForUserUseCase {
override suspend fun invoke(userId: UserId): Flow<LegalHoldState> =
clientRepository.observeClientsByUserId(userId).map {
it.fold(
{
LegalHoldState.Disabled
},
{ clients ->
val isLegalHoldEnabled = clients.any { otherUserClient ->
otherUserClient.deviceType == DeviceType.LegalHold
}
if (isLegalHoldEnabled) {
LegalHoldState.Enabled
} else {
LegalHoldState.Disabled
}
}
)
}
}

sealed class LegalHoldState {
data object Enabled : LegalHoldState()
data object Disabled : LegalHoldState()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.legalhold

import com.wire.kalium.logic.framework.TestUser
import io.mockative.Mock
import io.mockative.eq
import io.mockative.given
import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

class ObserveLegalHoldForSelfUserUseCaseTest {

@Test
fun givenLegalHoldObserverForUserReturnsEnabled_whenStartingObservingForSelfUser_thenEmitEnabled() =
runTest {
val (arrangement, useCase) = Arrangement()
.withLegalHoldEnabledState()
.arrange()

val result = useCase()

assertEquals(LegalHoldState.Enabled, result.first())
verify(arrangement.observeLegalHoldStateForUser)
.suspendFunction(arrangement.observeLegalHoldStateForUser::invoke)
.with(eq(TestUser.SELF.id))
.wasInvoked(once)
}

@Test
fun givenLegalHoldObserverForUserReturnsDisabled_whenStartingObservingForSelfUser_thenEmitDisabled() =
runTest {
val (arrangement, useCase) = Arrangement()
.withLegalHoldDisabledState()
.arrange()

val result = useCase()

assertEquals(LegalHoldState.Disabled, result.first())
verify(arrangement.observeLegalHoldStateForUser)
.suspendFunction(arrangement.observeLegalHoldStateForUser::invoke)
.with(eq(TestUser.SELF.id))
.wasInvoked(once)
}

private class Arrangement {

@Mock
val observeLegalHoldStateForUser = mock(ObserveLegalHoldStateForUserUseCase::class)

val observeLegalHoldForSelfUser: ObserveLegalHoldForSelfUserUseCase =
ObserveLegalHoldForSelfUserUseCaseImpl(
selfUserId = TestUser.SELF.id,
observeLegalHoldStateForUser = observeLegalHoldStateForUser
)

fun arrange() = this to observeLegalHoldForSelfUser

fun withLegalHoldEnabledState() = apply {
given(observeLegalHoldStateForUser)
.suspendFunction(observeLegalHoldStateForUser::invoke)
.whenInvokedWith(eq(TestUser.SELF.id))
.then {
flowOf(LegalHoldState.Enabled)
}
}

fun withLegalHoldDisabledState() = apply {
given(observeLegalHoldStateForUser)
.suspendFunction(observeLegalHoldStateForUser::invoke)
.whenInvokedWith(eq(TestUser.SELF.id))
.then {
flowOf(LegalHoldState.Disabled)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,54 +36,54 @@ import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertTrue

class LegalHoldRequestObserverTest {
class ObserveLegalHoldRequestUseCaseTest {

@Test
fun givenUserConfigRepositoryDataNotFoundFailure_whenObserving_thenPropagateNoLegalHoldRequest() =
runTest {
val (_, legalHoldRequestObserver) = Arrangement()
val (_, useCase) = Arrangement()
.withUserConfigRepositoryDataNotFound()
.arrange()

val result = legalHoldRequestObserver()
val result = useCase()

assertTrue(result.first() is LegalHoldRequestObserverResult.NoLegalHoldRequest)
assertTrue(result.first() is ObserveLegalHoldRequestUseCaseResult.NoObserveLegalHoldRequest)
}

@Test
fun givenUserConfigRepositoryOtherFailure_whenObserving_thenPropagateFailure() = runTest {
val (_, legalHoldRequestObserver) = Arrangement()
val (_, useCase) = Arrangement()
.withUserConfigRepositoryFailure()
.arrange()

val result = legalHoldRequestObserver()
val result = useCase()

assertTrue(result.first() is LegalHoldRequestObserverResult.Failure)
assertTrue(result.first() is ObserveLegalHoldRequestUseCaseResult.Failure)
}

@Test
fun givenPreKeyRepositoryFailure_whenObserving_thenPropagateFailure() = runTest {
val (_, legalHoldRequestObserver) = Arrangement()
val (_, useCase) = Arrangement()
.withUserConfigRepositorySuccess()
.withPreKeyRepositoryFailure()
.arrange()

val result = legalHoldRequestObserver()
val result = useCase()

assertTrue(result.first() is LegalHoldRequestObserverResult.Failure)
assertTrue(result.first() is ObserveLegalHoldRequestUseCaseResult.Failure)
}

@Test
fun givenPreKeyRepositorySuccess_whenObserving_thenPropagateLegalHoldRequestAvailable() =
runTest {
val (_, legalHoldRequestObserver) = Arrangement()
val (_, useCase) = Arrangement()
.withUserConfigRepositorySuccess()
.withPreKeyRepositorySuccess()
.arrange()

val result = legalHoldRequestObserver()
val result = useCase()

assertTrue(result.first() is LegalHoldRequestObserverResult.LegalHoldRequestAvailable)
assertTrue(result.first() is ObserveLegalHoldRequestUseCaseResult.ObserveLegalHoldRequestAvailable)
}

private class Arrangement {
Expand Down Expand Up @@ -129,7 +129,7 @@ class LegalHoldRequestObserverTest {
.thenReturn(Either.Right(fingerPrint))
}

fun arrange() = this to LegalHoldRequestUseCaseImpl(
fun arrange() = this to ObserveLegalHoldRequestUseCaseImpl(
userConfigRepository = userConfigRepository,
preKeyRepository = preKeyRepository
)
Expand Down
Loading
Loading