Merge pull request #3167 from BlackDex/issue-3166

Fix Javascript issue on non sqlite databases
This commit is contained in:
Daniel García 2023-02-12 18:48:03 +01:00 committed by GitHub
commit 0c295d5e6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 190 additions and 108 deletions

View file

@ -118,8 +118,8 @@ pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Er
"jdenticon.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jdenticon.js"))),
"datatables.js" => Ok((ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))),
"datatables.css" => Ok((ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))),
"jquery-3.6.2.slim.js" => {
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.2.slim.js")))
"jquery-3.6.3.slim.js" => {
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.3.slim.js")))
}
_ => err!(format!("Static file not found: {filename}")),
}

View file

@ -18,24 +18,31 @@ img {
border: var(--bs-alert-border);
}
#users-table .vw-account-details {
min-width: 250px;
}
#users-table .vw-created-at, #users-table .vw-last-active {
width: 85px;
min-width: 70px;
min-width: 85px;
max-width: 85px;
}
#users-table .vw-items {
width: 35px;
#users-table .vw-items, #orgs-table .vw-items, #orgs-table .vw-users {
min-width: 35px;
max-width: 40px;
}
#users-table .vw-organizations {
min-width: 120px;
#users-table .vw-attachments, #orgs-table .vw-attachments {
min-width: 100px;
max-width: 130px;
}
#users-table .vw-actions, #orgs-table .vw-actions {
width: 130px;
min-width: 130px;
max-width: 130px;
}
#users-table .vw-org-cell {
max-height: 120px;
}
#orgs-table .vw-org-details {
min-width: 285px;
}
#support-string {
height: 16rem;

View file

