-
Notifications
You must be signed in to change notification settings - Fork 743
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/bca/room caps restricted #3663
Changes from all commits
6c2a917
3da20ae
2f16a7f
c9ef08d
30c299e
a626f42
5adceac
88fec37
a7dc7e8
efdaa49
aaa9c7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Spaces - Support Restricted Room via room capabilities API |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Spaces | Support restricted room access in room settings |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,63 @@ data class HomeServerCapabilities( | |
*/ | ||
val roomVersions: RoomVersionCapabilities? = null | ||
) { | ||
|
||
enum class RoomCapabilitySupport { | ||
SUPPORTED, | ||
SUPPORTED_UNSTABLE, | ||
UNSUPPORTED, | ||
UNKNOWN | ||
} | ||
|
||
/** | ||
* Check if a feature is supported by the homeserver. | ||
* @return | ||
* UNKNOWN if the server does not implement room caps | ||
* UNSUPPORTED if this feature is not supported | ||
* SUPPORTED if this feature is supported by a stable version | ||
* SUPPORTED_UNSTABLE if this feature is supported by an unstable version | ||
* (unstable version should only be used for dev/experimental purpose) | ||
*/ | ||
fun isFeatureSupported(feature: String): RoomCapabilitySupport { | ||
if (roomVersions?.capabilities == null) return RoomCapabilitySupport.UNKNOWN | ||
val info = roomVersions.capabilities[feature] ?: return RoomCapabilitySupport.UNSUPPORTED | ||
|
||
val preferred = info.preferred ?: info.support.lastOrNull() | ||
val versionCap = roomVersions.supportedVersion.firstOrNull { it.version == preferred } | ||
|
||
return when { | ||
versionCap == null -> { | ||
RoomCapabilitySupport.UNKNOWN | ||
} | ||
versionCap.status == RoomVersionStatus.STABLE -> { | ||
RoomCapabilitySupport.SUPPORTED | ||
} | ||
else -> { | ||
RoomCapabilitySupport.SUPPORTED_UNSTABLE | ||
} | ||
} | ||
} | ||
fun isFeatureSupported(feature: String, byRoomVersion: String): Boolean { | ||
if (roomVersions?.capabilities == null) return false | ||
val info = roomVersions.capabilities[feature] ?: return false | ||
|
||
return info.preferred == byRoomVersion || info.support.contains(byRoomVersion) | ||
} | ||
|
||
/** | ||
* Use this method to know if you should force a version when creating | ||
* a room that requires this feature. | ||
* You can also use #isFeatureSupported prior to this call to check if the | ||
* feature is supported and report some feedback to user. | ||
*/ | ||
fun versionOverrideForFeature(feature: String) : String? { | ||
val cap = roomVersions?.capabilities?.get(feature) | ||
return cap?.preferred ?: cap?.support?.lastOrNull() | ||
} | ||
|
||
companion object { | ||
const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L | ||
const val ROOM_CAP_KNOCK = "knock" | ||
const val ROOM_CAP_RESTRICTED = "restricted" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefix with ROOM_FEATURE ? The other naming is like that ( |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,14 +18,21 @@ package org.matrix.android.sdk.api.session.homeserver | |
|
||
data class RoomVersionCapabilities( | ||
val defaultRoomVersion: String, | ||
val supportedVersion: List<RoomVersionInfo> | ||
val supportedVersion: List<RoomVersionInfo>, | ||
// Keys are capabilities defined per spec, as for now knock or restricted | ||
val capabilities: Map<String, RoomCapabilitySupport>? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are the keys? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added a comment |
||
) | ||
|
||
data class RoomVersionInfo( | ||
val version: String, | ||
val status: RoomVersionStatus | ||
) | ||
|
||
data class RoomCapabilitySupport( | ||
val preferred: String?, | ||
val support: List<String> | ||
) | ||
|
||
enum class RoomVersionStatus { | ||
STABLE, | ||
UNSTABLE | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.session.room.model.GuestAccess | |
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent | ||
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility | ||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility | ||
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry | ||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM | ||
|
||
open class CreateRoomParams { | ||
|
@@ -162,7 +161,7 @@ open class CreateRoomParams { | |
|
||
var roomVersion: String? = null | ||
|
||
var joinRuleRestricted: List<RoomJoinRulesAllowEntry>? = null | ||
var featurePreset: RoomFeaturePreset? = null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my other comment about SDK2 abstraction. |
||
|
||
companion object { | ||
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright 2020 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.model.create | ||
|
||
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.toContent | ||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities | ||
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.model.RoomJoinRulesContent | ||
|
||
interface RoomFeaturePreset { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interface and class must be moved to internal package and declared internal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's public, used in CreateSpaceViewModelTask for example |
||
|
||
fun updateRoomParams(params: CreateRoomParams) | ||
|
||
fun setupInitialStates(): List<Event>? | ||
} | ||
|
||
class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, val restrictedList: List<RoomJoinRulesAllowEntry>) : RoomFeaturePreset { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not ideal from a SDK2 user point of view to provide homeServerCapabilities here. Can you improve the SDK2 API please? |
||
|
||
override fun updateRoomParams(params: CreateRoomParams) { | ||
params.historyVisibility = params.historyVisibility ?: RoomHistoryVisibility.SHARED | ||
params.guestAccess = params.guestAccess ?: GuestAccess.Forbidden | ||
params.roomVersion = homeServerCapabilities.versionOverrideForFeature(HomeServerCapabilities.ROOM_CAP_RESTRICTED) | ||
} | ||
|
||
override fun setupInitialStates(): List<Event>? { | ||
return listOf( | ||
Event( | ||
type = EventType.STATE_ROOM_JOIN_RULES, | ||
stateKey = "", | ||
content = RoomJoinRulesContent( | ||
_joinRules = RoomJoinRules.RESTRICTED.value, | ||
allowList = restrictedList | ||
).toContent() | ||
) | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,7 +70,22 @@ internal data class RoomVersions( | |
* Required. A detailed description of the room versions the server supports. | ||
*/ | ||
@Json(name = "available") | ||
val available: JsonDict | ||
val available: JsonDict? = null, | ||
|
||
/** | ||
* "room_capabilities": { | ||
* "knock" : { | ||
* "preferred": "7", | ||
* "support" : ["7"] | ||
* }, | ||
* "restricted" : { | ||
* "preferred": "9", | ||
* "support" : ["8", "9"] | ||
* } | ||
* } | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the Json sample :) |
||
@Json(name = "room_capabilities") | ||
val roomCapabilities: JsonDict? = null | ||
) | ||
|
||
// The spec says: If not present, the client should assume that password changes are possible via the API | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,17 +17,24 @@ | |
package org.matrix.android.sdk.internal.session.permalinks | ||
|
||
import org.matrix.android.sdk.api.MatrixPatterns.getDomain | ||
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.state.StateEventDataSource | ||
import java.net.URLEncoder | ||
import javax.inject.Inject | ||
import javax.inject.Provider | ||
|
||
internal class ViaParameterFinder @Inject constructor( | ||
@UserId private val userId: String, | ||
private val roomGetterProvider: Provider<RoomGetter> | ||
private val roomGetterProvider: Provider<RoomGetter>, | ||
private val stateEventDataSource: StateEventDataSource | ||
) { | ||
|
||
fun computeViaParams(roomId: String, max: Int): List<String> { | ||
|
@@ -70,4 +77,28 @@ internal class ViaParameterFinder @Inject constructor( | |
.orEmpty() | ||
.toSet() | ||
} | ||
|
||
fun computeViaParamsForRestricted(roomId: String, max: Int): List<String> { | ||
val userThatCanInvite = roomGetterProvider.get().getRoom(roomId) | ||
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) }) | ||
?.map { it.userId } | ||
?.filter { userCanInvite(userId, roomId) } | ||
.orEmpty() | ||
.toSet() | ||
|
||
return userThatCanInvite.map { it.getDomain() } | ||
.groupBy { it } | ||
.mapValues { it.value.size } | ||
.toMutableMap() | ||
.let { map -> map.keys.sortedByDescending { map[it] } } | ||
.take(max) | ||
} | ||
|
||
fun userCanInvite(userId: String, roomId: String): Boolean { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private ? |
||
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) | ||
?.content?.toModel<PowerLevelsContent>() | ||
?.let { PowerLevelsHelper(it) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is a bit too much duplicated, we could create a PowerLevelsHelperCreator in the SDK or an extension... |
||
|
||
return powerLevelsHelper?.isUserAbleToInvite(userId) ?: false | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,16 +17,10 @@ | |
package org.matrix.android.sdk.internal.session.room.create | ||
|
||
import org.matrix.android.sdk.api.extensions.tryOrNull | ||
import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService | ||
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.toContent | ||
import org.matrix.android.sdk.api.session.identity.IdentityServiceError | ||
import org.matrix.android.sdk.api.session.identity.toMedium | ||
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.RoomJoinRulesContent | ||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams | ||
import org.matrix.android.sdk.api.util.MimeTypes | ||
import org.matrix.android.sdk.internal.crypto.DeviceListManager | ||
|
@@ -45,7 +39,6 @@ import javax.inject.Inject | |
|
||
internal class CreateRoomBodyBuilder @Inject constructor( | ||
private val ensureIdentityTokenTask: EnsureIdentityTokenTask, | ||
private val crossSigningService: CrossSigningService, | ||
private val deviceListManager: DeviceListManager, | ||
private val identityStore: IdentityStore, | ||
private val fileUploader: FileUploader, | ||
|
@@ -76,19 +69,18 @@ internal class CreateRoomBodyBuilder @Inject constructor( | |
} | ||
} | ||
|
||
if (params.joinRuleRestricted != null) { | ||
params.roomVersion = "org.matrix.msc3083" | ||
params.historyVisibility = params.historyVisibility ?: RoomHistoryVisibility.SHARED | ||
params.guestAccess = params.guestAccess ?: GuestAccess.Forbidden | ||
} | ||
val initialStates = (listOfNotNull( | ||
buildEncryptionWithAlgorithmEvent(params), | ||
buildHistoryVisibilityEvent(params), | ||
buildAvatarEvent(params), | ||
buildGuestAccess(params), | ||
buildJoinRulesRestricted(params) | ||
) | ||
+ buildCustomInitialStates(params)) | ||
params.featurePreset?.updateRoomParams(params) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. weird code |
||
|
||
val initialStates = ( | ||
listOfNotNull( | ||
buildEncryptionWithAlgorithmEvent(params), | ||
buildHistoryVisibilityEvent(params), | ||
buildAvatarEvent(params), | ||
buildGuestAccess(params) | ||
) | ||
+ params.featurePreset?.setupInitialStates().orEmpty() | ||
+ buildCustomInitialStates(params) | ||
) | ||
.takeIf { it.isNotEmpty() } | ||
|
||
return CreateRoomBody( | ||
|
@@ -158,20 +150,6 @@ internal class CreateRoomBodyBuilder @Inject constructor( | |
} | ||
} | ||
|
||
private fun buildJoinRulesRestricted(params: CreateRoomParams): Event? { | ||
return params.joinRuleRestricted | ||
?.let { allowList -> | ||
Event( | ||
type = EventType.STATE_ROOM_JOIN_RULES, | ||
stateKey = "", | ||
content = RoomJoinRulesContent( | ||
_joinRules = RoomJoinRules.RESTRICTED.value, | ||
allowList = allowList | ||
).toContent() | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Add the crypto algorithm to the room creation parameters. | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add some doc for this public APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done