diff --git a/dashboard/src/components/PasswordResetDialog.vue b/dashboard/src/components/PasswordResetDialog.vue
new file mode 100644
index 000000000..b79359997
--- /dev/null
+++ b/dashboard/src/components/PasswordResetDialog.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/dashboard/src/models/UsersModel.js b/dashboard/src/models/UsersModel.js
index adab6769e..77e08fce1 100644
--- a/dashboard/src/models/UsersModel.js
+++ b/dashboard/src/models/UsersModel.js
@@ -57,6 +57,28 @@ function create() {
if (result.status !== 204) return [result];
return [null];
},
+ async getPasswordResetLink(id) {
+ let result;
+ try {
+ result = await fetcher.get(`${origin}/api/v1/users/${id}/password_reset_link`, { access_token: accessToken });
+ } catch (e) {
+ return [e];
+ }
+
+ if (result.status !== 200) return [result];
+ return [null, result.body.passwordResetLink];
+ },
+ async sendPasswordResetEmail(id, email) {
+ let result;
+ try {
+ result = await fetcher.post(`${origin}/api/v1/users/${id}/send_password_reset_email`, { email }, { access_token: accessToken });
+ } catch (e) {
+ return [e];
+ }
+
+ if (result.status !== 202) return [result];
+ return [null];
+ },
};
}
diff --git a/dashboard/src/views/UsersView.vue b/dashboard/src/views/UsersView.vue
index d410a6114..06cfdca9e 100644
--- a/dashboard/src/views/UsersView.vue
+++ b/dashboard/src/views/UsersView.vue
@@ -10,6 +10,7 @@ import { ROLES } from '../constants.js';
import Section from '../components/Section.vue';
import GroupDialog from '../components/GroupDialog.vue';
import ImpersonateDialog from '../components/ImpersonateDialog.vue';
+import PasswordResetDialog from '../components/PasswordResetDialog.vue';
import UsersModel from '../models/UsersModel.js';
import GroupsModel from '../models/GroupsModel.js';
import ProfileModel from '../models/ProfileModel.js';
@@ -50,6 +51,7 @@ const roles = ref([]);
const inputDialog = useTemplateRef('inputDialog');
const groupDialog = useTemplateRef('groupDialog');
const impersonateDialog = useTemplateRef('impersonateDialog');
+const passwordResetDialog = useTemplateRef('passwordResetDialog');
const filteredUsers = computed(() => {
return users.value.filter(u => {
@@ -119,6 +121,10 @@ function onImpersonate(user) {
impersonateDialog.value.open(user);
}
+function onPasswordReset(user) {
+ passwordResetDialog.value.open(user);
+}
+
function onEditOrAddGroup(group = null) {
groupDialog.value.open(group);
}
@@ -184,6 +190,7 @@ onMounted(async () => {