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 3ab90259f20063b72c5560da3346840da7223acc
parent 93c881a7a9abf30c1d2cfea961d5637de2757b86
Author: Jake Howard <git@theorangeone.net>
Date:   Tue,  6 Apr 2021 21:54:42 +0100

Modify rustfmt file

Diffstat:
Mrustfmt.toml | 5+++++
Msrc/api/admin.rs | 9++-------
Msrc/api/core/accounts.rs | 10+---------
Msrc/api/core/ciphers.rs | 74++++++++++++++++++++++++++++----------------------------------------------
Msrc/api/core/folders.rs | 10+---------
Msrc/api/core/mod.rs | 16+++-------------
Msrc/api/core/organizations.rs | 18++++--------------
Msrc/api/core/sends.rs | 23+++--------------------
Msrc/api/core/two_factor/authenticator.rs | 23++++-------------------
Msrc/api/core/two_factor/duo.rs | 6+++++-
Msrc/api/core/two_factor/email.rs | 16+++-------------
Msrc/api/core/two_factor/mod.rs | 8+-------
Msrc/api/core/two_factor/u2f.rs | 24++++--------------------
Msrc/api/icons.rs | 27+++++++++++++--------------
Msrc/api/identity.rs | 32++++++++------------------------
Msrc/api/mod.rs | 6+++---
Msrc/api/notifications.rs | 19++++++++-----------
Msrc/api/web.rs | 54++++++++++++++----------------------------------------
Msrc/auth.rs | 24++++++++++++++----------
Msrc/config.rs | 19+++++--------------
Msrc/crypto.rs | 4+---
Msrc/db/mod.rs | 4+---
Msrc/db/models/cipher.rs | 23+++++++----------------
Msrc/db/models/collection.rs | 21+++++++--------------
Msrc/db/models/device.rs | 24++++--------------------
Msrc/db/models/organization.rs | 13++++---------
Msrc/db/models/user.rs | 4+++-
Msrc/error.rs | 6+-----
Msrc/mail.rs | 26+++++---------------------
Msrc/util.rs | 16+++++++---------
30 files changed, 169 insertions(+), 395 deletions(-)

