Browse Source

Add extra linting (#4977)

* Add extra linting

Added extra linting for some code styles.
Also added the Rust Edition 2024 lints.

Closes #4974

Signed-off-by: BlackDex <black.dex@gmail.com>

* Adjusted according to comments

Signed-off-by: BlackDex <black.dex@gmail.com>

---------

Signed-off-by: BlackDex <black.dex@gmail.com>
main 1.32.1
Mathijs van Veluw 2 weeks ago
committed by GitHub
parent
commit
040e2a7bb0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 20
      Cargo.lock
  2. 28
      Cargo.toml
  3. 6
      src/api/admin.rs
  4. 6
      src/api/core/accounts.rs
  5. 2
      src/api/core/organizations.rs
  6. 4
      src/api/core/public.rs
  7. 2
      src/api/core/two_factor/email.rs
  8. 2
      src/api/core/two_factor/protected_actions.rs
  9. 2
      src/api/core/two_factor/yubikey.rs
  10. 20
      src/api/icons.rs
  11. 2
      src/api/notifications.rs
  12. 6
      src/auth.rs
  13. 10
      src/config.rs
  14. 6
      src/db/mod.rs
  15. 2
      src/db/models/emergency_access.rs
  16. 6
      src/db/models/organization.rs
  17. 4
      src/db/models/user.rs
  18. 2
      src/error.rs
  19. 6
      src/http_client.rs
  20. 8
      src/main.rs
  21. 8
      src/util.rs

20
Cargo.lock

@ -2543,9 +2543,9 @@ dependencies = [
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.30" version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]] [[package]]
name = "polling" name = "polling"
@ -2564,9 +2564,9 @@ dependencies = [
[[package]] [[package]]
name = "portable-atomic" name = "portable-atomic"
version = "1.7.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
@ -3226,9 +3226,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.11.1" version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -3573,18 +3573,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.63" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.63" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

28
Cargo.toml

@ -198,33 +198,46 @@ lto = "thin"
codegen-units = 16 codegen-units = 16
# Linting config # Linting config
# https://doc.rust-lang.org/rustc/lints/groups.html
[lints.rust] [lints.rust]
# Forbid # Forbid
unsafe_code = "forbid" unsafe_code = "forbid"
non_ascii_idents = "forbid" non_ascii_idents = "forbid"
# Deny # Deny
deprecated_in_future = "deny"
future_incompatible = { level = "deny", priority = -1 } future_incompatible = { level = "deny", priority = -1 }
keyword_idents = { level = "deny", priority = -1 }
let_underscore = { level = "deny", priority = -1 }
noop_method_call = "deny" noop_method_call = "deny"
refining_impl_trait = { level = "deny", priority = -1 }
rust_2018_idioms = { level = "deny", priority = -1 } rust_2018_idioms = { level = "deny", priority = -1 }
rust_2021_compatibility = { level = "deny", priority = -1 } rust_2021_compatibility = { level = "deny", priority = -1 }
# rust_2024_compatibility = { level = "deny", priority = -1 } # Enable once we are at MSRV 1.81.0
single_use_lifetimes = "deny"
trivial_casts = "deny" trivial_casts = "deny"
trivial_numeric_casts = "deny" trivial_numeric_casts = "deny"
unused = { level = "deny", priority = -1 } unused = { level = "deny", priority = -1 }
unused_import_braces = "deny" unused_import_braces = "deny"
unused_lifetimes = "deny" unused_lifetimes = "deny"
deprecated_in_future = "deny" unused_qualifications = "deny"
variant_size_differences = "deny"
# The lints below are part of the rust_2024_compatibility group
static-mut-refs = "deny"
unsafe-op-in-unsafe-fn = "deny"
# https://rust-lang.github.io/rust-clippy/stable/index.html
[lints.clippy] [lints.clippy]
# Allow # Warn
# We need this since Rust v1.76+, since it has some bugs dbg_macro = "warn"
# https://github.com/rust-lang/rust-clippy/issues/12016 todo = "warn"
blocks_in_conditions = "allow"
# Deny # Deny
case_sensitive_file_extension_comparisons = "deny"
cast_lossless = "deny" cast_lossless = "deny"
clone_on_ref_ptr = "deny" clone_on_ref_ptr = "deny"
equatable_if_let = "deny" equatable_if_let = "deny"
filter_map_next = "deny"
float_cmp_const = "deny" float_cmp_const = "deny"
inefficient_to_string = "deny" inefficient_to_string = "deny"
iter_on_empty_collections = "deny" iter_on_empty_collections = "deny"
@ -234,13 +247,18 @@ macro_use_imports = "deny"
manual_assert = "deny" manual_assert = "deny"
manual_instant_elapsed = "deny" manual_instant_elapsed = "deny"
manual_string_new = "deny" manual_string_new = "deny"
match_on_vec_items = "deny"
match_wildcard_for_single_variants = "deny" match_wildcard_for_single_variants = "deny"
mem_forget = "deny" mem_forget = "deny"
needless_continue = "deny"
needless_lifetimes = "deny" needless_lifetimes = "deny"
option_option = "deny"
string_add_assign = "deny" string_add_assign = "deny"
string_to_string = "deny" string_to_string = "deny"
unnecessary_join = "deny" unnecessary_join = "deny"
unnecessary_self_imports = "deny" unnecessary_self_imports = "deny"
unnested_or_patterns = "deny"
unused_async = "deny" unused_async = "deny"
unused_self = "deny"
verbose_file_reads = "deny" verbose_file_reads = "deny"
zero_sized_map_values = "deny" zero_sized_map_values = "deny"

6
src/api/admin.rs

@ -197,7 +197,7 @@ fn post_admin_login(
let cookie = Cookie::build((COOKIE_NAME, jwt)) let cookie = Cookie::build((COOKIE_NAME, jwt))
.path(admin_path()) .path(admin_path())
.max_age(rocket::time::Duration::minutes(CONFIG.admin_session_lifetime())) .max_age(time::Duration::minutes(CONFIG.admin_session_lifetime()))
.same_site(SameSite::Strict) .same_site(SameSite::Strict)
.http_only(true) .http_only(true)
.secure(secure.https); .secure(secure.https);
@ -717,8 +717,8 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, mut conn: DbConn)
"db_version": get_sql_server_version(&mut conn).await, "db_version": get_sql_server_version(&mut conn).await,
"admin_url": format!("{}/diagnostics", admin_url()), "admin_url": format!("{}/diagnostics", admin_url()),
"overrides": &CONFIG.get_overrides().join(", "), "overrides": &CONFIG.get_overrides().join(", "),
"host_arch": std::env::consts::ARCH, "host_arch": env::consts::ARCH,
"host_os": std::env::consts::OS, "host_os": env::consts::OS,
"server_time_local": Local::now().format("%Y-%m-%d %H:%M:%S %Z").to_string(), "server_time_local": Local::now().format("%Y-%m-%d %H:%M:%S %Z").to_string(),
"server_time": Utc::now().format("%Y-%m-%d %H:%M:%S UTC").to_string(), // Run the server date/time check as late as possible to minimize the time difference "server_time": Utc::now().format("%Y-%m-%d %H:%M:%S UTC").to_string(), // Run the server date/time check as late as possible to minimize the time difference
"ntp_time": get_ntp_time(has_http_access).await, // Run the ntp check as late as possible to minimize the time difference "ntp_time": get_ntp_time(has_http_access).await, // Run the ntp check as late as possible to minimize the time difference

6
src/api/core/accounts.rs

@ -223,7 +223,7 @@ pub async fn _register(data: Json<RegisterData>, mut conn: DbConn) -> JsonResult
} }
if verified_by_invite && is_email_2fa_required(data.organization_user_id, &mut conn).await { if verified_by_invite && is_email_2fa_required(data.organization_user_id, &mut conn).await {
let _ = email::activate_email_2fa(&user, &mut conn).await; email::activate_email_2fa(&user, &mut conn).await.ok();
} }
} }
@ -232,7 +232,7 @@ pub async fn _register(data: Json<RegisterData>, mut conn: DbConn) -> JsonResult
// accept any open emergency access invitations // accept any open emergency access invitations
if !CONFIG.mail_enabled() && CONFIG.emergency_access_allowed() { if !CONFIG.mail_enabled() && CONFIG.emergency_access_allowed() {
for mut emergency_invite in EmergencyAccess::find_all_invited_by_grantee_email(&user.email, &mut conn).await { for mut emergency_invite in EmergencyAccess::find_all_invited_by_grantee_email(&user.email, &mut conn).await {
let _ = emergency_invite.accept_invite(&user.uuid, &user.email, &mut conn).await; emergency_invite.accept_invite(&user.uuid, &user.email, &mut conn).await.ok();
} }
} }
@ -1038,7 +1038,7 @@ async fn put_device_token(uuid: &str, data: Json<PushToken>, headers: Headers, m
return Ok(()); return Ok(());
} else { } else {
// Try to unregister already registered device // Try to unregister already registered device
let _ = unregister_push_device(device.push_uuid).await; unregister_push_device(device.push_uuid).await.ok();
} }
// clear the push_uuid // clear the push_uuid
device.push_uuid = None; device.push_uuid = None;

