diff --git a/README.md b/README.md
index 17ecce0..2adf6d7 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,7 @@ with a proper manifest.json generation on build)
* [Sanitize CSV on import](https://github.com/etkecc/synapse-admin/pull/101)
* Allow setting version using `SYNAPSE_ADMIN_VERSION` environment variable on build (if git is not available)
* [Add option to control user's experimental features](https://github.com/etkecc/synapse-admin/pull/111)
+* [Add random password generation on user create/edit form](https://github.com/etkecc/synapse-admin/pull/123)
_the list will be updated as new changes are added_
diff --git a/src/i18n/de.ts b/src/i18n/de.ts
index e1b8433..71c991f 100644
--- a/src/i18n/de.ts
+++ b/src/i18n/de.ts
@@ -190,6 +190,7 @@ const de: SynapseTranslationMessages = {
erase_avatar: "Avatar löschen",
delete_media: "Alle von dem/den Benutzer(n) hochgeladenen Medien löschen",
redact_events: "Schwärzen aller vom Benutzer gesendeten Ereignisse (-s)",
+ generate_password: "Passwort generieren",
},
},
rooms: {
diff --git a/src/i18n/en.ts b/src/i18n/en.ts
index e84b572..0224e52 100644
--- a/src/i18n/en.ts
+++ b/src/i18n/en.ts
@@ -159,7 +159,8 @@ const en: SynapseTranslationMessages = {
erase_avatar: "Erase avatar",
delete_media: "Delete all media uploaded by the user(-s)",
redact_events: "Redact all events sent by the user(-s)",
- }
+ generate_password: "Generate password",
+ },
},
rooms: {
name: "Room |||| Rooms",
diff --git a/src/i18n/fa.ts b/src/i18n/fa.ts
index cbb83b4..e4e4faf 100644
--- a/src/i18n/fa.ts
+++ b/src/i18n/fa.ts
@@ -155,6 +155,7 @@ const fa: SynapseTranslationMessages = {
erase_avatar: "محو الصورة الرمزية",
delete_media: "حذف جميع الوسائط التي تم تحميلها بواسطة المستخدم (المستخدمين)",
redact_events: "تنقيح جميع الأحداث المرسلة من قبل المستخدم (-s)",
+ generate_password: "توليد رمز عبور",
},
},
rooms: {
@@ -207,6 +208,11 @@ const fa: SynapseTranslationMessages = {
title: "حذف اتاق",
content:
"آیا مطمئن هستید که می خواهید اتاق را حذف کنید؟ این قابل بازگشت نیست. همه پیام ها و رسانه های مشترک در اتاق از سرور حذف می شوند!",
+ fields: {
+ block: "حذف",
+ },
+ success: "اتاق با موفقیت حذف شد.",
+ failure: "خطایی رخ داده است.",
},
},
},
diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts
index b34434a..1493f1d 100644
--- a/src/i18n/fr.ts
+++ b/src/i18n/fr.ts
@@ -157,6 +157,7 @@ const fr: SynapseTranslationMessages = {
erase_avatar: "Effacer l'avatar",
delete_media: "Supprimer tous les médias téléchargés par le(s) utilisateur(s)",
redact_events: "Expurger tous les événements envoyés par l'utilisateur(-s)",
+ generate_password: "Générer un mot de passe",
},
},
rooms: {
diff --git a/src/i18n/index.d.ts b/src/i18n/index.d.ts
index 6ddca8e..a95ca27 100644
--- a/src/i18n/index.d.ts
+++ b/src/i18n/index.d.ts
@@ -155,6 +155,7 @@ interface SynapseTranslationMessages extends TranslationMessages {
erase_avatar: string;
delete_media: string;
redact_events: string;
+ generate_password: string;
};
};
rooms: {
diff --git a/src/i18n/it.ts b/src/i18n/it.ts
index f1f5b4f..8014cbc 100644
--- a/src/i18n/it.ts
+++ b/src/i18n/it.ts
@@ -156,6 +156,7 @@ const it: SynapseTranslationMessages = {
erase_avatar: "Cancella l'avatar dell'utente",
delete_media: "Elimina tutti i media caricati dall'utente(-s)",
redact_events: "Ridurre tutti gli eventi inviati dall'utente(-s)",
+ generate_password: "Genera password",
},
},
rooms: {
diff --git a/src/i18n/ru.ts b/src/i18n/ru.ts
index b3773b1..6e476b2 100644
--- a/src/i18n/ru.ts
+++ b/src/i18n/ru.ts
@@ -193,6 +193,7 @@ const ru: SynapseTranslationMessages = {
erase_avatar: "Удалить аватар",
delete_media: "Удаление всех медиафайлов, загруженных пользователем (-ами)",
redact_events: "Удаление всех событий, отправленных пользователем (-ами)",
+ generate_password: "Сгенерировать пароль",
},
},
rooms: {
diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts
index ec96389..3532861 100644
--- a/src/i18n/zh.ts
+++ b/src/i18n/zh.ts
@@ -180,6 +180,7 @@ const zh: SynapseTranslationMessages = {
erase_avatar: "抹掉头像",
delete_media: "删除用户上传的所有媒体",
redact_events: "重新编辑用户(-s)发送的所有事件",
+ generate_password: "生成密码",
},
},
rooms: {
diff --git a/src/resources/users.tsx b/src/resources/users.tsx
index f649ec7..4ec180d 100644
--- a/src/resources/users.tsx
+++ b/src/resources/users.tsx
@@ -69,6 +69,8 @@ import { ServerNoticeButton, ServerNoticeBulkButton } from "../components/Server
import { DATE_FORMAT } from "../components/date";
import { DeviceRemoveButton } from "../components/devices";
import { MediaIDField, ProtectMediaButton, QuarantineMediaButton } from "../components/media";
+import { generateRandomPassword } from "../synapse/synapse";
+import { useFormContext } from "react-hook-form";
import { ExperimentalFeaturesList } from "../components/ExperimentalFeatures";
const choices_medium = [
@@ -301,12 +303,33 @@ const UserBooleanInput = props => {
const UserPasswordInput = props => {
const record = useRecordContext();
let asManagedUserIsSelected = false;
+
+ // Get form context to update field value
+ const form = useFormContext();
if (record) {
asManagedUserIsSelected = isASManaged(record.id);
}
+ const generatePassword = () => {
+ const password = generateRandomPassword();
+ if (record) {
+ form.setValue("password", password, { shouldDirty: true });
+ }
+ };
+
return (
-
+ <>
+
+
+ >
);
};
diff --git a/src/synapse/synapse.ts b/src/synapse/synapse.ts
index afe09a3..4fa025a 100644
--- a/src/synapse/synapse.ts
+++ b/src/synapse/synapse.ts
@@ -91,8 +91,8 @@ export function returnMXID(input: string | Identifier): string {
* Generate a random user password
* @returns a new random password as string
*/
-export function generateRandomPassword(length = 20): string {
- const characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$";
+export function generateRandomPassword(length = 64): string {
+ const characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~`!@#$%^&*()_-+={[}]|:;'.?/<>,";
return Array.from(crypto.getRandomValues(new Uint32Array(length)))
.map(x => characters[x % characters.length])
.join("");