Browse Source

Merge 3a4a2aecb6 into 07569a06da

pull/6484/merge
Rene Leonhardt 3 days ago
committed by GitHub
parent
commit
4446ec4d67
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      src/api/admin.rs
  2. 14
      src/api/core/accounts.rs
  3. 7
      src/api/core/ciphers.rs
  4. 166
      src/api/core/emergency_access.rs
  5. 7
      src/api/core/events.rs
  6. 7
      src/api/core/sends.rs
  7. 7
      src/api/core/two_factor/duo_oidc.rs
  8. 13
      src/auth.rs
  9. 19
      src/db/models/sso_nonce.rs
  10. 7
      src/util.rs

13
src/api/admin.rs

@ -716,13 +716,14 @@ async fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> A
let web_vault_version = get_web_vault_version(); let web_vault_version = get_web_vault_version();
// Check if the running version is newer than the latest stable released 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}")) { let web_vault_pre_release = match semver::VersionReq::parse(&format!(">{latest_web_build}")) {
web_ver_match.matches( Ok(web_ver_match) => web_ver_match.matches(
&semver::Version::parse(&web_vault_version).unwrap_or_else(|_| semver::Version::parse("2025.1.1").unwrap()), &semver::Version::parse(&web_vault_version).unwrap_or_else(|_| semver::Version::parse("2025.1.1").unwrap()),
) ),
} else { Err(_) => {
error!("Unable to parse latest_web_build: '{latest_web_build}'"); error!("Unable to parse latest_web_build: '{latest_web_build}'");
false false
}
}; };
let diagnostics_json = json!({ let diagnostics_json = json!({

14
src/api/core/accounts.rs

@ -324,8 +324,11 @@ pub async fn _register(data: Json<RegisterData>, email_verification: bool, conn:
error!("Error sending welcome email: {e:#?}"); error!("Error sending welcome email: {e:#?}");
} }
user.last_verifying_at = Some(user.created_at); user.last_verifying_at = Some(user.created_at);
} else if let Err(e) = mail::send_welcome(&user.email).await { } else {
error!("Error sending welcome email: {e:#?}"); 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 { if email_verified && is_email_2fa_required(data.organization_user_id, &conn).await {
@ -1692,9 +1695,8 @@ async fn get_auth_requests_pending(headers: Headers, conn: DbConn) -> JsonResult
pub async fn purge_auth_requests(pool: DbPool) { pub async fn purge_auth_requests(pool: DbPool) {
debug!("Purging auth requests"); debug!("Purging auth requests");
if let Ok(conn) = pool.get().await { match pool.get().await {
AuthRequest::purge_expired_auth_requests(&conn).await; Ok(conn) => AuthRequest::purge_expired_auth_requests(&conn).await,
} else { Err(_) => error!("Failed to get DB connection while purging trashed ciphers"),
error!("Failed to get DB connection while purging trashed ciphers")
} }
} }

7
src/api/core/ciphers.rs

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

166
src/api/core/emergency_access.rs

@ -721,52 +721,51 @@ pub async fn emergency_request_timeout_job(pool: DbPool) {
return; return;
} }
if let Ok(conn) = pool.get().await { let Ok(conn) = pool.get().await else {
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await; error!("Failed to get DB connection while searching emergency request timed out");
return;
};
if emergency_access_list.is_empty() { let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;
debug!("No emergency request timeout to approve");
} if emergency_access_list.is_empty() {
debug!("No emergency request timeout to approve");
}
let now = Utc::now().naive_utc(); let now = Utc::now().naive_utc();
for mut emer in emergency_access_list { for mut emer in emergency_access_list {
// The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None) // The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
let recovery_allowed_at = let recovery_allowed_at =
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days)).unwrap(); emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days)).unwrap();
if recovery_allowed_at.le(&now) { if recovery_allowed_at.le(&now) {
// Only update the access status // Only update the access status
// Updating the whole record could cause issues when the emergency_notification_reminder_job is also active // 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) 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 .await
.expect("Unable to update emergency access status"); .expect("Grantee user not found");
if CONFIG.mail_enabled() { mail::send_emergency_access_recovery_timed_out(
// get grantor user to send Accepted email &grantor_user.email,
let grantor_user = &grantee_user.name,
User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found"); emer.get_type_as_str(),
)
// get grantee user to send Accepted email .await
let grantee_user = .expect("Error on sending email");
User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name)
.expect("Grantee user not found");
mail::send_emergency_access_recovery_timed_out(
&grantor_user.email,
&grantee_user.name,
emer.get_type_as_str(),
)
.await .await
.expect("Error on sending email"); .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")
} }
} }
@ -776,55 +775,54 @@ pub async fn emergency_notification_reminder_job(pool: DbPool) {
return; return;
} }
if let Ok(conn) = pool.get().await { let Ok(conn) = pool.get().await else {
let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await; error!("Failed to get DB connection while searching emergency request timed out");
return;
};
if emergency_access_list.is_empty() { let emergency_access_list = EmergencyAccess::find_all_recoveries_initiated(&conn).await;
debug!("No emergency request reminder notification to send");
}
let now = Utc::now().naive_utc(); if emergency_access_list.is_empty() {
for mut emer in emergency_access_list { debug!("No emergency request reminder notification to send");
// 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 = let now = Utc::now().naive_utc();
emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days - 1)).unwrap(); for mut emer in emergency_access_list {
// Calculate if a day has passed since the previous notification, else no notification has been sent before // The find_all_recoveries_initiated already checks if the recovery_initiated_at is not null (None)
let next_recovery_reminder_at = if let Some(last_notification_at) = emer.last_notification_at { // Calculate the day before the recovery will become active
last_notification_at + TimeDelta::try_days(1).unwrap() let final_recovery_reminder_at =
} else { emer.recovery_initiated_at.unwrap() + TimeDelta::try_days(i64::from(emer.wait_time_days - 1)).unwrap();
now // 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 {
if final_recovery_reminder_at.le(&now) && next_recovery_reminder_at.le(&now) { last_notification_at + TimeDelta::try_days(1).unwrap()
// Only update the last notification date } else {
// Updating the whole record could cause issues when the emergency_request_timeout_job is also active now
emer.update_last_notification_date_and_save(&now, &conn) };
.await if final_recovery_reminder_at.le(&now) && next_recovery_reminder_at.le(&now) {
.expect("Unable to update emergency access notification date"); // Only update the last notification date
// Updating the whole record could cause issues when the emergency_request_timeout_job is also active
if CONFIG.mail_enabled() { emer.update_last_notification_date_and_save(&now, &conn)
// get grantor user to send Accepted email .await
let grantor_user = .expect("Unable to update emergency access notification date");
User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");
if CONFIG.mail_enabled() {
// get grantee user to send Accepted email // get grantor user to send Accepted email
let grantee_user = let grantor_user = User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect("Grantor user not found");
User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
.await // get grantee user to send Accepted email
.expect("Grantee user not found"); let grantee_user = User::find_by_uuid(&emer.grantee_uuid.clone().expect("Grantee user invalid"), &conn)
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 .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
src/api/core/events.rs

@ -335,9 +335,8 @@ pub async fn event_cleanup_job(pool: DbPool) {
return; return;
} }
if let Ok(conn) = pool.get().await { match pool.get().await {
Event::clean_events(&conn).await.ok(); Ok(conn) => Event::clean_events(&conn).await.ok().unwrap_or(()),
} else { Err(_) => error!("Failed to get DB connection while trying to cleanup the events table"),
error!("Failed to get DB connection while trying to cleanup the events table")
} }
} }

7
src/api/core/sends.rs

@ -60,10 +60,9 @@ pub fn routes() -> Vec<rocket::Route> {
pub async fn purge_sends(pool: DbPool) { pub async fn purge_sends(pool: DbPool) {
debug!("Purging sends"); debug!("Purging sends");
if let Ok(conn) = pool.get().await { match pool.get().await {
Send::purge(&conn).await; Ok(conn) => Send::purge(&conn).await,
} else { Err(_) => error!("Failed to get DB connection while purging sends"),
error!("Failed to get DB connection while purging sends")
} }
} }

7
src/api/core/two_factor/duo_oidc.rs

@ -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. // Task to clean up expired Duo authentication contexts that may have accumulated in the database.
pub async fn purge_duo_contexts(pool: DbPool) { pub async fn purge_duo_contexts(pool: DbPool) {
debug!("Purging Duo authentication contexts"); debug!("Purging Duo authentication contexts");
if let Ok(conn) = pool.get().await { match pool.get().await {
TwoFactorDuoContext::purge_expired_duo_contexts(&conn).await; Ok(conn) => TwoFactorDuoContext::purge_expired_duo_contexts(&conn).await,
} else { Err(_) => error!("Failed to get DB connection while purging expired Duo authentications"),
error!("Failed to get DB connection while purging expired Duo authentications")
} }
} }

13
src/auth.rs

@ -700,15 +700,10 @@ impl<'r> FromRequest<'r> for OrgHeaders {
// org_id is usually the second path param ("/organizations/<org_id>"), // org_id is usually the second path param ("/organizations/<org_id>"),
// but there are cases where it is a query value. // 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. // First check the path, if this is not a valid uuid, try the query values.
let url_org_id: Option<OrganizationId> = { let url_org_id: Option<OrganizationId> = request
if let Some(Ok(org_id)) = request.param::<OrganizationId>(1) { .param::<OrganizationId>(1)
Some(org_id) .and_then(|r| r.ok())
} else if let Some(Ok(org_id)) = request.query_value::<OrganizationId>("organizationId") { .or_else(|| request.query_value("organizationId").and_then(|r| r.ok()));
Some(org_id)
} else {
None
}
};
match url_org_id { match url_org_id {
Some(org_id) if uuid::Uuid::parse_str(&org_id).is_ok() => { Some(org_id) if uuid::Uuid::parse_str(&org_id).is_ok() => {

19
src/db/models/sso_nonce.rs

@ -73,15 +73,14 @@ impl SsoNonce {
pub async fn delete_expired(pool: DbPool) -> EmptyResult { pub async fn delete_expired(pool: DbPool) -> EmptyResult {
debug!("Purging expired sso_nonce"); debug!("Purging expired sso_nonce");
if let Ok(conn) = pool.get().await { let Ok(conn) = pool.get().await else {
let oldest = Utc::now().naive_utc() - *NONCE_EXPIRATION; err!("Failed to get DB connection while purging expired sso_nonce");
db_run! { conn: { };
diesel::delete(sso_nonce::table.filter(sso_nonce::created_at.lt(oldest))) let oldest = Utc::now().naive_utc() - *NONCE_EXPIRATION;
.execute(conn) db_run! { conn: {
.map_res("Error deleting expired SSO nonce") diesel::delete(sso_nonce::table.filter(sso_nonce::created_at.lt(oldest)))
}} .execute(conn)
} else { .map_res("Error deleting expired SSO nonce")
err!("Failed to get DB connection while purging expired sso_nonce") }}
}
} }
} }

7
src/util.rs

@ -375,10 +375,9 @@ where
S: AsRef<str>, S: AsRef<str>,
T: FromStr, T: FromStr,
{ {
if let Some(Ok(value)) = string.map(|s| s.as_ref().parse::<T>()) { match string.map(|s| s.as_ref().parse::<T>()) {
Some(value) Some(Ok(value)) => Some(value),
} else { _ => None,
None
} }
} }

Loading…
Cancel
Save