Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/api/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,13 +731,14 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
let web_vault_version = get_web_vault_version();

// Check if the running version is newer than the latest stable released version
let web_vault_pre_release = if let Ok(web_ver_match) = semver::VersionReq::parse(&format!(">{latest_web_build}")) {
web_ver_match.matches(
let web_vault_pre_release = match semver::VersionReq::parse(&format!(">{latest_web_build}")) {
Ok(web_ver_match) => web_ver_match.matches(
&semver::Version::parse(&web_vault_version).unwrap_or_else(|_| semver::Version::parse("2025.1.1").unwrap()),
)
} else {
error!("Unable to parse latest_web_build: '{latest_web_build}'");
false
),
Err(_) => {
error!("Unable to parse latest_web_build: '{latest_web_build}'");
false
}
};

let diagnostics_json = json!({
Expand Down
14 changes: 8 additions & 6 deletions src/api/core/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,11 @@ pub async fn _register(data: Json<RegisterData>, email_verification: bool, conn:
error!("Error sending welcome email: {e:#?}");
}
user.last_verifying_at = Some(user.created_at);
} else if let Err(e) = mail::send_welcome(&user.email).await {
error!("Error sending welcome email: {e:#?}");
} else {
match mail::send_welcome(&user.email).await {
Err(e) => error!("Error sending welcome email: {e:#?}"),
Ok(_) => (),
}
}

if email_verified && is_email_2fa_required(data.organization_user_id, &conn).await {
Expand Down Expand Up @@ -1692,9 +1695,8 @@ async fn get_auth_requests_pending(headers: Headers, conn: DbConn) -> JsonResult

pub async fn purge_auth_requests(pool: DbPool) {
debug!("Purging auth requests");
if let Ok(conn) = pool.get().await {
AuthRequest::purge_expired_auth_requests(&conn).await;
} else {
error!("Failed to get DB connection while purging trashed ciphers")
match pool.get().await {
Ok(conn) => AuthRequest::purge_expired_auth_requests(&conn).await,
Err(_) => error!("Failed to get DB connection while purging trashed ciphers"),
}
}
7 changes: 3 additions & 4 deletions src/api/core/ciphers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ pub fn routes() -> Vec<Route> {

pub async fn purge_trashed_ciphers(pool: DbPool) {
debug!("Purging trashed ciphers");
if let Ok(conn) = pool.get().await {
Cipher::purge_trash(&conn).await;
} else {
error!("Failed to get DB connection while purging trashed ciphers")
match pool.get().await {
Ok(conn) => Cipher::purge_trash(&conn).await,
Err(_) => error!("Failed to get DB connection while purging trashed ciphers"),
}
}

Expand Down
166 changes: 82 additions & 84 deletions src/api/core/emergency_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,52 +721,51 @@ pub async fn emergency_request_timeout_job(pool: DbPool) {
return;
}

if let Ok(conn) = pool.get().await {
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;
let Ok(conn) = pool.get().await else {
error!("Failed to get DB connection while searching emergency request timed out");
return;
};

if emergency_access_list.is_empty() {
debug!("No emergency request timeout to approve");
}
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;

if emergency_access_list.is_empty() {
debug!("No emergency request timeout to approve");
}

let now = Utc::now().naive_utc();
for mut emer in emergency_access_list {
// The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
let recovery_allowed_at =
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days)).unwrap();
if recovery_allowed_at.le(&now) {
// Only update the access status
// Updating the whole record could cause issues when the emergency_notification_reminder_job is also active
emer.update_access_status_and_save(EmergencyAccessStatus::RecoveryApproved as i32, &now, &conn)
let now = Utc::now().naive_utc();
for mut emer in emergency_access_list {
// The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
let recovery_allowed_at =
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days)).unwrap();
if recovery_allowed_at.le(&now) {
// Only update the access status
// Updating the whole record could cause issues when the emergency_notification_reminder_job is also active
emer.update_access_status_and_save(EmergencyAccessStatus::RecoveryApproved as i32, &now, &conn)
.await
.expect("Unable to update emergency access status");

if CONFIG.mail_enabled() {
// get grantor user to send Accepted email
let grantor_user = User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");

// get grantee user to send Accepted email
let grantee_user = User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await
.expect("Unable to update emergency access status");

if CONFIG.mail_enabled() {
// get grantor user to send Accepted email
let grantor_user =
User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");

// get grantee user to send Accepted email
let grantee_user =
User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await
.expect("Grantee user not found");

mail::send_emergency_access_recovery_timed_out(
&grantor_user.email,
&grantee_user.name,
emer.get_type_as_str(),
)
.expect("Grantee user not found");

mail::send_emergency_access_recovery_timed_out(
&grantor_user.email,
&grantee_user.name,
emer.get_type_as_str(),
)
.await
.expect("Error on sending email");

mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name)
.await
.expect("Error on sending email");

mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name)
.await
.expect("Error on sending email");
}
}
}
} else {
error!("Failed to get DB connection while searching emergency request timed out")
}
}

Expand All @@ -776,55 +775,54 @@ pub async fn emergency_notification_reminder_job(pool: DbPool) {
return;
}

if let Ok(conn) = pool.get().await {
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;
let Ok(conn) = pool.get().await else {
error!("Failed to get DB connection while searching emergency request timed out");
return;
};

if emergency_access_list.is_empty() {
debug!("No emergency request reminder notification to send");
}
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;

let now = Utc::now().naive_utc();
for mut emer in emergency_access_list {
// The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
// Calculate the day before the recovery will become active
let final_recovery_reminder_at =
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days - 1)).unwrap();
// Calculate if a day has passed since the previous notification, else no notification has been sent before
let next_recovery_reminder_at = if let Some(last_notification_at) = emer.last_notification_at {
last_notification_at + TimeDelta::try_days(1).unwrap()
} else {
now
};
if final_recovery_reminder_at.le(&now) && next_recovery_reminder_at.le(&now) {
// Only update the last notification date
// Updating the whole record could cause issues when the emergency_request_timeout_job is also active
emer.update_last_notification_date_and_save(&now, &conn)
.await
.expect("Unable to update emergency access notification date");

if CONFIG.mail_enabled() {
// get grantor user to send Accepted email
let grantor_user =
User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");

// get grantee user to send Accepted email
let grantee_user =
User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await
.expect("Grantee user not found");

mail::send_emergency_access_recovery_reminder(
&grantor_user.email,
&grantee_user.name,
emer.get_type_as_str(),
"1", // This notification is only triggered one day before the activation
)
if emergency_access_list.is_empty() {
debug!("No emergency request reminder notification to send");
}

let now = Utc::now().naive_utc();
for mut emer in emergency_access_list {
// The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
// Calculate the day before the recovery will become active
let final_recovery_reminder_at =
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days - 1)).unwrap();
// Calculate if a day has passed since the previous notification, else no notification has been sent before
let next_recovery_reminder_at = if let Some(last_notification_at) = emer.last_notification_at {
last_notification_at + TimeDelta::try_days(1).unwrap()
} else {
now
};
if final_recovery_reminder_at.le(&now) && next_recovery_reminder_at.le(&now) {
// Only update the last notification date
// Updating the whole record could cause issues when the emergency_request_timeout_job is also active
emer.update_last_notification_date_and_save(&now, &conn)
.await
.expect("Unable to update emergency access notification date");

if CONFIG.mail_enabled() {
// get grantor user to send Accepted email
let grantor_user = User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");

// get grantee user to send Accepted email
let grantee_user = User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await
.expect("Error on sending email");
}
.expect("Grantee user not found");

mail::send_emergency_access_recovery_reminder(
&grantor_user.email,
&grantee_user.name,
emer.get_type_as_str(),
"1", // This notification is only triggered one day before the activation
)
.await
.expect("Error on sending email");
}
}
} else {
error!("Failed to get DB connection while searching emergency notification reminder")
}
}
7 changes: 3 additions & 4 deletions src/api/core/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,8 @@ pub async fn event_cleanup_job(pool: DbPool) {
return;
}

