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

chore(mls): propagate activeOneOnOneConversation on ConversationDetails [WPB-4705] #2130

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 @@ -207,7 +207,8 @@ internal class ConversationMapperImpl(
connectionStatus = connectionStatusMapper.fromDaoModel(connectionStatus),
expiresAt = null,
defederated = userDefederated ?: false,
supportedProtocols = userSupportedProtocols?.map { it.toModel() }?.toSet()
supportedProtocols = userSupportedProtocols?.map { it.toModel() }?.toSet(),
activeOneOnOneConversationId = userActiveOneOnOneConversationId?.toModel()
),
legalHoldStatus = LegalHoldStatus.DISABLED,
userType = domainUserTypeMapper.fromUserTypeEntity(userType),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ object TestConversation {
archived = false,
archivedDateTime = null,
verificationStatus = ConversationEntity.VerificationStatus.NOT_VERIFIED,
userSupportedProtocols = null
userSupportedProtocols = null,
userActiveOneOnOneConversationId = null,
)

fun one_on_one(convId: ConversationId) = Conversation(
Expand Down Expand Up @@ -318,7 +319,8 @@ object TestConversation {
archived = false,
archivedDateTime = null,
verificationStatus = ConversationEntity.VerificationStatus.NOT_VERIFIED,
userSupportedProtocols = null
userSupportedProtocols = null,
userActiveOneOnOneConversationId = null,
)

val MLS_PROTOCOL_INFO = ProtocolInfo.MLS(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.qualified_id
WHEN 'CONNECTION_PENDING' THEN connection_user.qualified_id
END AS otherUserId,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.active_one_on_one_conversation_id
WHEN 'CONNECTION_PENDING' THEN connection_user.active_one_on_one_conversation_id
END AS otherUserActiveConversationId,
CASE
WHEN ((SELECT id FROM SelfUser LIMIT 1) LIKE (Conversation.creator_id || '@%')) THEN 1
ELSE 0
Expand Down
109 changes: 109 additions & 0 deletions persistence/src/commonMain/db_user/migrations/63.sqm
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@

DROP VIEW IF EXISTS ConversationDetails;

-- Re-create ConversationDetails view now that it has a new "otherUserActiveConversationId" field

CREATE VIEW IF NOT EXISTS ConversationDetails AS
SELECT
Conversation.qualified_id AS qualifiedId,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.name
WHEN 'CONNECTION_PENDING' THEN connection_user.name
ELSE Conversation.name
END AS name,
Conversation.type,
Call.status AS callStatus,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.preview_asset_id
WHEN 'CONNECTION_PENDING' THEN connection_user.preview_asset_id
END AS previewAssetId,
Conversation.muted_status AS mutedStatus,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.team
ELSE Conversation.team_id
END AS teamId,
CASE (Conversation.type)
WHEN 'CONNECTION_PENDING' THEN Connection.last_update_date
ELSE Conversation.last_modified_date
END AS lastModifiedDate,
Conversation.last_read_date AS lastReadDate,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.user_availability_status
WHEN 'CONNECTION_PENDING' THEN connection_user.user_availability_status
END AS userAvailabilityStatus,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.user_type
WHEN 'CONNECTION_PENDING' THEN connection_user.user_type
END AS userType,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.bot_service
WHEN 'CONNECTION_PENDING' THEN connection_user.bot_service
END AS botService,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.deleted
WHEN 'CONNECTION_PENDING' THEN connection_user.deleted
END AS userDeleted,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.defederated
WHEN 'CONNECTION_PENDING' THEN connection_user.defederated
END AS userDefederated,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.supported_protocols
WHEN 'CONNECTION_PENDING' THEN connection_user.supported_protocols
END AS userSupportedProtocols,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.connection_status
WHEN 'CONNECTION_PENDING' THEN connection_user.connection_status
END AS connectionStatus,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.qualified_id
WHEN 'CONNECTION_PENDING' THEN connection_user.qualified_id
END AS otherUserId,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN User.active_one_on_one_conversation_id
WHEN 'CONNECTION_PENDING' THEN connection_user.active_one_on_one_conversation_id
END AS otherUserActiveConversationId,
CASE
WHEN ((SELECT id FROM SelfUser LIMIT 1) LIKE (Conversation.creator_id || '@%')) THEN 1
ELSE 0
END AS isCreator,
CASE (Conversation.type)
WHEN 'ONE_ON_ONE' THEN coalesce(User.active_one_on_one_conversation_id = Conversation.qualified_id, 0)
ELSE 1
END AS isActive,
Conversation.last_notified_date AS lastNotifiedMessageDate,
memberRole. role AS selfRole,
Conversation.protocol,
Conversation.mls_cipher_suite,
Conversation.mls_epoch,
Conversation.mls_group_id,
Conversation.mls_last_keying_material_update_date,
Conversation.mls_group_state,
Conversation.access_list,
Conversation.access_role_list,
Conversation.team_id,
Conversation.mls_proposal_timer,
Conversation.muted_time,
Conversation.creator_id,
Conversation.last_modified_date,
Conversation.receipt_mode,
Conversation.message_timer,
Conversation.user_message_timer,
Conversation.incomplete_metadata,
Conversation.archived,
Conversation.archived_date_time,
Conversation.verification_status
FROM Conversation
LEFT JOIN Member ON Conversation.qualified_id = Member.conversation
AND Conversation.type IS 'ONE_ON_ONE'
AND Member.user IS NOT (SELECT SelfUser.id FROM SelfUser LIMIT 1)
LEFT JOIN Member AS memberRole ON Conversation.qualified_id = memberRole.conversation
AND memberRole.user IS (SELECT SelfUser.id FROM SelfUser LIMIT 1)
LEFT JOIN User ON User.qualified_id = Member.user
LEFT JOIN Connection ON Connection.qualified_conversation = Conversation.qualified_id
AND (Connection.status = 'SENT'
OR Connection.status = 'PENDING'
OR Connection.status = 'NOT_CONNECTED'
AND Conversation.type IS 'CONNECTION_PENDING')
LEFT JOIN User AS connection_user ON Connection.qualified_to = connection_user.qualified_id
LEFT JOIN Call ON Call.id IS (SELECT id FROM Call WHERE Call.conversation_id = Conversation.qualified_id AND Call.status IS 'STILL_ONGOING' ORDER BY created_at DESC LIMIT 1);
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ internal class ConversationMapper {
archived = archived,
archivedDateTime = archived_date_time,
verificationStatus = verification_status,
userSupportedProtocols = userSupportedProtocols
userSupportedProtocols = userSupportedProtocols,
userActiveOneOnOneConversationId = otherUserActiveConversationId
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.wire.kalium.persistence.dao.conversation

import com.wire.kalium.persistence.dao.BotIdEntity
import com.wire.kalium.persistence.dao.ConnectionEntity
import com.wire.kalium.persistence.dao.ConversationIDEntity
import com.wire.kalium.persistence.dao.QualifiedIDEntity
import com.wire.kalium.persistence.dao.SupportedProtocolEntity
import com.wire.kalium.persistence.dao.UserAvailabilityStatusEntity
Expand Down Expand Up @@ -68,7 +69,8 @@ data class ConversationViewEntity(
val archived: Boolean,
val archivedDateTime: Instant?,
val verificationStatus: ConversationEntity.VerificationStatus,
val userSupportedProtocols: Set<SupportedProtocolEntity>?
val userSupportedProtocols: Set<SupportedProtocolEntity>?,
val userActiveOneOnOneConversationId: ConversationIDEntity?
) {
val isMember: Boolean get() = selfRole != null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class ConversationDAOTest : BaseDatabaseTest() {
}

@Test
fun givenConversation_ThenConversationCanBeInserted() = runTest {
fun givenConversationIsInserted_whenFetchingById_thenConversationIsReturned() = runTest {
conversationDAO.insertConversation(conversationEntity1)
insertTeamUserAndMember(team, user1, conversationEntity1.id)
val result = conversationDAO.getConversationByQualifiedID(conversationEntity1.id)
Expand Down Expand Up @@ -1288,7 +1288,8 @@ class ConversationDAOTest : BaseDatabaseTest() {
archived = false,
archivedDateTime = null,
verificationStatus = ConversationEntity.VerificationStatus.NOT_VERIFIED,
userSupportedProtocols = if (type == ConversationEntity.Type.ONE_ON_ONE) userEntity?.supportedProtocols else null
userSupportedProtocols = if (type == ConversationEntity.Type.ONE_ON_ONE) userEntity?.supportedProtocols else null,
userActiveOneOnOneConversationId = null,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import com.wire.kalium.persistence.dao.member.MemberDAO
import com.wire.kalium.persistence.dao.member.MemberEntity
import com.wire.kalium.persistence.utils.stubs.newConversationEntity
import com.wire.kalium.persistence.utils.stubs.newUserEntity
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue

@OptIn(ExperimentalCoroutinesApi::class)
class UserConversationDAOIntegrationTest : BaseDatabaseTest() {

private val user1 = newUserEntity(id = "1")
Expand Down Expand Up @@ -251,6 +251,29 @@ class UserConversationDAOIntegrationTest : BaseDatabaseTest() {
}
}

@Test
fun givenActiveOneOnOneWasSetForConversation_whenFetchingConversationView_thenActiveOneOnOneShouldMatch() = runTest {
userDAO.insertUser(user1)
conversationDAO.insertConversation(conversationEntity1)
memberDAO.insertMember(member1, conversationEntity1.id)

userDAO.updateActiveOneOnOneConversation(user1.id, conversationEntity1.id)

val result = conversationDAO.getConversationByQualifiedID(conversationEntity1.id)
assertEquals(conversationEntity1.id, result?.userActiveOneOnOneConversationId)
}

@Test
fun givenActiveOneOnOneWasNotSetForConversation_whenFetchingConversationView_thenActiveOneOnOneShouldBeNull() = runTest {
userDAO.insertUser(user1)
conversationDAO.insertConversation(conversationEntity1)
memberDAO.insertMember(member1, conversationEntity1.id)

val result = conversationDAO.getConversationByQualifiedID(conversationEntity1.id)
assertNotNull(result)
assertNull(result.userActiveOneOnOneConversationId)
}

private suspend fun createTestConversation(conversationIDEntity: QualifiedIDEntity, members: List<MemberEntity>) {
conversationDAO.insertConversation(
newConversationEntity(conversationIDEntity)
Expand Down
Loading