Browse Source

Update admin diagnostics

Added a check if the templates are overridden and return which specific folder, `admin`, `email` or `scss`.
This way we could more quickly point users to possible outdated templates which they are using.

Also updated the Support String to use some emojis so we should be able to quicker see if there is something wrong.
Just checking `true` or `false` could be difficult sometimes, and sometimes what we had as `false` wasn't bad either.

Also adjusted the eslint comments so it will work with the latest version of eslint.

Signed-off-by: BlackDex <black.dex@gmail.com>
pull/7558/head
BlackDex 2 months ago
parent
commit
73c6027966
No known key found for this signature in database GPG Key ID: 58C80A2AA6C765E1
  1. 31
      src/api/admin.rs
  2. 3
      src/static/scripts/admin.js
  3. 36
      src/static/scripts/admin_diagnostics.js
  4. 3
      src/static/scripts/admin_organizations.js
  5. 1
      src/static/scripts/admin_settings.js
  6. 3
      src/static/scripts/admin_users.js
  7. 10
      src/static/templates/admin/diagnostics.hbs

31
src/api/admin.rs

@ -716,6 +716,36 @@ fn web_vault_compare(active: &str, latest: &str) -> i8 {
} }
} }
fn check_template_overrides() -> Vec<&'static str> {
let template_folder = std::path::PathBuf::from(CONFIG.templates_folder());
let mut overrides = Vec::new();
for folder in ["admin", "email", "scss"] {
if folder_has_hbs_files(&template_folder.join(folder)) {
overrides.push(folder);
}
}
if folder_has_hbs_files(&template_folder) {
overrides.push("other");
}
overrides
}
fn folder_has_hbs_files(dir: &std::path::Path) -> bool {
let Ok(files) = std::fs::read_dir(dir) else {
// No files in this directory at all, so we can return false
return false;
};
files.flatten().any(|f| {
// Validate if it is a file and if it has the `.hbs` extension and starts with a-z or 0-9
f.file_type().is_ok_and(|t| t.is_file())
&& f.path().extension().is_some_and(|e| e.eq_ignore_ascii_case("hbs"))
&& f.file_name().to_str().is_some_and(|n| n.starts_with(|c: char| c.is_ascii_alphanumeric()))
})
}
#[get("/diagnostics")] #[get("/diagnostics")]
async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResult<Html<String>> { async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResult<Html<String>> {
use chrono::prelude::*; use chrono::prelude::*;
@ -770,6 +800,7 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
"db_version": get_sql_server_version(&conn).await, "db_version": get_sql_server_version(&conn).await,
"admin_url": format!("{}/diagnostics", admin_url()), "admin_url": format!("{}/diagnostics", admin_url()),
"overrides": &CONFIG.get_overrides().join(", "), "overrides": &CONFIG.get_overrides().join(", "),
"template_overrides": check_template_overrides().join(", "),
"invalid_feature_flags": invalid_feature_flags, "invalid_feature_flags": invalid_feature_flags,
"host_arch": env::consts::ARCH, "host_arch": env::consts::ARCH,
"host_os": env::consts::OS, "host_os": env::consts::OS,

3
src/static/scripts/admin.js

@ -1,6 +1,5 @@
"use strict"; "use strict";
/* eslint-env es2017, browser */ /* exported BASE_URL, _post, _delete */
/* exported BASE_URL, _post _delete */
function getBaseUrl() { function getBaseUrl() {
// If the base URL is `https://vaultwarden.example.com/base/path/admin/`, // If the base URL is `https://vaultwarden.example.com/base/path/admin/`,

36
src/static/scripts/admin_diagnostics.js

@ -1,5 +1,4 @@
"use strict"; "use strict";
/* eslint-env es2017, browser */
/* global BASE_URL:readable, bootstrap:readable */ /* global BASE_URL:readable, bootstrap:readable */
var dnsCheck = false; var dnsCheck = false;
@ -80,37 +79,44 @@ async function generateSupportString(event, dj) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
// Health check Markdown emoji, if something is a failure or not
const chk = v => v ? "true :white_check_mark:" : "false :x:";
// Yes/No Markdown emoji, if something is not a failure, but just yes or no
const yn = v => v ? "yes :heavy_plus_sign:" : "no :heavy_minus_sign:";
const template_overrides = dj.template_overrides !== "" ? ` (${dj.template_overrides})` : "";
let supportString = "### Your environment (Generated via diagnostics page)\n\n"; let supportString = "### Your environment (Generated via diagnostics page)\n\n";
supportString += `* Vaultwarden version: v${dj.current_release}\n`; supportString += `* Vaultwarden version: v${dj.current_release}\n`;
supportString += `* Web-vault version: v${dj.active_web_release}\n`; supportString += `* Web-vault version: v${dj.active_web_release}\n`;
supportString += `* OS/Arch: ${dj.host_os}/${dj.host_arch}\n`; supportString += `* OS/Arch: ${dj.host_os}/${dj.host_arch}\n`;
supportString += `* Running within a container: ${dj.running_within_container} (Base: ${dj.container_base_image})\n`; supportString += `* Running within a container: ${yn(dj.running_within_container)} (Base: ${dj.container_base_image})\n`;
supportString += `* Database type: ${dj.db_type}\n`; supportString += `* Database type: ${dj.db_type}\n`;
supportString += `* Database version: ${dj.db_version}\n`; supportString += `* Database version: ${dj.db_version}\n`;
supportString += `* Uses config.json: ${dj.overrides !== ""}\n`; supportString += `* Uses config.json: ${yn(dj.overrides !== "")}\n`;
supportString += `* Uses a reverse proxy: ${dj.ip_header_exists}\n`; supportString += `* Uses custom templates: ${yn(dj.template_overrides !== "")}${template_overrides}\n`;
supportString += `* Uses a reverse proxy: ${yn(dj.ip_header_exists)}\n`;
if (dj.ip_header_exists) { if (dj.ip_header_exists) {
supportString += `* IP Header check: ${dj.ip_header_match} (${dj.ip_header_name})\n`; supportString += `* IP Header check: ${chk(dj.ip_header_match)} (${dj.ip_header_name})\n`;
} }
supportString += `* Internet access: ${dj.has_http_access}\n`; supportString += `* Internet access: ${chk(dj.has_http_access)}\n`;
supportString += `* Internet access via a proxy: ${dj.uses_proxy}\n`; supportString += `* Internet access via a proxy: ${yn(dj.uses_proxy)}\n`;
supportString += `* DNS Check: ${dnsCheck}\n`; supportString += `* DNS Check: ${chk(dnsCheck)}\n`;
if (dj.tz_env !== "") { if (dj.tz_env !== "") {
supportString += `* TZ environment: ${dj.tz_env}\n`; supportString += `* TZ environment: ${dj.tz_env}\n`;
} }
supportString += `* Browser/Server Time Check: ${timeCheck}\n`; supportString += `* Browser/Server Time Check: ${chk(timeCheck)}\n`;
supportString += `* Server/NTP Time Check: ${ntpTimeCheck}\n`; supportString += `* Server/NTP Time Check: ${chk(ntpTimeCheck)}\n`;
supportString += `* Domain Configuration Check: ${domainCheck}\n`; supportString += `* Domain Configuration Check: ${chk(domainCheck)}\n`;
supportString += `* HTTPS Check: ${httpsCheck}\n`; supportString += `* HTTPS Check: ${chk(httpsCheck)}\n`;
if (dj.enable_websocket) { if (dj.enable_websocket) {
supportString += `* Websocket Check: ${websocketCheck}\n`; supportString += `* Websocket Check: ${chk(websocketCheck)}\n`;
} else { } else {
supportString += "* Websocket Check: disabled\n"; supportString += "* Websocket Check: disabled\n";
} }
supportString += `* HTTP Response Checks: ${httpResponseCheck}\n`; supportString += `* HTTP Response Checks: ${chk(httpResponseCheck)}\n`;
if (dj.invalid_feature_flags != "") { if (dj.invalid_feature_flags != "") {
supportString += `* Invalid feature flags: true\n`; supportString += "* Invalid feature flags: true\n";
} }
const jsonResponse = await fetch(`${BASE_URL}/admin/diagnostics/config`, { const jsonResponse = await fetch(`${BASE_URL}/admin/diagnostics/config`, {

3
src/static/scripts/admin_organizations.js

@ -1,6 +1,5 @@
"use strict"; "use strict";
/* eslint-env es2017, browser, jquery */ /* global jQuery, _post:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
/* global _post:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
function deleteOrganization(event) { function deleteOrganization(event) {
event.preventDefault(); event.preventDefault();

1
src/static/scripts/admin_settings.js

@ -1,5 +1,4 @@
"use strict"; "use strict";
/* eslint-env es2017, browser */
/* global _post:readable, BASE_URL:readable */ /* global _post:readable, BASE_URL:readable */
function smtpTest(event) { function smtpTest(event) {

3
src/static/scripts/admin_users.js

@ -1,6 +1,5 @@
"use strict"; "use strict";
/* eslint-env es2017, browser, jquery */ /* global jQuery, _post:readable, _delete:readable, BASE_URL:readable, reload:readable, jdenticon:readable */
/* global _post:readable, _delete:readable BASE_URL:readable, reload:readable, jdenticon:readable */
function deleteUser(event) { function deleteUser(event) {
event.preventDefault(); event.preventDefault();

10
src/static/templates/admin/diagnostics.hbs

@ -77,6 +77,16 @@
<span class="d-block"><b>No</b></span> <span class="d-block"><b>No</b></span>
{{/unless}} {{/unless}}
</dd> </dd>
<dt class="col-sm-5">Uses custom templates</dt>
<dd class="col-sm-7">
{{#if page_data.template_overrides}}
<span class="d-inline"><b>Yes</b></span>
<span class="badge bg-info text-dark abbr-badge" title="Custom template files are used.&#013;&#010;{{page_data.template_overrides}}">Details</span>
{{/if}}
{{#unless page_data.template_overrides}}
<span class="d-block"><b>No</b></span>
{{/unless}}
</dd>
<dt class="col-sm-5">Uses a reverse proxy</dt> <dt class="col-sm-5">Uses a reverse proxy</dt>
<dd class="col-sm-7"> <dd class="col-sm-7">
{{#if page_data.ip_header_exists}} {{#if page_data.ip_header_exists}}

Loading…
Cancel
Save