Files
vaultwarden/src/static/scripts/admin_users.js
T
Mathijs van Veluw 6729e83521 Misc Updates (#7676)
* Misc Updates

- Update Rust to v1.98.0
- Update all the crates and adjusted code where needed
- Updated JavaScript libraries
  Removed jquery as this isn't needed anymore, adjusted code where needed
- Updated all GitHub Actions
- Fixed nightly clippy lint warnings

Signed-off-by: BlackDex <black.dex@gmail.com>

* Adjust email validation as suggested

Signed-off-by: BlackDex <black.dex@gmail.com>

---------

Signed-off-by: BlackDex <black.dex@gmail.com>
2026-09-03 00:07:00 +02:00

327 lines
11 KiB
JavaScript
Vendored

"use strict";
/* global DataTable, _post:readable, _delete:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
function deleteUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const input_email = prompt(`To delete user "${email}", please type the email below`);
if (input_email != null) {
if (input_email == email) {
_post(`${BASE_URL}/admin/users/${id}/delete`,
"User deleted correctly",
"Error deleting user"
);
} else {
alert("Wrong email, please try again");
}
}
}
function deleteSSOUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const input_email = prompt(`To delete user "${email}" SSO association, please type the email below`);
if (input_email != null) {
if (input_email == email) {
_delete(`${BASE_URL}/admin/users/${id}/sso`,
"User SSO association deleted correctly",
"Error deleting user SSO association"
);
} else {
alert("Wrong email, please try again");
}
}
}
function remove2fa(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const confirmed = confirm(`Are you sure you want to remove 2FA for "${email}"?`);
if (confirmed) {
_post(`${BASE_URL}/admin/users/${id}/remove-2fa`,
"2FA removed correctly",
"Error removing 2FA"
);
}
}
function deauthUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const confirmed = confirm(`Are you sure you want to deauthorize sessions for "${email}"?`);
if (confirmed) {
_post(`${BASE_URL}/admin/users/${id}/deauth`,
"Sessions deauthorized correctly",
"Error deauthorizing sessions"
);
}
}
function disableUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const confirmed = confirm(`Are you sure you want to disable user "${email}"? This will also deauthorize their sessions.`);
if (confirmed) {
_post(`${BASE_URL}/admin/users/${id}/disable`,
"User disabled successfully",
"Error disabling user"
);
}
}
function enableUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const confirmed = confirm(`Are you sure you want to enable user "${email}"?`);
if (confirmed) {
_post(`${BASE_URL}/admin/users/${id}/enable`,
"User enabled successfully",
"Error enabling user"
);
}
}
function updateRevisions(event) {
event.preventDefault();
event.stopPropagation();
_post(`${BASE_URL}/admin/users/update_revision`,
"Success, clients will sync next time they connect",
"Error forcing clients to sync"
);
}
function inviteUser(event) {
event.preventDefault();
event.stopPropagation();
const email = document.getElementById("inviteEmail");
const data = JSON.stringify({
"email": email.value
});
email.value = "";
_post(`${BASE_URL}/admin/invite`,
"User invited correctly",
"Error inviting user",
data
);
}
function resendUserInvite(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
const email = event.target.parentNode.dataset.vwUserEmail;
if (!id || !email) {
alert("Required parameters not found!");
return false;
}
const confirmed = confirm(`Are you sure you want to resend invitation for "${email}"?`);
if (confirmed) {
_post(`${BASE_URL}/admin/users/${id}/invite/resend`,
"Invite sent successfully",
"Error resend invite"
);
}
}
const ORG_TYPES = {
"0": {
"name": "Owner",
"bg": "orange",
"font": "black"
},
"1": {
"name": "Admin",
"bg": "blueviolet"
},
"2": {
"name": "User",
"bg": "blue"
},
"4": {
"name": "Manager",
"bg": "green"
},
};
const userOrgTypeDialog = document.getElementById("userOrgTypeDialog");
// Fill the form and title
userOrgTypeDialog.addEventListener("show.bs.modal", function (event) {
// Get shared values
const userEmail = event.relatedTarget.parentNode.dataset.vwUserEmail;
const userUuid = event.relatedTarget.parentNode.dataset.vwUserUuid;
// Get org specific values
const userOrgType = event.relatedTarget.dataset.vwOrgType;
const userOrgTypeName = ORG_TYPES[userOrgType]["name"];
const orgName = event.relatedTarget.dataset.vwOrgName;
const orgUuid = event.relatedTarget.dataset.vwOrgUuid;
document.getElementById("userOrgTypeDialogOrgName").textContent = orgName;
document.getElementById("userOrgTypeDialogUserEmail").textContent = userEmail;
document.getElementById("userOrgTypeUserUuid").value = userUuid;
document.getElementById("userOrgTypeOrgUuid").value = orgUuid;
document.getElementById(`userOrgType${userOrgTypeName}`).checked = true;
}, false);
// Prevent accidental submission of the form with valid elements after the modal has been hidden.
userOrgTypeDialog.addEventListener("hide.bs.modal", function () {
document.getElementById("userOrgTypeDialogOrgName").textContent = "";
document.getElementById("userOrgTypeDialogUserEmail").textContent = "";
document.getElementById("userOrgTypeUserUuid").value = "";
document.getElementById("userOrgTypeOrgUuid").value = "";
}, false);
function updateUserOrgType(event) {
event.preventDefault();
event.stopPropagation();
const data = JSON.stringify(Object.fromEntries(new FormData(event.target).entries()));
_post(`${BASE_URL}/admin/users/org_type`,
"Updated organization type of the user successfully",
"Error updating organization type of the user",
data
);
}
function initUserTable() {
// Color all the org buttons per type
document.querySelectorAll("button[data-vw-org-type]").forEach(function (e) {
const orgType = ORG_TYPES[e.dataset.vwOrgType];
e.style.backgroundColor = orgType.bg;
if (orgType.font !== undefined) {
e.style.color = orgType.font;
}
e.title = orgType.name;
});
document.querySelectorAll("button[vw-remove2fa]").forEach(btn => {
btn.addEventListener("click", remove2fa);
});
document.querySelectorAll("button[vw-deauth-user]").forEach(btn => {
btn.addEventListener("click", deauthUser);
});
document.querySelectorAll("button[vw-delete-user]").forEach(btn => {
btn.addEventListener("click", deleteUser);
});
document.querySelectorAll("button[vw-delete-sso-user]").forEach(btn => {
btn.addEventListener("click", deleteSSOUser);
});
document.querySelectorAll("button[vw-disable-user]").forEach(btn => {
btn.addEventListener("click", disableUser);
});
document.querySelectorAll("button[vw-enable-user]").forEach(btn => {
btn.addEventListener("click", enableUser);
});
document.querySelectorAll("button[vw-resend-user-invite]").forEach(btn => {
btn.addEventListener("click", resendUserInvite);
});
if (jdenticon) {
jdenticon();
}
}
// Special sort function to sort dates in ISO format and have anything else as 0
DataTable.ext.type.order["date-iso-pre"] = function (a) {
let x;
const sortDate = a.replace(/(<([^>]+)>)/gi, "").trim();
if (sortDate !== "") {
const dtParts = sortDate.split(" ");
const timeParts = (undefined != dtParts[1]) ? dtParts[1].split(":") : ["00", "00", "00"];
const dateParts = dtParts[0].split("-");
x = (dateParts[0] + dateParts[1] + dateParts[2] + timeParts[0] + timeParts[1] + ((undefined != timeParts[2]) ? timeParts[2] : 0)) * 1;
if (isNaN(x)) {
x = 0;
}
} else {
x = Infinity;
}
return x;
};
// onLoad events
document.addEventListener("DOMContentLoaded", (/*event*/) => {
DataTable.ext.type.detect.unshift(function (data) {
if (typeof data !== "string") { return null; }
return data.indexOf("data-sort-type=\"date-iso\"") !== -1
? "date-iso"
: null;
});
const columnCount = document.getElementById("users-table").querySelectorAll("thead th").length;
new DataTable("#users-table", {
"typeDetect": true,
"drawCallback": function () {
initUserTable();
},
"stateSave": true,
"responsive": true,
"lengthMenu": [
[-1, 2, 5, 10, 25, 50],
["All", 2, 5, 10, 25, 50]
],
"pageLength": -1, // Default show all
"columnDefs": [{
"targets": columnCount - 1, // Do not include the last column into the search/order features
"searchable": false,
"orderable": false
}]
});
// Add click events for user actions
initUserTable();
const btnUpdateRevisions = document.getElementById("updateRevisions");
if (btnUpdateRevisions) {
btnUpdateRevisions.addEventListener("click", updateRevisions);
}
const btnReload = document.getElementById("reload");
if (btnReload) {
btnReload.addEventListener("click", reload);
}
const btnUserOrgTypeForm = document.getElementById("userOrgTypeForm");
if (btnUserOrgTypeForm) {
btnUserOrgTypeForm.addEventListener("submit", updateUserOrgType);
}
const btnInviteUserForm = document.getElementById("inviteUserForm");
if (btnInviteUserForm) {
btnInviteUserForm.addEventListener("submit", inviteUser);
}
});