geforkt von mirrored/vaultwarden
Merge branch 'BlackDex-future-clippy-fixes'
Dieser Commit ist enthalten in:
Commit
e8e6c89927
16 geänderte Dateien mit 67 neuen und 55 gelöschten Zeilen
1
clippy.toml
Normale Datei
1
clippy.toml
Normale Datei
|
@ -0,0 +1 @@
|
||||||
|
msrv = "1.60.0"
|
|
@ -705,7 +705,7 @@ async fn password_hint(data: JsonUpcase<PasswordHintData>, mut conn: DbConn) ->
|
||||||
mail::send_password_hint(email, hint).await?;
|
mail::send_password_hint(email, hint).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else if let Some(hint) = hint {
|
} else if let Some(hint) = hint {
|
||||||
err!(format!("Your password hint is: {}", hint));
|
err!(format!("Your password hint is: {hint}"));
|
||||||
} else {
|
} else {
|
||||||
err!(NO_HINT);
|
err!(NO_HINT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1043,7 +1043,7 @@ async fn save_attachment(
|
||||||
} else {
|
} else {
|
||||||
attachment.delete(&mut conn).await.ok();
|
attachment.delete(&mut conn).await.ok();
|
||||||
|
|
||||||
err!(format!("Attachment size mismatch (expected within [{}, {}], got {})", min_size, max_size, size));
|
err!(format!("Attachment size mismatch (expected within [{min_size}, {max_size}], got {size})"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Legacy API
|
// Legacy API
|
||||||
|
|
|
@ -172,8 +172,7 @@ async fn put_eq_domains(
|
||||||
#[get("/hibp/breach?<username>")]
|
#[get("/hibp/breach?<username>")]
|
||||||
async fn hibp_breach(username: String) -> JsonResult {
|
async fn hibp_breach(username: String) -> JsonResult {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"https://haveibeenpwned.com/api/v3/breachedaccount/{}?truncateResponse=false&includeUnverified=false",
|
"https://haveibeenpwned.com/api/v3/breachedaccount/{username}?truncateResponse=false&includeUnverified=false"
|
||||||
username
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(api_key) = crate::CONFIG.hibp_api_key() {
|
if let Some(api_key) = crate::CONFIG.hibp_api_key() {
|
||||||
|
@ -195,7 +194,7 @@ async fn hibp_breach(username: String) -> JsonResult {
|
||||||
"Domain": "haveibeenpwned.com",
|
"Domain": "haveibeenpwned.com",
|
||||||
"BreachDate": "2019-08-18T00:00:00Z",
|
"BreachDate": "2019-08-18T00:00:00Z",
|
||||||
"AddedDate": "2019-08-18T00:00:00Z",
|
"AddedDate": "2019-08-18T00:00:00Z",
|
||||||
"Description": format!("Go to: <a href=\"https://haveibeenpwned.com/account/{account}\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/account/{account}</a> for a manual check.<br/><br/>HaveIBeenPwned API key not set!<br/>Go to <a href=\"https://haveibeenpwned.com/API/Key\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/API/Key</a> to purchase an API key from HaveIBeenPwned.<br/><br/>", account=username),
|
"Description": format!("Go to: <a href=\"https://haveibeenpwned.com/account/{username}\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/account/{username}</a> for a manual check.<br/><br/>HaveIBeenPwned API key not set!<br/>Go to <a href=\"https://haveibeenpwned.com/API/Key\" target=\"_blank\" rel=\"noreferrer\">https://haveibeenpwned.com/API/Key</a> to purchase an API key from HaveIBeenPwned.<br/><br/>"),
|
||||||
"LogoPath": "vw_static/hibp.png",
|
"LogoPath": "vw_static/hibp.png",
|
||||||
"PwnCount": 0,
|
"PwnCount": 0,
|
||||||
"DataClasses": [
|
"DataClasses": [
|
||||||
|
|
|
@ -713,7 +713,7 @@ async fn send_invite(
|
||||||
let user = match User::find_by_mail(&email, &mut conn).await {
|
let user = match User::find_by_mail(&email, &mut conn).await {
|
||||||
None => {
|
None => {
|
||||||
if !CONFIG.invitations_allowed() {
|
if !CONFIG.invitations_allowed() {
|
||||||
err!(format!("User does not exist: {}", email))
|
err!(format!("User does not exist: {email}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !CONFIG.is_email_domain_allowed(&email) {
|
if !CONFIG.is_email_domain_allowed(&email) {
|
||||||
|
@ -731,7 +731,7 @@ async fn send_invite(
|
||||||
}
|
}
|
||||||
Some(user) => {
|
Some(user) => {
|
||||||
if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await.is_some() {
|
if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &mut conn).await.is_some() {
|
||||||
err!(format!("User already in organization: {}", email))
|
err!(format!("User already in organization: {email}"))
|
||||||
} else {
|
} else {
|
||||||
// automatically accept existing users if mail is disabled
|
// automatically accept existing users if mail is disabled
|
||||||
if !CONFIG.mail_enabled() && !user.password_hash.is_empty() {
|
if !CONFIG.mail_enabled() && !user.password_hash.is_empty() {
|
||||||
|
@ -808,7 +808,7 @@ async fn bulk_reinvite_user(
|
||||||
for org_user_id in data.Ids {
|
for org_user_id in data.Ids {
|
||||||
let err_msg = match _reinvite_user(&org_id, &org_user_id, &headers.user.email, &mut conn).await {
|
let err_msg = match _reinvite_user(&org_id, &org_user_id, &headers.user.email, &mut conn).await {
|
||||||
Ok(_) => String::new(),
|
Ok(_) => String::new(),
|
||||||
Err(e) => format!("{:?}", e),
|
Err(e) => format!("{e:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
bulk_response.push(json!(
|
bulk_response.push(json!(
|
||||||
|
@ -970,7 +970,7 @@ async fn bulk_confirm_invite(
|
||||||
let err_msg = match _confirm_invite(&org_id, org_user_id, user_key, &headers, &mut conn, &ip, &nt).await
|
let err_msg = match _confirm_invite(&org_id, org_user_id, user_key, &headers, &mut conn, &ip, &nt).await
|
||||||
{
|
{
|
||||||
Ok(_) => String::new(),
|
Ok(_) => String::new(),
|
||||||
Err(e) => format!("{:?}", e),
|
Err(e) => format!("{e:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
bulk_response.push(json!(
|
bulk_response.push(json!(
|
||||||
|
@ -1224,7 +1224,7 @@ async fn bulk_delete_user(
|
||||||
for org_user_id in data.Ids {
|
for org_user_id in data.Ids {
|
||||||
let err_msg = match _delete_user(&org_id, &org_user_id, &headers, &mut conn, &ip, &nt).await {
|
let err_msg = match _delete_user(&org_id, &org_user_id, &headers, &mut conn, &ip, &nt).await {
|
||||||
Ok(_) => String::new(),
|
Ok(_) => String::new(),
|
||||||
Err(e) => format!("{:?}", e),
|
Err(e) => format!("{e:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
bulk_response.push(json!(
|
bulk_response.push(json!(
|
||||||
|
@ -1819,7 +1819,7 @@ async fn bulk_revoke_organization_user(
|
||||||
let org_user_id = org_user_id.as_str().unwrap_or_default();
|
let org_user_id = org_user_id.as_str().unwrap_or_default();
|
||||||
let err_msg = match _revoke_organization_user(&org_id, org_user_id, &headers, &mut conn, &ip).await {
|
let err_msg = match _revoke_organization_user(&org_id, org_user_id, &headers, &mut conn, &ip).await {
|
||||||
Ok(_) => String::new(),
|
Ok(_) => String::new(),
|
||||||
Err(e) => format!("{:?}", e),
|
Err(e) => format!("{e:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
bulk_response.push(json!(
|
bulk_response.push(json!(
|
||||||
|
@ -1934,7 +1934,7 @@ async fn bulk_restore_organization_user(
|
||||||
let org_user_id = org_user_id.as_str().unwrap_or_default();
|
let org_user_id = org_user_id.as_str().unwrap_or_default();
|
||||||
let err_msg = match _restore_organization_user(&org_id, org_user_id, &headers, &mut conn, &ip).await {
|
let err_msg = match _restore_organization_user(&org_id, org_user_id, &headers, &mut conn, &ip).await {
|
||||||
Ok(_) => String::new(),
|
Ok(_) => String::new(),
|
||||||
Err(e) => format!("{:?}", e),
|
Err(e) => format!("{e:?}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
bulk_response.push(json!(
|
bulk_response.push(json!(
|
||||||
|
|
|
@ -462,7 +462,7 @@ async fn post_access_file(
|
||||||
#[get("/sends/<send_id>/<file_id>?<t>")]
|
#[get("/sends/<send_id>/<file_id>?<t>")]
|
||||||
async fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> {
|
async fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> {
|
||||||
if let Ok(claims) = crate::auth::decode_send(&t) {
|
if let Ok(claims) = crate::auth::decode_send(&t) {
|
||||||
if claims.sub == format!("{}/{}", send_id, file_id) {
|
if claims.sub == format!("{send_id}/{file_id}") {
|
||||||
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok();
|
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,11 +270,11 @@ pub async fn generate_duo_signature(email: &str, conn: &mut DbConn) -> ApiResult
|
||||||
let duo_sign = sign_duo_values(&sk, email, &ik, DUO_PREFIX, now + DUO_EXPIRE);
|
let duo_sign = sign_duo_values(&sk, email, &ik, DUO_PREFIX, now + DUO_EXPIRE);
|
||||||
let app_sign = sign_duo_values(&ak, email, &ik, APP_PREFIX, now + APP_EXPIRE);
|
let app_sign = sign_duo_values(&ak, email, &ik, APP_PREFIX, now + APP_EXPIRE);
|
||||||
|
|
||||||
Ok((format!("{}:{}", duo_sign, app_sign), host))
|
Ok((format!("{duo_sign}:{app_sign}"), host))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_duo_values(key: &str, email: &str, ikey: &str, prefix: &str, expire: i64) -> String {
|
fn sign_duo_values(key: &str, email: &str, ikey: &str, prefix: &str, expire: i64) -> String {
|
||||||
let val = format!("{}|{}|{}", email, ikey, expire);
|
let val = format!("{email}|{ikey}|{expire}");
|
||||||
let cookie = format!("{}|{}", prefix, BASE64.encode(val.as_bytes()));
|
let cookie = format!("{}|{}", prefix, BASE64.encode(val.as_bytes()));
|
||||||
|
|
||||||
format!("{}|{}", cookie, crypto::hmac_sign(key, &cookie))
|
format!("{}|{}", cookie, crypto::hmac_sign(key, &cookie))
|
||||||
|
@ -327,7 +327,7 @@ fn parse_duo_values(key: &str, val: &str, ikey: &str, prefix: &str, time: i64) -
|
||||||
let u_b64 = split[1];
|
let u_b64 = split[1];
|
||||||
let u_sig = split[2];
|
let u_sig = split[2];
|
||||||
|
|
||||||
let sig = crypto::hmac_sign(key, &format!("{}|{}", u_prefix, u_b64));
|
let sig = crypto::hmac_sign(key, &format!("{u_prefix}|{u_b64}"));
|
||||||
|
|
||||||
if !crypto::ct_eq(crypto::hmac_sign(key, &sig), crypto::hmac_sign(key, u_sig)) {
|
if !crypto::ct_eq(crypto::hmac_sign(key, &sig), crypto::hmac_sign(key, u_sig)) {
|
||||||
err!("Duo signatures don't match")
|
err!("Duo signatures don't match")
|
||||||
|
|
|
@ -304,7 +304,7 @@ pub fn obscure_email(email: &str) -> String {
|
||||||
_ => {
|
_ => {
|
||||||
let stars = "*".repeat(name_size - 2);
|
let stars = "*".repeat(name_size - 2);
|
||||||
name.truncate(2);
|
name.truncate(2);
|
||||||
format!("{}{}", name, stars)
|
format!("{name}{stars}")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ fn is_valid_domain(domain: &str) -> bool {
|
||||||
const ALLOWED_CHARS: &str = "_-.";
|
const ALLOWED_CHARS: &str = "_-.";
|
||||||
|
|
||||||
// If parsing the domain fails using Url, it will not work with reqwest.
|
// If parsing the domain fails using Url, it will not work with reqwest.
|
||||||
if let Err(parse_error) = url::Url::parse(format!("https://{}", domain).as_str()) {
|
if let Err(parse_error) = url::Url::parse(format!("https://{domain}").as_str()) {
|
||||||
debug!("Domain parse error: '{}' - {:?}", domain, parse_error);
|
debug!("Domain parse error: '{}' - {:?}", domain, parse_error);
|
||||||
return false;
|
return false;
|
||||||
} else if domain.is_empty()
|
} else if domain.is_empty()
|
||||||
|
@ -575,7 +575,7 @@ async fn get_page_with_referer(url: &str, referer: &str) -> Result<Response, Err
|
||||||
|
|
||||||
match client.send().await {
|
match client.send().await {
|
||||||
Ok(c) => c.error_for_status().map_err(Into::into),
|
Ok(c) => c.error_for_status().map_err(Into::into),
|
||||||
Err(e) => err_silent!(format!("{}", e)),
|
Err(e) => err_silent!(format!("{e}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +797,7 @@ impl reqwest::cookie::CookieStore for Jar {
|
||||||
let cookie_store = self.0.read().unwrap();
|
let cookie_store = self.0.read().unwrap();
|
||||||
let s = cookie_store
|
let s = cookie_store
|
||||||
.get_request_values(url)
|
.get_request_values(url)
|
||||||
.map(|(name, value)| format!("{}={}", name, value))
|
.map(|(name, value)| format!("{name}={value}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("; ");
|
.join("; ");
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,6 @@ pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Er
|
||||||
"jquery-3.6.2.slim.js" => {
|
"jquery-3.6.2.slim.js" => {
|
||||||
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.2.slim.js")))
|
Ok((ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.6.2.slim.js")))
|
||||||
}
|
}
|
||||||
_ => err!(format!("Static file not found: {}", filename)),
|
_ => err!(format!("Static file not found: {filename}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/auth.rs
14
src/auth.rs
|
@ -25,16 +25,16 @@ static JWT_ADMIN_ISSUER: Lazy<String> = Lazy::new(|| format!("{}|admin", CONFIG.
|
||||||
static JWT_SEND_ISSUER: Lazy<String> = Lazy::new(|| format!("{}|send", CONFIG.domain_origin()));
|
static JWT_SEND_ISSUER: Lazy<String> = Lazy::new(|| format!("{}|send", CONFIG.domain_origin()));
|
||||||
|
|
||||||
static PRIVATE_RSA_KEY_VEC: Lazy<Vec<u8>> = Lazy::new(|| {
|
static PRIVATE_RSA_KEY_VEC: Lazy<Vec<u8>> = Lazy::new(|| {
|
||||||
std::fs::read(CONFIG.private_rsa_key()).unwrap_or_else(|e| panic!("Error loading private RSA Key.\n{}", e))
|
std::fs::read(CONFIG.private_rsa_key()).unwrap_or_else(|e| panic!("Error loading private RSA Key.\n{e}"))
|
||||||
});
|
});
|
||||||
static PRIVATE_RSA_KEY: Lazy<EncodingKey> = Lazy::new(|| {
|
static PRIVATE_RSA_KEY: Lazy<EncodingKey> = Lazy::new(|| {
|
||||||
EncodingKey::from_rsa_pem(&PRIVATE_RSA_KEY_VEC).unwrap_or_else(|e| panic!("Error decoding private RSA Key.\n{}", e))
|
EncodingKey::from_rsa_pem(&PRIVATE_RSA_KEY_VEC).unwrap_or_else(|e| panic!("Error decoding private RSA Key.\n{e}"))
|
||||||
});
|
});
|
||||||
static PUBLIC_RSA_KEY_VEC: Lazy<Vec<u8>> = Lazy::new(|| {
|
static PUBLIC_RSA_KEY_VEC: Lazy<Vec<u8>> = Lazy::new(|| {
|
||||||
std::fs::read(CONFIG.public_rsa_key()).unwrap_or_else(|e| panic!("Error loading public RSA Key.\n{}", e))
|
std::fs::read(CONFIG.public_rsa_key()).unwrap_or_else(|e| panic!("Error loading public RSA Key.\n{e}"))
|
||||||
});
|
});
|
||||||
static PUBLIC_RSA_KEY: Lazy<DecodingKey> = Lazy::new(|| {
|
static PUBLIC_RSA_KEY: Lazy<DecodingKey> = Lazy::new(|| {
|
||||||
DecodingKey::from_rsa_pem(&PUBLIC_RSA_KEY_VEC).unwrap_or_else(|e| panic!("Error decoding public RSA Key.\n{}", e))
|
DecodingKey::from_rsa_pem(&PUBLIC_RSA_KEY_VEC).unwrap_or_else(|e| panic!("Error decoding public RSA Key.\n{e}"))
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn load_keys() {
|
pub fn load_keys() {
|
||||||
|
@ -45,7 +45,7 @@ pub fn load_keys() {
|
||||||
pub fn encode_jwt<T: Serialize>(claims: &T) -> String {
|
pub fn encode_jwt<T: Serialize>(claims: &T) -> String {
|
||||||
match jsonwebtoken::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
|
match jsonwebtoken::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
|
||||||
Ok(token) => token,
|
Ok(token) => token,
|
||||||
Err(e) => panic!("Error encoding jwt {}", e),
|
Err(e) => panic!("Error encoding jwt {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ pub fn generate_send_claims(send_id: &str, file_id: &str) -> BasicJwtClaims {
|
||||||
nbf: time_now.timestamp(),
|
nbf: time_now.timestamp(),
|
||||||
exp: (time_now + Duration::minutes(2)).timestamp(),
|
exp: (time_now + Duration::minutes(2)).timestamp(),
|
||||||
iss: JWT_SEND_ISSUER.to_string(),
|
iss: JWT_SEND_ISSUER.to_string(),
|
||||||
sub: format!("{}/{}", send_id, file_id),
|
sub: format!("{send_id}/{file_id}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ impl<'r> FromRequest<'r> for Host {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
format!("{}://{}", protocol, host)
|
format!("{protocol}://{host}")
|
||||||
};
|
};
|
||||||
|
|
||||||
Outcome::Success(Host {
|
Outcome::Success(Host {
|
||||||
|
|
|
@ -13,12 +13,12 @@ use crate::{
|
||||||
|
|
||||||
static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
|
static CONFIG_FILE: Lazy<String> = Lazy::new(|| {
|
||||||
let data_folder = get_env("DATA_FOLDER").unwrap_or_else(|| String::from("data"));
|
let data_folder = get_env("DATA_FOLDER").unwrap_or_else(|| String::from("data"));
|
||||||
get_env("CONFIG_FILE").unwrap_or_else(|| format!("{}/config.json", data_folder))
|
get_env("CONFIG_FILE").unwrap_or_else(|| format!("{data_folder}/config.json"))
|
||||||
});
|
});
|
||||||
|
|
||||||
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
pub static CONFIG: Lazy<Config> = Lazy::new(|| {
|
||||||
Config::load().unwrap_or_else(|e| {
|
Config::load().unwrap_or_else(|e| {
|
||||||
println!("Error loading config:\n\t{:?}\n", e);
|
println!("Error loading config:\n\t{e:?}\n");
|
||||||
exit(12)
|
exit(12)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -675,7 +675,19 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
|
||||||
|
|
||||||
let limit = 256;
|
let limit = 256;
|
||||||
if cfg.database_max_conns < 1 || cfg.database_max_conns > limit {
|
if cfg.database_max_conns < 1 || cfg.database_max_conns > limit {
|
||||||
err!(format!("`DATABASE_MAX_CONNS` contains an invalid value. Ensure it is between 1 and {}.", limit,));
|
err!(format!("`DATABASE_MAX_CONNS` contains an invalid value. Ensure it is between 1 and {limit}.",));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(log_file) = &cfg.log_file {
|
||||||
|
if std::fs::OpenOptions::new().append(true).create(true).open(log_file).is_err() {
|
||||||
|
err!("Unable to write to log file", log_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(log_file) = &cfg.log_file {
|
||||||
|
if std::fs::OpenOptions::new().append(true).create(true).open(log_file).is_err() {
|
||||||
|
err!("Unable to write to log file", log_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(log_file) = &cfg.log_file {
|
if let Some(log_file) = &cfg.log_file {
|
||||||
|
@ -764,7 +776,7 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
|
||||||
let validate_regex = regex::Regex::new(r);
|
let validate_regex = regex::Regex::new(r);
|
||||||
match validate_regex {
|
match validate_regex {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => err!(format!("`ICON_BLACKLIST_REGEX` is invalid: {:#?}", e)),
|
Err(e) => err!(format!("`ICON_BLACKLIST_REGEX` is invalid: {e:#?}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,12 +786,12 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> {
|
||||||
"internal" | "bitwarden" | "duckduckgo" | "google" => (),
|
"internal" | "bitwarden" | "duckduckgo" | "google" => (),
|
||||||
_ => {
|
_ => {
|
||||||
if !icon_service.starts_with("http") {
|
if !icon_service.starts_with("http") {
|
||||||
err!(format!("Icon service URL `{}` must start with \"http\"", icon_service))
|
err!(format!("Icon service URL `{icon_service}` must start with \"http\""))
|
||||||
}
|
}
|
||||||
match icon_service.matches("{}").count() {
|
match icon_service.matches("{}").count() {
|
||||||
1 => (), // nominal
|
1 => (), // nominal
|
||||||
0 => err!(format!("Icon service URL `{}` has no placeholder \"{{}}\"", icon_service)),
|
0 => err!(format!("Icon service URL `{icon_service}` has no placeholder \"{{}}\"")),
|
||||||
_ => err!(format!("Icon service URL `{}` has more than one placeholder \"{{}}\"", icon_service)),
|
_ => err!(format!("Icon service URL `{icon_service}` has more than one placeholder \"{{}}\"")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -831,7 +843,7 @@ fn extract_url_origin(url: &str) -> String {
|
||||||
match Url::parse(url) {
|
match Url::parse(url) {
|
||||||
Ok(u) => u.origin().ascii_serialization(),
|
Ok(u) => u.origin().ascii_serialization(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error validating domain: {}", e);
|
println!("Error validating domain: {e}");
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1206,7 +1218,7 @@ fn js_escape_helper<'reg, 'rc>(
|
||||||
|
|
||||||
let mut escaped_value = value.replace('\\', "").replace('\'', "\\x22").replace('\"', "\\x27");
|
let mut escaped_value = value.replace('\\', "").replace('\'', "\\x22").replace('\"', "\\x27");
|
||||||
if !no_quote {
|
if !no_quote {
|
||||||
escaped_value = format!(""{}"", escaped_value);
|
escaped_value = format!(""{escaped_value}"");
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write(&escaped_value)?;
|
out.write(&escaped_value)?;
|
||||||
|
|
|
@ -383,7 +383,7 @@ pub async fn backup_database(conn: &mut DbConn) -> Result<(), Error> {
|
||||||
let db_url = CONFIG.database_url();
|
let db_url = CONFIG.database_url();
|
||||||
let db_path = Path::new(&db_url).parent().unwrap().to_string_lossy();
|
let db_path = Path::new(&db_url).parent().unwrap().to_string_lossy();
|
||||||
let file_date = chrono::Utc::now().format("%Y%m%d_%H%M%S").to_string();
|
let file_date = chrono::Utc::now().format("%Y%m%d_%H%M%S").to_string();
|
||||||
diesel::sql_query(format!("VACUUM INTO '{}/db_{}.sqlite3'", db_path, file_date)).execute(conn)?;
|
diesel::sql_query(format!("VACUUM INTO '{db_path}/db_{file_date}.sqlite3'")).execute(conn)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/mail.rs
16
src/mail.rs
|
@ -88,7 +88,7 @@ fn mailer() -> AsyncSmtpTransport<Tokio1Executor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
|
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
|
||||||
let (subject_html, body_html) = get_template(&format!("{}.html", template_name), &data)?;
|
let (subject_html, body_html) = get_template(&format!("{template_name}.html"), &data)?;
|
||||||
let (_subject_text, body_text) = get_template(template_name, &data)?;
|
let (_subject_text, body_text) = get_template(template_name, &data)?;
|
||||||
Ok((subject_html, body_html, body_text))
|
Ok((subject_html, body_html, body_text))
|
||||||
}
|
}
|
||||||
|
@ -531,27 +531,27 @@ async fn send_email(address: &str, subject: &str, body_html: String, body_text:
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.is_client() {
|
if e.is_client() {
|
||||||
debug!("SMTP Client error: {:#?}", e);
|
debug!("SMTP Client error: {:#?}", e);
|
||||||
err!(format!("SMTP Client error: {}", e));
|
err!(format!("SMTP Client error: {e}"));
|
||||||
} else if e.is_transient() {
|
} else if e.is_transient() {
|
||||||
debug!("SMTP 4xx error: {:#?}", e);
|
debug!("SMTP 4xx error: {:#?}", e);
|
||||||
err!(format!("SMTP 4xx error: {}", e));
|
err!(format!("SMTP 4xx error: {e}"));
|
||||||
} else if e.is_permanent() {
|
} else if e.is_permanent() {
|
||||||
debug!("SMTP 5xx error: {:#?}", e);
|
debug!("SMTP 5xx error: {:#?}", e);
|
||||||
let mut msg = e.to_string();
|
let mut msg = e.to_string();
|
||||||
// Add a special check for 535 to add a more descriptive message
|
// Add a special check for 535 to add a more descriptive message
|
||||||
if msg.contains("(535)") {
|
if msg.contains("(535)") {
|
||||||
msg = format!("{} - Authentication credentials invalid", msg);
|
msg = format!("{msg} - Authentication credentials invalid");
|
||||||
}
|
}
|
||||||
err!(format!("SMTP 5xx error: {}", msg));
|
err!(format!("SMTP 5xx error: {msg}"));
|
||||||
} else if e.is_timeout() {
|
} else if e.is_timeout() {
|
||||||
debug!("SMTP timeout error: {:#?}", e);
|
debug!("SMTP timeout error: {:#?}", e);
|
||||||
err!(format!("SMTP timeout error: {}", e));
|
err!(format!("SMTP timeout error: {e}"));
|
||||||
} else if e.is_tls() {
|
} else if e.is_tls() {
|
||||||
debug!("SMTP Encryption error: {:#?}", e);
|
debug!("SMTP Encryption error: {:#?}", e);
|
||||||
err!(format!("SMTP Encryption error: {}", e));
|
err!(format!("SMTP Encryption error: {e}"));
|
||||||
} else {
|
} else {
|
||||||
debug!("SMTP {:#?}", e);
|
debug!("SMTP {:#?}", e);
|
||||||
err!(format!("SMTP {}", e));
|
err!(format!("SMTP {e}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -135,11 +135,11 @@ fn parse_args() {
|
||||||
let version = VERSION.unwrap_or("(Version info from Git not present)");
|
let version = VERSION.unwrap_or("(Version info from Git not present)");
|
||||||
|
|
||||||
if pargs.contains(["-h", "--help"]) {
|
if pargs.contains(["-h", "--help"]) {
|
||||||
println!("vaultwarden {}", version);
|
println!("vaultwarden {version}");
|
||||||
print!("{}", HELP);
|
print!("{HELP}");
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if pargs.contains(["-v", "--version"]) {
|
} else if pargs.contains(["-v", "--version"]) {
|
||||||
println!("vaultwarden {}", version);
|
println!("vaultwarden {version}");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ fn launch_info() {
|
||||||
println!("| Starting Vaultwarden |");
|
println!("| Starting Vaultwarden |");
|
||||||
|
|
||||||
if let Some(version) = VERSION {
|
if let Some(version) = VERSION {
|
||||||
println!("|{:^68}|", format!("Version {}", version));
|
println!("|{:^68}|", format!("Version {version}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("|--------------------------------------------------------------------|");
|
println!("|--------------------------------------------------------------------|");
|
||||||
|
@ -224,7 +224,7 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
logger = logger.format(|out, message, _| out.finish(format_args!("{}", message)));
|
logger = logger.format(|out, message, _| out.finish(format_args!("{message}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(log_file) = CONFIG.log_file() {
|
if let Some(log_file) = CONFIG.log_file() {
|
||||||
|
@ -299,7 +299,7 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch {
|
||||||
|
|
||||||
fn create_dir(path: &str, description: &str) {
|
fn create_dir(path: &str, description: &str) {
|
||||||
// Try to create the specified dir, if it doesn't already exist.
|
// Try to create the specified dir, if it doesn't already exist.
|
||||||
let err_msg = format!("Error creating {} directory '{}'", description, path);
|
let err_msg = format!("Error creating {description} directory '{path}'");
|
||||||
create_dir_all(path).expect(&err_msg);
|
create_dir_all(path).expect(&err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -411,16 +411,16 @@ where
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
pub fn get_env_str_value(key: &str) -> Option<String> {
|
pub fn get_env_str_value(key: &str) -> Option<String> {
|
||||||
let key_file = format!("{}_FILE", key);
|
let key_file = format!("{key}_FILE");
|
||||||
let value_from_env = env::var(key);
|
let value_from_env = env::var(key);
|
||||||
let value_file = env::var(&key_file);
|
let value_file = env::var(&key_file);
|
||||||
|
|
||||||
match (value_from_env, value_file) {
|
match (value_from_env, value_file) {
|
||||||
(Ok(_), Ok(_)) => panic!("You should not define both {} and {}!", key, key_file),
|
(Ok(_), Ok(_)) => panic!("You should not define both {key} and {key_file}!"),
|
||||||
(Ok(v_env), Err(_)) => Some(v_env),
|
(Ok(v_env), Err(_)) => Some(v_env),
|
||||||
(Err(_), Ok(v_file)) => match fs::read_to_string(v_file) {
|
(Err(_), Ok(v_file)) => match fs::read_to_string(v_file) {
|
||||||
Ok(content) => Some(content.trim().to_string()),
|
Ok(content) => Some(content.trim().to_string()),
|
||||||
Err(e) => panic!("Failed to load {}: {:?}", key, e),
|
Err(e) => panic!("Failed to load {key}: {e:?}"),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
Laden …
In neuem Issue referenzieren