2
src/api/core/organizations.rs

@ -1720,7 +1720,7 @@ async fn list_policies_token(org_id: &str, token: &str, mut conn: DbConn) -> Jso
return Ok(Json(json!({}))); return Ok(Json(json!({})));
} }
let invite = crate::auth::decode_invite(token)?; let invite = decode_invite(token)?;
let invite_org_id = match invite.org_id { let invite_org_id = match invite.org_id {
Some(invite_org_id) => invite_org_id, Some(invite_org_id) => invite_org_id,

4
src/api/core/public.rs

@ -1,6 +1,6 @@
use chrono::Utc; use chrono::Utc;
use rocket::{ use rocket::{
request::{self, FromRequest, Outcome}, request::{FromRequest, Outcome},
serde::json::Json, serde::json::Json,
Request, Route, Request, Route,
}; };
@ -192,7 +192,7 @@ pub struct PublicToken(String);
impl<'r> FromRequest<'r> for PublicToken { impl<'r> FromRequest<'r> for PublicToken {
type Error = &'static str; type Error = &'static str;
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
let headers = request.headers(); let headers = request.headers();
// Get access_token // Get access_token
let access_token: &str = match headers.get_one("Authorization") { let access_token: &str = match headers.get_one("Authorization") {

2
src/api/core/two_factor/email.rs

@ -292,7 +292,7 @@ impl EmailTokenData {
} }
pub fn from_json(string: &str) -> Result<EmailTokenData, Error> { pub fn from_json(string: &str) -> Result<EmailTokenData, Error> {
let res: Result<EmailTokenData, crate::serde_json::Error> = serde_json::from_str(string); let res: Result<EmailTokenData, serde_json::Error> = serde_json::from_str(string);
match res { match res {
Ok(x) => Ok(x), Ok(x) => Ok(x),
Err(_) => err!("Could not decode EmailTokenData from string"), Err(_) => err!("Could not decode EmailTokenData from string"),

2
src/api/core/two_factor/protected_actions.rs

@ -42,7 +42,7 @@ impl ProtectedActionData {
} }
pub fn from_json(string: &str) -> Result<Self, Error> { pub fn from_json(string: &str) -> Result<Self, Error> {
let res: Result<Self, crate::serde_json::Error> = serde_json::from_str(string); let res: Result<Self, serde_json::Error> = serde_json::from_str(string);
match res { match res {
Ok(x) => Ok(x), Ok(x) => Ok(x),
Err(_) => err!("Could not decode ProtectedActionData from string"), Err(_) => err!("Could not decode ProtectedActionData from string"),

2
src/api/core/two_factor/yubikey.rs

@ -49,7 +49,7 @@ fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
data_keys.iter().filter_map(|e| e.as_ref().cloned()).collect() data_keys.iter().filter_map(|e| e.as_ref().cloned()).collect()
} }
fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value { fn jsonify_yubikeys(yubikeys: Vec<String>) -> Value {
let mut result = Value::Object(serde_json::Map::new()); let mut result = Value::Object(serde_json::Map::new());
for (i, key) in yubikeys.into_iter().enumerate() { for (i, key) in yubikeys.into_iter().enumerate() {

20
src/api/icons.rs

@ -1,4 +1,5 @@
use std::{ use std::{
collections::HashMap,
net::IpAddr, net::IpAddr,
sync::Arc, sync::Arc,
time::{Duration, SystemTime}, time::{Duration, SystemTime},
@ -446,6 +447,9 @@ async fn get_page_with_referer(url: &str, referer: &str) -> Result<Response, Err
/// priority2 = get_icon_priority("https://example.com/path/to/a/favicon.ico", ""); /// priority2 = get_icon_priority("https://example.com/path/to/a/favicon.ico", "");
/// ``` /// ```
fn get_icon_priority(href: &str, sizes: &str) -> u8 { fn get_icon_priority(href: &str, sizes: &str) -> u8 {
static PRIORITY_MAP: Lazy<HashMap<&'static str, u8>> =
Lazy::new(|| [(".png", 10), (".jpg", 20), (".jpeg", 20)].into_iter().collect());
// Check if there is a dimension set // Check if there is a dimension set
let (width, height) = parse_sizes(sizes); let (width, height) = parse_sizes(sizes);
@ -470,13 +474,9 @@ fn get_icon_priority(href: &str, sizes: &str) -> u8 {
200 200
} }
} else { } else {
// Change priority by file extension match href.rsplit_once('.') {
if href.ends_with(".png") { Some((_, extension)) => PRIORITY_MAP.get(&*extension.to_ascii_lowercase()).copied().unwrap_or(30),
10 None => 30,
} else if href.ends_with(".jpg") || href.ends_with(".jpeg") {
20
} else {
30
} }
} }
} }
@ -623,7 +623,7 @@ use cookie_store::CookieStore;
pub struct Jar(std::sync::RwLock<CookieStore>); pub struct Jar(std::sync::RwLock<CookieStore>);
impl reqwest::cookie::CookieStore for Jar { impl reqwest::cookie::CookieStore for Jar {
fn set_cookies(&self, cookie_headers: &mut dyn Iterator<Item = &header::HeaderValue>, url: &url::Url) { fn set_cookies(&self, cookie_headers: &mut dyn Iterator<Item = &HeaderValue>, url: &url::Url) {
use cookie::{Cookie as RawCookie, ParseError as RawCookieParseError}; use cookie::{Cookie as RawCookie, ParseError as RawCookieParseError};
use time::Duration; use time::Duration;
@ -642,7 +642,7 @@ impl reqwest::cookie::CookieStore for Jar {
cookie_store.store_response_cookies(cookies, url); cookie_store.store_response_cookies(cookies, url);
} }
fn cookies(&self, url: &url::Url) -> Option<header::HeaderValue> { fn cookies(&self, url: &url::Url) -> Option<HeaderValue> {
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)
@ -654,7 +654,7 @@ impl reqwest::cookie::CookieStore for Jar {
return None; return None;
} }
header::HeaderValue::from_maybe_shared(Bytes::from(s)).ok() HeaderValue::from_maybe_shared(Bytes::from(s)).ok()
} }
} }

2
src/api/notifications.rs

@ -428,7 +428,7 @@ impl WebSocketUsers {
let (user_uuid, collection_uuids, revision_date) = if let Some(collection_uuids) = collection_uuids { let (user_uuid, collection_uuids, revision_date) = if let Some(collection_uuids) = collection_uuids {
( (
Value::Nil, Value::Nil,
Value::Array(collection_uuids.into_iter().map(|v| v.into()).collect::<Vec<rmpv::Value>>()), Value::Array(collection_uuids.into_iter().map(|v| v.into()).collect::<Vec<Value>>()),
serialize_date(Utc::now().naive_utc()), serialize_date(Utc::now().naive_utc()),
) )
} else { } else {

6
src/auth.rs

@ -35,8 +35,8 @@ static JWT_FILE_DOWNLOAD_ISSUER: Lazy<String> = Lazy::new(|| format!("{}|file_do
static PRIVATE_RSA_KEY: OnceCell<EncodingKey> = OnceCell::new(); static PRIVATE_RSA_KEY: OnceCell<EncodingKey> = OnceCell::new();
static PUBLIC_RSA_KEY: OnceCell<DecodingKey> = OnceCell::new(); static PUBLIC_RSA_KEY: OnceCell<DecodingKey> = OnceCell::new();
pub fn initialize_keys() -> Result<(), crate::error::Error> { pub fn initialize_keys() -> Result<(), Error> {
fn read_key(create_if_missing: bool) -> Result<(Rsa<openssl::pkey::Private>, Vec<u8>), crate::error::Error> { fn read_key(create_if_missing: bool) -> Result<(Rsa<openssl::pkey::Private>, Vec<u8>), Error> {
let mut priv_key_buffer = Vec::with_capacity(2048); let mut priv_key_buffer = Vec::with_capacity(2048);
let mut priv_key_file = File::options() let mut priv_key_file = File::options()
@ -53,7 +53,7 @@ pub fn initialize_keys() -> Result<(), crate::error::Error> {
Rsa::private_key_from_pem(&priv_key_buffer[..bytes_read])? Rsa::private_key_from_pem(&priv_key_buffer[..bytes_read])?
} else if create_if_missing { } else if create_if_missing {
// Only create the key if the file doesn't exist or is empty // Only create the key if the file doesn't exist or is empty
let rsa_key = openssl::rsa::Rsa::generate(2048)?; let rsa_key = Rsa::generate(2048)?;
priv_key_buffer = rsa_key.private_key_to_pem()?; priv_key_buffer = rsa_key.private_key_to_pem()?;
priv_key_file.write_all(&priv_key_buffer)?; priv_key_file.write_all(&priv_key_buffer)?;
info!("Private key '{}' created correctly", CONFIG.private_rsa_key()); info!("Private key '{}' created correctly", CONFIG.private_rsa_key());

10
src/config.rs

@ -1225,7 +1225,7 @@ impl Config {
} }
pub fn private_rsa_key(&self) -> String { pub fn private_rsa_key(&self) -> String {
format!("{}.pem", CONFIG.rsa_key_filename()) format!("{}.pem", self.rsa_key_filename())
} }
pub fn mail_enabled(&self) -> bool { pub fn mail_enabled(&self) -> bool {
let inner = &self.inner.read().unwrap().config; let inner = &self.inner.read().unwrap().config;
@ -1256,12 +1256,8 @@ impl Config {
token.is_some() && !token.unwrap().trim().is_empty() token.is_some() && !token.unwrap().trim().is_empty()
} }
pub fn render_template<T: serde::ser::Serialize>( pub fn render_template<T: serde::ser::Serialize>(&self, name: &str, data: &T) -> Result<String, Error> {
&self, if self.reload_templates() {
name: &str,
data: &T,
) -> Result<String, crate::error::Error> {
if CONFIG.reload_templates() {
warn!("RELOADING TEMPLATES"); warn!("RELOADING TEMPLATES");
let hb = load_templates(CONFIG.templates_folder()); let hb = load_templates(CONFIG.templates_folder());
hb.render(name, data).map_err(Into::into) hb.render(name, data).map_err(Into::into)

6
src/db/mod.rs

@ -300,19 +300,17 @@ pub trait FromDb {
impl<T: FromDb> FromDb for Vec<T> { impl<T: FromDb> FromDb for Vec<T> {
type Output = Vec<T::Output>; type Output = Vec<T::Output>;
#[allow(clippy::wrong_self_convention)]
#[inline(always)] #[inline(always)]
fn from_db(self) -> Self::Output { fn from_db(self) -> Self::Output {
self.into_iter().map(crate::db::FromDb::from_db).collect() self.into_iter().map(FromDb::from_db).collect()
} }
} }
impl<T: FromDb> FromDb for Option<T> { impl<T: FromDb> FromDb for Option<T> {
type Output = Option<T::Output>; type Output = Option<T::Output>;
#[allow(clippy::wrong_self_convention)]
#[inline(always)] #[inline(always)]
fn from_db(self) -> Self::Output { fn from_db(self) -> Self::Output {
self.map(crate::db::FromDb::from_db) self.map(FromDb::from_db)
} }
} }

2
src/db/models/emergency_access.rs

@ -89,7 +89,7 @@ impl EmergencyAccess {
Some(user) => user, Some(user) => user,
None => { None => {
// remove outstanding invitations which should not exist // remove outstanding invitations which should not exist
let _ = Self::delete_all_by_grantee_email(email, conn).await; Self::delete_all_by_grantee_email(email, conn).await.ok();
return None; return None;
} }
} }

6
src/db/models/organization.rs

@ -116,7 +116,7 @@ impl PartialOrd<i32> for UserOrgType {
} }
fn ge(&self, other: &i32) -> bool { fn ge(&self, other: &i32) -> bool {
matches!(self.partial_cmp(other), Some(Ordering::Greater) | Some(Ordering::Equal)) matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal))
} }
} }
@ -139,7 +139,7 @@ impl PartialOrd<UserOrgType> for i32 {
} }
fn le(&self, other: &UserOrgType) -> bool { 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 | Ordering::Equal) | None)
} }
} }
@ -632,7 +632,7 @@ impl UserOrganization {
} }
pub async fn find_by_email_and_org(email: &str, org_id: &str, conn: &mut DbConn) -> Option<UserOrganization> { pub async fn find_by_email_and_org(email: &str, org_id: &str, conn: &mut DbConn) -> Option<UserOrganization> {
if let Some(user) = super::User::find_by_mail(email, conn).await { if let Some(user) = User::find_by_mail(email, conn).await {
if let Some(user_org) = UserOrganization::find_by_user_and_org(&user.uuid, org_id, conn).await { if let Some(user_org) = UserOrganization::find_by_user_and_org(&user.uuid, org_id, conn).await {
return Some(user_org); return Some(user_org);
} }

4
src/db/models/user.rs

@ -144,14 +144,14 @@ impl User {
pub fn check_valid_recovery_code(&self, recovery_code: &str) -> bool { pub fn check_valid_recovery_code(&self, recovery_code: &str) -> bool {
if let Some(ref totp_recover) = self.totp_recover { if let Some(ref totp_recover) = self.totp_recover {
crate::crypto::ct_eq(recovery_code, totp_recover.to_lowercase()) crypto::ct_eq(recovery_code, totp_recover.to_lowercase())
} else { } else {
false false
} }
} }
pub fn check_valid_api_key(&self, key: &str) -> bool { pub fn check_valid_api_key(&self, key: &str) -> bool {
matches!(self.api_key, Some(ref api_key) if crate::crypto::ct_eq(api_key, key)) matches!(self.api_key, Some(ref api_key) if crypto::ct_eq(api_key, key))
} }
/// Set the password hash generated /// Set the password hash generated

2
src/error.rs

@ -209,7 +209,7 @@ use rocket::http::{ContentType, Status};
use rocket::request::Request; use rocket::request::Request;
use rocket::response::{self, Responder, Response}; use rocket::response::{self, Responder, Response};
impl<'r> Responder<'r, 'static> for Error { impl Responder<'_, 'static> for Error {
fn respond_to(self, _: &Request<'_>) -> response::Result<'static> { fn respond_to(self, _: &Request<'_>) -> response::Result<'static> {
match self.error { match self.error {
ErrorKind::Empty(_) => {} // Don't print the error in this situation ErrorKind::Empty(_) => {} // Don't print the error in this situation

6
src/http_client.rs

@ -102,9 +102,9 @@ fn should_block_address_regex(domain_or_ip: &str) -> bool {
fn should_block_host(host: Host<&str>) -> Result<(), CustomHttpClientError> { fn should_block_host(host: Host<&str>) -> Result<(), CustomHttpClientError> {
let (ip, host_str): (Option<IpAddr>, String) = match host { let (ip, host_str): (Option<IpAddr>, String) = match host {
url::Host::Ipv4(ip) => (Some(ip.into()), ip.to_string()), Host::Ipv4(ip) => (Some(ip.into()), ip.to_string()),
url::Host::Ipv6(ip) => (Some(ip.into()), ip.to_string()), Host::Ipv6(ip) => (Some(ip.into()), ip.to_string()),
url::Host::Domain(d) => (None, d.to_string()), Host::Domain(d) => (None, d.to_string()),
}; };
if let Some(ip) = ip { if let Some(ip) = ip {

8
src/main.rs

@ -84,7 +84,7 @@ async fn main() -> Result<(), Error> {
let pool = create_db_pool().await; let pool = create_db_pool().await;
schedule_jobs(pool.clone()); schedule_jobs(pool.clone());
crate::db::models::TwoFactor::migrate_u2f_to_webauthn(&mut pool.get().await.unwrap()).await.unwrap(); db::models::TwoFactor::migrate_u2f_to_webauthn(&mut pool.get().await.unwrap()).await.unwrap();
let extra_debug = matches!(level, log::LevelFilter::Trace | log::LevelFilter::Debug); let extra_debug = matches!(level, log::LevelFilter::Trace | log::LevelFilter::Debug);
launch_rocket(pool, extra_debug).await // Blocks until program termination. launch_rocket(pool, extra_debug).await // Blocks until program termination.
@ -168,7 +168,7 @@ fn parse_args() {
} }
let argon2 = Argon2::new(Argon2id, V0x13, argon2_params.build().unwrap()); let argon2 = Argon2::new(Argon2id, V0x13, argon2_params.build().unwrap());
let salt = SaltString::encode_b64(&crate::crypto::get_random_bytes::<32>()).unwrap(); let salt = SaltString::encode_b64(&crypto::get_random_bytes::<32>()).unwrap();
let argon2_timer = tokio::time::Instant::now(); let argon2_timer = tokio::time::Instant::now();
if let Ok(password_hash) = argon2.hash_password(password.as_bytes(), &salt) { if let Ok(password_hash) = argon2.hash_password(password.as_bytes(), &salt) {
@ -204,7 +204,7 @@ fn backup_sqlite() -> Result<String, Error> {
use crate::db::{backup_sqlite_database, DbConnType}; use crate::db::{backup_sqlite_database, DbConnType};
if DbConnType::from_url(&CONFIG.database_url()).map(|t| t == DbConnType::sqlite).unwrap_or(false) { if DbConnType::from_url(&CONFIG.database_url()).map(|t| t == DbConnType::sqlite).unwrap_or(false) {
use diesel::Connection; use diesel::Connection;
let url = crate::CONFIG.database_url(); let url = CONFIG.database_url();
// Establish a connection to the sqlite database // Establish a connection to the sqlite database
let mut conn = diesel::sqlite::SqliteConnection::establish(&url)?; let mut conn = diesel::sqlite::SqliteConnection::establish(&url)?;
@ -615,7 +615,7 @@ async fn launch_rocket(pool: db::DbPool, extra_debug: bool) -> Result<(), Error>
}); });
} }
let _ = instance.launch().await?; instance.launch().await?;
info!("Vaultwarden process exited!"); info!("Vaultwarden process exited!");
Ok(()) Ok(())

8
src/util.rs

@ -213,7 +213,7 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for Cache
}; };
res.set_raw_header("Cache-Control", cache_control_header); res.set_raw_header("Cache-Control", cache_control_header);
let time_now = chrono::Local::now(); let time_now = Local::now();
let expiry_time = time_now + chrono::TimeDelta::try_seconds(self.ttl.try_into().unwrap()).unwrap(); let expiry_time = time_now + chrono::TimeDelta::try_seconds(self.ttl.try_into().unwrap()).unwrap();
res.set_raw_header("Expires", format_datetime_http(&expiry_time)); res.set_raw_header("Expires", format_datetime_http(&expiry_time));
Ok(res) Ok(res)
@ -222,8 +222,8 @@ impl<'r, R: 'r + Responder<'r, 'static> + Send> Responder<'r, 'static> for Cache
pub struct SafeString(String); pub struct SafeString(String);
impl std::fmt::Display for SafeString { impl fmt::Display for SafeString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
} }
@ -612,7 +612,7 @@ impl<'de> Visitor<'de> for LowerCaseVisitor {
fn _process_key(key: &str) -> String { fn _process_key(key: &str) -> String {
match key.to_lowercase().as_ref() { match key.to_lowercase().as_ref() {
"ssn" => "ssn".into(), "ssn" => "ssn".into(),
_ => self::lcase_first(key), _ => lcase_first(key),
} }
} }

Loading…
Cancel
Save