if let Ok(conn) = pool.get().await {
Event::clean_events(&conn).await.ok();
} else {
error!("Failed to get DB connection while trying to cleanup the events table")
match pool.get().await {
Ok(conn) => Event::clean_events(&conn).await.ok().unwrap_or(()),
Err(_) => error!("Failed to get DB connection while trying to cleanup the events table"),
}
}
7 changes: 3 additions & 4 deletions src/api/core/sends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,9 @@ pub fn routes() -> Vec<rocket::Route> {

pub async fn purge_sends(pool: DbPool) {
debug!("Purging sends");
if let Ok(conn) = pool.get().await {
Send::purge(&conn).await;
} else {
error!("Failed to get DB connection while purging sends")
match pool.get().await {
Ok(conn) => Send::purge(&conn).await,
Err(_) => error!("Failed to get DB connection while purging sends"),
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/api/core/two_factor/duo_oidc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,9 @@ async fn extract_context(state: &str, conn: &DbConn) -> Option<DuoAuthContext> {
// Task to clean up expired Duo authentication contexts that may have accumulated in the database.
pub async fn purge_duo_contexts(pool: DbPool) {
debug!("Purging Duo authentication contexts");
if let Ok(conn) = pool.get().await {
TwoFactorDuoContext::purge_expired_duo_contexts(&conn).await;
} else {
error!("Failed to get DB connection while purging expired Duo authentications")
match pool.get().await {
Ok(conn) => TwoFactorDuoContext::purge_expired_duo_contexts(&conn).await,
Err(_) => error!("Failed to get DB connection while purging expired Duo authentications"),
}
}

Expand Down
13 changes: 4 additions & 9 deletions src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,15 +700,10 @@ impl<'r> FromRequest<'r> for OrgHeaders {
// org_id is usually the second path param ("/organizations/<org_id>"),
// but there are cases where it is a query value.
// First check the path, if this is not a valid uuid, try the query values.
let url_org_id: Option<OrganizationId> = {
if let Some(Ok(org_id)) = request.param::<OrganizationId>(1) {
Some(org_id)
} else if let Some(Ok(org_id)) = request.query_value::<OrganizationId>("organizationId") {
Some(org_id)
} else {
None
}
};
let url_org_id: Option<OrganizationId> = request
.param::<OrganizationId>(1)
.and_then(|r| r.ok())
.or_else(|| request.query_value("organizationId").and_then(|r| r.ok()));

match url_org_id {
Some(org_id) if uuid::Uuid::parse_str(&org_id).is_ok() => {
Expand Down
19 changes: 9 additions & 10 deletions src/db/models/sso_nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,14 @@ impl SsoNonce {

pub async fn delete_expired(pool: DbPool) -> EmptyResult {
debug!("Purging expired sso_nonce");
if let Ok(conn) = pool.get().await {
let oldest = Utc::now().naive_utc() - *NONCE_EXPIRATION;
db_run! { conn: {
diesel::delete(sso_nonce::table.filter(sso_nonce::created_at.lt(oldest)))
.execute(conn)
.map_res("Error deleting expired SSO nonce")
}}
} else {
err!("Failed to get DB connection while purging expired sso_nonce")
}
let Ok(conn) = pool.get().await else {
err!("Failed to get DB connection while purging expired sso_nonce");
};
let oldest = Utc::now().naive_utc() - *NONCE_EXPIRATION;
db_run! { conn: {
diesel::delete(sso_nonce::table.filter(sso_nonce::created_at.lt(oldest)))
.execute(conn)
.map_res("Error deleting expired SSO nonce")
}}
}
}
7 changes: 3 additions & 4 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,9 @@ where
S: AsRef<str>,
T: FromStr,
{
if let Some(Ok(value)) = string.map(|s| s.as_ref().parse::<T>()) {
Some(value)
} else {
None
match string.map(|s| s.as_ref().parse::<T>()) {
Some(Ok(value)) => Some(value),
_ => None,
}
}

Expand Down
Loading