Merge pull request #4212 from element-hq/feature/fga/room_settings_security_privacy

Feature : room settings - security and privacy
This commit is contained in:
ganfra 2025-01-29 17:29:56 +01:00 committed by GitHub
commit 346e3648e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
125 changed files with 3387 additions and 347 deletions

View file

@ -23,9 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride
import io.element.android.libraries.matrix.api.createroom.RoomPreset
import io.element.android.libraries.matrix.api.createroom.RoomVisibility
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.notification.NotificationService
@ -38,8 +36,10 @@ import io.element.android.libraries.matrix.api.room.PendingRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
@ -59,8 +59,10 @@ import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber
import io.element.android.libraries.matrix.impl.room.RustRoomFactory
import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper
import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService
import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory
import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService
import io.element.android.libraries.matrix.impl.sync.RustSyncService
@ -112,9 +114,7 @@ import kotlin.jvm.optionals.getOrNull
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import org.matrix.rustcomponents.sdk.CreateRoomParameters as RustCreateRoomParameters
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset
import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService
class RustMatrixClient(
@ -310,36 +310,23 @@ class RustMatrixClient(
topic = createRoomParams.topic,
isEncrypted = createRoomParams.isEncrypted,
isDirect = createRoomParams.isDirect,
visibility = when (createRoomParams.visibility) {
RoomVisibility.PUBLIC -> RustRoomVisibility.Public
RoomVisibility.PRIVATE -> RustRoomVisibility.Private
},
preset = when (createRoomParams.visibility) {
RoomVisibility.PRIVATE -> {
if (createRoomParams.isDirect) {
RustRoomPreset.TRUSTED_PRIVATE_CHAT
} else {
RustRoomPreset.PRIVATE_CHAT
}
}
RoomVisibility.PUBLIC -> {
RustRoomPreset.PUBLIC_CHAT
}
visibility = createRoomParams.visibility.map(),
preset = when (createRoomParams.preset) {
RoomPreset.PRIVATE_CHAT -> RustRoomPreset.PRIVATE_CHAT
RoomPreset.TRUSTED_PRIVATE_CHAT -> RustRoomPreset.TRUSTED_PRIVATE_CHAT
RoomPreset.PUBLIC_CHAT -> RustRoomPreset.PUBLIC_CHAT
},
invite = createRoomParams.invite?.map { it.value },
avatar = createRoomParams.avatar,
powerLevelContentOverride = defaultRoomCreationPowerLevels.copy(
invite = if (createRoomParams.joinRuleOverride == JoinRuleOverride.Knock) {
invite = if (createRoomParams.joinRuleOverride == JoinRule.Knock) {
// override the invite power level so it's the same as kick.
RoomMember.Role.MODERATOR.powerLevel.toInt()
} else {
null
}
),
joinRuleOverride = when (createRoomParams.joinRuleOverride) {
JoinRuleOverride.Knock -> RustJoinRule.Knock
JoinRuleOverride.None -> null
},
joinRuleOverride = createRoomParams.joinRuleOverride?.map(),
canonicalAlias = createRoomParams.roomAliasName.getOrNull(),
)
val roomId = RoomId(innerClient.createRoom(rustParams))
@ -358,7 +345,7 @@ class RustMatrixClient(
name = null,
isEncrypted = true,
isDirect = true,
visibility = RoomVisibility.PRIVATE,
visibility = RoomVisibility.Private,
preset = RoomPreset.TRUSTED_PRIVATE_CHAT,
invite = listOf(userId),
)

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.room.history.map
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import kotlinx.collections.immutable.ImmutableMap
@ -60,6 +61,7 @@ class MatrixRoomInfoMapper {
numUnreadMessages = it.numUnreadMessages.toLong(),
numUnreadMentions = it.numUnreadMentions.toLong(),
numUnreadNotifications = it.numUnreadNotifications.toLong(),
historyVisibility = it.historyVisibility.map(),
)
}
}

View file

@ -38,11 +38,14 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.knock.KnockRequest
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
@ -51,10 +54,13 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
import io.element.android.libraries.matrix.impl.core.RustSendHandle
import io.element.android.libraries.matrix.impl.mapper.map
import io.element.android.libraries.matrix.impl.room.draft.into
import io.element.android.libraries.matrix.impl.room.history.map
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.knock.RustKnockRequest
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsMapper
import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.timeline.RustTimeline
import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType
import io.element.android.libraries.matrix.impl.util.MessageEventContent
@ -101,6 +107,7 @@ import org.matrix.rustcomponents.sdk.KnockRequest as InnerKnockRequest
import org.matrix.rustcomponents.sdk.Room as InnerRoom
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
@Suppress("LargeClass")
class RustMatrixRoom(
override val sessionId: SessionId,
private val deviceId: DeviceId,
@ -306,7 +313,7 @@ class RustMatrixRoom(
override val isEncrypted: Boolean
get() = runCatching { innerRoom.isEncrypted() }.getOrDefault(false)
override val alias: RoomAlias?
override val canonicalAlias: RoomAlias?
get() = runCatching { innerRoom.canonicalAlias()?.let(::RoomAlias) }.getOrDefault(null)
override val alternativeAliases: List<RoomAlias>
@ -805,6 +812,54 @@ class RustMatrixRoom(
}
}
override suspend fun updateCanonicalAlias(canonicalAlias: RoomAlias?, alternativeAliases: List<RoomAlias>): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateCanonicalAlias(canonicalAlias?.value, alternativeAliases.map { it.value })
}
}
override suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
runCatching {
innerRoom.publishRoomAliasInRoomDirectory(roomAlias.value)
}
}
override suspend fun removeRoomAliasFromRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
runCatching {
innerRoom.removeRoomAliasFromRoomDirectory(roomAlias.value)
}
}
override suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateRoomVisibility(roomVisibility.map())
}
}
override suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateHistoryVisibility(historyVisibility.map())
}
}
override suspend fun getRoomVisibility(): Result<RoomVisibility> = withContext(roomDispatcher) {
runCatching {
innerRoom.getRoomVisibility().map()
}
}
override suspend fun enableEncryption(): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.enableEncryption()
}
}
override suspend fun updateJoinRule(joinRule: JoinRule): Result<Unit> = withContext(roomDispatcher) {
runCatching {
innerRoom.updateJoinRules(joinRule.map())
}
}
private fun createTimeline(
timeline: InnerTimeline,
mode: Timeline.Mode,

View file

@ -0,0 +1,31 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.room.history
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
fun RoomHistoryVisibility.map(): RustRoomHistoryVisibility {
return when (this) {
RoomHistoryVisibility.WorldReadable -> RustRoomHistoryVisibility.WorldReadable
RoomHistoryVisibility.Invited -> RustRoomHistoryVisibility.Invited
RoomHistoryVisibility.Joined -> RustRoomHistoryVisibility.Joined
RoomHistoryVisibility.Shared -> RustRoomHistoryVisibility.Shared
is RoomHistoryVisibility.Custom -> RustRoomHistoryVisibility.Custom(value)
}
}
fun RustRoomHistoryVisibility.map(): RoomHistoryVisibility {
return when (this) {
RustRoomHistoryVisibility.WorldReadable -> RoomHistoryVisibility.WorldReadable
RustRoomHistoryVisibility.Invited -> RoomHistoryVisibility.Invited
RustRoomHistoryVisibility.Joined -> RoomHistoryVisibility.Joined
RustRoomHistoryVisibility.Shared -> RoomHistoryVisibility.Shared
is RustRoomHistoryVisibility.Custom -> RoomHistoryVisibility.Custom(value)
}
}

View file

@ -17,3 +17,10 @@ fun RustAllowRule.map(): AllowRule {
is RustAllowRule.Custom -> AllowRule.Custom(json)
}
}
fun AllowRule.map(): RustAllowRule {
return when (this) {
is AllowRule.RoomMembership -> RustAllowRule.RoomMembership(roomId.toString())
is AllowRule.Custom -> RustAllowRule.Custom(json)
}
}

