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();
// 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!({

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:#?}");
}
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 {
@ -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
src/api/core/ciphers.rs

@ -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"),
}
}

166
src/api/core/emergency_access.rs

@ -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")
}
}
@ -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
src/api/core/events.rs

@ -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
src/api/core/sends.rs

@ -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"),
}
}

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.
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"),
}
}

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>"),
// 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() => {

19
src/db/models/sso_nonce.rs

@ -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
src/util.rs

@ -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,
}
}

Loading…
Cancel
Save