@ -1,4 +1,6 @@
"use strict";
/* eslint-env es2017, browser */
/* exported BASE_URL, _post */
function getBaseUrl() {
// If the base URL is `https://vaultwarden.example.com/base/path/`,
@ -26,6 +28,8 @@ function msg(text, reload_page = true) {
}
function _post(url, successMsg, errMsg, body, reload_page = true) {
let respStatus;
let respStatusText;
fetch(url, {
method: "POST",
body: body,
@ -33,22 +37,30 @@ function _post(url, successMsg, errMsg, body, reload_page = true) {
credentials: "same-origin",
headers: { "Content-Type": "application/json" }
}).then( resp => {
if (resp.ok) { msg(successMsg, reload_page); return Promise.reject({error: false}); }
const respStatus = resp.status;
const respStatusText = resp.statusText;
if (resp.ok) {
msg(successMsg, reload_page);
// Abuse the catch handler by setting error to false and continue
return Promise.reject({error: false});
}
respStatus = resp.status;
respStatusText = resp.statusText;
return resp.text();
}).then( respText => {
try {
const respJson = JSON.parse(respText);
return respJson ? respJson.ErrorModel.Message : "Unknown error";
if (respJson.ErrorModel && respJson.ErrorModel.Message) {
return respJson.ErrorModel.Message;
} else {
return Promise.reject({body:`${respStatus} - ${respStatusText}\n\nUnknown error`, error: true});
}
} catch (e) {
return Promise.reject({body:respStatus + " - " + respStatusText, error: true});
return Promise.reject({body:`${respStatus} - ${respStatusText}\n\n[Catch] ${e}`, error: true});
}
}).then( apiMsg => {
msg(errMsg + "\n" + apiMsg, reload_page);
msg(`${errMsg}\n${apiMsg}`, reload_page);
}).catch( e => {
if (e.error === false) { return true; }
else { msg(errMsg + "\n" + e.body, reload_page); }
else { msg(`${errMsg}\n${e.body}`, reload_page); }
});
}

View file

@ -1,4 +1,6 @@
"use strict";
/* eslint-env es2017, browser */
/* global BASE_URL:readable, BSN:readable */
var dnsCheck = false;
var timeCheck = false;
@ -65,7 +67,7 @@ function checkVersions(platform, installed, latest, commit=null) {
// ================================
// Generate support string to be pasted on github or the forum
async function generateSupportString(dj) {
async function generateSupportString(event, dj) {
event.preventDefault();
event.stopPropagation();
@ -114,7 +116,7 @@ async function generateSupportString(dj) {
document.getElementById("copy-support").classList.remove("d-none");
}
function copyToClipboard() {
function copyToClipboard(event) {
event.preventDefault();
event.stopPropagation();
@ -208,12 +210,18 @@ function init(dj) {
}
// onLoad events
document.addEventListener("DOMContentLoaded", (/*event*/) => {
document.addEventListener("DOMContentLoaded", (event) => {
const diag_json = JSON.parse(document.getElementById("diagnostics_json").innerText);
init(diag_json);
document.getElementById("gen-support").addEventListener("click", () => {
generateSupportString(diag_json);
});
document.getElementById("copy-support").addEventListener("click", copyToClipboard);
const btnGenSupport = document.getElementById("gen-support");
if (btnGenSupport) {
btnGenSupport.addEventListener("click", () => {
generateSupportString(event, diag_json);
});
}
const btnCopySupport = document.getElementById("copy-support");
if (btnCopySupport) {
btnCopySupport.addEventListener("click", copyToClipboard);
}
});

View file

@ -1,6 +1,8 @@
"use strict";
/* eslint-env es2017, browser, jquery */
/* global _post:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
function deleteOrganization() {
function deleteOrganization(event) {
event.preventDefault();
event.stopPropagation();
const org_uuid = event.target.dataset.vwOrgUuid;
@ -28,9 +30,22 @@ function deleteOrganization() {
}
}
function initActions() {
document.querySelectorAll("button[vw-delete-organization]").forEach(btn => {
btn.addEventListener("click", deleteOrganization);
});
if (jdenticon) {
jdenticon();
}
}
// onLoad events
document.addEventListener("DOMContentLoaded", (/*event*/) => {
jQuery("#orgs-table").DataTable({
"drawCallback": function() {
initActions();
},
"stateSave": true,
"responsive": true,
"lengthMenu": [
@ -46,9 +61,10 @@ document.addEventListener("DOMContentLoaded", (/*event*/) => {
});
// Add click events for organization actions
document.querySelectorAll("button[vw-delete-organization]").forEach(btn => {
btn.addEventListener("click", deleteOrganization);
});
initActions();
document.getElementById("reload").addEventListener("click", reload);
const btnReload = document.getElementById("reload");
if (btnReload) {
btnReload.addEventListener("click", reload);
}
});

View file

@ -1,6 +1,8 @@
"use strict";
/* eslint-env es2017, browser */
/* global _post:readable, BASE_URL:readable */
function smtpTest() {
function smtpTest(event) {
event.preventDefault();
event.stopPropagation();
if (formHasChanges(config_form)) {
@ -41,7 +43,7 @@ function getFormData() {
return data;
}
function saveConfig() {
function saveConfig(event) {
const data = JSON.stringify(getFormData());
_post(`${BASE_URL}/admin/config/`,
"Config saved correctly",
@ -51,7 +53,7 @@ function saveConfig() {
event.preventDefault();
}
function deleteConf() {
function deleteConf(event) {
event.preventDefault();
event.stopPropagation();
const input = prompt(
@ -68,7 +70,7 @@ function deleteConf() {
}
}
function backupDatabase() {
function backupDatabase(event) {
event.preventDefault();
event.stopPropagation();
_post(`${BASE_URL}/admin/config/backup_db`,
@ -94,24 +96,26 @@ function formHasChanges(form) {
// This function will prevent submitting a from when someone presses enter.
function preventFormSubmitOnEnter(form) {
form.onkeypress = function(e) {
const key = e.charCode || e.keyCode || 0;
if (key == 13) {
e.preventDefault();
}
};
if (form) {
form.addEventListener("keypress", (event) => {
if (event.key == "Enter") {
event.preventDefault();
}
});
}
}
// This function will hook into the smtp-test-email input field and will call the smtpTest() function when enter is pressed.
function submitTestEmailOnEnter() {
const smtp_test_email_input = document.getElementById("smtp-test-email");
smtp_test_email_input.onkeypress = function(e) {
const key = e.charCode || e.keyCode || 0;
if (key == 13) {
e.preventDefault();
smtpTest();
}
};
if (smtp_test_email_input) {
smtp_test_email_input.addEventListener("keypress", (event) => {
if (event.key == "Enter") {
event.preventDefault();
smtpTest(event);
}
});
}
}
// Colorize some settings which are high risk
@ -124,11 +128,11 @@ function colorRiskSettings() {
});
}
function toggleVis(evt) {
function toggleVis(event) {
event.preventDefault();
event.stopPropagation();
const elem = document.getElementById(evt.target.dataset.vwPwToggle);
const elem = document.getElementById(event.target.dataset.vwPwToggle);
const type = elem.getAttribute("type");
if (type === "text") {
elem.setAttribute("type", "password");
@ -146,9 +150,11 @@ function masterCheck(check_id, inputs_query) {
}
const checkbox = document.getElementById(check_id);
const onChange = onChanged(checkbox, inputs_query);
onChange(); // Trigger the event initially
checkbox.addEventListener("change", onChange);
if (checkbox) {
const onChange = onChanged(checkbox, inputs_query);
onChange(); // Trigger the event initially
checkbox.addEventListener("change", onChange);
}
}
const config_form = document.getElementById("config-form");
@ -172,9 +178,18 @@ document.addEventListener("DOMContentLoaded", (/*event*/) => {
password_toggle_btn.addEventListener("click", toggleVis);
});
document.getElementById("backupDatabase").addEventListener("click", backupDatabase);
document.getElementById("deleteConf").addEventListener("click", deleteConf);
document.getElementById("smtpTest").addEventListener("click", smtpTest);
const btnBackupDatabase = document.getElementById("backupDatabase");
if (btnBackupDatabase) {
btnBackupDatabase.addEventListener("click", backupDatabase);
}
const btnDeleteConf = document.getElementById("deleteConf");
if (btnDeleteConf) {
btnDeleteConf.addEventListener("click", deleteConf);
}
const btnSmtpTest = document.getElementById("smtpTest");
if (btnSmtpTest) {
btnSmtpTest.addEventListener("click", smtpTest);
}
config_form.addEventListener("submit", saveConfig);
});

View file

@ -1,6 +1,8 @@
"use strict";
/* eslint-env es2017, browser, jquery */
/* global _post:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
function deleteUser() {
function deleteUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
@ -22,7 +24,7 @@ function deleteUser() {
}
}
function remove2fa() {
function remove2fa(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
@ -36,7 +38,7 @@ function remove2fa() {
);
}
function deauthUser() {
function deauthUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
@ -50,7 +52,7 @@ function deauthUser() {
);
}
function disableUser() {
function disableUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
@ -68,7 +70,7 @@ function disableUser() {
}
}
function enableUser() {
function enableUser(event) {
event.preventDefault();
event.stopPropagation();
const id = event.target.parentNode.dataset.vwUserUuid;
@ -86,7 +88,7 @@ function enableUser() {
}
}
function updateRevisions() {
function updateRevisions(event) {
event.preventDefault();
event.stopPropagation();
_post(`${BASE_URL}/admin/users/update_revision`,
@ -95,7 +97,7 @@ function updateRevisions() {
);
}
function inviteUser() {
function inviteUser(event) {
event.preventDefault();
event.stopPropagation();
const email = document.getElementById("inviteEmail");
@ -182,7 +184,7 @@ userOrgTypeDialog.addEventListener("hide.bs.modal", function() {
document.getElementById("userOrgTypeOrgUuid").value = "";
}, false);
function updateUserOrgType() {
function updateUserOrgType(event) {
event.preventDefault();
event.stopPropagation();
@ -195,26 +197,7 @@ function updateUserOrgType() {
);
}
// onLoad events
document.addEventListener("DOMContentLoaded", (/*event*/) => {
jQuery("#users-table").DataTable({
"stateSave": true,
"responsive": true,
"lengthMenu": [
[-1, 5, 10, 25, 50],
["All", 5, 10, 25, 50]
],
"pageLength": -1, // Default show all
"columnDefs": [{
"targets": [1, 2],
"type": "date-iso"
}, {
"targets": 6,
"searchable": false,
"orderable": false
}]
});
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];
@ -222,7 +205,6 @@ document.addEventListener("DOMContentLoaded", (/*event*/) => {
e.title = orgType.name;
});
// Add click events for user actions
document.querySelectorAll("button[vw-remove2fa]").forEach(btn => {
btn.addEventListener("click", remove2fa);
});
@ -239,8 +221,51 @@ document.addEventListener("DOMContentLoaded", (/*event*/) => {
btn.addEventListener("click", enableUser);
});
document.getElementById("updateRevisions").addEventListener("click", updateRevisions);
document.getElementById("reload").addEventListener("click", reload);
document.getElementById("userOrgTypeForm").addEventListener("submit", updateUserOrgType);
document.getElementById("inviteUserForm").addEventListener("submit", inviteUser);
if (jdenticon) {
jdenticon();
}
}
// onLoad events
document.addEventListener("DOMContentLoaded", (/*event*/) => {
jQuery("#users-table").DataTable({
"drawCallback": function() {
initUserTable();
},
"stateSave": true,
"responsive": true,
"lengthMenu": [
[-1, 2, 5, 10, 25, 50],
["All", 2, 5, 10, 25, 50]
],
"pageLength": 2, // Default show all
"columnDefs": [{
"targets": [1, 2],
"type": "date-iso"
}, {
"targets": 6,
"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);
}
});

View file

@ -1,5 +1,5 @@
/*!
* jQuery JavaScript Library v3.6.2 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector
* jQuery JavaScript Library v3.6.3 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector
* https://jquery.com/
*
* Includes Sizzle.js
@ -9,7 +9,7 @@
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2022-12-13T14:56Z
* Date: 2022-12-20T21:28Z
*/
( function( global, factory ) {
@ -151,7 +151,7 @@ function toType( obj ) {
var
version = "3.6.2 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector",
version = "3.6.3 -ajax,-ajax/jsonp,-ajax/load,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-deprecated/ajax-event-alias,-effects,-effects/Tween,-effects/animatedSelector",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
@ -522,14 +522,14 @@ function isArrayLike( obj ) {
}
var Sizzle =
/*!
* Sizzle CSS Selector Engine v2.3.8
* Sizzle CSS Selector Engine v2.3.9
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2022-11-16
* Date: 2022-12-19
*/
( function( window ) {
var i,
@ -890,7 +890,7 @@ function Sizzle( selector, context, results, seed ) {
if ( support.cssSupportsSelector &&
// eslint-disable-next-line no-undef
!CSS.supports( "selector(" + newSelector + ")" ) ) {
!CSS.supports( "selector(:is(" + newSelector + "))" ) ) {
// Support: IE 11+
// Throw to get to the same code path as an error directly in qSA.
@ -1492,9 +1492,8 @@ setDocument = Sizzle.setDocument = function( node ) {
// `:has()` uses a forgiving selector list as an argument so our regular
// `try-catch` mechanism fails to catch `:has()` with arguments not supported
// natively like `:has(:contains("Foo"))`. Where supported & spec-compliant,
// we now use `CSS.supports("selector(SELECTOR_TO_BE_TESTED)")` but outside
// that, let's mark `:has` as buggy to always use jQuery traversal for
// `:has()`.
// we now use `CSS.supports("selector(:is(SELECTOR_TO_BE_TESTED))")`, but
// outside that we mark `:has` as buggy.
rbuggyQSA.push( ":has" );
}

View file

@ -5,10 +5,10 @@
<table id="orgs-table" class="table table-sm table-striped table-hover">
<thead>
<tr>
<th>Organization</th>
<th>Users</th>
<th>Items</th>
<th>Attachments</th>
<th class="vw-org-details">Organization</th>
<th class="vw-users">Users</th>
<th class="vw-items">Items</th>
<th class="vw-attachments">Attachments</th>
<th class="vw-actions">Actions</th>
</tr>
</thead>
@ -38,7 +38,7 @@
{{/if}}
</td>
<td class="text-end px-0 small">
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-delete-organization data-vw-org-uuid="{{jsesc Id no_quote}}" data-vw-org-name="{{jsesc Name no_quote}}" data-vw-billing-email="{{jsesc BillingEmail no_quote}}">Delete Organization</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-delete-organization data-vw-org-uuid="{{jsesc Id no_quote}}" data-vw-org-name="{{jsesc Name no_quote}}" data-vw-billing-email="{{jsesc BillingEmail no_quote}}">Delete Organization</button>
</td>
</tr>
{{/each}}
@ -53,7 +53,7 @@
</main>
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
<script src="{{urlpath}}/vw_static/jquery-3.6.2.slim.js"></script>
<script src="{{urlpath}}/vw_static/jquery-3.6.3.slim.js"></script>
<script src="{{urlpath}}/vw_static/datatables.js"></script>
<script src="{{urlpath}}/vw_static/admin_organizations.js"></script>
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>

View file

@ -5,7 +5,7 @@
<table id="users-table" class="table table-sm table-striped table-hover">
<thead>
<tr>
<th>User</th>
<th class="vw-account-details">User</th>
<th class="vw-created-at">Created at</th>
<th class="vw-last-active">Last Active</th>
<th class="vw-items">Items</th>
@ -63,14 +63,14 @@
<td class="text-end px-0 small">
<span data-vw-user-uuid="{{jsesc Id no_quote}}" data-vw-user-email="{{jsesc Email no_quote}}">
{{#if TwoFactorEnabled}}
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-remove2fa>Remove all 2FA</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-remove2fa>Remove all 2FA</button>
{{/if}}
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-deauth-user>Deauthorize sessions</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-delete-user>Delete User</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-deauth-user>Deauthorize sessions</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-delete-user>Delete User</button>
{{#if user_enabled}}
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-disable-user>Disable User</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-disable-user>Disable User</button>
{{else}}
<button type="button" class="btn btn-sm btn-link p-0 border-0" vw-enable-user>Enable User</button>
<button type="button" class="btn btn-sm btn-link p-0 border-0 float-right" vw-enable-user>Enable User</button>
{{/if}}
</span>
</td>
@ -137,7 +137,7 @@
</main>
<link rel="stylesheet" href="{{urlpath}}/vw_static/datatables.css" />
<script src="{{urlpath}}/vw_static/jquery-3.6.2.slim.js"></script>
<script src="{{urlpath}}/vw_static/jquery-3.6.3.slim.js"></script>
<script src="{{urlpath}}/vw_static/datatables.js"></script>
<script src="{{urlpath}}/vw_static/admin_users.js"></script>
<script src="{{urlpath}}/vw_static/jdenticon.js"></script>