diff --git a/src/components/users.js b/src/components/users.js index b690377..38dd01f 100644 --- a/src/components/users.js +++ b/src/components/users.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { Fragment } from "react"; import PersonPinIcon from "@material-ui/icons/PersonPin"; import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent"; import { @@ -10,6 +10,7 @@ import { Edit, List, Filter, + Toolbar, SimpleForm, SimpleFormIterator, TabbedForm, @@ -22,7 +23,11 @@ import { TextInput, ReferenceField, SelectInput, + BulkDeleteButton, + DeleteButton, + SaveButton, regex, + useTranslate, Pagination, } from "react-admin"; @@ -41,12 +46,25 @@ const UserFilter = props => ( ); +const UserBulkActionButtons = props => { + const translate = useTranslate(); + return ( + + + + ); +}; + export const UserList = props => ( } filterDefaultValues={{ guests: true, deactivated: false }} - bulkActionButtons={false} + bulkActionButtons={} pagination={} > @@ -81,6 +99,19 @@ const validateUser = regex( "synapseadmin.users.invalid_user_id" ); +const UserEditToolbar = props => { + const translate = useTranslate(); + return ( + + + + + ); +}; + export const UserCreate = props => ( @@ -106,7 +137,7 @@ export const UserCreate = props => ( export const UserEdit = props => ( - + }> }> diff --git a/src/i18n/de.js b/src/i18n/de.js index 86ace87..07a83fe 100644 --- a/src/i18n/de.js +++ b/src/i18n/de.js @@ -37,6 +37,10 @@ export default { }, helper: { deactivate: "Deaktivierte Nutzer können nicht wieder aktiviert werden.", + erase: "DSGVO konformes Löschen der Benutzerdaten", + }, + action: { + erase: "Lösche Benutzerdaten", }, }, rooms: { diff --git a/src/i18n/en.js b/src/i18n/en.js index 296883f..7bb739a 100644 --- a/src/i18n/en.js +++ b/src/i18n/en.js @@ -37,6 +37,10 @@ export default { }, helper: { deactivate: "Deactivated users cannot be reactivated", + erase: "Mark the user as GDPR-erased", + }, + action: { + erase: "Erase user data", }, }, rooms: { diff --git a/src/synapse/dataProvider.js b/src/synapse/dataProvider.js index 7ffc40d..303d25c 100644 --- a/src/synapse/dataProvider.js +++ b/src/synapse/dataProvider.js @@ -30,6 +30,11 @@ const resourceMap = { ? parseInt(json.next_token, 10) + perPage : from + json.users.length; }, + delete: id => ({ + endpoint: `/_synapse/admin/v1/deactivate/${id}`, + body: { erase: true }, + method: "POST", + }), }, rooms: { path: "/_synapse/admin/v1/rooms", @@ -202,12 +207,24 @@ const dataProvider = { const res = resourceMap[resource]; - const homeserver_url = homeserver + res.path; - return jsonClient(`${homeserver_url}/${params.id}`, { - method: "DELETE", - }).then(({ json }) => ({ - data: json, - })); + if ("delete" in res) { + const del = res["delete"](params.id); + const homeserver_url = homeserver + del.endpoint; + return jsonClient(homeserver_url, { + method: del.method, + body: JSON.stringify(del.body), + }).then(({ json }) => ({ + data: json, + })); + } else { + const homeserver_url = homeserver + res.path; + return jsonClient(`${homeserver_url}/${params.id}`, { + method: "DELETE", + body: JSON.stringify(params.data, filterNullValues), + }).then(({ json }) => ({ + data: json, + })); + } }, deleteMany: (resource, params) => { @@ -217,17 +234,32 @@ const dataProvider = { const res = resourceMap[resource]; - const homeserver_url = homeserver + res.path; - return Promise.all( - params.ids.map(id => - jsonClient(`${homeserver_url}/${id}`, { - method: "DELETE", - body: JSON.stringify(params.data, filterNullValues), - }).then(responses => ({ - data: responses.map(({ json }) => json), - })) - ) - ); + if ("delete" in res) { + return Promise.all( + params.ids.map(id => { + const del = res["delete"](id); + const homeserver_url = homeserver + del.endpoint; + return jsonClient(homeserver_url, { + method: del.method, + body: JSON.stringify(del.body), + }); + }) + ).then(responses => ({ + data: responses.map(({ json }) => json), + })); + } else { + const homeserver_url = homeserver + res.path; + return Promise.all( + params.ids.map(id => + jsonClient(`${homeserver_url}/${id}`, { + method: "DELETE", + body: JSON.stringify(params.data, filterNullValues), + }) + ) + ).then(responses => ({ + data: responses.map(({ json }) => json), + })); + } }, };