vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit a72809b225bc66d5b819113b23f877c29c264d06
parent 9976e4736e8fc43c91c7b6b8fa618153544154c8
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Wed,  6 Feb 2019 00:38:57 +0100

Yubico and SMTP enable/disable master switches

Diffstat:
Msrc/config.rs | 72++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/static/templates/admin/page.hbs | 59++++++++++++++++++++++++++++++++++++++++-------------------
2 files changed, 84 insertions(+), 47 deletions(-)

diff --git a/src/config.rs b/src/config.rs @@ -16,7 +16,7 @@ macro_rules! make_config { ( $( $(#[doc = $groupdoc:literal])? - $group:ident { + $group:ident $(: $group_enabled:ident)? { $( $(#[doc = $doc:literal])+ $name:ident : $ty:ty, $editable:literal, $none_action:ident $(, $default:expr)?; @@ -108,28 +108,6 @@ macro_rules! make_config { } )+)+ - pub fn load() -> Result<Self, Error> { - // Loading from env and file - let _env = ConfigBuilder::from_env(); - let _usr = ConfigBuilder::from_file(&CONFIG_FILE).unwrap_or_default(); - - // Create merged config, config file overwrites env - let builder = _env.merge(&_usr); - - // Fill any missing with defaults - let config = builder.build(); - validate_config(&config)?; - - Ok(Config { - inner: RwLock::new(Inner { - templates: load_templates(&config.templates_folder), - config, - _env, - _usr, - }), - }) - } - pub fn prepare_json(&self) -> serde_json::Value { let (def, cfg) = { let inner = &self.inner.read().unwrap(); @@ -155,6 +133,7 @@ macro_rules! make_config { json!([ $({ "group": stringify!($group), + "grouptoggle": stringify!($($group_enabled)?), "groupdoc": make_config!{ @show $($groupdoc)? }, "elements": [ $( { @@ -172,7 +151,7 @@ macro_rules! make_config { // Group or empty string ( @show ) => { "" }; - ( @show $groupdoc:literal ) => { $groupdoc }; + ( @show $lit:literal ) => { $lit }; // Wrap the optionals in an Option type ( @type $ty:ty, option) => { Option<$ty> }; @@ -273,7 +252,9 @@ make_config! { }, /// Yubikey settings - yubico { + yubico: _enable_yubico { + /// Enabled + _enable_yubico: bool, true, def, true; /// Client ID yubico_client_id: String, true, option; /// Secret Key @@ -283,7 +264,9 @@ make_config! { }, /// SMTP Email Settings - smtp { + smtp: _enable_smtp { + /// Enabled + _enable_smtp: bool, true, def, true; /// Host smtp_host: String, true, option; /// Enable SSL @@ -318,9 +301,34 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> { } impl Config { + pub fn load() -> Result<Self, Error> { + // Loading from env and file + let _env = ConfigBuilder::from_env(); + let _usr = ConfigBuilder::from_file(&CONFIG_FILE).unwrap_or_default(); + + // Create merged config, config file overwrites env + let builder = _env.merge(&_usr); + + // Fill any missing with defaults + let config = builder.build(); + validate_config(&config)?; + + Ok(Config { + inner: RwLock::new(Inner { + templates: load_templates(&config.templates_folder), + config, + _env, + _usr, + }), + }) + } + pub fn update_config(&self, other: ConfigBuilder) -> Result<(), Error> { // Remove default values - let builder = other.remove(&self.inner.read().unwrap()._env); + //let builder = other.remove(&self.inner.read().unwrap()._env); + + // TODO: Remove values that are defaults, above only checks those set by env and not the defaults + let builder = other; // Serialize now before we consume the builder let config_str = serde_json::to_string_pretty(&builder)?; @@ -357,7 +365,15 @@ impl Config { format!("{}.pub.der", CONFIG.rsa_key_filename()) } pub fn mail_enabled(&self) -> bool { - self.inner.read().unwrap().config.smtp_host.is_some() + let inner = &self.inner.read().unwrap().config; + inner._enable_smtp + && inner.smtp_host.is_some() + } + pub fn yubico_enabled(&self) -> bool { + let inner = &self.inner.read().unwrap().config; + inner._enable_yubico + && inner.yubico_client_id.is_some() + && inner.yubico_secret_key.is_some() } pub fn render_template<T: serde::ser::Serialize>( diff --git a/src/static/templates/admin/page.hbs b/src/static/templates/admin/page.hbs @@ -70,18 +70,20 @@ {{#case type "text" "number"}} <label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label> <div class="col-sm-8"> - <input class="form-control" id="input_{{name}}" type="{{type}}" name="{{name}}" value="{{value}}" - {{#if default}} placeholder="Default: {{default}}" {{/if}}> + <input class="form-control conf-{{type}}" id="input_{{name}}" type="{{type}}" name="{{name}}" + value="{{value}}" {{#if default}} placeholder="Default: {{default}}" {{/if}}> </div> {{/case}} {{#case type "checkbox"}} <div class="col-sm-3">{{doc.name}}</div> <div class="col-sm-8"> <div class="form-check"> - <input class="form-check-input" type="checkbox" id="input_{{name}}" name="{{name}}" - {{#if value}} checked {{/if}}> + <input class="form-check-input conf-{{type}}" type="checkbox" id="input_{{name}}" + name="{{name}}" {{#if value}} checked {{/if}}> + {{#if default}} <label class="form-check-label" for="input_{{name}}"> Default: {{default}} </label> + {{/if}} </div> </div> {{/case}} @@ -152,30 +154,43 @@ "Error inviting user", data); return false; } - function getFormData(form) { - var form_array = form.serializeArray(); - var indexed_array = {}; + function getFormData() { + let data = {}; - $.each(form_array, function (i, v) { - indexed_array[v.name] = process_value(v.value); + $(".conf-checkbox").each(function (i, e) { + data[e.name] = $(e).is(":checked"); }); - return indexed_array; - } - function process_value(val) { - val = val.trim(); - if (val === "") { return null; } - if (!isNaN(val)) { return +val; } - if (val === "true" || val === "on") { return true; } - if (val === "false" || val === "off") { return false; } - return val; + $(".conf-number").each(function (i, e) { + data[e.name] = +e.value; + }); + + $(".conf-text").each(function (i, e) { + data[e.name] = e.value || null; + }); + return data; } function saveConfig() { - data = JSON.stringify(getFormData($("#config-form"))); + data = JSON.stringify(getFormData()); _post("/admin/config/", "Config saved correctly", "Error saving config", data); return false; } + function masterCheck(check_id, inputs_query) { + function toggleEnabled(check_id, inputs_query, enabled) { + $(inputs_query).prop("disabled", !enabled) + if (!enabled) + $(inputs_query).val(""); + $(check_id).prop("disabled", false); + }; + function onChanged(check_id, inputs_query) { + return function _fn() { toggleEnabled(check_id, inputs_query, this.checked); }; + }; + + toggleEnabled(check_id, inputs_query, $(check_id).is(":checked")); + $(check_id).change(onChanged(check_id, inputs_query)); + + } let OrgTypes = { "0": { "name": "Owner", "color": "orange" }, "1": { "name": "Admin", "color": "blueviolet" }, @@ -193,5 +208,11 @@ e.style.backgroundColor = orgtype.color; e.title = orgtype.name; }); + + // 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}} }); </script> \ No newline at end of file