0
0
Fork 0
mirror of https://github.com/dani-garcia/vaultwarden synced 2024-05-23 23:33:47 +02:00
bitwarden_rs/src/static/templates/admin/settings.hbs
BlackDex b0a411b733 Update some JS Libraries and fix small issues
- Updated JS Libraries
- Downgraded bootstrap.css to v5.0.2 which works with Bootstrap-Native.
- Fixed issue with settings being able to open/collapse on some systems.
- Added .js and .css to the exclude list for the end-of-file-fixer pre-commit
2021-09-18 19:49:44 +02:00

258 lines
13 KiB
Handlebars

<main class="container-xl">
<div id="config-block" class="align-items-center p-3 mb-3 bg-secondary rounded shadow">
<div>
<h6 class="text-white mb-3">Configuration</h6>
<div class="small text-white mb-3">
<span class="font-weight-bolder">NOTE:</span> The settings here override the environment variables. Once saved, it's recommended to stop setting them to avoid confusion.<br>
This does not apply to the read-only section, which can only be set via environment variables.<br>
Settings which are overridden are shown with <span class="is-overridden-true">double underscores</span>.
</div>
<form class="form needs-validation" id="config-form" onsubmit="saveConfig(); return false;" novalidate>
{{#each config}}
{{#if groupdoc}}
<div class="card bg-light mb-3">
<button id="b_{{group}}" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_{{group}}" data-bs-toggle="collapse" data-bs-target="#g_{{group}}">{{groupdoc}}</button>
<div id="g_{{group}}" class="card-body collapse">
{{#each elements}}
{{#if editable}}
<div class="row my-2 align-items-center is-overridden-{{overridden}}" title="[{{name}}] {{doc.description}}">
{{#case type "text" "number" "password"}}
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control conf-{{type}}" id="input_{{name}}" type="{{type}}"
name="{{name}}" value="{{value}}" {{#if default}} placeholder="Default: {{default}}"{{/if}}>
{{#case type "password"}}
<button class="btn btn-outline-secondary input-group-text" type="button" onclick="toggleVis('input_{{name}}');">Show/hide</button>
{{/case}}
</div>
</div>
{{/case}}
{{#case type "checkbox"}}
<div class="col-sm-3 col-form-label">{{doc.name}}</div>
<div class="col-sm-8">
<div class="form-check">
<input class="form-check-input conf-{{type}}" type="checkbox" id="input_{{name}}"
name="{{name}}" {{#if value}} checked {{/if}}>
<label class="form-check-label" for="input_{{name}}"> Default: {{default}} </label>
</div>
</div>
{{/case}}
</div>
{{/if}}
{{/each}}
{{#case group "smtp"}}
<div class="row my-2 align-items-center pt-3 border-top" title="Send a test email to given email address">
<label for="smtp-test-email" class="col-sm-3 col-form-label">Test SMTP</label>
<div class="col-sm-8 input-group">
<input class="form-control" id="smtp-test-email" type="email" placeholder="Enter test email" required>
<button type="button" class="btn btn-outline-primary input-group-text" onclick="smtpTest(); return false;">Send test email</button>
<div class="invalid-tooltip">Please provide a valid email address</div>
</div>
</div>
{{/case}}
</div>
</div>
{{/if}}
{{/each}}
<div class="card bg-light mb-3">
<button id="b_readonly" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_readonly"
data-bs-toggle="collapse" data-bs-target="#g_readonly">Read-Only Config</button>
<div id="g_readonly" class="card-body collapse">
<div class="small mb-3">
NOTE: These options can't be modified in the editor because they would require the server
to be restarted. To modify them, you need to set the correct environment variables when
launching the server. You can check the variable names in the tooltips of each option.
</div>
{{#each config}}
{{#each elements}}
{{#unless editable}}
<div class="row my-2 align-items-center" title="[{{name}}] {{doc.description}}">
{{#case type "text" "number" "password"}}
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
<div class="col-sm-8">
<div class="input-group">
<input readonly class="form-control" id="input_{{name}}" type="{{type}}"
value="{{value}}" {{#if default}} placeholder="Default: {{default}}" {{/if}}>
{{#case type "password"}}
<button class="btn btn-outline-secondary" type="button" onclick="toggleVis('input_{{name}}');">Show/hide</button>
{{/case}}
</div>
</div>
{{/case}}
{{#case type "checkbox"}}
<div class="col-sm-3 col-form-label">{{doc.name}}</div>
<div class="col-sm-8">
<div class="form-check align-middle">
<input disabled class="form-check-input" type="checkbox" id="input_{{name}}"
{{#if value}} checked {{/if}}>
<label class="form-check-label" for="input_{{name}}"> Default: {{default}} </label>
</div>
</div>
{{/case}}
</div>
{{/unless}}
{{/each}}
{{/each}}
</div>
</div>
{{#if can_backup}}
<div class="card bg-light mb-3">
<button id="b_database" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_database"
data-bs-toggle="collapse" data-bs-target="#g_database">Backup Database</button>
<div id="g_database" class="card-body collapse">
<div class="small mb-3">
WARNING: This function only creates a backup copy of the SQLite database.
This does not include any configuration or file attachment data that may
also be needed to fully restore a vaultwarden instance. For details on
how to perform complete backups, refer to the wiki page on
<a href="https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault">backups</a>.
</div>
<button type="button" class="btn btn-primary" onclick="backupDatabase();">Backup Database</button>
</div>
</div>
{{/if}}
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-danger float-end" onclick="deleteConf();">Reset defaults</button>
</form>
</div>
</div>
</main>
<style>
#config-block ::placeholder {
/* Most modern browsers support this now. */
color: orangered;
}
.is-overridden-true {
text-decoration: underline double;
}
</style>
<script>
'use strict';
function smtpTest() {
if (formHasChanges(config_form)) {
event.preventDefault();
event.stopPropagation();
alert("Config has been changed but not yet saved.\nPlease save the changes first before sending a test email.");
return false;
}
let test_email = document.getElementById("smtp-test-email");
// Do a very very basic email address check.
if (test_email.value.match(/\S+@\S+/i) === null) {
test_email.parentElement.classList.add('was-validated');
event.preventDefault();
event.stopPropagation();
return false;
}
const data = JSON.stringify({ "email": test_email.value });
_post("{{urlpath}}/admin/test/smtp/",
"SMTP Test email sent correctly",
"Error sending SMTP test email", data, false);
return false;
}
function getFormData() {
let data = {};
document.querySelectorAll(".conf-checkbox").forEach(function (e) {
data[e.name] = e.checked;
});
document.querySelectorAll(".conf-number").forEach(function (e) {
data[e.name] = e.value ? +e.value : null;
});
document.querySelectorAll(".conf-text, .conf-password").forEach(function (e) {
data[e.name] = e.value || null;
});
return data;
}
function saveConfig() {
const data = JSON.stringify(getFormData());
_post("{{urlpath}}/admin/config/", "Config saved correctly",
"Error saving config", data);
return false;
}
function deleteConf() {
var input = prompt("This will remove all user configurations, and restore the defaults and the " +
"values set by the environment. This operation could be dangerous. Type 'DELETE' to proceed:");
if (input === "DELETE") {
_post("{{urlpath}}/admin/config/delete",
"Config deleted correctly",
"Error deleting config");
} else {
alert("Wrong input, please try again")
}
return false;
}
function backupDatabase() {
_post("{{urlpath}}/admin/config/backup_db",
"Backup created successfully",
"Error creating backup", null, false);
return false;
}
function masterCheck(check_id, inputs_query) {
function onChanged(checkbox, inputs_query) {
return function _fn() {
document.querySelectorAll(inputs_query).forEach(function (e) { e.disabled = !checkbox.checked; });
checkbox.disabled = false;
};
}
const checkbox = document.getElementById(check_id);
const onChange = onChanged(checkbox, inputs_query);
onChange(); // Trigger the event initially
checkbox.addEventListener("change", onChange);
}
// These are formatted because otherwise the
// VSCode formatter breaks But they still work
// {{#each config}} {{#if grouptoggle}}
masterCheck("input_{{grouptoggle}}", "#g_{{group}} input");
// {{/if}} {{/each}}
// Two functions to help check if there were changes to the form fields
// Useful for example during the smtp test to prevent people from clicking save before testing there new settings
function initChangeDetection(form) {
const ignore_fields = ["smtp-test-email"];
Array.from(form).forEach((el) => {
if (! ignore_fields.includes(el.id)) {
el.dataset.origValue = el.value
}
});
}
function formHasChanges(form) {
return Array.from(form).some(el => 'origValue' in el.dataset && ( el.dataset.origValue !== el.value));
}
// Trigger Form Change Detection
const config_form = document.getElementById('config-form');
initChangeDetection(config_form);
// Colorize some settings which are high risk
const risk_items = document.getElementsByClassName('col-form-label');
function colorRiskSettings(risk_el) {
Array.from(risk_el).forEach((el) => {
if (el.innerText.toLowerCase().includes('risks') ) {
el.parentElement.className += ' alert-danger'
}
});
}
colorRiskSettings(risk_items);
</script>