1
Fork 0
mirror of https://github.com/Steffo99/twom.git synced 2024-11-21 23:54:26 +00:00

Add permission checks to invite and kicks

This commit is contained in:
Steffo 2024-02-05 01:40:10 +01:00
parent 04e8aa3743
commit 40bfd858ee
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
5 changed files with 96 additions and 3 deletions

View file

@ -10,6 +10,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import eu.steffo.twom.R
import eu.steffo.twom.viewroom.effects.canIInvite
@Composable
@Preview
@ -17,7 +18,10 @@ fun InviteFAB(
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
) {
// TODO: Hide if unprivileged
if (!canIInvite()) {
return
}
ExtendedFloatingActionButton(
modifier = modifier,
onClick = { onClick() },

View file

@ -28,6 +28,7 @@ import eu.steffo.twom.avatar.components.AvatarUser
import eu.steffo.twom.errorhandling.components.ErrorText
import eu.steffo.twom.matrix.complocals.LocalSession
import eu.steffo.twom.viewroom.complocals.LocalRoom
import eu.steffo.twom.viewroom.effects.canIKick
import eu.steffo.twom.viewroom.effects.observeRSVP
import eu.steffo.twom.viewroom.effects.resolveUser
import eu.steffo.twom.viewroom.utils.RSVPAnswer
@ -67,6 +68,7 @@ fun MemberListItem(
// This might not be necessary; I'm not sure when the internal Matrix client resolves users
val user = resolveUser(member.userId)
val canKick = canIKick()
val scope = rememberCoroutineScope()
@ -132,8 +134,7 @@ fun MemberListItem(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
// TODO: Also hide if unprivileged
if (member.userId != session.myUserId) {
if (member.userId != session.myUserId && canKick) {
DropdownMenuItem(
text = {
Text(stringResource(R.string.room_uninvite_label))

View file

@ -0,0 +1,14 @@
package eu.steffo.twom.viewroom.effects
import androidx.compose.runtime.Composable
import eu.steffo.twom.matrix.complocals.LocalSession
import observePowerLevels
import kotlin.jvm.optionals.getOrNull
@Composable
fun canIInvite(): Boolean {
val session = LocalSession.current ?: return false
val powerLevelsRequest = observePowerLevels() ?: return false
val powerLevels = powerLevelsRequest.getOrNull() ?: return false
return powerLevels.second.isUserAbleToInvite(session.myUserId)
}

View file

@ -0,0 +1,14 @@
package eu.steffo.twom.viewroom.effects
import androidx.compose.runtime.Composable
import eu.steffo.twom.matrix.complocals.LocalSession
import observePowerLevels
import kotlin.jvm.optionals.getOrNull
@Composable
fun canIKick(): Boolean {
val session = LocalSession.current ?: return false
val powerLevelsRequest = observePowerLevels() ?: return false
val powerLevels = powerLevelsRequest.getOrNull() ?: return false
return powerLevels.second.isUserAbleToKick(session.myUserId)
}

View file

@ -0,0 +1,60 @@
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import eu.steffo.twom.viewroom.complocals.LocalRoom
import org.matrix.android.sdk.api.query.QueryStringValue
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.powerlevels.PowerLevelsHelper
import java.util.Optional
import kotlin.jvm.optionals.getOrNull
private const val TAG = "observePowerLevels"
@Composable
fun observePowerLevels(): Optional<Pair<PowerLevelsContent, PowerLevelsHelper>>? {
val roomRequest = LocalRoom.current
if (roomRequest == null) {
Log.v(TAG, "Requesting room information, not doing anything.")
return null
}
val room = roomRequest.getOrNull()
if (room == null) {
Log.e(TAG, "Room was not found, not doing anything.")
return null
}
val powerLevelsRequest by room.stateService().getStateEventLive(
eventType = "m.room.power_levels",
stateKey = QueryStringValue.IsEmpty,
).observeAsState()
if (powerLevelsRequest == null) {
Log.v(TAG, "Power level event is being requested.")
return null
}
val powerLevels = powerLevelsRequest?.getOrNull()
if (powerLevels == null) {
Log.v(TAG, "No power level event has been found.")
return Optional.empty()
}
val powerLevelsContent = powerLevels.content.toModel<PowerLevelsContent>()
if (powerLevelsContent == null) {
Log.e(TAG, "Could not deserialize power levels event.")
return Optional.empty()
}
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
return Optional.of(Pair(powerLevelsContent, powerLevelsHelper))
}