View file

@ -21,3 +21,15 @@ fun RustJoinRule.map(): JoinRule {
is RustJoinRule.KnockRestricted -> JoinRule.KnockRestricted(rules.map { it.map() })
}
}
fun JoinRule.map(): RustJoinRule {
return when (this) {
JoinRule.Public -> RustJoinRule.Public
JoinRule.Private -> RustJoinRule.Private
JoinRule.Knock -> RustJoinRule.Knock
JoinRule.Invite -> RustJoinRule.Invite
is JoinRule.Restricted -> RustJoinRule.Restricted(rules.map { it.map() })
is JoinRule.Custom -> RustJoinRule.Custom(value)
is JoinRule.KnockRestricted -> RustJoinRule.KnockRestricted(rules.map { it.map() })
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.roomdirectory
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility
fun RoomVisibility.map(): RustRoomVisibility {
return when (this) {
RoomVisibility.Public -> RustRoomVisibility.Public
RoomVisibility.Private -> RustRoomVisibility.Private
is RoomVisibility.Custom -> RustRoomVisibility.Custom(value)
}
}
fun RustRoomVisibility.map(): RoomVisibility {
return when (this) {
RustRoomVisibility.Public -> RoomVisibility.Public
RustRoomVisibility.Private -> RoomVisibility.Private
is RustRoomVisibility.Custom -> RoomVisibility.Custom(value)
}
}

View file

@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero
@ -33,6 +34,7 @@ import kotlinx.collections.immutable.toPersistentList
import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
class MatrixRoomInfoMapperTest {
@ -72,6 +74,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMentions = 14uL,
pinnedEventIds = listOf(AN_EVENT_ID.value),
roomCreator = A_USER_ID,
historyVisibility = RustRoomHistoryVisibility.Joined,
)
)
).isEqualTo(
@ -113,6 +116,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMessages = 12L,
numUnreadNotifications = 13L,
numUnreadMentions = 14L,
historyVisibility = RoomHistoryVisibility.Joined,
)
)
}
@ -188,6 +192,7 @@ class MatrixRoomInfoMapperTest {
numUnreadMessages = 12L,
numUnreadNotifications = 13L,
numUnreadMentions = 14L,
historyVisibility = RoomHistoryVisibility.Joined,
)
)
}