Add support to remove user devices (#57)

Change-Id: I19176daa656b9280ccd00f1ca0095e72870ca21e
This commit is contained in:
Manuel Stahl 2020-07-08 11:11:24 +02:00
parent 78e7c5f391
commit 314906657f
5 changed files with 118 additions and 8 deletions

89
src/components/devices.js Normal file
View file

@ -0,0 +1,89 @@
import React, { Fragment, useState } from "react";
import {
Button,
useMutation,
useNotify,
Confirm,
useRefresh,
} from "react-admin";
import ActionDelete from "@material-ui/icons/Delete";
import { makeStyles } from "@material-ui/core/styles";
import { fade } from "@material-ui/core/styles/colorManipulator";
import classnames from "classnames";
const useStyles = makeStyles(
theme => ({
deleteButton: {
color: theme.palette.error.main,
"&:hover": {
backgroundColor: fade(theme.palette.error.main, 0.12),
// Reset on mouse devices
"@media (hover: none)": {
backgroundColor: "transparent",
},
},
},
}),
{ name: "RaDeleteDeviceButton" }
);
export const DeviceRemoveButton = props => {
const { record } = props;
const classes = useStyles(props);
const [open, setOpen] = useState(false);
const refresh = useRefresh();
const notify = useNotify();
const [removeDevice, { loading }] = useMutation();
if (!record) return null;
const handleClick = () => setOpen(true);
const handleDialogClose = () => setOpen(false);
const handleConfirm = () => {
removeDevice(
{
type: "delete",
resource: "devices",
payload: {
id: record.id,
user_id: record.user_id,
},
},
{
onSuccess: () => {
notify("resources.devices.action.erase.success");
refresh();
},
onFailure: () =>
notify("resources.devices.action.erase.failure", "error"),
}
);
setOpen(false);
};
return (
<Fragment>
<Button
label="ra.action.remove"
onClick={handleClick}
className={classnames("ra-delete-button", classes.deleteButton)}
>
<ActionDelete />
</Button>
<Confirm
isOpen={open}
loading={loading}
onConfirm={handleConfirm}
onClose={handleDialogClose}
title="resources.devices.action.erase.title"
content="resources.devices.action.erase.content"
translateOptions={{
id: record.id,
name: record.display_name ? record.display_name : record.id,
}}
/>
</Fragment>
);
};

View file

@ -38,6 +38,7 @@ import {
sanitizeListRestProps, sanitizeListRestProps,
} from "react-admin"; } from "react-admin";
import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices"; import { ServerNoticeButton, ServerNoticeBulkButton } from "./ServerNotices";
import { DeviceRemoveButton } from "./devices";
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles({ const useStyles = makeStyles({
@ -284,6 +285,7 @@ export const UserEdit = props => {
}} }}
sortable={false} sortable={false}
/> />
<DeviceRemoveButton />
</Datagrid> </Datagrid>
</ReferenceManyField> </ReferenceManyField>
</FormTab> </FormTab>

View file

@ -114,6 +114,14 @@ export default {
}, },
devices: { devices: {
name: "Gerät |||| Geräte", name: "Gerät |||| Geräte",
action: {
erase: {
title: "Entferne %{id}",
content: 'Möchten Sie das Gerät "%{name}" wirklich entfernen?',
success: "Gerät erfolgreich entfernt.",
failure: "Beim Entfernen ist ein Fehler aufgetreten.",
},
},
}, },
servernotices: { servernotices: {
name: "Serverbenachrichtigungen", name: "Serverbenachrichtigungen",

View file

@ -112,6 +112,14 @@ export default {
}, },
devices: { devices: {
name: "Device |||| Devices", name: "Device |||| Devices",
action: {
erase: {
title: "Removing %{id}",
content: 'Are you sure you want to remove the device "%{name}"?',
success: "Device successfully removed.",
failure: "An error has occurred.",
},
},
}, },
servernotices: { servernotices: {
name: "Server Notices", name: "Server Notices",

View file

@ -45,8 +45,8 @@ const resourceMap = {
body: data, body: data,
method: "PUT", method: "PUT",
}), }),
delete: id => ({ delete: params => ({
endpoint: `/_synapse/admin/v1/deactivate/${id}`, endpoint: `/_synapse/admin/v1/deactivate/${params.id}`,
body: { erase: true }, body: { erase: true },
method: "POST", method: "POST",
}), }),
@ -76,6 +76,9 @@ const resourceMap = {
reference: id => ({ reference: id => ({
endpoint: `/_synapse/admin/v2/users/${id}/devices`, endpoint: `/_synapse/admin/v2/users/${id}/devices`,
}), }),
delete: params => ({
endpoint: `/_synapse/admin/v2/users/${params.user_id}/devices/${params.id}`,
}),
}, },
connections: { connections: {
path: "/_synapse/admin/v1/whois", path: "/_synapse/admin/v1/whois",
@ -274,11 +277,11 @@ const dataProvider = {
const res = resourceMap[resource]; const res = resourceMap[resource];
if ("delete" in res) { if ("delete" in res) {
const del = res["delete"](params.id); const del = res["delete"](params);
const endpoint_url = homeserver + del.endpoint; const endpoint_url = homeserver + del.endpoint;
return jsonClient(endpoint_url, { return jsonClient(endpoint_url, {
method: del.method, method: "method" in del ? del.method : "DELETE",
body: JSON.stringify(del.body), body: "body" in del ? JSON.stringify(del.body) : null,
}).then(({ json }) => ({ }).then(({ json }) => ({
data: json, data: json,
})); }));
@ -303,11 +306,11 @@ const dataProvider = {
if ("delete" in res) { if ("delete" in res) {
return Promise.all( return Promise.all(
params.ids.map(id => { params.ids.map(id => {
const del = res["delete"](id); const del = res["delete"]({ ...params, id: id });
const endpoint_url = homeserver + del.endpoint; const endpoint_url = homeserver + del.endpoint;
return jsonClient(endpoint_url, { return jsonClient(endpoint_url, {
method: del.method, method: "method" in del ? del.method : "DELETE",
body: JSON.stringify(del.body), body: "body" in del ? JSON.stringify(del.body) : null,
}); });
}) })
).then(responses => ({ ).then(responses => ({