Skip to content

Commit f3080e9

Browse files
authored
Provide options to delete media and redact events on user erase (#49)
* Provide options to delete media and redact events on user erase * update readme
1 parent f8fe116 commit f3080e9

12 files changed

Lines changed: 205 additions & 16 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ The following changes are already implemented:
6060
* [Upgrade react-admin to v5](https://github.com/etkecc/synapse-admin/pull/40)
6161
* [Restrict actions on specific users](https://github.com/etkecc/synapse-admin/pull/42)
6262
* [Add `Contact support` menu item](https://github.com/etkecc/synapse-admin/pull/45)
63+
* [Provide options to delete media and redact events on user erase](https://github.com/etkecc/synapse-admin/pull/49)
6364

6465
_the list will be updated as new changes are added_
6566

@@ -136,7 +137,7 @@ Synapse-Admin provides a support link in the main menu - `Contact support`. By d
136137

137138
### Supported Synapse
138139

139-
It needs at least [Synapse](https://github.com/element-hq/synapse) v1.93.0 for all functions to work as expected!
140+
It needs at least [Synapse](https://github.com/element-hq/synapse) v1.116.0 for all functions to work as expected!
140141

141142
You get your server version with the request `/_synapse/admin/v1/server_version`.
142143
See also [Synapse version API](https://element-hq.github.io/synapse/latest/admin_api/version_api.html).
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "@mui/material";
2+
import { Fragment, useState } from "react";
3+
import { SimpleForm, BooleanInput, useTranslate, RaRecord, useNotify, useRedirect, useDelete, NotificationType, useDeleteMany, Identifier, useUnselectAll } from "react-admin";
4+
import ActionDelete from "@mui/icons-material/Delete";
5+
import ActionCheck from "@mui/icons-material/CheckCircle";
6+
import AlertError from "@mui/icons-material/ErrorOutline";
7+
8+
interface DeleteUserButtonProps {
9+
selectedIds: Identifier[];
10+
confirmTitle: string;
11+
confirmContent: string;
12+
}
13+
14+
const resourceName = "users";
15+
16+
const DeleteUserButton: React.FC<DeleteUserButtonProps> = (props) => {
17+
const translate = useTranslate();
18+
const [open, setOpen] = useState(false);
19+
const [deleteMedia, setDeleteMedia] = useState(false);
20+
const [redactEvents, setRedactEvents] = useState(false);
21+
22+
const notify = useNotify();
23+
const redirect = useRedirect();
24+
25+
const [deleteMany, { isLoading }] = useDeleteMany();
26+
const unselectAll = useUnselectAll(resourceName);
27+
const recordIds = props.selectedIds;
28+
29+
const handleDialogOpen = () => setOpen(true);
30+
const handleDialogClose = () => setOpen(false);
31+
32+
const handleDelete = (values: {deleteMedia: boolean, redactEvents: boolean}) => {
33+
deleteMany(
34+
resourceName,
35+
{ ids: recordIds, meta: values },
36+
{
37+
onSuccess: () => {
38+
handleDialogClose();
39+
unselectAll();
40+
redirect("/users");
41+
},
42+
onError: (error) =>
43+
notify("ra.notification.data_provider_error", { type: 'error' as NotificationType }),
44+
}
45+
);
46+
};
47+
48+
const handleConfirm = () => {
49+
setOpen(false);
50+
handleDelete({ deleteMedia: deleteMedia, redactEvents: redactEvents });
51+
};
52+
53+
return (
54+
<Fragment>
55+
<Button
56+
onClick={handleDialogOpen}
57+
disabled={isLoading}
58+
className={"ra-delete-button"}
59+
key="button"
60+
size="small"
61+
sx={{
62+
"&.MuiButton-sizeSmall": {
63+
lineHeight: 1.5,
64+
},
65+
}}
66+
color={"error"}
67+
startIcon={<ActionDelete />}
68+
>
69+
{translate("ra.action.delete")}
70+
</Button>
71+
<Dialog open={open} onClose={handleDialogClose}>
72+
<DialogTitle>{translate(props.confirmTitle)}</DialogTitle>
73+
<DialogContent>
74+
<DialogContentText>{translate(props.confirmContent)}</DialogContentText>
75+
<SimpleForm toolbar={false}>
76+
<BooleanInput
77+
source="deleteMedia"
78+
value={deleteMedia}
79+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setDeleteMedia(event.target.checked)}
80+
label="resources.users.action.delete_media"
81+
defaultValue={false}
82+
/>
83+
<BooleanInput
84+
source="redactEvents"
85+
value={redactEvents}
86+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => setRedactEvents(event.target.checked)}
87+
label="resources.users.action.redact_events"
88+
defaultValue={false}
89+
/>
90+
</SimpleForm>
91+
</DialogContent>
92+
<DialogActions>
93+
<Button disabled={false} onClick={handleDialogClose} startIcon={<AlertError />}>
94+
{translate("ra.action.cancel")}
95+
</Button>
96+
<Button
97+
disabled={false}
98+
onClick={handleConfirm}
99+
className={"ra-confirm RaConfirm-confirmPrimary"}
100+
autoFocus
101+
startIcon={<ActionCheck />}
102+
>
103+
{translate("ra.action.confirm")}
104+
</Button>
105+
</DialogActions>
106+
</Dialog>
107+
</Fragment>
108+
);
109+
};
110+
111+
export default DeleteUserButton;

src/i18n/de.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,15 @@ const de: SynapseTranslationMessages = {
151151
password: "Durch die Änderung des Passworts wird der Benutzer von allen Sitzungen abgemeldet.",
152152
deactivate: "Sie müssen ein Passwort angeben, um ein Konto wieder zu aktivieren.",
153153
erase: "DSGVO konformes Löschen der Benutzerdaten.",
154+
erase_text: "Das bedeutet, dass die von dem/den Benutzer(n) gesendeten Nachrichten für alle, die zum Zeitpunkt des Sendens im Raum waren, sichtbar bleiben, aber für Benutzer, die dem Raum später beitreten, nicht sichtbar sind.",
154155
erase_admin_error: "Das Löschen des eigenen Benutzers ist nicht erlaubt.",
155156
modify_managed_user_error: "Das Ändern eines vom System verwalteten Benutzers ist nicht zulässig.",
156157
},
157158
action: {
158159
erase: "Lösche Benutzerdaten",
159-
erase_avatar: "Avatar löschen"
160+
erase_avatar: "Avatar löschen",
161+
delete_media: "Alle von dem/den Benutzer(n) hochgeladenen Medien löschen",
162+
redact_events: "Schwärzen aller vom Benutzer gesendeten Ereignisse (-s)",
160163
},
161164
},
162165
rooms: {

src/i18n/en.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,15 @@ const en: SynapseTranslationMessages = {
142142
password: "Changing password will log user out of all sessions.",
143143
deactivate: "You must provide a password to re-activate an account.",
144144
erase: "Mark the user as GDPR-erased",
145+
erase_text: "This means messages sent by the user(-s) will still be visible by anyone who was in the room when these messages were sent, but hidden from users joining the room afterward.",
145146
erase_admin_error: "Deleting own user is not allowed.",
146147
modify_managed_user_error: "Modifying a system-managed user is not allowed.",
147148
},
148149
action: {
149150
erase: "Erase user data",
150-
erase_avatar: "Erase avatar"
151+
erase_avatar: "Erase avatar",
152+
delete_media: "Delete all media uploaded by the user(-s)",
153+
redact_events: "Redact all events sent by the user(-s)",
151154
},
152155
},
153156
rooms: {

src/i18n/fa.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,15 @@ const fa: SynapseTranslationMessages = {
138138
password: "با تغییر رمز عبور کاربر از تمام دستگاه ها خارج می شود.",
139139
deactivate: "برای فعالسازی مجدد حساب باید رمز عبور وارد کنید.",
140140
erase: "کاربر را به عنوان GDPR پاک شده علامت گذاری کنید",
141+
erase_text: "وهذا يعني أن الرسائل المرسلة من قبل المستخدم (المستخدمين) ستظل مرئية من قبل أي شخص كان في الغرفة عند إرسال هذه الرسائل، ولكنها مخفية عن المستخدمين الذين ينضمون إلى الغرفة بعد ذلك.",
141142
erase_admin_error: "حذف المستخدم الخاص غير مسموح به.",
142143
modify_managed_user_error: "لا يُسمح بتغيير المستخدم الذي يديره النظام.",
143144
},
144145
action: {
145146
erase: "پاک کردن اطلاعات کاربر",
147+
erase_avatar: "محو الصورة الرمزية",
148+
delete_media: "حذف جميع الوسائط التي تم تحميلها بواسطة المستخدم (المستخدمين)",
149+
redact_events: "تنقيح جميع الأحداث المرسلة من قبل المستخدم (-s)",
146150
},
147151
},
148152
rooms: {

src/i18n/fr.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,15 @@ const fr: SynapseTranslationMessages = {
140140
helper: {
141141
deactivate: "Vous devrez fournir un mot de passe pour réactiver le compte.",
142142
erase: "Marquer l'utilisateur comme effacé conformément au RGPD",
143+
erase_text: "Cela signifie que les messages envoyés par le(s) utilisateur(s) seront toujours visibles par toute personne qui se trouvait dans la salle au moment où ces messages ont été envoyés, mais qu'ils seront cachés aux utilisateurs qui rejoindront la salle par la suite.",
143144
erase_admin_error: "La suppression de son propre utilisateur n'est pas autorisée.",
144145
modify_managed_user_error: "La modification d'un utilisateur géré par le système n'est pas autorisée.",
145146
},
146147
action: {
147148
erase: "Effacer les données de l'utilisateur",
148149
erase_avatar: "Effacer l'avatar",
150+
delete_media: "Supprimer tous les médias téléchargés par le(s) utilisateur(s)",
151+
redact_events: "Expurger tous les événements envoyés par l'utilisateur(-s)",
149152
},
150153
},
151154
rooms: {

src/i18n/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,15 @@ interface SynapseTranslationMessages extends TranslationMessages {
138138
password?: string;
139139
deactivate: string;
140140
erase: string;
141+
erase_text: string;
141142
erase_admin_error: string;
142143
modify_managed_user_error: string;
143144
};
144145
action: {
145146
erase: string;
146147
erase_avatar: string;
148+
delete_media: string;
149+
redact_events: string;
147150
};
148151
};
149152
rooms: {

src/i18n/it.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,15 @@ const it: SynapseTranslationMessages = {
139139
password: "Cambiando la password l'utente verrà disconnesso da tutte le sessioni attive.",
140140
deactivate: "Devi fornire una password per riattivare l'account.",
141141
erase: "Constrassegna l'utente come cancellato dal GDPR",
142+
erase_text: "Ciò significa che i messaggi inviati dall'utente (o dagli utenti) saranno ancora visibili da chiunque si trovasse nella stanza al momento dell'invio, ma saranno nascosti agli utenti che si uniranno alla stanza in seguito.",
143+
erase_admin_error: "Non è consentito eliminare il proprio utente.",
144+
modify_managed_user_error: "La modifica di un utente gestito dal sistema non è consentita.",
142145
},
143146
action: {
144147
erase: "Cancella i dati dell'utente",
145-
erase_admin_error: "Non è consentito eliminare il proprio utente.",
146-
modify_managed_user_error: "La modifica di un utente gestito dal sistema non è consentita.",
148+
erase_avatar: "Cancella l'avatar dell'utente",
149+
delete_media: "Elimina tutti i media caricati dall'utente(-s)",
150+
redact_events: "Ridurre tutti gli eventi inviati dall'utente(-s)",
147151
},
148152
},
149153
rooms: {

src/i18n/ru.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,15 @@ const ru: SynapseTranslationMessages = {
159159
password: "Смена пароля завершит все сессии пользователя.",
160160
deactivate: "Вы должны предоставить пароль для реактивации учётной записи.",
161161
erase: "Пометить пользователя как удалённого в соответствии с GDPR",
162+
erase_text: "Это означает, что сообщения, отправленные пользователем (-ами), будут по-прежнему видны всем, кто находился в комнате в момент их отправки, но будут скрыты от пользователей, присоединившихся к комнате после этого.",
162163
erase_admin_error: "Удаление собственного пользователя запрещено.",
163164
modify_managed_user_error: "Изменение пользователя, управляемого системой, не допускается.",
164165
},
165166
action: {
166167
erase: "Удалить данные пользователя",
167168
erase_avatar: "Удалить аватар",
169+
delete_media: "Удаление всех медиафайлов, загруженных пользователем (-ами)",
170+
redact_events: "Удаление всех событий, отправленных пользователем (-ами)",
168171
},
169172
},
170173
rooms: {

src/i18n/zh.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,15 @@ const zh: SynapseTranslationMessages = {
143143
helper: {
144144
deactivate: "您必须提供一串密码来激活账户。",
145145
erase: "将用户标记为根据 GDPR 的要求抹除了",
146+
erase_text: "这意味着用户发送的信息对于发送信息时在房间内的任何人来说都是可见的,但对于之后加入房间的用户来说则是隐藏的。",
146147
erase_admin_error: "不允许删除自己的用户",
147148
modify_managed_user_error: "不允许修改系统管理的用户。",
148149
},
149150
action: {
150151
erase: "抹除用户信息",
151152
erase_avatar: "抹掉头像",
153+
delete_media: "删除用户上传的所有媒体",
154+
redact_events: "重新编辑用户(-s)发送的所有事件",
152155
},
153156
},
154157
rooms: {

0 commit comments

Comments
 (0)