From 918cd5885aabf4395ec28468f730e930184e0b82 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Sat, 5 Oct 2024 16:15:06 +0200 Subject: [PATCH] Add versions and fallback to built-in - Add both Vaultwarden and web-vault versions to the css_options. - Fallback to the inner templates if rendering or compiling the scss fails. This ensures the basics are always working even if someone breaks the templates. Signed-off-by: BlackDex --- src/api/web.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++---- src/config.rs | 9 +++++-- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/api/web.rs b/src/api/web.rs index 3b5192a29f..853e0f1cbd 100644 --- a/src/api/web.rs +++ b/src/api/web.rs @@ -1,3 +1,4 @@ +use once_cell::sync::Lazy; use std::path::{Path, PathBuf}; use rocket::{ @@ -13,7 +14,7 @@ use crate::{ api::{core::now, ApiResult, EmptyResult}, auth::decode_file_download, error::Error, - util::{Cached, SafeString}, + util::{get_web_vault_version, Cached, SafeString}, CONFIG, }; @@ -53,19 +54,79 @@ fn not_found() -> ApiResult> { #[get("/css/vaultwarden.css")] fn vaultwarden_css() -> Cached> { + // Configure the web-vault version as an integer so it can be used as a comparison smaller or greater then. + // The default is based upon the version since this feature is added. + static WEB_VAULT_VERSION: Lazy = Lazy::new(|| { + let re = regex::Regex::new(r"(\d{4})\.(\d{1,2})\.(\d{1,2})").unwrap(); + let vault_version = get_web_vault_version(); + + let (major, minor, patch) = match re.captures(&vault_version) { + Some(c) if c.len() == 4 => ( + c.get(1).unwrap().as_str().parse().unwrap(), + c.get(2).unwrap().as_str().parse().unwrap(), + c.get(3).unwrap().as_str().parse().unwrap(), + ), + _ => (2024, 6, 2), + }; + format!("{major}{minor:02}{patch:02}").parse::().unwrap() + }); + + // Configure the Vaultwarden version as an integer so it can be used as a comparison smaller or greater then. + // The default is based upon the version since this feature is added. + static VW_VERSION: Lazy = Lazy::new(|| { + let re = regex::Regex::new(r"(\d{1})\.(\d{1,2})\.(\d{1,2})").unwrap(); + let vw_version = crate::VERSION.unwrap_or("1.32.1"); + + let (major, minor, patch) = match re.captures(vw_version) { + Some(c) if c.len() == 4 => ( + c.get(1).unwrap().as_str().parse().unwrap(), + c.get(2).unwrap().as_str().parse().unwrap(), + c.get(3).unwrap().as_str().parse().unwrap(), + ), + _ => (1, 32, 1), + }; + format!("{major}{minor:02}{patch:02}").parse::().unwrap() + }); + let css_options = json!({ + "web_vault_version": *WEB_VAULT_VERSION, + "vw_version": *VW_VERSION, "signup_disabled": !CONFIG.signups_allowed() && CONFIG.signups_domains_whitelist().is_empty(), "mail_enabled": CONFIG.mail_enabled(), "yubico_enabled": CONFIG._enable_yubico() && (CONFIG.yubico_client_id().is_some() == CONFIG.yubico_secret_key().is_some()), "emergency_access_allowed": CONFIG.emergency_access_allowed(), "sends_allowed": CONFIG.sends_allowed(), }); - let scss = CONFIG.render_template("scss/vaultwarden.scss", &css_options).expect("Rendered scss/vaultwarden.scss"); - let css = grass_compiler::from_string( + + let scss = match CONFIG.render_template("scss/vaultwarden.scss", &css_options) { + Ok(t) => t, + Err(e) => { + // Something went wrong loading the template. Fallback to the built-in templates + warn!("Loading scss/vaultwarden.scss.hbs or scss/user.vaultwarden.scss.hbs failed. {e}"); + CONFIG + .render_inner_template("scss/vaultwarden.scss", &css_options) + .expect("Inner scss/vaultwarden.scss.hbs to render") + } + }; + + let css = match grass_compiler::from_string( scss, &grass_compiler::Options::default().style(grass_compiler::OutputStyle::Compressed), - ) - .expect("scss/vaultwarden.scss to compile"); + ) { + Ok(css) => css, + Err(e) => { + // Something went wrong compiling the scss. Fallback to the built-in tempaltes + warn!("Compiling the Vaultwarden SCSS styles failed. {e}"); + let scss = CONFIG + .render_inner_template("scss/vaultwarden.scss", &css_options) + .expect("Inner scss/vaultwarden.scss.hbs to render"); + grass_compiler::from_string( + scss, + &grass_compiler::Options::default().style(grass_compiler::OutputStyle::Compressed), + ) + .expect("SCSS to compile") + } + }; // Cache for one day should be enough and not too much Cached::ttl(Css(css), 86_400, false) diff --git a/src/config.rs b/src/config.rs index e98b8d564f..c8e793bb63 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1269,11 +1269,16 @@ impl Config { let hb = load_templates(CONFIG.templates_folder()); hb.render(name, data).map_err(Into::into) } else { - let hb = &CONFIG.inner.read().unwrap().templates; - hb.render(name, data).map_err(Into::into) + self.render_inner_template(name, data) } } + #[inline] + pub fn render_inner_template(&self, name: &str, data: &T) -> Result { + let hb = &self.inner.read().unwrap().templates; + hb.render(name, data).map_err(Into::into) + } + pub fn set_rocket_shutdown_handle(&self, handle: rocket::Shutdown) { self.inner.write().unwrap().rocket_shutdown_handle = Some(handle); }