Skip to content

Commit

Permalink
feat: new conversation started unverified warning system message (WPB…
Browse files Browse the repository at this point in the history
…-2266) (#2163)

* feat: base for system msg creator

* feat: base for system msg creator

* feat: base for system msg creator

* feat: base for system msg creator

* feat: base for system msg creator tests

* feat: base for system msg creator tests

* feat: base for system msg creator tests

* feat: add message createor on conn req

* feat: add message createor on conn req

* feat: test cov
  • Loading branch information
yamilmedina authored Oct 24, 2023
1 parent 872981a commit 85418fc
Show file tree
Hide file tree
Showing 20 changed files with 241 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ internal class ConversationGroupRepositoryImpl(
)
}
}
}.flatMap {
wrapStorageRequest {
newGroupConversationSystemMessagesCreator.value.conversationStartedUnverifiedWarning(
conversationEntity.id.toModel()
)
}
}.flatMap {
wrapStorageRequest {
conversationDAO.getConversationByQualifiedID(conversationEntity.id)?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ internal interface NewGroupConversationSystemMessagesCreator {
conversationId: ConversationId,
userIdList: Set<UserId>
): Either<CoreFailure, Unit>

suspend fun conversationStartedUnverifiedWarning(conversationId: ConversationId): Either<CoreFailure, Unit>
}

internal class NewGroupConversationSystemMessagesCreatorImpl(
Expand Down Expand Up @@ -196,4 +198,18 @@ internal class NewGroupConversationSystemMessagesCreatorImpl(
}

}

override suspend fun conversationStartedUnverifiedWarning(conversationId: ConversationId): Either<CoreFailure, Unit> =
persistMessage(
Message.System(
uuid4().toString(),
MessageContent.ConversationStartedUnverifiedWarning,
conversationId,
DateTimeUtil.currentIsoDateTimeString(),
selfUserId,
Message.Status.Sent,
Message.Visibility.VISIBLE,
expirationData = null
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ sealed interface Message {
is MessageContent.ConversationProtocolChanged -> mutableMapOf(
typeKey to "conversationProtocolChanged"
)

is MessageContent.ConversationStartedUnverifiedWarning -> mutableMapOf(
typeKey to "conversationStartedUnverifiedWarning"
)
}

val standardProperties = mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ sealed class MessageContent {

data object HistoryLost : System()
data object ConversationCreated : System()
data object ConversationStartedUnverifiedWarning : System()
data object ConversationDegradedMLS : System()
data object ConversationVerifiedMLS : System()
data object ConversationDegradedProteus : System()
Expand Down Expand Up @@ -357,6 +358,7 @@ fun MessageContent?.getType() = when (this) {
is MessageContent.Unknown -> "Unknown"
MessageContent.ConversationVerifiedMLS -> "ConversationVerification.Verified.MLS"
MessageContent.ConversationVerifiedProteus -> "ConversationVerification.Verified.Proteus"
is MessageContent.ConversationStartedUnverifiedWarning -> "ConversationStartedUnverifiedWarning"
null -> "null"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ class MessageMapperImpl(
MessageEntity.ContentType.CONVERSATION_VERIFIED_MLS -> null
MessageEntity.ContentType.CONVERSATION_VERIFIED_PREOTEUS -> null
MessageEntity.ContentType.CONVERSATION_PROTOCOL_CHANGED -> null
MessageEntity.ContentType.CONVERSATION_STARTED_UNVERIFIED_WARNING -> null
}
}

Expand Down Expand Up @@ -378,6 +379,7 @@ class MessageMapperImpl(
MessageEntity.FederationType.CONNECTION_REMOVED -> MessageContent.FederationStopped.ConnectionRemoved(domainList)
}
is MessageEntityContent.ConversationProtocolChanged -> MessageContent.ConversationProtocolChanged(protocol.toModel())
is MessageEntityContent.ConversationStartedUnverifiedWarning -> MessageContent.ConversationStartedUnverifiedWarning
}
}

Expand Down Expand Up @@ -592,4 +594,5 @@ fun MessageContent.System.toMessageEntityContent(): MessageEntityContent.System
MessageContent.ConversationVerifiedProteus -> MessageEntityContent.ConversationVerifiedProteus
is MessageContent.ConversationProtocolChanged -> MessageEntityContent.ConversationProtocolChanged(protocol.toDao())
MessageContent.HistoryLostProtocolChanged -> MessageEntityContent.HistoryLostProtocolChanged
is MessageContent.ConversationStartedUnverifiedWarning -> MessageEntityContent.ConversationStartedUnverifiedWarning
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,6 @@ internal class PersistMessageUseCaseImpl(
is MessageContent.FederationStopped.ConnectionRemoved -> false
is MessageContent.FederationStopped.Removed -> false
is MessageContent.ConversationProtocolChanged -> false
is MessageContent.ConversationStartedUnverifiedWarning -> false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,8 @@ class UserSessionScope internal constructor(
logout,
oneOnOneResolver,
userId,
clientIdProvider
clientIdProvider,
lazy { conversations.newGroupConversationSystemMessagesCreator }
)

private val userPropertiesEventReceiver: UserPropertiesEventReceiver
Expand Down Expand Up @@ -1646,7 +1647,8 @@ class UserSessionScope internal constructor(
connectionRepository,
conversationRepository,
userRepository,
oneOnOneResolver
oneOnOneResolver,
conversations.newGroupConversationSystemMessagesCreator
)

val observeSecurityClassificationLabel: ObserveSecurityClassificationLabelUseCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.wire.kalium.logic.feature.connection
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.connection.ConnectionRepository
import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.conversation.NewGroupConversationSystemMessagesCreator
import com.wire.kalium.logic.data.user.ConnectionState
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolver
Expand All @@ -33,7 +34,7 @@ import com.wire.kalium.util.DateTimeUtil
/**
* Use Case that allows a user accept a connection request to connect with another User
*/
fun interface AcceptConnectionRequestUseCase {
interface AcceptConnectionRequestUseCase {
/**
* Use case [AcceptConnectionRequestUseCase] operation
*
Expand All @@ -46,7 +47,8 @@ fun interface AcceptConnectionRequestUseCase {
internal class AcceptConnectionRequestUseCaseImpl(
private val connectionRepository: ConnectionRepository,
private val conversationRepository: ConversationRepository,
private val oneOnOneResolver: OneOnOneResolver
private val oneOnOneResolver: OneOnOneResolver,
private val newGroupConversationSystemMessagesCreator: NewGroupConversationSystemMessagesCreator
) : AcceptConnectionRequestUseCase {

override suspend fun invoke(userId: UserId): AcceptConnectionRequestUseCaseResult {
Expand All @@ -62,6 +64,10 @@ internal class AcceptConnectionRequestUseCaseImpl(
oneOnOneResolver.resolveOneOnOneConversationWithUserId(
connection.qualifiedToId
).map { }
}.flatMap {
newGroupConversationSystemMessagesCreator.conversationStartedUnverifiedWarning(
connection.qualifiedConversationId
)
}
}
.fold({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,25 @@ package com.wire.kalium.logic.feature.connection

import com.wire.kalium.logic.data.connection.ConnectionRepository
import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.conversation.NewGroupConversationSystemMessagesCreator
import com.wire.kalium.logic.data.user.UserRepository
import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolver

class ConnectionScope internal constructor(
private val connectionRepository: ConnectionRepository,
private val conversationRepository: ConversationRepository,
private val userRepository: UserRepository,
private val oneOnOneResolver: OneOnOneResolver
private val oneOnOneResolver: OneOnOneResolver,
private val newGroupConversationSystemMessagesCreator: NewGroupConversationSystemMessagesCreator
) {
val sendConnectionRequest: SendConnectionRequestUseCase get() = SendConnectionRequestUseCaseImpl(connectionRepository, userRepository)

val acceptConnectionRequest: AcceptConnectionRequestUseCase
get() = AcceptConnectionRequestUseCaseImpl(
connectionRepository,
conversationRepository,
oneOnOneResolver
oneOnOneResolver,
newGroupConversationSystemMessagesCreator
)

val cancelConnectionRequest: CancelConnectionRequestUseCase get() = CancelConnectionRequestUseCaseImpl(connectionRepository)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.connection.ConnectionRepository
import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.conversation.NewGroupConversationSystemMessagesCreator
import com.wire.kalium.logic.data.event.Event
import com.wire.kalium.logic.data.event.EventLoggingStatus
import com.wire.kalium.logic.data.event.logEventProcessing
Expand All @@ -34,8 +35,8 @@ import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.feature.auth.LogoutUseCase
import com.wire.kalium.logic.feature.conversation.mls.OneOnOneResolver
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.flatMapLeft
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.flatMapLeft
import com.wire.kalium.logic.functional.map
import com.wire.kalium.logic.functional.onFailure
import com.wire.kalium.logic.functional.onSuccess
Expand All @@ -54,7 +55,8 @@ internal class UserEventReceiverImpl internal constructor(
private val logout: LogoutUseCase,
private val oneOnOneResolver: OneOnOneResolver,
private val selfUserId: UserId,
private val currentClientIdProvider: CurrentClientIdProvider
private val currentClientIdProvider: CurrentClientIdProvider,
private val newGroupConversationSystemMessagesCreator: Lazy<NewGroupConversationSystemMessagesCreator>
) : UserEventReceiver {

override suspend fun onEvent(event: Event.User): Either<CoreFailure, Unit> {
Expand Down Expand Up @@ -108,6 +110,10 @@ internal class UserEventReceiverImpl internal constructor(
delay = if (event.live) 3.seconds else ZERO
)
Either.Right(Unit)
}.flatMap {
newGroupConversationSystemMessagesCreator.value.conversationStartedUnverifiedWarning(
event.connection.qualifiedConversationId
)
}
}
.onSuccess {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ internal class NewConversationEventHandlerImpl(
event.conversation
)
newGroupConversationSystemMessagesCreator.conversationReadReceiptStatus(event.conversation)
newGroupConversationSystemMessagesCreator.conversationStartedUnverifiedWarning(event.conversation.id.toModel())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class ConversationGroupRepositoryTest {
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
.withSuccessfulNewConversationMemberHandled()
.withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled()
.arrange()

val result = conversationGroupRepository.createGroupConversation(
Expand Down Expand Up @@ -130,6 +131,7 @@ class ConversationGroupRepositoryTest {
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
.withSuccessfulNewConversationMemberHandled()
.withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled()
.arrange()

val result = conversationGroupRepository.createGroupConversation(
Expand Down Expand Up @@ -167,6 +169,7 @@ class ConversationGroupRepositoryTest {
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
.withSuccessfulNewConversationMemberHandled()
.withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled()
.arrange()

val unreachableUserId = TestUser.USER_ID.copy(domain = "unstableDomain2.com")
Expand Down Expand Up @@ -255,6 +258,7 @@ class ConversationGroupRepositoryTest {
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
.withSuccessfulNewConversationMemberHandled()
.withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled()
.arrange()

val result = conversationGroupRepository.createGroupConversation(
Expand Down Expand Up @@ -1148,6 +1152,39 @@ class ConversationGroupRepositoryTest {
.wasInvoked(once)
}

@Test
fun givenAValidConversation_whenCreating_thenConversationIsCreatedAndUnverifiedWarningSystemMessagePersisted() = runTest {
val (arrangement, conversationGroupRepository) = Arrangement()
.withCreateNewConversationAPIResponses(arrayOf(NetworkResponse.Success(CONVERSATION_RESPONSE, emptyMap(), 201)))
.withSelfTeamId(Either.Right(null))
.withInsertConversationSuccess()
.withConversationDetailsById(TestConversation.GROUP_VIEW_ENTITY(PROTEUS_PROTOCOL_INFO))
.withSuccessfulNewConversationGroupStartedHandled()
.withSuccessfulNewConversationMemberHandled()
.withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled()
.arrange()

val result = conversationGroupRepository.createGroupConversation(
GROUP_NAME,
listOf(TestUser.USER_ID),
ConversationOptions(protocol = ConversationOptions.Protocol.PROTEUS)
)

result.shouldSucceed()

with(arrangement) {
verify(conversationDAO)
.suspendFunction(conversationDAO::insertConversation)
.with(anything())
.wasInvoked(once)

verify(newGroupConversationSystemMessagesCreator)
.suspendFunction(newGroupConversationSystemMessagesCreator::conversationStartedUnverifiedWarning)
.with(anything())
.wasInvoked(once)
}
}

private class Arrangement :
MemberDAOArrangement by MemberDAOArrangementImpl() {

Expand Down Expand Up @@ -1540,6 +1577,13 @@ class ConversationGroupRepositoryTest {
.thenReturnSequentially(*networkResponses)
}

fun withSuccessfulNewConversationGroupStartedUnverifiedWarningHandled() = apply {
given(newGroupConversationSystemMessagesCreator)
.suspendFunction(newGroupConversationSystemMessagesCreator::conversationStartedUnverifiedWarning)
.whenInvokedWith(any())
.thenReturn(Either.Right(Unit))
}

fun arrange() = this to conversationGroupRepository
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package com.wire.kalium.logic.data.conversation
import com.wire.kalium.logic.data.id.QualifiedIdMapper
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.message.MessageContent
import com.wire.kalium.logic.data.message.PersistMessageUseCase
import com.wire.kalium.logic.feature.user.IsSelfATeamMemberUseCase
Expand Down Expand Up @@ -342,6 +343,26 @@ class NewGroupConversationSystemMessagesCreatorTest {
.wasInvoked(once)
}

@Test
fun givenAGroupConversation_whenPersistingAndValid_ThenShouldCreateAStartedUnverifiedSystemMessage() = runTest {
val (arrangement, sysMessageCreator) = Arrangement()
.withPersistMessageSuccess()
.arrange()

val result = sysMessageCreator.conversationStartedUnverifiedWarning(
TestConversation.ENTITY.copy(type = ConversationEntity.Type.GROUP).id.toModel()
)

result.shouldSucceed()

verify(arrangement.persistMessage)
.suspendFunction(arrangement.persistMessage::invoke)
.with(matching {
(it.content is MessageContent.System && it.content is MessageContent.ConversationStartedUnverifiedWarning)
})
.wasInvoked(once)
}

private class Arrangement {
@Mock
val persistMessage = mock(PersistMessageUseCase::class)
Expand Down
Loading

0 comments on commit 85418fc

Please sign in to comment.