Skip to content

Commit

Permalink
feat: Create observer for legal hold state (WPB-5442) (#2251)
Browse files Browse the repository at this point in the history
* feat: Create observer for legal hold state

* chore: rename use case
  • Loading branch information
ohassine authored and augustocdias committed Dec 5, 2023
1 parent aba5f75 commit 21fa1eb
Show file tree
Hide file tree
Showing 7 changed files with 371 additions and 32 deletions.
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

0 comments on commit 21fa1eb

Please sign in to comment.