Add a button to MemberInfo to deactivate a user

Part of https://github.com/vector-im/riot-web/issues/4125
This commit is contained in:
Travis Ralston 2019-09-01 18:04:24 -06:00 committed by David Baker
parent 9016be22a4
commit 9e2cdecb9b
2 changed files with 47 additions and 6 deletions

View file

@ -45,6 +45,7 @@ import MultiInviter from "../../../utils/MultiInviter";
import SettingsStore from "../../../settings/SettingsStore"; import SettingsStore from "../../../settings/SettingsStore";
import E2EIcon from "./E2EIcon"; import E2EIcon from "./E2EIcon";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import MatrixClientPeg from "../../../MatrixClientPeg";
module.exports = withMatrixClient(React.createClass({ module.exports = withMatrixClient(React.createClass({
displayName: 'MemberInfo', displayName: 'MemberInfo',
@ -61,6 +62,7 @@ module.exports = withMatrixClient(React.createClass({
ban: false, ban: false,
mute: false, mute: false,
modifyLevel: false, modifyLevel: false,
synapseDeactivate: false,
}, },
muted: false, muted: false,
isTargetMod: false, isTargetMod: false,
@ -211,8 +213,8 @@ module.exports = withMatrixClient(React.createClass({
} }
}, },
_updateStateForNewMember: function(member) { _updateStateForNewMember: async function(member) {
const newState = this._calculateOpsPermissions(member); const newState = await this._calculateOpsPermissions(member);
newState.devicesLoading = true; newState.devicesLoading = true;
newState.devices = null; newState.devices = null;
this.setState(newState); this.setState(newState);
@ -460,6 +462,25 @@ module.exports = withMatrixClient(React.createClass({
}); });
}, },
onSynapseDeactivate: function() {
const QuestionDialog = sdk.getComponent('views.dialogs.QuestionDialog');
Modal.createTrackedDialog('Synapse User Deactivation', '', QuestionDialog, {
title: _t("Deactivate user?"),
description:
<div>{ _t(
"Deactivating this user will log them out and prevent them from logging back in. Additionally, " +
"they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to " +
"deactivate this user?"
) }</div>,
button: _t("Deactivate user"),
danger: true,
onFinished: (accepted) => {
if (!accepted) return;
this.context.matrixClient.deactivateSynapseUser(this.props.member.userId);
},
});
},
_applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) { _applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) {
this.setState({ updating: this.state.updating + 1 }); this.setState({ updating: this.state.updating + 1 });
this.props.matrixClient.setPowerLevel(roomId, target, parseInt(powerLevel), powerLevelEvent).then( this.props.matrixClient.setPowerLevel(roomId, target, parseInt(powerLevel), powerLevelEvent).then(
@ -544,7 +565,7 @@ module.exports = withMatrixClient(React.createClass({
}); });
}, },
_calculateOpsPermissions: function(member) { _calculateOpsPermissions: async function(member) {
const defaultPerms = { const defaultPerms = {
can: {}, can: {},
muted: false, muted: false,
@ -560,7 +581,7 @@ module.exports = withMatrixClient(React.createClass({
const them = member; const them = member;
return { return {
can: this._calculateCanPermissions( can: await this._calculateCanPermissions(
me, them, powerLevels.getContent(), me, them, powerLevels.getContent(),
), ),
muted: this._isMuted(them, powerLevels.getContent()), muted: this._isMuted(them, powerLevels.getContent()),
@ -568,7 +589,7 @@ module.exports = withMatrixClient(React.createClass({
}; };
}, },
_calculateCanPermissions: function(me, them, powerLevels) { _calculateCanPermissions: async function(me, them, powerLevels) {
const isMe = me.userId === them.userId; const isMe = me.userId === them.userId;
const can = { const can = {
kick: false, kick: false,
@ -577,6 +598,10 @@ module.exports = withMatrixClient(React.createClass({
modifyLevel: false, modifyLevel: false,
modifyLevelMax: 0, modifyLevelMax: 0,
}; };
// Calculate permissions for Synapse before doing the PL checks
can.synapseDeactivate = await this.context.matrixClient.isSynapseAdministrator();
const canAffectUser = them.powerLevel < me.powerLevel || isMe; const canAffectUser = them.powerLevel < me.powerLevel || isMe;
if (!canAffectUser) { if (!canAffectUser) {
//console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel); //console.log("Cannot affect user: %s >= %s", them.powerLevel, me.powerLevel);
@ -782,6 +807,7 @@ module.exports = withMatrixClient(React.createClass({
let banButton; let banButton;
let muteButton; let muteButton;
let giveModButton; let giveModButton;
let synapseDeactivateButton;
let spinner; let spinner;
if (this.props.member.userId !== this.props.matrixClient.credentials.userId) { if (this.props.member.userId !== this.props.matrixClient.credentials.userId) {
@ -886,8 +912,19 @@ module.exports = withMatrixClient(React.createClass({
</AccessibleButton>; </AccessibleButton>;
} }
// We don't need a perfect check here, just something to pass as "probably not our homeserver". If
// someone does figure out how to bypass this check the worst that happens is an error.
const sameHomeserver = this.props.member.userId.endsWith(`:${MatrixClientPeg.getHomeserverName()}`);
if (this.state.can.synapseDeactivate && sameHomeserver) {
synapseDeactivateButton = (
<AccessibleButton onClick={this.onSynapseDeactivate} className="mx_MemberInfo_field">
{_t("Deactivate user")}
</AccessibleButton>
);
}
let adminTools; let adminTools;
if (kickButton || banButton || muteButton || giveModButton) { if (kickButton || banButton || muteButton || giveModButton || synapseDeactivateButton) {
adminTools = adminTools =
<div> <div>
<h3>{ _t("Admin Tools") }</h3> <h3>{ _t("Admin Tools") }</h3>
@ -897,6 +934,7 @@ module.exports = withMatrixClient(React.createClass({
{ kickButton } { kickButton }
{ banButton } { banButton }
{ giveModButton } { giveModButton }
{ synapseDeactivateButton }
</div> </div>
</div>; </div>;
} }

View file

@ -729,6 +729,9 @@
"Demote": "Demote", "Demote": "Demote",
"Failed to mute user": "Failed to mute user", "Failed to mute user": "Failed to mute user",
"Failed to toggle moderator status": "Failed to toggle moderator status", "Failed to toggle moderator status": "Failed to toggle moderator status",
"Deactivate user?": "Deactivate user?",
"Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?",
"Deactivate user": "Deactivate user",
"Failed to change power level": "Failed to change power level", "Failed to change power level": "Failed to change power level",
"You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.",
"No devices with registered encryption keys": "No devices with registered encryption keys", "No devices with registered encryption keys": "No devices with registered encryption keys",