2022-12-28 20:05:10 +01:00
|
|
|
"use strict";
|
2023-01-24 23:31:38 +01:00
|
|
|
/* eslint-env es2017, browser */
|
|
|
|
/* global BASE_URL:readable, BSN:readable */
|
2022-12-28 20:05:10 +01:00
|
|
|
|
|
|
|
var dnsCheck = false;
|
|
|
|
var timeCheck = false;
|
2023-02-28 20:43:22 +01:00
|
|
|
var ntpTimeCheck = false;
|
2022-12-28 20:05:10 +01:00
|
|
|
var domainCheck = false;
|
|
|
|
var httpsCheck = false;
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
// Date & Time Check
|
|
|
|
const d = new Date();
|
|
|
|
const year = d.getUTCFullYear();
|
|
|
|
const month = String(d.getUTCMonth()+1).padStart(2, "0");
|
|
|
|
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
|
|
const hour = String(d.getUTCHours()).padStart(2, "0");
|
|
|
|
const minute = String(d.getUTCMinutes()).padStart(2, "0");
|
|
|
|
const seconds = String(d.getUTCSeconds()).padStart(2, "0");
|
|
|
|
const browserUTC = `${year}-${month}-${day} ${hour}:${minute}:${seconds} UTC`;
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
// Check if the output is a valid IP
|
|
|
|
const isValidIp = value => (/^(?:(?:^|\.)(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)){4}$/.test(value) ? true : false);
|
|
|
|
|
|
|
|
function checkVersions(platform, installed, latest, commit=null) {
|
|
|
|
if (installed === "-" || latest === "-") {
|
|
|
|
document.getElementById(`${platform}-failed`).classList.remove("d-none");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only check basic versions, no commit revisions
|
|
|
|
if (commit === null || installed.indexOf("-") === -1) {
|
|
|
|
if (installed !== latest) {
|
|
|
|
document.getElementById(`${platform}-warning`).classList.remove("d-none");
|
|
|
|
} else {
|
|
|
|
document.getElementById(`${platform}-success`).classList.remove("d-none");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Check if this is a branched version.
|
|
|
|
const branchRegex = /(?:\s)\((.*?)\)/;
|
|
|
|
const branchMatch = installed.match(branchRegex);
|
|
|
|
if (branchMatch !== null) {
|
|
|
|
document.getElementById(`${platform}-branch`).classList.remove("d-none");
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will remove branch info and check if there is a commit hash
|
|
|
|
const installedRegex = /(\d+\.\d+\.\d+)-(\w+)/;
|
|
|
|
const instMatch = installed.match(installedRegex);
|
|
|
|
|
|
|
|
// It could be that a new tagged version has the same commit hash.
|
|
|
|
// In this case the version is the same but only the number is different
|
|
|
|
if (instMatch !== null) {
|
|
|
|
if (instMatch[2] === commit) {
|
|
|
|
// The commit hashes are the same, so latest version is installed
|
|
|
|
document.getElementById(`${platform}-success`).classList.remove("d-none");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (installed === latest) {
|
|
|
|
document.getElementById(`${platform}-success`).classList.remove("d-none");
|
|
|
|
} else {
|
|
|
|
document.getElementById(`${platform}-warning`).classList.remove("d-none");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
// Generate support string to be pasted on github or the forum
|
2023-01-24 23:31:38 +01:00
|
|
|
async function generateSupportString(event, dj) {
|
2022-12-28 20:05:10 +01:00
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
|
|
let supportString = "### Your environment (Generated via diagnostics page)\n";
|
|
|
|
|
|
|
|
supportString += `* Vaultwarden version: v${dj.current_release}\n`;
|
|
|
|
supportString += `* Web-vault version: v${dj.web_vault_version}\n`;
|
|
|
|
supportString += `* OS/Arch: ${dj.host_os}/${dj.host_arch}\n`;
|
|
|
|
supportString += `* Running within Docker: ${dj.running_within_docker} (Base: ${dj.docker_base_image})\n`;
|
|
|
|
supportString += "* Environment settings overridden: ";
|
|
|
|
if (dj.overrides != "") {
|
|
|
|
supportString += "true\n";
|
|
|
|
} else {
|
|
|
|
supportString += "false\n";
|
|
|
|
}
|
|
|
|
supportString += `* Uses a reverse proxy: ${dj.ip_header_exists}\n`;
|
|
|
|
if (dj.ip_header_exists) {
|
|
|
|
supportString += `* IP Header check: ${dj.ip_header_match} (${dj.ip_header_name})\n`;
|
|
|
|
}
|
|
|
|
supportString += `* Internet access: ${dj.has_http_access}\n`;
|
|
|
|
supportString += `* Internet access via a proxy: ${dj.uses_proxy}\n`;
|
|
|
|
supportString += `* DNS Check: ${dnsCheck}\n`;
|
2023-02-28 20:43:22 +01:00
|
|
|
supportString += `* Browser/Server Time Check: ${timeCheck}\n`;
|
|
|
|
supportString += `* Server/NTP Time Check: ${ntpTimeCheck}\n`;
|
2022-12-28 20:05:10 +01:00
|
|
|
supportString += `* Domain Configuration Check: ${domainCheck}\n`;
|
|
|
|
supportString += `* HTTPS Check: ${httpsCheck}\n`;
|
|
|
|
supportString += `* Database type: ${dj.db_type}\n`;
|
|
|
|
supportString += `* Database version: ${dj.db_version}\n`;
|
|
|
|
supportString += "* Clients used: \n";
|
|
|
|
supportString += "* Reverse proxy and version: \n";
|
|
|
|
supportString += "* Other relevant information: \n";
|
|
|
|
|
|
|
|
const jsonResponse = await fetch(`${BASE_URL}/admin/diagnostics/config`, {
|
|
|
|
"headers": { "Accept": "application/json" }
|
|
|
|
});
|
|
|
|
if (!jsonResponse.ok) {
|
|
|
|
alert("Generation failed: " + jsonResponse.statusText);
|
|
|
|
throw new Error(jsonResponse);
|
|
|
|
}
|
|
|
|
const configJson = await jsonResponse.json();
|
|
|
|
supportString += "\n### Config (Generated via diagnostics page)\n<details><summary>Show Running Config</summary>\n";
|
|
|
|
supportString += `\n**Environment settings which are overridden:** ${dj.overrides}\n`;
|
|
|
|
supportString += "\n\n```json\n" + JSON.stringify(configJson, undefined, 2) + "\n```\n</details>\n";
|
|
|
|
|
|
|
|
document.getElementById("support-string").innerText = supportString;
|
|
|
|
document.getElementById("support-string").classList.remove("d-none");
|
|
|
|
document.getElementById("copy-support").classList.remove("d-none");
|
|
|
|
}
|
|
|
|
|
2023-01-24 23:31:38 +01:00
|
|
|
function copyToClipboard(event) {
|
2022-12-28 20:05:10 +01:00
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
|
|
const supportStr = document.getElementById("support-string").innerText;
|
|
|
|
const tmpCopyEl = document.createElement("textarea");
|
|
|
|
|
|
|
|
tmpCopyEl.setAttribute("id", "copy-support-string");
|
|
|
|
tmpCopyEl.setAttribute("readonly", "");
|
|
|
|
tmpCopyEl.value = supportStr;
|
|
|
|
tmpCopyEl.style.position = "absolute";
|
|
|
|
tmpCopyEl.style.left = "-9999px";
|
|
|
|
document.body.appendChild(tmpCopyEl);
|
|
|
|
tmpCopyEl.select();
|
|
|
|
document.execCommand("copy");
|
|
|
|
tmpCopyEl.remove();
|
|
|
|
|
|
|
|
new BSN.Toast("#toastClipboardCopy").show();
|
|
|
|
}
|
|
|
|
|
2023-02-28 20:43:22 +01:00
|
|
|
function checkTimeDrift(utcTimeA, utcTimeB, statusPrefix) {
|
2022-12-28 20:05:10 +01:00
|
|
|
const timeDrift = (
|
2023-02-28 20:43:22 +01:00
|
|
|
Date.parse(utcTimeA.replace(" ", "T").replace(" UTC", "")) -
|
|
|
|
Date.parse(utcTimeB.replace(" ", "T").replace(" UTC", ""))
|
2022-12-28 20:05:10 +01:00
|
|
|
) / 1000;
|
2023-02-28 20:43:22 +01:00
|
|
|
if (timeDrift > 15 || timeDrift < -15) {
|
|
|
|
document.getElementById(`${statusPrefix}-warning`).classList.remove("d-none");
|
|
|
|
return false;
|
2022-12-28 20:05:10 +01:00
|
|
|
} else {
|
2023-02-28 20:43:22 +01:00
|
|
|
document.getElementById(`${statusPrefix}-success`).classList.remove("d-none");
|
|
|
|
return true;
|
2022-12-28 20:05:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkDomain(browserURL, serverURL) {
|
|
|
|
if (serverURL == browserURL) {
|
|
|
|
document.getElementById("domain-success").classList.remove("d-none");
|
|
|
|
domainCheck = true;
|
|
|
|
} else {
|
|
|
|
document.getElementById("domain-warning").classList.remove("d-none");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for HTTPS at domain-server-string
|
|
|
|
if (serverURL.startsWith("https://") ) {
|
|
|
|
document.getElementById("https-success").classList.remove("d-none");
|
|
|
|
httpsCheck = true;
|
|
|
|
} else {
|
|
|
|
document.getElementById("https-warning").classList.remove("d-none");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function initVersionCheck(dj) {
|
|
|
|
const serverInstalled = dj.current_release;
|
|
|
|
const serverLatest = dj.latest_release;
|
|
|
|
const serverLatestCommit = dj.latest_commit;
|
|
|
|
|
|
|
|
if (serverInstalled.indexOf("-") !== -1 && serverLatest !== "-" && serverLatestCommit !== "-") {
|
|
|
|
document.getElementById("server-latest-commit").classList.remove("d-none");
|
|
|
|
}
|
|
|
|
checkVersions("server", serverInstalled, serverLatest, serverLatestCommit);
|
|
|
|
|
|
|
|
if (!dj.running_within_docker) {
|
|
|
|
const webInstalled = dj.web_vault_version;
|
|
|
|
const webLatest = dj.latest_web_build;
|
|
|
|
checkVersions("web", webInstalled, webLatest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkDns(dns_resolved) {
|
|
|
|
if (isValidIp(dns_resolved)) {
|
|
|
|
document.getElementById("dns-success").classList.remove("d-none");
|
|
|
|
dnsCheck = true;
|
|
|
|
} else {
|
|
|
|
document.getElementById("dns-warning").classList.remove("d-none");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function init(dj) {
|
|
|
|
// Time check
|
|
|
|
document.getElementById("time-browser-string").innerText = browserUTC;
|
2023-02-28 20:43:22 +01:00
|
|
|
|
|
|
|
// Check if we were able to fetch a valid NTP Time
|
|
|
|
// If so, compare both browser and server with NTP
|
|
|
|
// Else, compare browser and server.
|
|
|
|
if (dj.ntp_time.indexOf("UTC") !== -1) {
|
|
|
|
timeCheck = checkTimeDrift(dj.server_time, browserUTC, "time");
|
|
|
|
checkTimeDrift(dj.ntp_time, browserUTC, "ntp-browser");
|
|
|
|
ntpTimeCheck = checkTimeDrift(dj.ntp_time, dj.server_time, "ntp-server");
|
|
|
|
} else {
|
|
|
|
timeCheck = checkTimeDrift(dj.server_time, browserUTC, "time");
|
|
|
|
ntpTimeCheck = "n/a";
|
|
|
|
}
|
2022-12-28 20:05:10 +01:00
|
|
|
|
|
|
|
// Domain check
|
|
|
|
const browserURL = location.href.toLowerCase();
|
|
|
|
document.getElementById("domain-browser-string").innerText = browserURL;
|
|
|
|
checkDomain(browserURL, dj.admin_url.toLowerCase());
|
|
|
|
|
|
|
|
// Version check
|
|
|
|
initVersionCheck(dj);
|
|
|
|
|
|
|
|
// DNS Check
|
|
|
|
checkDns(dj.dns_resolved);
|
|
|
|
}
|
|
|
|
|
|
|
|
// onLoad events
|
2023-01-24 23:31:38 +01:00
|
|
|
document.addEventListener("DOMContentLoaded", (event) => {
|
2022-12-28 20:05:10 +01:00
|
|
|
const diag_json = JSON.parse(document.getElementById("diagnostics_json").innerText);
|
|
|
|
init(diag_json);
|
|
|
|
|
2023-01-24 23:31:38 +01:00
|
|
|
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);
|
|
|
|
}
|
2022-12-28 20:05:10 +01:00
|
|
|
});
|