mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-05 15:52:47 +02:00
Merge pull request #9065 from element-hq/feature/room_v12_support
Room v12 support
This commit is contained in:
@@ -40,8 +40,8 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RestrictedRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
|
||||
import org.matrix.android.sdk.common.CommonTestHelper.Companion.runSessionTest
|
||||
import org.matrix.android.sdk.common.SessionTestParams
|
||||
@@ -500,12 +500,12 @@ class SpaceHierarchyTest : InstrumentedTest {
|
||||
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!)
|
||||
|
||||
commonTestHelper.retryPeriodically {
|
||||
val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!!
|
||||
val roomPowerLevels = aliceSession.getRoom(bobRoomId)!!
|
||||
.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
?.content
|
||||
?.toModel<PowerLevelsContent>()
|
||||
?.let { PowerLevelsHelper(it) }
|
||||
powerLevelsHelper!!.isUserAllowedToSend(aliceSession.myUserId, true, EventType.STATE_SPACE_PARENT)
|
||||
?.let { RoomPowerLevels(it) }
|
||||
roomPowerLevels!!.isUserAllowedToSend(aliceSession.myUserId, true, EventType.STATE_SPACE_PARENT)
|
||||
}
|
||||
|
||||
aliceSession.spaceService().setSpaceParent(bobRoomId, spaceAInfo.spaceId, false, listOf(bobSession.sessionParams.homeServerHost ?: ""))
|
||||
|
@@ -30,15 +30,21 @@ object MatrixPatterns {
|
||||
// Note: TLD is not mandatory (localhost, IP address...)
|
||||
private const val DOMAIN_REGEX = ":[A-Z0-9.-]+(:[0-9]{2,5})?"
|
||||
|
||||
private const val BASE_64_ALPHABET = "[0-9A-Za-z/\\+=]+"
|
||||
private const val BASE_64_URL_SAFE_ALPHABET = "[0-9A-Za-z/\\-_]+"
|
||||
|
||||
// regex pattern to find matrix user ids in a string.
|
||||
// See https://matrix.org/docs/spec/appendices#historical-user-ids
|
||||
private const val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
|
||||
val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = MATRIX_USER_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
// regex pattern to find room ids in a string.
|
||||
private const val MATRIX_ROOM_IDENTIFIER_REGEX = "![A-Z0-9]+$DOMAIN_REGEX"
|
||||
private const val MATRIX_ROOM_IDENTIFIER_REGEX = "^!.+$DOMAIN_REGEX$"
|
||||
private val PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER = MATRIX_ROOM_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
private const val MATRIX_ROOM_IDENTIFIER_DOMAINLESS_REGEX = "!$BASE_64_URL_SAFE_ALPHABET"
|
||||
private val PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER_DOMAINLESS = MATRIX_ROOM_IDENTIFIER_DOMAINLESS_REGEX.toRegex()
|
||||
|
||||
// regex pattern to find room aliases in a string.
|
||||
private const val MATRIX_ROOM_ALIAS_REGEX = "#[A-Z0-9._%#@=+-]+$DOMAIN_REGEX"
|
||||
private val PATTERN_CONTAIN_MATRIX_ALIAS = MATRIX_ROOM_ALIAS_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
@@ -48,11 +54,11 @@ object MatrixPatterns {
|
||||
private val PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER = MATRIX_EVENT_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
// regex pattern to find message ids in a string.
|
||||
private const val MATRIX_EVENT_IDENTIFIER_V3_REGEX = "\\$[A-Z0-9/+]+"
|
||||
private const val MATRIX_EVENT_IDENTIFIER_V3_REGEX = "\\$$BASE_64_ALPHABET"
|
||||
private val PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3 = MATRIX_EVENT_IDENTIFIER_V3_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
// Ref: https://matrix.org/docs/spec/rooms/v4#event-ids
|
||||
private const val MATRIX_EVENT_IDENTIFIER_V4_REGEX = "\\$[A-Z0-9\\-_]+"
|
||||
private const val MATRIX_EVENT_IDENTIFIER_V4_REGEX = "\\$$BASE_64_URL_SAFE_ALPHABET"
|
||||
private val PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4 = MATRIX_EVENT_IDENTIFIER_V4_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
// regex pattern to find group ids in a string.
|
||||
@@ -76,7 +82,10 @@ object MatrixPatterns {
|
||||
PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER,
|
||||
PATTERN_CONTAIN_MATRIX_ALIAS,
|
||||
PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER,
|
||||
PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER_DOMAINLESS,
|
||||
PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER,
|
||||
PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3,
|
||||
PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4,
|
||||
PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
|
||||
)
|
||||
|
||||
@@ -97,7 +106,9 @@ object MatrixPatterns {
|
||||
* @return true if the string is a valid room Id
|
||||
*/
|
||||
fun isRoomId(str: String?): Boolean {
|
||||
return str != null && str matches PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER
|
||||
return str != null &&
|
||||
(str matches PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER ||
|
||||
str matches PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER_DOMAINLESS)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -16,8 +16,7 @@
|
||||
package org.matrix.android.sdk.api.session.pushrules
|
||||
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
|
||||
class SenderNotificationPermissionCondition(
|
||||
/**
|
||||
@@ -35,8 +34,7 @@ class SenderNotificationPermissionCondition(
|
||||
|
||||
override fun technicalDescription() = "User power level <$key>"
|
||||
|
||||
fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
|
||||
val powerLevelsHelper = PowerLevelsHelper(powerLevels)
|
||||
return event.senderId != null && powerLevelsHelper.getUserPowerLevelValue(event.senderId) >= powerLevels.notificationLevel(key)
|
||||
fun isSatisfied(event: Event, roomPowerLevels: RoomPowerLevels): Boolean {
|
||||
return event.senderId != null && roomPowerLevels.isUserAbleToTriggerNotification(event.senderId, key)
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
||||
|
||||
import org.matrix.android.sdk.api.query.QueryStateEventValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
|
||||
/**
|
||||
@@ -34,3 +35,10 @@ fun Room.getTimelineEvent(eventId: String): TimelineEvent? =
|
||||
*/
|
||||
fun Room.getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? =
|
||||
stateService().getStateEvent(eventType, stateKey)
|
||||
|
||||
/**
|
||||
* Get the current RoomPowerLevels of the room.
|
||||
*/
|
||||
fun Room.getRoomPowerLevels(): RoomPowerLevels {
|
||||
return stateService().getRoomPowerLevels()
|
||||
}
|
||||
|
@@ -18,7 +18,8 @@ package org.matrix.android.sdk.api.session.room.model
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent.Companion.NOTIFICATIONS_ROOM_KEY
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||
|
||||
/**
|
||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||
@@ -34,7 +35,7 @@ data class PowerLevelsContent(
|
||||
*/
|
||||
@Json(name = "kick") val kick: Int? = null,
|
||||
/**
|
||||
* The level required to invite a user. Defaults to 50 if unspecified.
|
||||
* The level required to invite a user. Defaults to 0 if unspecified.
|
||||
*/
|
||||
@Json(name = "invite") val invite: Int? = null,
|
||||
/**
|
||||
@@ -88,7 +89,7 @@ data class PowerLevelsContent(
|
||||
* Get the notification level for a dedicated key.
|
||||
*
|
||||
* @param key the notification key
|
||||
* @return the level, default to Moderator if the key is not found
|
||||
* @return the level
|
||||
*/
|
||||
fun notificationLevel(key: String): Int {
|
||||
return when (val value = notifications.orEmpty()[key]) {
|
||||
@@ -96,10 +97,9 @@ data class PowerLevelsContent(
|
||||
is String -> value.toInt()
|
||||
is Double -> value.toInt()
|
||||
is Int -> value
|
||||
else -> Role.Moderator.value
|
||||
else -> defaultNotificationLevel(key)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Key to use for content.notifications and get the level required to trigger an @room notification. Defaults to 50 if unspecified.
|
||||
@@ -108,11 +108,20 @@ data class PowerLevelsContent(
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultNotificationLevel(key: String): Int {
|
||||
return when (key) {
|
||||
NOTIFICATIONS_ROOM_KEY -> UserPowerLevel.Moderator.value
|
||||
else -> UserPowerLevel.User.value
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to default value, defined in the Matrix specification
|
||||
fun PowerLevelsContent.banOrDefault() = ban ?: Role.Moderator.value
|
||||
fun PowerLevelsContent.kickOrDefault() = kick ?: Role.Moderator.value
|
||||
fun PowerLevelsContent.inviteOrDefault() = invite ?: Role.Moderator.value
|
||||
fun PowerLevelsContent.redactOrDefault() = redact ?: Role.Moderator.value
|
||||
fun PowerLevelsContent.eventsDefaultOrDefault() = eventsDefault ?: Role.Default.value
|
||||
fun PowerLevelsContent.usersDefaultOrDefault() = usersDefault ?: Role.Default.value
|
||||
fun PowerLevelsContent.stateDefaultOrDefault() = stateDefault ?: Role.Moderator.value
|
||||
fun PowerLevelsContent?.banOrDefault() = this?.ban ?: UserPowerLevel.Moderator.value
|
||||
fun PowerLevelsContent?.kickOrDefault() = this?.kick ?: UserPowerLevel.Moderator.value
|
||||
fun PowerLevelsContent?.inviteOrDefault() = this?.invite ?: UserPowerLevel.User.value
|
||||
fun PowerLevelsContent?.redactOrDefault() = this?.redact ?: UserPowerLevel.Moderator.value
|
||||
fun PowerLevelsContent?.eventsDefaultOrDefault() = this?.eventsDefault ?: UserPowerLevel.User.value
|
||||
fun PowerLevelsContent?.usersDefaultOrDefault() = this?.usersDefault ?: UserPowerLevel.User.value
|
||||
fun PowerLevelsContent?.stateDefaultOrDefault() = this?.stateDefault ?: UserPowerLevel.Moderator.value
|
||||
|
||||
fun PowerLevelsContent?.notificationLevelOrDefault(key: String) = this?.notificationLevel(key) ?: defaultNotificationLevel(key)
|
||||
|
@@ -18,15 +18,39 @@ package org.matrix.android.sdk.api.session.room.model.create
|
||||
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
|
||||
/**
|
||||
* Content of a m.room.create type event.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RoomCreateContent(
|
||||
// Creator should be replaced by the sender of the event
|
||||
@Json(name = "creator") val creator: String? = null,
|
||||
@Json(name = "room_version") val roomVersion: String? = null,
|
||||
@Json(name = "predecessor") val predecessor: Predecessor? = null,
|
||||
// Defines the room type, see #RoomType (user extensible)
|
||||
@Json(name = "type") val type: String? = null
|
||||
@Json(name = "type") val type: String? = null,
|
||||
@Json(name = "additional_creators") val additionalCreators: List<String>? = null,
|
||||
)
|
||||
|
||||
data class RoomCreateContentWithSender(
|
||||
val senderId: String,
|
||||
val inner: RoomCreateContent
|
||||
) {
|
||||
val creators = setOf(senderId) + inner.additionalCreators.orEmpty().toSet()
|
||||
}
|
||||
|
||||
fun Event.getRoomCreateContentWithSender(): RoomCreateContentWithSender? {
|
||||
if (this.type != EventType.STATE_ROOM_CREATE) return null
|
||||
val innerContent = getClearContent().toModel<RoomCreateContent>() ?: return null
|
||||
val senderId = senderId ?: return null
|
||||
return RoomCreateContentWithSender(senderId, innerContent)
|
||||
}
|
||||
|
||||
fun RoomCreateContent.explicitlyPrivilegeRoomCreators(): Boolean {
|
||||
val supportedRoomVersions = listOf("org.matrix.hydra.11", "12")
|
||||
return supportedRoomVersions.contains(roomVersion)
|
||||
}
|
||||
|
@@ -17,26 +17,21 @@
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.powerlevels
|
||||
|
||||
sealed class Role(open val value: Int) : Comparable<Role> {
|
||||
object Admin : Role(100)
|
||||
object Moderator : Role(50)
|
||||
object Default : Role(0)
|
||||
data class Custom(override val value: Int) : Role(value)
|
||||
|
||||
override fun compareTo(other: Role): Int {
|
||||
return value.compareTo(other.value)
|
||||
}
|
||||
enum class Role {
|
||||
Creator,
|
||||
SuperAdmin,
|
||||
Admin,
|
||||
Moderator,
|
||||
User;
|
||||
|
||||
companion object {
|
||||
|
||||
// Order matters, default value should be checked after defined roles
|
||||
fun fromValue(value: Int, default: Int): Role {
|
||||
return when (value) {
|
||||
Admin.value -> Admin
|
||||
Moderator.value -> Moderator
|
||||
Default.value,
|
||||
default -> Default
|
||||
else -> Custom(value)
|
||||
fun getSuggestedRole(userPowerLevel: UserPowerLevel): Role {
|
||||
return when {
|
||||
userPowerLevel == UserPowerLevel.Infinite -> Creator
|
||||
userPowerLevel >= UserPowerLevel.SuperAdmin -> SuperAdmin
|
||||
userPowerLevel >= UserPowerLevel.Admin -> Admin
|
||||
userPowerLevel >= UserPowerLevel.Moderator -> Moderator
|
||||
else -> User
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,17 +19,23 @@ package org.matrix.android.sdk.api.session.room.powerlevels
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.banOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContentWithSender
|
||||
import org.matrix.android.sdk.api.session.room.model.create.explicitlyPrivilegeRoomCreators
|
||||
import org.matrix.android.sdk.api.session.room.model.eventsDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.inviteOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.kickOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.notificationLevelOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.redactOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.stateDefaultOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.usersDefaultOrDefault
|
||||
|
||||
/**
|
||||
* This class is an helper around PowerLevelsContent.
|
||||
* This class is an helper around PowerLevelsContent and RoomCreateContent.
|
||||
*/
|
||||
class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
class RoomPowerLevels(
|
||||
val powerLevelsContent: PowerLevelsContent?,
|
||||
private val roomCreateContent: RoomCreateContentWithSender?,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns the user power level of a dedicated user Id.
|
||||
@@ -37,10 +43,14 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @param userId the user id
|
||||
* @return the power level
|
||||
*/
|
||||
fun getUserPowerLevelValue(userId: String): Int {
|
||||
return powerLevelsContent.users
|
||||
fun getUserPowerLevel(userId: String): UserPowerLevel {
|
||||
if (shouldGiveInfinitePowerLevel(userId)) return UserPowerLevel.Infinite
|
||||
if (powerLevelsContent == null) return UserPowerLevel.User
|
||||
val value = powerLevelsContent.users
|
||||
?.get(userId)
|
||||
?: powerLevelsContent.usersDefaultOrDefault()
|
||||
|
||||
return UserPowerLevel.Value(value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,10 +59,9 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @param userId the user id
|
||||
* @return the power level
|
||||
*/
|
||||
fun getUserRole(userId: String): Role {
|
||||
val value = getUserPowerLevelValue(userId)
|
||||
// I think we should use powerLevelsContent.usersDefault, but Ganfra told me that it was like that on riot-Web
|
||||
return Role.fromValue(value, powerLevelsContent.eventsDefaultOrDefault())
|
||||
fun getSuggestedRole(userId: String): Role {
|
||||
val value = getUserPowerLevel(userId)
|
||||
return Role.getSuggestedRole(value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,14 +74,14 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
*/
|
||||
fun isUserAllowedToSend(userId: String, isState: Boolean, eventType: String?): Boolean {
|
||||
return if (userId.isNotEmpty()) {
|
||||
val powerLevel = getUserPowerLevelValue(userId)
|
||||
val minimumPowerLevel = powerLevelsContent.events?.get(eventType)
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
val minimumPowerLevel = powerLevelsContent?.events?.get(eventType)
|
||||
?: if (isState) {
|
||||
powerLevelsContent.stateDefaultOrDefault()
|
||||
} else {
|
||||
powerLevelsContent.eventsDefaultOrDefault()
|
||||
}
|
||||
powerLevel >= minimumPowerLevel
|
||||
powerLevel >= UserPowerLevel.Value(minimumPowerLevel)
|
||||
} else false
|
||||
}
|
||||
|
||||
@@ -82,8 +91,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @return true if able to invite
|
||||
*/
|
||||
fun isUserAbleToInvite(userId: String): Boolean {
|
||||
val powerLevel = getUserPowerLevelValue(userId)
|
||||
return powerLevel >= powerLevelsContent.inviteOrDefault()
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.inviteOrDefault())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,8 +101,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @return true if able to ban
|
||||
*/
|
||||
fun isUserAbleToBan(userId: String): Boolean {
|
||||
val powerLevel = getUserPowerLevelValue(userId)
|
||||
return powerLevel >= powerLevelsContent.banOrDefault()
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.banOrDefault())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,8 +111,8 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @return true if able to kick
|
||||
*/
|
||||
fun isUserAbleToKick(userId: String): Boolean {
|
||||
val powerLevel = getUserPowerLevelValue(userId)
|
||||
return powerLevel >= powerLevelsContent.kickOrDefault()
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.kickOrDefault())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +121,22 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
||||
* @return true if able to redact
|
||||
*/
|
||||
fun isUserAbleToRedact(userId: String): Boolean {
|
||||
val powerLevel = getUserPowerLevelValue(userId)
|
||||
return powerLevel >= powerLevelsContent.redactOrDefault()
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
return powerLevel >= UserPowerLevel.Value(powerLevelsContent.redactOrDefault())
|
||||
}
|
||||
|
||||
fun isUserAbleToTriggerNotification(userId: String, notificationKey: String): Boolean {
|
||||
val userPowerLevel = getUserPowerLevel(userId)
|
||||
val notificationPowerLevel = UserPowerLevel.Value(powerLevelsContent.notificationLevelOrDefault(key = notificationKey))
|
||||
return userPowerLevel >= notificationPowerLevel
|
||||
}
|
||||
|
||||
private fun shouldGiveInfinitePowerLevel(userId: String): Boolean {
|
||||
if (roomCreateContent == null) return false
|
||||
return if (roomCreateContent.inner.explicitlyPrivilegeRoomCreators()) {
|
||||
roomCreateContent.creators.contains(userId)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2025 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.api.session.room.powerlevels
|
||||
|
||||
sealed interface UserPowerLevel : Comparable<UserPowerLevel> {
|
||||
data object Infinite : UserPowerLevel
|
||||
|
||||
@JvmInline
|
||||
value class Value(val value: Int) : UserPowerLevel
|
||||
|
||||
override fun compareTo(other: UserPowerLevel): Int {
|
||||
return when (this) {
|
||||
Infinite -> when (other) {
|
||||
Infinite -> 0
|
||||
is Value -> 1
|
||||
}
|
||||
is Value -> when (other) {
|
||||
Infinite -> -1
|
||||
is Value -> value.compareTo(other.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val User = Value(0)
|
||||
val Moderator = Value(50)
|
||||
val Admin = Value(100)
|
||||
val SuperAdmin = Value(150)
|
||||
}
|
||||
}
|
@@ -24,6 +24,7 @@ import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
|
||||
@@ -106,4 +107,6 @@ interface StateService {
|
||||
suspend fun setJoinRulePublic()
|
||||
suspend fun setJoinRuleInviteOnly()
|
||||
suspend fun setJoinRuleRestricted(allowList: List<String>)
|
||||
fun getRoomPowerLevels(): RoomPowerLevels
|
||||
fun getRoomPowerLevelsLive(): LiveData<RoomPowerLevels>
|
||||
}
|
||||
|
@@ -17,15 +17,11 @@
|
||||
package org.matrix.android.sdk.internal.session.permalinks
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixPatterns.getServerName
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import java.net.URLEncoder
|
||||
import javax.inject.Inject
|
||||
@@ -101,10 +97,7 @@ internal class ViaParameterFinder @Inject constructor(
|
||||
}
|
||||
|
||||
fun userCanInvite(userId: String, roomId: String): Boolean {
|
||||
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
?.content?.toModel<PowerLevelsContent>()
|
||||
?.let { PowerLevelsHelper(it) }
|
||||
|
||||
return powerLevelsHelper?.isUserAbleToInvite(userId) ?: false
|
||||
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(roomId)
|
||||
return roomPowerLevels.isUserAbleToInvite(userId)
|
||||
}
|
||||
}
|
||||
|
@@ -15,24 +15,20 @@
|
||||
*/
|
||||
package org.matrix.android.sdk.internal.session.pushers
|
||||
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.pushrules.ConditionResolver
|
||||
import org.matrix.android.sdk.api.session.pushrules.ContainsDisplayNameCondition
|
||||
import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition
|
||||
import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition
|
||||
import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition
|
||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultConditionResolver @Inject constructor(
|
||||
private val roomGetter: RoomGetter,
|
||||
@UserId private val userId: String
|
||||
@UserId private val userId: String,
|
||||
) : ConditionResolver {
|
||||
|
||||
override fun resolveEventMatchCondition(
|
||||
@@ -55,13 +51,8 @@ internal class DefaultConditionResolver @Inject constructor(
|
||||
): Boolean {
|
||||
val roomId = event.roomId ?: return false
|
||||
val room = roomGetter.getRoom(roomId) ?: return false
|
||||
|
||||
val powerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
?.content
|
||||
?.toModel<PowerLevelsContent>()
|
||||
?: PowerLevelsContent()
|
||||
|
||||
return condition.isSatisfied(event, powerLevelsContent)
|
||||
val roomPowerLevels = room.getRoomPowerLevels()
|
||||
return condition.isSatisfied(event, roomPowerLevels)
|
||||
}
|
||||
|
||||
override fun resolveContainsDisplayNameCondition(
|
||||
|
@@ -16,7 +16,6 @@
|
||||
package org.matrix.android.sdk.internal.session.room
|
||||
|
||||
import io.realm.Realm
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
|
||||
import org.matrix.android.sdk.api.session.events.model.AggregatedAnnotation
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
@@ -27,7 +26,6 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
|
||||
import org.matrix.android.sdk.api.session.events.model.getRelationContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
|
||||
@@ -36,7 +34,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
|
||||
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.internal.SessionManager
|
||||
import org.matrix.android.sdk.internal.crypto.verification.toState
|
||||
import org.matrix.android.sdk.internal.database.helper.findRootThreadEvent
|
||||
@@ -62,6 +59,7 @@ import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.poll.PollAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.aggregation.utd.EncryptedReferenceAggregationProcessor
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import org.matrix.android.sdk.internal.util.time.Clock
|
||||
import timber.log.Timber
|
||||
@@ -216,9 +214,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||
}
|
||||
in EventType.POLL_END.values -> {
|
||||
sessionManager.getSessionComponent(sessionId)?.session()?.let { session ->
|
||||
getPowerLevelsHelper(event.roomId)?.let {
|
||||
pollAggregationProcessor.handlePollEndEvent(session, it, realm, event)
|
||||
}
|
||||
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(event.roomId)
|
||||
pollAggregationProcessor.handlePollEndEvent(session, roomPowerLevels, realm, event)
|
||||
}
|
||||
}
|
||||
in EventType.STATE_ROOM_BEACON_INFO.values -> {
|
||||
@@ -381,12 +378,6 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPowerLevelsHelper(roomId: String): PowerLevelsHelper? {
|
||||
return stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
?.content?.toModel<PowerLevelsContent>()
|
||||
?.let { PowerLevelsHelper(it) }
|
||||
}
|
||||
|
||||
private fun handleInitialAggregatedRelations(
|
||||
realm: Realm,
|
||||
event: Event,
|
||||
|
@@ -32,7 +32,7 @@ import org.matrix.android.sdk.api.session.room.model.VoteInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.VoteSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
|
||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
|
||||
@@ -160,13 +160,13 @@ internal class DefaultPollAggregationProcessor @Inject constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handlePollEndEvent(session: Session, powerLevelsHelper: PowerLevelsHelper, realm: Realm, event: Event): Boolean {
|
||||
override fun handlePollEndEvent(session: Session, roomPowerLevels: RoomPowerLevels, realm: Realm, event: Event): Boolean {
|
||||
val roomId = event.roomId ?: return false
|
||||
val pollEventId = event.getRelationContent()?.eventId ?: return false
|
||||
val pollOwnerId = getPollEvent(session, roomId, pollEventId)?.root?.senderId
|
||||
val isPollOwner = pollOwnerId == event.senderId
|
||||
|
||||
if (!isPollOwner && !powerLevelsHelper.isUserAbleToRedact(event.senderId ?: "")) {
|
||||
if (!isPollOwner && !roomPowerLevels.isUserAbleToRedact(event.senderId ?: "")) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.session.room.aggregation.poll
|
||||
import io.realm.Realm
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
|
||||
internal interface PollAggregationProcessor {
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ internal interface PollAggregationProcessor {
|
||||
*/
|
||||
fun handlePollEndEvent(
|
||||
session: Session,
|
||||
powerLevelsHelper: PowerLevelsHelper,
|
||||
roomPowerLevels: RoomPowerLevels,
|
||||
realm: Realm,
|
||||
event: Event
|
||||
): Boolean
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2025 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.session.room.powerlevels
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.create.getRoomCreateContentWithSender
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
|
||||
internal fun StateEventDataSource.getRoomPowerLevels(roomId: String): RoomPowerLevels {
|
||||
val powerLevelsEvent = getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
val roomCreateEvent = getStateEvent(roomId, EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
|
||||
return createRoomPowerLevels(powerLevelsEvent = powerLevelsEvent, roomCreateEvent = roomCreateEvent)
|
||||
}
|
||||
|
||||
internal fun StateEventDataSource.getRoomPowerLevelsLive(roomId: String): LiveData<RoomPowerLevels> {
|
||||
val powerLevelsEventLive = getStateEventLive(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
val roomCreateEventLive = getStateEventLive(roomId, EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
|
||||
val resultLiveData = MediatorLiveData<RoomPowerLevels>()
|
||||
|
||||
fun emitIfReady(powerLevelEvent: Optional<Event>?, roomCreateEvent: Optional<Event>?) {
|
||||
if (powerLevelEvent != null && roomCreateEvent != null) {
|
||||
val roomPowerLevels = createRoomPowerLevels(powerLevelEvent.get(), roomCreateEvent.get())
|
||||
resultLiveData.postValue(roomPowerLevels)
|
||||
}
|
||||
}
|
||||
resultLiveData.apply {
|
||||
var powerLevelEvent: Optional<Event>? = null
|
||||
var roomCreateEvent: Optional<Event>? = null
|
||||
|
||||
addSource(powerLevelsEventLive) {
|
||||
powerLevelEvent = it
|
||||
emitIfReady(powerLevelEvent, roomCreateEvent)
|
||||
}
|
||||
addSource(roomCreateEventLive) {
|
||||
roomCreateEvent = it
|
||||
emitIfReady(powerLevelEvent, roomCreateEvent)
|
||||
}
|
||||
}
|
||||
return resultLiveData
|
||||
}
|
||||
|
||||
private fun createRoomPowerLevels(powerLevelsEvent: Event?, roomCreateEvent: Event?): RoomPowerLevels {
|
||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
|
||||
val roomCreateContent = roomCreateEvent?.getRoomCreateContentWithSender()
|
||||
return RoomPowerLevels(powerLevelsContent, roomCreateContent)
|
||||
}
|
@@ -31,11 +31,14 @@ import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.session.room.state.StateService
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.api.util.MimeTypes
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.internal.session.content.FileUploader
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevelsLive
|
||||
|
||||
internal class DefaultStateService @AssistedInject constructor(
|
||||
@Assisted private val roomId: String,
|
||||
@@ -65,6 +68,14 @@ internal class DefaultStateService @AssistedInject constructor(
|
||||
return stateEventDataSource.getStateEventsLive(roomId, eventTypes, stateKey)
|
||||
}
|
||||
|
||||
override fun getRoomPowerLevels(): RoomPowerLevels {
|
||||
return stateEventDataSource.getRoomPowerLevels(roomId)
|
||||
}
|
||||
|
||||
override fun getRoomPowerLevelsLive(): LiveData<RoomPowerLevels> {
|
||||
return stateEventDataSource.getRoomPowerLevelsLive(roomId)
|
||||
}
|
||||
|
||||
override suspend fun sendStateEvent(
|
||||
eventType: String,
|
||||
stateKey: String,
|
||||
|
@@ -34,7 +34,8 @@ import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomType
|
||||
import org.matrix.android.sdk.api.session.room.model.VersioningState
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContentWithSender
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
|
||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
|
||||
@@ -313,13 +314,25 @@ internal class RoomSummaryUpdater @Inject constructor(
|
||||
// check if sender can post child relation in parent?
|
||||
val senderId = parentInfo.stateEventSender
|
||||
val parentRoomId = parentInfo.roomId
|
||||
val powerLevelsHelper = CurrentStateEventEntity
|
||||
val powerLevelsContent = CurrentStateEventEntity
|
||||
.getOrNull(realm, parentRoomId, "", EventType.STATE_ROOM_POWER_LEVELS)
|
||||
?.root
|
||||
?.let { ContentMapper.map(it.content).toModel<PowerLevelsContent>() }
|
||||
?.let { PowerLevelsHelper(it) }
|
||||
|
||||
isValidRelation = powerLevelsHelper?.isUserAllowedToSend(senderId, true, EventType.STATE_SPACE_CHILD) ?: false
|
||||
val roomCreateContent = CurrentStateEventEntity
|
||||
.getOrNull(realm, parentRoomId, "", EventType.STATE_ROOM_CREATE)
|
||||
?.root
|
||||
?.let {
|
||||
val content = ContentMapper.map(it.content).toModel<RoomCreateContent>()
|
||||
val sender = it.sender
|
||||
if (content != null && sender != null) {
|
||||
RoomCreateContentWithSender(sender, content)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
val roomPowerLevels = RoomPowerLevels(powerLevelsContent, roomCreateContent)
|
||||
isValidRelation = roomPowerLevels.isUserAllowedToSend(senderId, true, EventType.STATE_SPACE_CHILD)
|
||||
}
|
||||
|
||||
if (isValidRelation) {
|
||||
|
@@ -23,11 +23,10 @@ import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.homeserver.RoomVersionStatus
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.version.RoomVersionService
|
||||
import org.matrix.android.sdk.internal.session.homeserver.HomeServerCapabilitiesDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
|
||||
internal class DefaultRoomVersionService @AssistedInject constructor(
|
||||
@@ -71,11 +70,8 @@ internal class DefaultRoomVersionService @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override fun userMayUpgradeRoom(userId: String): Boolean {
|
||||
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
|
||||
?.content?.toModel<PowerLevelsContent>()
|
||||
?.let { PowerLevelsHelper(it) }
|
||||
|
||||
return powerLevelsHelper?.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_TOMBSTONE) ?: false
|
||||
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(roomId)
|
||||
return roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_TOMBSTONE)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@@ -35,8 +35,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||
import org.matrix.android.sdk.api.session.space.CreateSpaceParams
|
||||
import org.matrix.android.sdk.api.session.space.JoinSpaceResult
|
||||
import org.matrix.android.sdk.api.session.space.Space
|
||||
@@ -47,11 +46,13 @@ import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
|
||||
import org.matrix.android.sdk.api.session.space.model.SpaceChildSummaryEvent
|
||||
import org.matrix.android.sdk.api.session.space.model.SpaceParentContent
|
||||
import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.room.RoomGetter
|
||||
import org.matrix.android.sdk.internal.session.room.SpaceGetter
|
||||
import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoomTask
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
|
||||
import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
|
||||
@@ -83,7 +84,7 @@ internal class DefaultSpaceService @Inject constructor(
|
||||
if (isPublic) {
|
||||
this.roomAliasName = roomAliasLocalPart
|
||||
this.powerLevelContentOverride = (powerLevelContentOverride ?: PowerLevelsContent()).copy(
|
||||
invite = if (isPublic) Role.Default.value else Role.Moderator.value
|
||||
invite = UserPowerLevel.User.value
|
||||
)
|
||||
this.preset = CreateRoomPreset.PRESET_PUBLIC_CHAT
|
||||
this.historyVisibility = RoomHistoryVisibility.WORLD_READABLE
|
||||
@@ -253,15 +254,8 @@ internal class DefaultSpaceService @Inject constructor(
|
||||
if (roomSummaryDataSource.getRoomSummary(parentSpaceId)?.membership != Membership.JOIN) {
|
||||
throw UnsupportedOperationException("Cannot add canonical child if not member of parent")
|
||||
}
|
||||
val powerLevelsEvent = stateEventDataSource.getStateEvent(
|
||||
roomId = parentSpaceId,
|
||||
eventType = EventType.STATE_ROOM_POWER_LEVELS,
|
||||
stateKey = QueryStringValue.IsEmpty
|
||||
)
|
||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
|
||||
?: throw UnsupportedOperationException("Cannot add canonical child, missing power level")
|
||||
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
|
||||
if (!powerLevelsHelper.isUserAllowedToSend(userId, true, EventType.STATE_SPACE_CHILD)) {
|
||||
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(parentSpaceId)
|
||||
if (!roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_SPACE_CHILD)) {
|
||||
throw UnsupportedOperationException("Cannot add canonical child, not enough power level")
|
||||
}
|
||||
}
|
||||
|
@@ -30,15 +30,13 @@ import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
||||
import org.matrix.android.sdk.api.session.events.model.Content
|
||||
import org.matrix.android.sdk.api.session.events.model.Event
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.widgets.WidgetManagementFailure
|
||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||
import org.matrix.android.sdk.internal.di.UserId
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManager
|
||||
import org.matrix.android.sdk.internal.session.room.powerlevels.getRoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
|
||||
import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
|
||||
import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
|
||||
@@ -200,12 +198,7 @@ internal class WidgetManager @Inject constructor(
|
||||
}
|
||||
|
||||
fun hasPermissionsToHandleWidgets(roomId: String): Boolean {
|
||||
val powerLevelsEvent = stateEventDataSource.getStateEvent(
|
||||
roomId = roomId,
|
||||
eventType = EventType.STATE_ROOM_POWER_LEVELS,
|
||||
stateKey = QueryStringValue.IsEmpty
|
||||
)
|
||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() ?: return false
|
||||
return PowerLevelsHelper(powerLevelsContent).isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY)
|
||||
val roomPowerLevels = stateEventDataSource.getRoomPowerLevels(roomId)
|
||||
return roomPowerLevels.isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY)
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.RoomPowerLevels
|
||||
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntity
|
||||
import org.matrix.android.sdk.internal.database.model.EventAnnotationsSummaryEntityFields
|
||||
import org.matrix.android.sdk.internal.database.model.PollResponseAggregatedSummaryEntity
|
||||
@@ -255,9 +255,9 @@ class DefaultPollAggregationProcessorTest {
|
||||
every { room.getTimelineEvent(eventId) } returns if (hasExistingTimelineEvent) A_TIMELINE_EVENT else null
|
||||
}
|
||||
|
||||
private fun mockRedactionPowerLevels(userId: String, isAbleToRedact: Boolean): PowerLevelsHelper {
|
||||
val powerLevelsHelper = mockk<PowerLevelsHelper>()
|
||||
every { powerLevelsHelper.isUserAbleToRedact(userId) } returns isAbleToRedact
|
||||
return powerLevelsHelper
|
||||
private fun mockRedactionPowerLevels(userId: String, isAbleToRedact: Boolean): RoomPowerLevels {
|
||||
val roomPowerLevels = mockk<RoomPowerLevels>()
|
||||
every { roomPowerLevels.isUserAbleToRedact(userId) } returns isAbleToRedact
|
||||
return roomPowerLevels
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomThirdPartyInviteContent
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomTopicContent
|
||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomPreset
|
||||
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.UserPowerLevel
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
import org.matrix.android.sdk.internal.session.profile.ThirdPartyIdentifier.Companion.MEDIUM_EMAIL
|
||||
@@ -372,13 +372,13 @@ internal class DefaultCreateLocalRoomStateEventsTaskTest {
|
||||
// Power levels
|
||||
val powerLevelsContent = result.find { it.type == EventType.STATE_ROOM_POWER_LEVELS }?.content.toModel<PowerLevelsContent>()
|
||||
powerLevelsContent.shouldNotBeNull()
|
||||
powerLevelsContent.ban shouldBeEqualTo Role.Moderator.value
|
||||
powerLevelsContent.kick shouldBeEqualTo Role.Moderator.value
|
||||
powerLevelsContent.invite shouldBeEqualTo Role.Moderator.value
|
||||
powerLevelsContent.redact shouldBeEqualTo Role.Moderator.value
|
||||
powerLevelsContent.eventsDefault shouldBeEqualTo Role.Default.value
|
||||
powerLevelsContent.usersDefault shouldBeEqualTo Role.Default.value
|
||||
powerLevelsContent.stateDefault shouldBeEqualTo Role.Moderator.value
|
||||
powerLevelsContent.ban shouldBeEqualTo UserPowerLevel.Moderator.value
|
||||
powerLevelsContent.kick shouldBeEqualTo UserPowerLevel.Moderator.value
|
||||
powerLevelsContent.invite shouldBeEqualTo UserPowerLevel.User.value
|
||||
powerLevelsContent.redact shouldBeEqualTo UserPowerLevel.Moderator.value
|
||||
powerLevelsContent.eventsDefault shouldBeEqualTo UserPowerLevel.User.value
|
||||
powerLevelsContent.usersDefault shouldBeEqualTo UserPowerLevel.User.value
|
||||
powerLevelsContent.stateDefault shouldBeEqualTo UserPowerLevel.Moderator.value
|
||||
// Guest access
|
||||
result.find { it.type == EventType.STATE_ROOM_GUEST_ACCESS }
|
||||
?.content.toModel<RoomGuestAccessContent>()?.guestAccess shouldBeEqualTo GuestAccess.Forbidden
|
||||
|
Reference in New Issue
Block a user