Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-11-16 04:12:53 +01:00
add configuration support for multiple domains
Dieser Commit ist enthalten in:
Ursprung
79ce5b49bc
Commit
80d3c61cc2
1 geänderte Dateien mit 81 neuen und 11 gelöschten Zeilen
|
@ -1,6 +1,7 @@
|
||||||
use std::env::consts::EXE_SUFFIX;
|
use std::{env::consts::EXE_SUFFIX, collections::HashMap};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use job_scheduler_ng::Schedule;
|
use job_scheduler_ng::Schedule;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -47,6 +48,10 @@ macro_rules! make_config {
|
||||||
_usr: ConfigBuilder,
|
_usr: ConfigBuilder,
|
||||||
|
|
||||||
_overrides: Vec<String>,
|
_overrides: Vec<String>,
|
||||||
|
|
||||||
|
domain_hostmap: OnceLock<HostHashMap>,
|
||||||
|
domain_origins: OnceLock<HostHashMap>,
|
||||||
|
domain_paths: OnceLock<HostHashMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Deserialize, Serialize)]
|
#[derive(Clone, Default, Deserialize, Serialize)]
|
||||||
|
@ -135,13 +140,20 @@ macro_rules! make_config {
|
||||||
|
|
||||||
fn build(&self) -> ConfigItems {
|
fn build(&self) -> ConfigItems {
|
||||||
let mut config = ConfigItems::default();
|
let mut config = ConfigItems::default();
|
||||||
let _domain_set = self.domain.is_some();
|
let _domain_set = self.domain_change_back.is_some();
|
||||||
$($(
|
$($(
|
||||||
config.$name = make_config!{ @build self.$name.clone(), &config, $none_action, $($default)? };
|
config.$name = make_config!{ @build self.$name.clone(), &config, $none_action, $($default)? };
|
||||||
)+)+
|
)+)+
|
||||||
config.domain_set = _domain_set;
|
config.domain_set = _domain_set;
|
||||||
|
|
||||||
config.domain = config.domain.trim_end_matches('/').to_string();
|
config.domain_change_back = config.domain_change_back.split(',').map(|d| d.trim_end_matches('/')).fold(String::new(), |acc, d| {
|
||||||
|
acc.push_str(d);
|
||||||
|
acc.push(',');
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove trailing comma
|
||||||
|
config.domain_change_back.pop();
|
||||||
|
|
||||||
config.signups_domains_whitelist = config.signups_domains_whitelist.trim().to_lowercase();
|
config.signups_domains_whitelist = config.signups_domains_whitelist.trim().to_lowercase();
|
||||||
config.org_creation_users = config.org_creation_users.trim().to_lowercase();
|
config.org_creation_users = config.org_creation_users.trim().to_lowercase();
|
||||||
|
@ -335,6 +347,8 @@ macro_rules! make_config {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HostHashMap = HashMap<String, String>;
|
||||||
|
|
||||||
//STRUCTURE:
|
//STRUCTURE:
|
||||||
// /// Short description (without this they won't appear on the list)
|
// /// Short description (without this they won't appear on the list)
|
||||||
// group {
|
// group {
|
||||||
|
@ -414,15 +428,15 @@ make_config! {
|
||||||
|
|
||||||
/// General settings
|
/// General settings
|
||||||
settings {
|
settings {
|
||||||
/// Domain URL |> This needs to be set to the URL used to access the server, including 'http[s]://'
|
/// Comma seperated list of Domain URLs |> This needs to be set to the URL used to access the server, including
|
||||||
/// and port, if it's different than the default. Some server functions don't work correctly without this value
|
/// 'http[s]://' and port, if it's different than the default. Some server functions don't work correctly without this value
|
||||||
domain: String, true, def, "http://localhost".to_string();
|
// TODO: Change back, this is only done to break existing references
|
||||||
|
domain_change_back: String, true, def, "http://localhost".to_string();
|
||||||
/// Domain Set |> Indicates if the domain is set by the admin. Otherwise the default will be used.
|
/// Domain Set |> Indicates if the domain is set by the admin. Otherwise the default will be used.
|
||||||
domain_set: bool, false, def, false;
|
domain_set: bool, false, def, false;
|
||||||
/// Domain origin |> Domain URL origin (in https://example.com:8443/path, https://example.com:8443 is the origin)
|
|
||||||
domain_origin: String, false, auto, |c| extract_url_origin(&c.domain);
|
|
||||||
/// Domain path |> Domain URL path (in https://example.com:8443/path, /path is the path)
|
/// Domain path |> Domain URL path (in https://example.com:8443/path, /path is the path)
|
||||||
domain_path: String, false, auto, |c| extract_url_path(&c.domain);
|
/// MUST be the same for all domains.
|
||||||
|
domain_path: String, false, auto, |c| extract_url_path(&c.domain_change_back.split(',').nth(0).expect("Missing domain"));
|
||||||
/// Enable web vault
|
/// Enable web vault
|
||||||
web_vault_enabled: bool, false, def, true;
|
web_vault_enabled: bool, false, def, true;
|
||||||
|
|
||||||
|
@ -667,7 +681,7 @@ make_config! {
|
||||||
/// Embed images as email attachments.
|
/// Embed images as email attachments.
|
||||||
smtp_embed_images: bool, true, def, true;
|
smtp_embed_images: bool, true, def, true;
|
||||||
/// _smtp_img_src
|
/// _smtp_img_src
|
||||||
_smtp_img_src: String, false, gen, |c| generate_smtp_img_src(c.smtp_embed_images, &c.domain);
|
_smtp_img_src: String, false, gen, |c| generate_smtp_img_src(c.smtp_embed_images, &c.domain_change_back);
|
||||||
/// Enable SMTP debugging (Know the risks!) |> DANGEROUS: Enabling this will output very detailed SMTP messages. This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!
|
/// Enable SMTP debugging (Know the risks!) |> DANGEROUS: Enabling this will output very detailed SMTP messages. This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!
|
||||||
smtp_debug: bool, false, def, false;
|
smtp_debug: bool, false, def, false;
|
||||||
/// Accept Invalid Certs (Know the risks!) |> DANGEROUS: Allow invalid certificates. This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
/// Accept Invalid Certs (Know the risks!) |> DANGEROUS: Allow invalid certificates. This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||||
|
@ -1010,10 +1024,33 @@ fn extract_url_path(url: &str) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_smtp_img_src(embed_images: bool, domain: &str) -> String {
|
/// Extracts host part from a URL.
|
||||||
|
pub fn extract_url_host(url: &str) -> String {
|
||||||
|
match Url::parse(url) {
|
||||||
|
Ok(u) => {
|
||||||
|
let Some(mut host) = u.host_str().map(|s| s.to_string()) else {
|
||||||
|
println!("Domain does not contain host!");
|
||||||
|
return String::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(port) = u.port().map(|p| p.to_string()) {
|
||||||
|
host.push_str(&port);
|
||||||
|
}
|
||||||
|
|
||||||
|
host
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// we already print it in the method above, no need to do it again
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_smtp_img_src(embed_images: bool, domains: &str) -> String {
|
||||||
if embed_images {
|
if embed_images {
|
||||||
"cid:".to_string()
|
"cid:".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
let domain = domains.split(',').nth(0).expect("Domain missing");
|
||||||
format!("{domain}/vw_static/")
|
format!("{domain}/vw_static/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1082,6 +1119,9 @@ impl Config {
|
||||||
_env,
|
_env,
|
||||||
_usr,
|
_usr,
|
||||||
_overrides,
|
_overrides,
|
||||||
|
domain_origins: OnceLock::new(),
|
||||||
|
domain_paths: OnceLock::new(),
|
||||||
|
domain_hostmap: OnceLock::new(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1249,6 +1289,36 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn domain_origin(&self, host: &str) -> Option<String> {
|
||||||
|
// This is done to prevent deadlock, when read-locking an rwlock twice
|
||||||
|
let domains = self.domain_change_back();
|
||||||
|
|
||||||
|
self.inner.read().unwrap().domain_origins.get_or_init(|| {
|
||||||
|
domains.split(',')
|
||||||
|
.map(|d| {
|
||||||
|
(extract_url_host(d), extract_url_origin(d))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}).get(host).map(|h| h.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn host_to_domain(&self, host: &str) -> Option<String> {
|
||||||
|
// This is done to prevent deadlock, when read-locking an rwlock twice
|
||||||
|
let domains = self.domain_change_back();
|
||||||
|
|
||||||
|
self.inner.read().unwrap().domain_hostmap.get_or_init(|| {
|
||||||
|
domains.split(',')
|
||||||
|
.map(|d| {
|
||||||
|
(extract_url_host(d), extract_url_path(d))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}).get(host).map(|h| h.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main_domain(&self) -> String {
|
||||||
|
self.domain_change_back().split(',').nth(0).expect("Missing domain").to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use handlebars::{
|
use handlebars::{
|
||||||
|
|
Laden …
In neuem Issue referenzieren