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

Feature : room settings - security and privacy #4212

Merged
merged 30 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
002325c
feat(security&privacy) : first implementation of ui
ganfra Jan 8, 2025
d354144
change(room details) : update room details with new sections organisa…
ganfra Jan 17, 2025
a781cc0
feat(security & privacy) : introduce EditRoomAddress screen
ganfra Jan 17, 2025
b549400
feat(security&privacy) : expose new sdk methods
ganfra Jan 21, 2025
c391b5b
feat(security&privacy) : get data from sdk
ganfra Jan 21, 2025
129eb45
feat(security&privacy) : introduce navigator
ganfra Jan 21, 2025
9faa305
feat(room address) : extract some reusable code
ganfra Jan 21, 2025
f8cd8b3
feat(security&privacy) : start handling edition of room address
ganfra Jan 21, 2025
b7831f4
feat(security&privacy) : expose methods from sdk to update alias and …
ganfra Jan 22, 2025
65e5447
feat(security&privacy) : manage save action for edit room address
ganfra Jan 22, 2025
0e6c86f
feat(privacy&security) : extract some code for address management
ganfra Jan 22, 2025
392299d
feat(security&privacy) : update the save address algorithm
ganfra Jan 22, 2025
7eda945
feat(security&privacy) : manage encryption settings
ganfra Jan 22, 2025
19d49a3
feat(security&privacy) : expose more methods from sdk
ganfra Jan 23, 2025
edee18a
feat(security&privacy) : manage save action and some edge cases.
ganfra Jan 23, 2025
75fef6b
feat(security&privacy) : introduce permissions and use in RoomDetails
ganfra Jan 23, 2025
88fce64
feat(security&privacy) : use permissions and improve save
ganfra Jan 23, 2025
ba0a857
feat(security&privacy) : update strings
ganfra Jan 24, 2025
c07a7d9
feat(security&privacy) : make the whole RoomDirectoryVisibility item …
ganfra Jan 24, 2025
fdc4f1b
feat(security&privacy) : start writing tests
ganfra Jan 27, 2025
c0c7d5b
feat(security&privacy) : write View tests
ganfra Jan 27, 2025
876d06f
feat(security&privacy) : add all tests for EditRoomAddress classes
ganfra Jan 27, 2025
d992f38
feat(security&privacy) : clean code
ganfra Jan 28, 2025
58918b1
feat(security&privacy) : update canShowSecurityAndPrivacy check
ganfra Jan 28, 2025
d586bdc
feat(security&privacy) : some more clean up
ganfra Jan 28, 2025
706b298
feat(security&privacy) : fix tests after some rework landed
ganfra Jan 28, 2025
82f5926
Update screenshots
ElementBot Jan 28, 2025
8880eed
feat(security&privacy) : improve and document code after PR review.
ganfra Jan 29, 2025
15f2d0b
feat(security&privacy) : add more previews
ganfra Jan 29, 2025
c10da01
Update screenshots
ElementBot Jan 29, 2025
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 @@ -31,9 +31,9 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
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.room.alias.RoomAliasHelper
import io.element.android.libraries.matrix.api.roomAliasFromName
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.ui.media.AvatarAction
import io.element.android.libraries.mediapickers.api.PickerProvider
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
Expand Down Expand Up @@ -191,7 +191,7 @@ class ConfigureRoomPresenter @Inject constructor(
topic = config.topic,
isEncrypted = false,
isDirect = false,
visibility = RoomVisibility.PUBLIC,
visibility = RoomVisibility.Public,
joinRuleOverride = config.roomVisibility.roomAccess.toJoinRule(),
preset = RoomPreset.PUBLIC_CHAT,
invite = config.invites.map { it.userId },
Expand All @@ -204,7 +204,7 @@ class ConfigureRoomPresenter @Inject constructor(
topic = config.topic,
isEncrypted = config.roomVisibility is RoomVisibilityState.Private,
isDirect = false,
visibility = RoomVisibility.PRIVATE,
visibility = RoomVisibility.Private,
preset = RoomPreset.PRIVATE_CHAT,
invite = config.invites.map { it.userId },
avatar = avatarUrl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@

package io.element.android.features.createroom.impl.configureroom

import io.element.android.libraries.matrix.api.createroom.JoinRuleOverride
import io.element.android.libraries.matrix.api.room.join.JoinRule

enum class RoomAccess {
Anyone,
Knocking
}

fun RoomAccess.toJoinRule(): JoinRuleOverride {
fun RoomAccess.toJoinRule(): JoinRule? {
return when (this) {
RoomAccess.Anyone -> JoinRuleOverride.None
RoomAccess.Knocking -> JoinRuleOverride.Knock
RoomAccess.Anyone -> null
RoomAccess.Knocking -> JoinRule.Knock
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
package io.element.android.libraries.matrix.api.createroom

import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import java.util.Optional

data class CreateRoomParameters(
Expand All @@ -19,6 +21,6 @@ data class CreateRoomParameters(
val preset: RoomPreset,
val invite: List<UserId>? = null,
val avatar: String? = null,
val joinRuleOverride: JoinRuleOverride = JoinRuleOverride.None,
val joinRuleOverride: JoinRule? = null,
val roomAliasName: Optional<String> = Optional.empty(),
)

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
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.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.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
Expand Down Expand Up @@ -402,4 +404,32 @@ interface MatrixRoom : Closeable {
suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle): Result<Unit>

override fun close() = destroy()

/**
* Update the canonical alias of the room.
*
* Note that publishing the alias in the room directory is done separately.
*/
suspend fun updateCanonicalAlias(
canonicalAlias: RoomAlias?,
alternativeAliases: List<RoomAlias>
): Result<Unit>

/**
* Update the room's visibility in the room directory.
*/
suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit>

/**
* Update room history visibility for this room.
*/
suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit>

/**
* Returns the visibility for this room in the room directory.
*
* [Public](`RoomVisibility::Public`) rooms are listed in the room
* directory and can be found using it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦀 spotted!

*/
suspend fun getRoomVisibility(): Result<RoomVisibility>
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
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 kotlinx.collections.immutable.ImmutableList
Expand Down Expand Up @@ -71,6 +72,7 @@ data class MatrixRoomInfo(
val heroes: ImmutableList<MatrixUser>,
val pinnedEventIds: ImmutableList<EventId>,
val creator: UserId?,
val historyVisibility: RoomHistoryVisibility,
) {
val aliases: List<RoomAlias>
get() = listOfNotNull(canonicalAlias) + alternativeAliases
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.api.room.history

sealed interface RoomHistoryVisibility {
/**
* Previous events are accessible to newly joined members from the point
* they were invited onwards.
*
* Events stop being accessible when the member's state changes to
* something other than *invite* or *join*.
*/
data object Invited : RoomHistoryVisibility

/**
* Previous events are accessible to newly joined members from the point
* they joined the room onwards.
* Events stop being accessible when the member's state changes to
* something other than *join*.
*/
data object Joined : RoomHistoryVisibility

/**
* Previous events are always accessible to newly joined members.
*
* All events in the room are accessible, even those sent when the member
* was not a part of the room.
*/
data object Shared : RoomHistoryVisibility

/**
* All events while this is the `HistoryVisibility` value may be shared by
* any participating homeserver with anyone, regardless of whether they
* have ever joined the room.
*/
data object WorldReadable : RoomHistoryVisibility

/**
* A custom visibility value.
*/
data class Custom(val value: String) : RoomHistoryVisibility
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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.api.roomdirectory

/**
* Enum class representing the visibility of a room in the room directory.
*/
sealed interface RoomVisibility {
/**
* Indicates that the room will be shown in the published room list.
*/
data object Public : RoomVisibility

/**
* Indicates that the room will not be shown in the published room list.
*/
data object Private : RoomVisibility

/**
* A custom value that's not present in the spec.
*/
data class Custom(val value: String) : RoomVisibility
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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))
Expand All @@ -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),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -60,6 +61,7 @@ class MatrixRoomInfoMapper {
numUnreadMessages = it.numUnreadMessages.toLong(),
numUnreadMentions = it.numUnreadMentions.toLong(),
numUnreadNotifications = it.numUnreadNotifications.toLong(),
historyVisibility = it.historyVisibility.map(),
)
}
}
Expand Down
Loading