diff --git a/rustfmt.toml b/rustfmt.toml @@ -1,2 +1,7 @@ version = "Two" +edition = "2018" max_width = 120 +newline_style = "Unix" +use_small_heuristics = "Off" +struct_lit_single_line = false +overflow_delimited_expr = true diff --git a/src/api/admin.rs b/src/api/admin.rs @@ -65,9 +65,7 @@ static DB_TYPE: Lazy<&str> = Lazy::new(|| { }); static CAN_BACKUP: Lazy<bool> = Lazy::new(|| { - DbConnType::from_url(&CONFIG.database_url()) - .map(|t| t == DbConnType::sqlite) - .unwrap_or(false) + DbConnType::from_url(&CONFIG.database_url()).map(|t| t == DbConnType::sqlite).unwrap_or(false) && Command::new("sqlite3").arg("-version").status().is_ok() }); @@ -171,10 +169,7 @@ fn post_admin_login( // If the token is invalid, redirect to login page if !_validate_token(&data.token) { error!("Invalid admin token. IP: {}", ip.ip); - Err(Flash::error( - Redirect::to(admin_url(referer)), - "Invalid admin token, please try again.", - )) + Err(Flash::error(Redirect::to(admin_url(referer)), "Invalid admin token, please try again.")) } else { // If the token received is valid, generate JWT and save it as a cookie let claims = generate_admin_claims(); diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs @@ -320,15 +320,7 @@ fn post_rotatekey(data: JsonUpcase<KeyData>, headers: Headers, conn: DbConn, nt: err!("The cipher is not owned by the user") } - update_cipher_from_data( - &mut saved_cipher, - cipher_data, - &headers, - false, - &conn, - &nt, - UpdateType::CipherUpdate, - )? + update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &conn, &nt, UpdateType::CipherUpdate)? } // Update user data diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs @@ -91,19 +91,15 @@ fn sync(data: Form<SyncData>, headers: Headers, conn: DbConn) -> Json<Value> { let folders_json: Vec<Value> = folders.iter().map(Folder::to_json).collect(); let collections = Collection::find_by_user_uuid(&headers.user.uuid, &conn); - let collections_json: Vec<Value> = collections - .iter() - .map(|c| c.to_json_details(&headers.user.uuid, &conn)) - .collect(); + let collections_json: Vec<Value> = + collections.iter().map(|c| c.to_json_details(&headers.user.uuid, &conn)).collect(); let policies = OrgPolicy::find_by_user(&headers.user.uuid, &conn); let policies_json: Vec<Value> = policies.iter().map(OrgPolicy::to_json).collect(); let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn); - let ciphers_json: Vec<Value> = ciphers - .iter() - .map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)) - .collect(); + let ciphers_json: Vec<Value> = + ciphers.iter().map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)).collect(); let sends = Send::find_by_user(&headers.user.uuid, &conn); let sends_json: Vec<Value> = sends.iter().map(|s| s.to_json()).collect(); @@ -130,10 +126,8 @@ fn sync(data: Form<SyncData>, headers: Headers, conn: DbConn) -> Json<Value> { fn get_ciphers(headers: Headers, conn: DbConn) -> Json<Value> { let ciphers = Cipher::find_by_user_visible(&headers.user.uuid, &conn); - let ciphers_json: Vec<Value> = ciphers - .iter() - .map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)) - .collect(); + let ciphers_json: Vec<Value> = + ciphers.iter().map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)).collect(); Json(json!({ "Data": ciphers_json, @@ -583,11 +577,8 @@ fn post_collections_admin( } let posted_collections: HashSet<String> = data.CollectionIds.iter().cloned().collect(); - let current_collections: HashSet<String> = cipher - .get_collections(&headers.user.uuid, &conn) - .iter() - .cloned() - .collect(); + let current_collections: HashSet<String> = + cipher.get_collections(&headers.user.uuid, &conn).iter().cloned().collect(); for collection in posted_collections.symmetric_difference(&current_collections) { match Collection::find_by_uuid(&collection, &conn) { @@ -823,30 +814,25 @@ fn post_attachment( let file_name = HEXLOWER.encode(&crypto::get_random(vec![0; 10])); let path = base_path.join(&file_name); - let size = match field - .data - .save() - .memory_threshold(0) - .size_limit(size_limit) - .with_path(path.clone()) - { - SaveResult::Full(SavedData::File(_, size)) => size as i32, - SaveResult::Full(other) => { - std::fs::remove_file(path).ok(); - error = Some(format!("Attachment is not a file: {:?}", other)); - return; - } - SaveResult::Partial(_, reason) => { - std::fs::remove_file(path).ok(); - error = Some(format!("Attachment size limit exceeded with this file: {:?}", reason)); - return; - } - SaveResult::Error(e) => { - std::fs::remove_file(path).ok(); - error = Some(format!("Error: {:?}", e)); - return; - } - }; + let size = + match field.data.save().memory_threshold(0).size_limit(size_limit).with_path(path.clone()) { + SaveResult::Full(SavedData::File(_, size)) => size as i32, + SaveResult::Full(other) => { + std::fs::remove_file(path).ok(); + error = Some(format!("Attachment is not a file: {:?}", other)); + return; + } + SaveResult::Partial(_, reason) => { + std::fs::remove_file(path).ok(); + error = Some(format!("Attachment size limit exceeded with this file: {:?}", reason)); + return; + } + SaveResult::Error(e) => { + std::fs::remove_file(path).ok(); + error = Some(format!("Error: {:?}", e)); + return; + } + }; let mut attachment = Attachment::new(file_name, cipher.uuid.clone(), name, size); attachment.akey = attachment_key.clone(); @@ -878,11 +864,7 @@ fn post_attachment_admin( post_attachment(uuid, data, content_type, headers, conn, nt) } -#[post( - "/ciphers/<uuid>/attachment/<attachment_id>/share", - format = "multipart/form-data", - data = "<data>" -)] +#[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")] fn post_attachment_share( uuid: String, attachment_id: String, diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs @@ -8,15 +8,7 @@ use crate::{ }; pub fn routes() -> Vec<rocket::Route> { - routes![ - get_folders, - get_folder, - post_folders, - post_folder, - put_folder, - delete_folder_post, - delete_folder, - ] + routes![get_folders, get_folder, post_folders, post_folder, put_folder, delete_folder_post, delete_folder,] } #[get("/folders")] diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs @@ -8,14 +8,8 @@ pub mod two_factor; pub use sends::start_send_deletion_scheduler; pub fn routes() -> Vec<Route> { - let mut mod_routes = routes![ - clear_device_token, - put_device_token, - get_eq_domains, - post_eq_domains, - put_eq_domains, - hibp_breach, - ]; + let mut mod_routes = + routes![clear_device_token, put_device_token, get_eq_domains, post_eq_domains, put_eq_domains, hibp_breach,]; let mut routes = Vec::new(); routes.append(&mut accounts::routes()); @@ -157,11 +151,7 @@ fn hibp_breach(username: String) -> JsonResult { if let Some(api_key) = crate::CONFIG.hibp_api_key() { let hibp_client = Client::builder().build()?; - let res = hibp_client - .get(&url) - .header(USER_AGENT, user_agent) - .header("hibp-api-key", api_key) - .send()?; + let res = hibp_client.get(&url).header(USER_AGENT, user_agent).header("hibp-api-key", api_key).send()?; // If we get a 404, return a 404, it means no breached accounts if res.status() == 404 { diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs @@ -446,10 +446,8 @@ struct OrgIdData { #[get("/ciphers/organization-details?<data..>")] fn get_org_details(data: Form<OrgIdData>, headers: Headers, conn: DbConn) -> Json<Value> { let ciphers = Cipher::find_by_org(&data.organization_id, &conn); - let ciphers_json: Vec<Value> = ciphers - .iter() - .map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)) - .collect(); + let ciphers_json: Vec<Value> = + ciphers.iter().map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)).collect(); Json(json!({ "Data": ciphers_json, @@ -904,16 +902,8 @@ fn post_org_import( .into_iter() .map(|cipher_data| { let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); - update_cipher_from_data( - &mut cipher, - cipher_data, - &headers, - false, - &conn, - &nt, - UpdateType::CipherCreate, - ) - .ok(); + update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &conn, &nt, UpdateType::CipherCreate) + .ok(); cipher }) .collect(); diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs @@ -16,15 +16,7 @@ use crate::{ const SEND_INACCESSIBLE_MSG: &str = "Send does not exist or is no longer available"; pub fn routes() -> Vec<rocket::Route> { - routes![ - post_send, - post_send_file, - post_access, - post_access_file, - put_send, - delete_send, - put_remove_password - ] + routes![post_send, post_send_file, post_access, post_access_file, put_send, delete_send, put_remove_password] } pub fn start_send_deletion_scheduler(pool: crate::db::DbPool) { @@ -179,13 +171,7 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn None => err!("No model entry present"), }; - let size = match data_entry - .data - .save() - .memory_threshold(0) - .size_limit(size_limit) - .with_path(&file_path) - { + let size = match data_entry.data.save().memory_threshold(0).size_limit(size_limit).with_path(&file_path) { SaveResult::Full(SavedData::File(_, size)) => size as i32, SaveResult::Full(other) => { std::fs::remove_file(&file_path).ok(); @@ -206,10 +192,7 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn if let Some(o) = data_value.as_object_mut() { o.insert(String::from("Id"), Value::String(file_id)); o.insert(String::from("Size"), Value::Number(size.into())); - o.insert( - String::from("SizeName"), - Value::String(crate::util::get_display_size(size)), - ); + o.insert(String::from("SizeName"), Value::String(crate::util::get_display_size(size))); } send.data = serde_json::to_string(&data_value)?; diff --git a/src/api/core/two_factor/authenticator.rs b/src/api/core/two_factor/authenticator.rs @@ -17,11 +17,7 @@ use crate::{ pub use crate::config::CONFIG; pub fn routes() -> Vec<Route> { - routes![ - generate_authenticator, - activate_authenticator, - activate_authenticator_put, - ] + routes![generate_authenticator, activate_authenticator, activate_authenticator_put,] } #[post("/two-factor/get-authenticator", data = "<data>")] @@ -163,22 +159,11 @@ pub fn validate_totp_code(user_uuid: &str, totp_code: u64, secret: &str, ip: &Cl twofactor.save(&conn)?; return Ok(()); } else if generated == totp_code && time_step <= twofactor.last_used as i64 { - warn!( - "This or a TOTP code within {} steps back and forward has already been used!", - steps - ); - err!(format!( - "Invalid TOTP code! Server time: {} IP: {}", - current_time.format("%F %T UTC"), - ip.ip - )); + warn!("This or a TOTP code within {} steps back and forward has already been used!", steps); + err!(format!("Invalid TOTP code! Server time: {} IP: {}", current_time.format("%F %T UTC"), ip.ip)); } } // Else no valide code received, deny access - err!(format!( - "Invalid TOTP code! Server time: {} IP: {}", - current_time.format("%F %T UTC"), - ip.ip - )); + err!(format!("Invalid TOTP code! Server time: {} IP: {}", current_time.format("%F %T UTC"), ip.ip)); } diff --git a/src/api/core/two_factor/duo.rs b/src/api/core/two_factor/duo.rs @@ -59,7 +59,11 @@ impl DuoData { ik.replace_range(digits.., replaced); sk.replace_range(digits.., replaced); - Self { host, ik, sk } + Self { + host, + ik, + sk, + } } } diff --git a/src/api/core/two_factor/email.rs b/src/api/core/two_factor/email.rs @@ -65,10 +65,7 @@ pub fn send_token(user_uuid: &str, conn: &DbConn) -> EmptyResult { twofactor.data = twofactor_data.to_json(); twofactor.save(&conn)?; - mail::send_token( - &twofactor_data.email, - &twofactor_data.last_token.map_res("Token is empty")?, - )?; + mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?; Ok(()) } @@ -128,17 +125,10 @@ fn send_email(data: JsonUpcase<SendEmailData>, headers: Headers, conn: DbConn) - let twofactor_data = EmailTokenData::new(data.Email, generated_token); // Uses EmailVerificationChallenge as type to show that it's not verified yet. - let twofactor = TwoFactor::new( - user.uuid, - TwoFactorType::EmailVerificationChallenge, - twofactor_data.to_json(), - ); + let twofactor = TwoFactor::new(user.uuid, TwoFactorType::EmailVerificationChallenge, twofactor_data.to_json()); twofactor.save(&conn)?; - mail::send_token( - &twofactor_data.email, - &twofactor_data.last_token.map_res("Token is empty")?, - )?; + mail::send_token(&twofactor_data.email, &twofactor_data.last_token.map_res("Token is empty")?)?; Ok(()) } diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs @@ -20,13 +20,7 @@ pub mod u2f; pub mod yubikey; pub fn routes() -> Vec<Route> { - let mut routes = routes![ - get_twofactor, - get_recover, - recover, - disable_twofactor, - disable_twofactor_put, - ]; + let mut routes = routes![get_twofactor, get_recover, recover, disable_twofactor, disable_twofactor_put,]; routes.append(&mut authenticator::routes()); routes.append(&mut duo::routes()); diff --git a/src/api/core/two_factor/u2f.rs b/src/api/core/two_factor/u2f.rs @@ -28,13 +28,7 @@ static APP_ID: Lazy<String> = Lazy::new(|| format!("{}/app-id.json", &CONFIG.dom static U2F: Lazy<U2f> = Lazy::new(|| U2f::new(APP_ID.clone())); pub fn routes() -> Vec<Route> { - routes![ - generate_u2f, - generate_u2f_challenge, - activate_u2f, - activate_u2f_put, - delete_u2f, - ] + routes![generate_u2f, generate_u2f_challenge, activate_u2f, activate_u2f_put, delete_u2f,] } #[post("/two-factor/get-u2f", data = "<data>")] @@ -161,10 +155,7 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn) let response: RegisterResponseCopy = serde_json::from_str(&data.DeviceResponse)?; - let error_code = response - .error_code - .clone() - .map_or("0".into(), NumberOrString::into_string); + let error_code = response.error_code.clone().map_or("0".into(), NumberOrString::into_string); if error_code != "0" { err!("Error registering U2F token") @@ -300,20 +291,13 @@ fn _old_parse_registrations(registations: &str) -> Vec<Registration> { let regs: Vec<Value> = serde_json::from_str(registations).expect("Can't parse Registration data"); - regs.into_iter() - .map(|r| serde_json::from_value(r).unwrap()) - .map(|Helper(r)| r) - .collect() + regs.into_iter().map(|r| serde_json::from_value(r).unwrap()).map(|Helper(r)| r).collect() } pub fn generate_u2f_login(user_uuid: &str, conn: &DbConn) -> ApiResult<U2fSignRequest> { let challenge = _create_u2f_challenge(user_uuid, TwoFactorType::U2fLoginChallenge, conn); - let registrations: Vec<_> = get_u2f_registrations(user_uuid, conn)? - .1 - .into_iter() - .map(|r| r.reg) - .collect(); + let registrations: Vec<_> = get_u2f_registrations(user_uuid, conn)?.1.into_iter().map(|r| r.reg).collect(); if registrations.is_empty() { err!("No U2F devices registered") diff --git a/src/api/icons.rs b/src/api/icons.rs @@ -22,10 +22,7 @@ static CLIENT: Lazy<Client> = Lazy::new(|| { // Generate the default headers let mut default_headers = header::HeaderMap::new(); default_headers.insert(header::USER_AGENT, header::HeaderValue::from_static("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15")); - default_headers.insert( - header::ACCEPT_LANGUAGE, - header::HeaderValue::from_static("en-US,en;q=0.8"), - ); + default_headers.insert(header::ACCEPT_LANGUAGE, header::HeaderValue::from_static("en-US,en;q=0.8")); default_headers.insert(header::CACHE_CONTROL, header::HeaderValue::from_static("no-cache")); default_headers.insert(header::PRAGMA, header::HeaderValue::from_static("no-cache")); default_headers.insert( @@ -64,10 +61,7 @@ fn icon(domain: String) -> Cached<Content<Vec<u8>>> { match get_icon(&domain) { Some(i) => Cached::ttl(Content(ContentType::new("image", "x-icon"), i), CONFIG.icon_cache_ttl()), - _ => Cached::ttl( - Content(ContentType::new("image", "png"), FALLBACK_ICON.to_vec()), - CONFIG.icon_cache_negttl(), - ), + _ => Cached::ttl(Content(ContentType::new("image", "png"), FALLBACK_ICON.to_vec()), CONFIG.icon_cache_negttl()), } } @@ -100,10 +94,7 @@ fn is_valid_domain(domain: &str) -> bool { for c in domain.chars() { if !c.is_alphanumeric() && !ALLOWED_CHARS.contains(c) { - debug!( - "Domain validation error: '{}' contains an invalid character '{}'", - domain, c - ); + debug!("Domain validation error: '{}' contains an invalid character '{}'", domain, c); return false; } } @@ -352,12 +343,20 @@ struct Icon { impl Icon { const fn new(priority: u8, href: String) -> Self { - Self { href, priority } + Self { + href, + priority, + } } } fn get_favicons_node(node: &std::rc::Rc<markup5ever_rcdom::Node>, icons: &mut Vec<Icon>, url: &Url) { - if let markup5ever_rcdom::NodeData::Element { name, attrs, .. } = &node.data { + if let markup5ever_rcdom::NodeData::Element { + name, + attrs, + .. + } = &node.data + { if name.local.as_ref() == "link" { let mut has_rel = false; let mut href = None; diff --git a/src/api/identity.rs b/src/api/identity.rs @@ -87,27 +87,18 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult let username = data.username.as_ref().unwrap(); let user = match User::find_by_mail(username, &conn) { Some(user) => user, - None => err!( - "Username or password is incorrect. Try again", - format!("IP: {}. Username: {}.", ip.ip, username) - ), + None => err!("Username or password is incorrect. Try again", format!("IP: {}. Username: {}.", ip.ip, username)), }; // Check password let password = data.password.as_ref().unwrap(); if !user.check_valid_password(password) { - err!( - "Username or password is incorrect. Try again", - format!("IP: {}. Username: {}.", ip.ip, username) - ) + err!("Username or password is incorrect. Try again", format!("IP: {}. Username: {}.", ip.ip, username)) } // Check if the user is disabled if !user.enabled { - err!( - "This user has been disabled", - format!("IP: {}. Username: {}.", ip.ip, username) - ) + err!("This user has been disabled", format!("IP: {}. Username: {}.", ip.ip, username)) } let now = Local::now(); @@ -137,10 +128,7 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult } // We still want the login to fail until they actually verified the email address - err!( - "Please verify your email before trying again.", - format!("IP: {}. Username: {}.", ip.ip, username) - ) + err!("Please verify your email before trying again.", format!("IP: {}. Username: {}.", ip.ip, username)) } let (mut device, new_device) = get_device(&data, &conn, &user); @@ -234,10 +222,7 @@ fn twofactor_auth( let twofactor_code = match data.two_factor_token { Some(ref code) => code, - None => err_json!( - _json_err_twofactor(&twofactor_ids, user_uuid, conn)?, - "2FA token not provided" - ), + None => err_json!(_json_err_twofactor(&twofactor_ids, user_uuid, conn)?, "2FA token not provided"), }; let selected_twofactor = twofactors.into_iter().find(|tf| tf.atype == selected_id && tf.enabled); @@ -266,10 +251,9 @@ fn twofactor_auth( Some(ref code) if !CONFIG.disable_2fa_remember() && ct_eq(code, twofactor_code) => { remember = 1; // Make sure we also return the token here, otherwise it will only remember the first time } - _ => err_json!( - _json_err_twofactor(&twofactor_ids, user_uuid, conn)?, - "2FA Remember token not provided" - ), + _ => { + err_json!(_json_err_twofactor(&twofactor_ids, user_uuid, conn)?, "2FA Remember token not provided") + } } } _ => err!("Invalid two factor provider"), diff --git a/src/api/mod.rs b/src/api/mod.rs @@ -54,9 +54,9 @@ impl NumberOrString { use std::num::ParseIntError as PIE; match self { NumberOrString::Number(n) => Ok(n), - NumberOrString::String(s) => s - .parse() - .map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string())), + NumberOrString::String(s) => { + s.parse().map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string())) + } } } } diff --git a/src/api/notifications.rs b/src/api/notifications.rs @@ -15,9 +15,7 @@ static SHOW_WEBSOCKETS_MSG: AtomicBool = AtomicBool::new(true); #[get("/hub")] fn websockets_err() -> EmptyResult { if CONFIG.websocket_enabled() - && SHOW_WEBSOCKETS_MSG - .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) - .is_ok() + && SHOW_WEBSOCKETS_MSG.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed).is_ok() { err!( " @@ -205,9 +203,7 @@ impl Handler for WsHandler { let handler_insert = self.out.clone(); let handler_update = self.out.clone(); - self.users - .map - .upsert(user_uuid, || vec![handler_insert], |ref mut v| v.push(handler_update)); + self.users.map.upsert(user_uuid, || vec![handler_insert], |ref mut v| v.push(handler_update)); // Schedule a ping to keep the connection alive self.out.timeout(PING_MS, PING) @@ -217,7 +213,11 @@ impl Handler for WsHandler { if let Message::Text(text) = msg.clone() { let json = &text[..text.len() - 1]; // Remove last char - if let Ok(InitialMessage { protocol, version }) = from_str::<InitialMessage>(json) { + if let Ok(InitialMessage { + protocol, + version, + }) = from_str::<InitialMessage>(json) + { if &protocol == "messagepack" && version == 1 { return self.out.send(&INITIAL_RESPONSE[..]); // Respond to initial message } @@ -296,10 +296,7 @@ impl WebSocketUsers { // NOTE: The last modified date needs to be updated before calling these methods pub fn send_user_update(&self, ut: UpdateType, user: &User) { let data = create_update( - vec![ - ("UserId".into(), user.uuid.clone().into()), - ("Date".into(), serialize_date(user.updated_at)), - ], + vec![("UserId".into(), user.uuid.clone().into()), ("Date".into(), serialize_date(user.updated_at))], ut, ); diff --git a/src/api/web.rs b/src/api/web.rs @@ -76,48 +76,22 @@ fn alive() -> Json<String> { #[get("/bwrs_static/<filename>")] fn static_files(filename: String) -> Result<Content<&'static [u8]>, Error> { match filename.as_ref() { - "mail-github.png" => Ok(Content( - ContentType::PNG, - include_bytes!("../static/images/mail-github.png"), - )), - "logo-gray.png" => Ok(Content( - ContentType::PNG, - include_bytes!("../static/images/logo-gray.png"), - )), - "shield-white.png" => Ok(Content( - ContentType::PNG, - include_bytes!("../static/images/shield-white.png"), - )), - "error-x.svg" => Ok(Content( - ContentType::SVG, - include_bytes!("../static/images/error-x.svg"), - )), + "mail-github.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/mail-github.png"))), + "logo-gray.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))), + "shield-white.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/shield-white.png"))), + "error-x.svg" => Ok(Content(ContentType::SVG, include_bytes!("../static/images/error-x.svg"))), "hibp.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/hibp.png"))), - "bootstrap.css" => Ok(Content( - ContentType::CSS, - include_bytes!("../static/scripts/bootstrap.css"), - )), - "bootstrap-native.js" => Ok(Content( - ContentType::JavaScript, - include_bytes!("../static/scripts/bootstrap-native.js"), - )), - "identicon.js" => Ok(Content( - ContentType::JavaScript, - include_bytes!("../static/scripts/identicon.js"), - )), - "datatables.js" => Ok(Content( - ContentType::JavaScript, - include_bytes!("../static/scripts/datatables.js"), - )), - "datatables.css" => Ok(Content( - ContentType::CSS, - include_bytes!("../static/scripts/datatables.css"), - )), - "jquery-3.5.1.slim.js" => Ok(Content( - ContentType::JavaScript, - include_bytes!("../static/scripts/jquery-3.5.1.slim.js"), - )), + "bootstrap.css" => Ok(Content(ContentType::CSS, include_bytes!("../static/scripts/bootstrap.css"))), + "bootstrap-native.js" => { + Ok(Content(ContentType::JavaScript, include_bytes!("../static/scripts/bootstrap-native.js"))) + } + "identicon.js" => Ok(Content(ContentType::JavaScript, include_bytes!("../static/scripts/identicon.js"))), + "datatables.js" => Ok(Content(ContentType::JavaScript, include_bytes!("../static/scripts/datatables.js"))), + "datatables.css" => Ok(Content(ContentType::CSS, include_bytes!("../static/scripts/datatables.css"))), + "jquery-3.5.1.slim.js" => { + Ok(Content(ContentType::JavaScript, include_bytes!("../static/scripts/jquery-3.5.1.slim.js"))) + } _ => err!(format!("Static file not found: {}", filename)), } } diff --git a/src/auth.rs b/src/auth.rs @@ -260,7 +260,9 @@ impl<'a, 'r> FromRequest<'a, 'r> for Host { format!("{}://{}", protocol, host) }; - Outcome::Success(Host { host }) + Outcome::Success(Host { + host, + }) } } @@ -316,10 +318,8 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers { }; if user.security_stamp != claims.sstamp { - if let Some(stamp_exception) = user - .stamp_exception - .as_deref() - .and_then(|s| serde_json::from_str::<UserStampException>(s).ok()) + if let Some(stamp_exception) = + user.stamp_exception.as_deref().and_then(|s| serde_json::from_str::<UserStampException>(s).ok()) { let current_route = match request.route().and_then(|r| r.name) { Some(name) => name, @@ -337,7 +337,11 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers { } } - Outcome::Success(Headers { host, device, user }) + Outcome::Success(Headers { + host, + device, + user, + }) } } @@ -639,10 +643,10 @@ impl<'a, 'r> FromRequest<'a, 'r> for ClientIp { None }; - let ip = ip - .or_else(|| req.remote().map(|r| r.ip())) - .unwrap_or_else(|| "0.0.0.0".parse().unwrap()); + let ip = ip.or_else(|| req.remote().map(|r| r.ip())).unwrap_or_else(|| "0.0.0.0".parse().unwrap()); - Outcome::Success(ClientIp { ip }) + Outcome::Success(ClientIp { + ip, + }) } } diff --git a/src/config.rs b/src/config.rs @@ -511,10 +511,7 @@ fn validate_config(cfg: &ConfigItems) -> Result<(), Error> { let limit = 256; 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,)); } let dom = cfg.domain.to_lowercase(); @@ -855,9 +852,7 @@ fn case_helper<'reg, 'rc>( rc: &mut RenderContext<'reg, 'rc>, out: &mut dyn Output, ) -> HelperResult { - let param = h - .param(0) - .ok_or_else(|| RenderError::new("Param not found for helper \"case\""))?; + let param = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"case\""))?; let value = param.value().clone(); if h.params().iter().skip(1).any(|x| x.value() == &value) { @@ -874,16 +869,12 @@ fn js_escape_helper<'reg, 'rc>( _rc: &mut RenderContext<'reg, 'rc>, out: &mut dyn Output, ) -> HelperResult { - let param = h - .param(0) - .ok_or_else(|| RenderError::new("Param not found for helper \"js_escape\""))?; + let param = h.param(0).ok_or_else(|| RenderError::new("Param not found for helper \"js_escape\""))?; let no_quote = h.param(1).is_some(); - let value = param - .value() - .as_str() - .ok_or_else(|| RenderError::new("Param for helper \"js_escape\" is not a String"))?; + let value = + param.value().as_str().ok_or_else(|| RenderError::new("Param for helper \"js_escape\" is not a String"))?; let mut escaped_value = value.replace('\\', "").replace('\'', "\\x22").replace('\"', "\\x27"); if !no_quote { diff --git a/src/crypto.rs b/src/crypto.rs @@ -47,9 +47,7 @@ pub fn get_random_64() -> Vec<u8> { pub fn get_random(mut array: Vec<u8>) -> Vec<u8> { use ring::rand::{SecureRandom, SystemRandom}; - SystemRandom::new() - .fill(&mut array) - .expect("Error generating random values"); + SystemRandom::new().fill(&mut array).expect("Error generating random values"); array } diff --git a/src/db/mod.rs b/src/db/mod.rs @@ -314,9 +314,7 @@ mod sqlite_migrations { // Turn on WAL in SQLite if crate::CONFIG.enable_db_wal() { - diesel::sql_query("PRAGMA journal_mode=wal") - .execute(&connection) - .expect("Failed to turn on WAL"); + diesel::sql_query("PRAGMA journal_mode=wal").execute(&connection).expect("Failed to turn on WAL"); } embedded_migrations::run_with_output(&connection, &mut std::io::stdout())?; diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs @@ -83,16 +83,9 @@ impl Cipher { attachments.iter().map(|c| c.to_json(host)).collect() }; - let fields_json = self - .fields - .as_ref() - .and_then(|s| serde_json::from_str(s).ok()) - .unwrap_or(Value::Null); - let password_history_json = self - .password_history - .as_ref() - .and_then(|s| serde_json::from_str(s).ok()) - .unwrap_or(Value::Null); + let fields_json = self.fields.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or(Value::Null); + let password_history_json = + self.password_history.as_ref().and_then(|s| serde_json::from_str(s).ok()).unwrap_or(Value::Null); let (read_only, hide_passwords) = match self.get_access_restrictions(&user_uuid, conn) { Some((ro, hp)) => (ro, hp), @@ -195,12 +188,10 @@ impl Cipher { None => { // Belongs to Organization, need to update affected users if let Some(ref org_uuid) = self.organization_uuid { - UserOrganization::find_by_cipher_and_org(&self.uuid, &org_uuid, conn) - .iter() - .for_each(|user_org| { - User::update_uuid_revision(&user_org.user_uuid, conn); - user_uuids.push(user_org.user_uuid.clone()) - }); + UserOrganization::find_by_cipher_and_org(&self.uuid, &org_uuid, conn).iter().for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn); + user_uuids.push(user_org.user_uuid.clone()) + }); } } }; diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs @@ -127,11 +127,9 @@ impl Collection { } pub fn update_users_revision(&self, conn: &DbConn) { - UserOrganization::find_by_collection_and_org(&self.uuid, &self.org_uuid, conn) - .iter() - .for_each(|user_org| { - User::update_uuid_revision(&user_org.user_uuid, conn); - }); + UserOrganization::find_by_collection_and_org(&self.uuid, &self.org_uuid, conn).iter().for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn); + }); } pub fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> { @@ -170,10 +168,7 @@ impl Collection { } pub fn find_by_organization_and_user_uuid(org_uuid: &str, user_uuid: &str, conn: &DbConn) -> Vec<Self> { - Self::find_by_user_uuid(user_uuid, conn) - .into_iter() - .filter(|c| c.org_uuid == org_uuid) - .collect() + Self::find_by_user_uuid(user_uuid, conn).into_iter().filter(|c| c.org_uuid == org_uuid).collect() } pub fn find_by_organization(org_uuid: &str, conn: &DbConn) -> Vec<Self> { @@ -380,11 +375,9 @@ impl CollectionUser { } pub fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> EmptyResult { - CollectionUser::find_by_collection(&collection_uuid, conn) - .iter() - .for_each(|collection| { - User::update_uuid_revision(&collection.user_uuid, conn); - }); + CollectionUser::find_by_collection(&collection_uuid, conn).iter().for_each(|collection| { + User::update_uuid_revision(&collection.user_uuid, conn); + }); db_run! { conn: { diesel::delete(users_collections::table.filter(users_collections::collection_uuid.eq(collection_uuid))) diff --git a/src/db/models/device.rs b/src/db/models/device.rs @@ -74,26 +74,10 @@ impl Device { let time_now = Utc::now().naive_utc(); self.updated_at = time_now; - let orgowner: Vec<_> = orgs - .iter() - .filter(|o| o.atype == 0) - .map(|o| o.org_uuid.clone()) - .collect(); - let orgadmin: Vec<_> = orgs - .iter() - .filter(|o| o.atype == 1) - .map(|o| o.org_uuid.clone()) - .collect(); - let orguser: Vec<_> = orgs - .iter() - .filter(|o| o.atype == 2) - .map(|o| o.org_uuid.clone()) - .collect(); - let orgmanager: Vec<_> = orgs - .iter() - .filter(|o| o.atype == 3) - .map(|o| o.org_uuid.clone()) - .collect(); + let orgowner: Vec<_> = orgs.iter().filter(|o| o.atype == 0).map(|o| o.org_uuid.clone()).collect(); + let orgadmin: Vec<_> = orgs.iter().filter(|o| o.atype == 1).map(|o| o.org_uuid.clone()).collect(); + let orguser: Vec<_> = orgs.iter().filter(|o| o.atype == 2).map(|o| o.org_uuid.clone()).collect(); + let orgmanager: Vec<_> = orgs.iter().filter(|o| o.atype == 3).map(|o| o.org_uuid.clone()).collect(); // Create the JWT claims struct, to send to the client use crate::auth::{encode_jwt, LoginJwtClaims, DEFAULT_VALIDITY, JWT_LOGIN_ISSUER}; diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs @@ -116,10 +116,7 @@ impl PartialOrd<UserOrgType> for i32 { } fn le(&self, other: &UserOrgType) -> bool { - matches!( - self.partial_cmp(other), - Some(Ordering::Less) | Some(Ordering::Equal) | None - ) + matches!(self.partial_cmp(other), Some(Ordering::Less) | Some(Ordering::Equal) | None) } } @@ -192,11 +189,9 @@ use crate::error::MapResult; /// Database methods impl Organization { pub fn save(&self, conn: &DbConn) -> EmptyResult { - UserOrganization::find_by_org(&self.uuid, conn) - .iter() - .for_each(|user_org| { - User::update_uuid_revision(&user_org.user_uuid, conn); - }); + UserOrganization::find_by_org(&self.uuid, conn).iter().for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn); + }); db_run! { conn: sqlite, mysql { diff --git a/src/db/models/user.rs b/src/db/models/user.rs @@ -348,7 +348,9 @@ impl User { impl Invitation { pub const fn new(email: String) -> Self { - Self { email } + Self { + email, + } } pub fn save(&self, conn: &DbConn) -> EmptyResult { diff --git a/src/error.rs b/src/error.rs @@ -198,11 +198,7 @@ impl<'r> Responder<'r> for Error { let code = Status::from_code(self.error_code).unwrap_or(Status::BadRequest); - Response::build() - .status(code) - .header(ContentType::JSON) - .sized_body(Cursor::new(format!("{}", self))) - .ok() + Response::build().status(code).header(ContentType::JSON).sized_body(Cursor::new(format!("{}", self))).ok() } } diff --git a/src/mail.rs b/src/mail.rs @@ -58,18 +58,12 @@ fn mailer() -> SmtpTransport { let smtp_client = match CONFIG.smtp_auth_mechanism() { Some(mechanism) => { - let allowed_mechanisms = [ - SmtpAuthMechanism::Plain, - SmtpAuthMechanism::Login, - SmtpAuthMechanism::Xoauth2, - ]; + let allowed_mechanisms = [SmtpAuthMechanism::Plain, SmtpAuthMechanism::Login, SmtpAuthMechanism::Xoauth2]; let mut selected_mechanisms = vec![]; for wanted_mechanism in mechanism.split(',') { for m in &allowed_mechanisms { if m.to_string().to_lowercase() - == wanted_mechanism - .trim_matches(|c| c == '"' || c == '\'' || c == ' ') - .to_lowercase() + == wanted_mechanism.trim_matches(|c| c == '"' || c == '\'' || c == ' ').to_lowercase() { selected_mechanisms.push(*m); } @@ -80,10 +74,7 @@ fn mailer() -> SmtpTransport { smtp_client.authentication(selected_mechanisms) } else { // Only show a warning, and return without setting an actual authentication mechanism - warn!( - "No valid SMTP Auth mechanism found for '{}', using default values", - mechanism - ); + warn!("No valid SMTP Auth mechanism found for '{}', using default values", mechanism); smtp_client } } @@ -327,16 +318,9 @@ fn send_email(address: &str, subject: &str, body_html: String, body_text: String let smtp_from = &CONFIG.smtp_from(); let email = Message::builder() - .message_id(Some(format!( - "<{}@{}>", - crate::util::get_uuid(), - smtp_from.split('@').collect::<Vec<&str>>()[1] - ))) + .message_id(Some(format!("<{}@{}>", crate::util::get_uuid(), smtp_from.split('@').collect::<Vec<&str>>()[1]))) .to(Mailbox::new(None, Address::from_str(&address)?)) - .from(Mailbox::new( - Some(CONFIG.smtp_from_name()), - Address::from_str(smtp_from)?, - )) + .from(Mailbox::new(Some(CONFIG.smtp_from_name()), Address::from_str(smtp_from)?)) .subject(subject) .multipart(MultiPart::alternative().singlepart(text).singlepart(html))?; diff --git a/src/util.rs b/src/util.rs @@ -127,14 +127,8 @@ impl<'r, R: Responder<'r>> Responder<'r> for Cached<R> { // Log all the routes from the main paths list, and the attachments endpoint // Effectively ignores, any static file route, and the alive endpoint -const LOGGED_ROUTES: [&str; 6] = [ - "/api", - "/admin", - "/identity", - "/icons", - "/notifications/hub/negotiate", - "/attachments", -]; +const LOGGED_ROUTES: [&str; 6] = + ["/api", "/admin", "/identity", "/icons", "/notifications/hub/negotiate", "/attachments"]; // Boolean is extra debug, when true, we ignore the whitelist above and also print the mounts pub struct BetterLogging(pub bool); @@ -161,7 +155,11 @@ impl Fairing for BetterLogging { } let config = rocket.config(); - let scheme = if config.tls_enabled() { "https" } else { "http" }; + let scheme = if config.tls_enabled() { + "https" + } else { + "http" + }; let addr = format!("{}://{}:{}", &scheme, &config.address, &config.port); info!(target: "start", "Rocket has launched from {}", addr); }