Skip to content

Commit

Permalink
fix: exclude users from other teams when missing-legalhold-consent [W…
Browse files Browse the repository at this point in the history
…PB-9404] (#2803)

* fix: exclude users from other teams when missing-legalhold-consent [WPB-9404]

* remove unused import
  • Loading branch information
saleniuk committed Jun 7, 2024
1 parent 0738b82 commit 771a409
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -653,13 +653,23 @@ internal class ConversationGroupRepositoryImpl(
}

/**
* Filter the initial [userIdList] into valid and invalid users where valid users are only team members.
* Filter the initial [userIdList] into valid and invalid users where valid users are only team members and people with consent.
*/
private suspend fun fetchAndExtractValidUsersForRetryableLegalHoldError(
userIdList: List<UserId>
): Either<CoreFailure, ValidToInvalidUsers> =
userRepository.fetchUsersLegalHoldConsent(userIdList.toSet()).map {
ValidToInvalidUsers(it.usersWithConsent, it.usersWithoutConsent + it.usersFailed, FailedToAdd.Type.LegalHold)
teamIdProvider().flatMap { selfTeamId ->
userRepository.fetchUsersLegalHoldConsent(userIdList.toSet()).map {
it.usersWithConsent
.partition { (_, teamId) -> teamId == selfTeamId }
.let { (validUsers, membersFromOtherTeam) ->
ValidToInvalidUsers(
validUsers = validUsers.map { (userId, _) -> userId },
failedUsers = membersFromOtherTeam.map { (userId, _) -> userId } + it.usersWithoutConsent + it.usersFailed,
failType = FailedToAdd.Type.LegalHold
)
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
*/
package com.wire.kalium.logic.data.legalhold

import com.wire.kalium.logic.data.id.TeamId
import com.wire.kalium.logic.data.user.UserId

data class ListUsersLegalHoldConsent(
val usersWithConsent: List<UserId>,
val usersWithConsent: List<Pair<UserId, TeamId?>>,
val usersWithoutConsent: List<UserId>,
val usersFailed: List<UserId>,
)
fun List<Pair<UserId, TeamId?>>.ids() = map { (id, _) -> id }
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ internal class UserDataSource internal constructor(
.partition { it.legalHoldStatus != LegalHoldStatusDTO.NO_CONSENT }
.let { (usersWithConsent, usersWithoutConsent) ->
ListUsersLegalHoldConsent(
usersWithConsent = usersWithConsent.map { it.id.toModel() },
usersWithConsent = usersWithConsent.map { it.id.toModel() to it.teamId?.let { TeamId(it) } },
usersWithoutConsent = usersWithoutConsent.map { it.id.toModel() },
usersFailed = listUsersDTO.usersFailed.map { it.toModel() }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import com.wire.kalium.logic.data.id.toApi
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.data.id.toModel
import com.wire.kalium.logic.data.legalhold.ListUsersLegalHoldConsent
import com.wire.kalium.logic.data.legalhold.ids
import com.wire.kalium.logic.data.message.MessageContent
import com.wire.kalium.logic.data.mls.CipherSuite
import com.wire.kalium.logic.data.service.ServiceId
Expand Down Expand Up @@ -286,14 +287,19 @@ class ConversationGroupRepositoryTest {

@Test
fun givenCreatingAGroupConversation_whenThereIsAMissingLegalHoldConsentError_thenRetryIsExecutedWithValidUsersOnly() = runTest {
val usersWithConsent = listOf(TestUser.USER_ID, TestUser.OTHER_USER_ID.copy(value = "idWithConsent"))
val validUsers = listOf(
TestUser.SELF.id to TestUser.SELF.teamId,
TestUser.OTHER.id.copy(value = "idWithConsentSameTeam") to TestUser.SELF.teamId,
)
val usersWithConsentFromOtherTeams = listOf(TestUser.OTHER.id.copy(value = "idWithConsentOtherTeam") to TestUser.OTHER.teamId)
val usersWithConsent = validUsers + usersWithConsentFromOtherTeams
val usersWithoutConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithoutConsent"))
val usersFailed = listOf(TestUser.OTHER_USER_ID.copy(value = "idFailed"))
val (arrangement, conversationGroupRepository) = Arrangement()
.withCreateNewConversationAPIResponses(
arrayOf(ERROR_MISSING_LEGALHOLD_CONSENT, NetworkResponse.Success(CONVERSATION_RESPONSE, emptyMap(), 201))
)
.withSelfTeamId(Either.Right(null))
.withSelfTeamId(Either.Right(TestUser.SELF.teamId))
.withInsertConversationSuccess()
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
Expand All @@ -306,15 +312,15 @@ class ConversationGroupRepositoryTest {

val result = conversationGroupRepository.createGroupConversation(
GROUP_NAME,
usersWithConsent + usersWithoutConsent + usersFailed,
usersWithConsent.ids() + usersWithoutConsent + usersFailed,
ConversationOptions(protocol = ConversationOptions.Protocol.PROTEUS)
)

result.shouldSucceed()

with(arrangement) {
coVerify {
conversationApi.createNewConversation(matches { it.qualifiedUsers?.size == 4 })
conversationApi.createNewConversation(matches { it.qualifiedUsers?.size == 5 })
}.wasInvoked(once)

coVerify {
Expand All @@ -332,7 +338,7 @@ class ConversationGroupRepositoryTest {
coVerify {
newGroupConversationSystemMessagesCreator.conversationFailedToAddMembers(
any(),
userIdList = eq(usersWithoutConsent + usersFailed),
userIdList = eq(usersWithConsentFromOtherTeams.ids() + usersWithoutConsent + usersFailed),
eq(MessageContent.MemberChange.FailedToAdd.Type.LegalHold)
)
}.wasInvoked(once)
Expand All @@ -341,12 +347,17 @@ class ConversationGroupRepositoryTest {

@Test
fun givenCreatingAGroupConversation_whenThereIsAMissingLegalHoldConsentError_thenRetryIsExecutedWithValidUsersOnlyOnce() = runTest {
val usersWithConsent = listOf(TestUser.USER_ID, TestUser.OTHER_USER_ID.copy(value = "idWithConsent"))
val validUsers = listOf(
TestUser.SELF.id to TestUser.SELF.teamId,
TestUser.OTHER.id.copy(value = "idWithConsentSameTeam") to TestUser.SELF.teamId,
)
val usersWithConsentFromOtherTeams = listOf(TestUser.OTHER.id.copy(value = "idWithConsentOtherTeam") to TestUser.OTHER.teamId)
val usersWithConsent = validUsers + usersWithConsentFromOtherTeams
val usersWithoutConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithoutConsent"))
val usersFailed = listOf(TestUser.OTHER_USER_ID.copy(value = "idFailed"))
val (arrangement, conversationGroupRepository) = Arrangement()
.withCreateNewConversationAPIResponses(arrayOf(ERROR_MISSING_LEGALHOLD_CONSENT, ERROR_MISSING_LEGALHOLD_CONSENT))
.withSelfTeamId(Either.Right(null))
.withSelfTeamId(Either.Right(TestUser.SELF.teamId))
.withInsertConversationSuccess()
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
Expand All @@ -356,7 +367,7 @@ class ConversationGroupRepositoryTest {

val result = conversationGroupRepository.createGroupConversation(
GROUP_NAME,
usersWithConsent + usersWithoutConsent + usersFailed,
usersWithConsent.ids() + usersWithoutConsent + usersFailed,
ConversationOptions(protocol = ConversationOptions.Protocol.PROTEUS)
)

Expand Down Expand Up @@ -1533,11 +1544,17 @@ class ConversationGroupRepositoryTest {
fun givenAConversationAndAPIFailsWithMissingLHConsent_whenAddingMembersToConversation_thenShouldRetryWithValidUsers() =
runTest {
// given
val usersWithConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithConsent"))
val validUsers = listOf(
TestUser.SELF.id to TestUser.SELF.teamId,
TestUser.OTHER.id.copy(value = "idWithConsentSameTeam") to TestUser.SELF.teamId,
)
val usersWithConsentFromOtherTeams = listOf(TestUser.OTHER.id.copy(value = "idWithConsentOtherTeam") to TestUser.OTHER.teamId)
val usersWithConsent = validUsers + usersWithConsentFromOtherTeams
val usersWithoutConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithoutConsent"))
val usersFailed = listOf(TestUser.OTHER_USER_ID.copy(value = "idFailed"))
val expectedInitialUsers = usersWithConsent + usersWithoutConsent + usersFailed
val expectedInitialUsers = usersWithConsent.ids() + usersWithoutConsent + usersFailed
val (arrangement, conversationGroupRepository) = Arrangement()
.withSelfTeamId(Either.Right(TestUser.SELF.teamId))
.withConversationDetailsById(TestConversation.CONVERSATION)
.withProtocolInfoById(PROTEUS_PROTOCOL_INFO)
.withFetchUsersIfUnknownByIdsSuccessful()
Expand All @@ -1556,15 +1573,15 @@ class ConversationGroupRepositoryTest {
)
}.wasInvoked(exactly = once)
coVerify {
arrangement.conversationApi.addMember(matches { it.users == usersWithConsent.map { it.toApi() } }, any())
arrangement.conversationApi.addMember(matches { it.users == validUsers.ids().map { it.toApi() } }, any())
}.wasInvoked(exactly = once)
coVerify {
arrangement.memberJoinEventHandler.handle(any())
}.wasInvoked(exactly = once)
coVerify {
arrangement.newGroupConversationSystemMessagesCreator.conversationFailedToAddMembers(
conversationId = any(),
userIdList = eq(usersWithoutConsent + usersFailed),
userIdList = eq(usersWithConsentFromOtherTeams.ids() + usersWithoutConsent + usersFailed),
type = any()
)
}.wasInvoked(exactly = once)
Expand All @@ -1574,11 +1591,17 @@ class ConversationGroupRepositoryTest {
fun givenAConversationAndAPIFailsWithMissingLHConsent_whenAddingMembersToConversation_thenRetryIsExecutedWithValidUsersOnlyOnce() =
runTest {
// given
val usersWithConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithConsent"))
val validUsers = listOf(
TestUser.SELF.id to TestUser.SELF.teamId,
TestUser.OTHER.id.copy(value = "idWithConsentSameTeam") to TestUser.SELF.teamId,
)
val usersWithConsentFromOtherTeams = listOf(TestUser.OTHER.id.copy(value = "idWithConsentOtherTeam") to TestUser.OTHER.teamId)
val usersWithConsent = validUsers + usersWithConsentFromOtherTeams
val usersWithoutConsent = listOf(TestUser.OTHER_USER_ID.copy(value = "idWithoutConsent"))
val usersFailed = listOf(TestUser.OTHER_USER_ID.copy(value = "idFailed"))
val expectedInitialUsers = usersWithConsent + usersWithoutConsent + usersFailed
val expectedInitialUsers = usersWithConsent.ids() + usersWithoutConsent + usersFailed
val (arrangement, conversationGroupRepository) = Arrangement()
.withSelfTeamId(Either.Right(TestUser.SELF.teamId))
.withConversationDetailsById(TestConversation.CONVERSATION)
.withProtocolInfoById(PROTEUS_PROTOCOL_INFO)
.withFetchUsersIfUnknownByIdsSuccessful()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import app.cash.turbine.test
import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.id.SelfTeamIdProvider
import com.wire.kalium.logic.data.id.TeamId
import com.wire.kalium.logic.data.id.toApi
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.data.legalhold.ListUsersLegalHoldConsent
Expand Down Expand Up @@ -755,7 +756,7 @@ class UserRepositoryTest {
val userIdFailed = TestUser.OTHER_USER_ID.copy(value = "idFailed")
val requestedUserIds = setOf(userIdWithConsent, userIdWithoutConsent, userIdFailed)
val expectedResult = ListUsersLegalHoldConsent(
usersWithConsent = listOf(userIdWithConsent),
usersWithConsent = listOf(userIdWithConsent to TeamId("teamId")),
usersWithoutConsent = listOf(userIdWithoutConsent),
usersFailed = listOf(userIdFailed),
)
Expand Down

0 comments on commit 771a409

Please sign in to comment.