diff --git a/src/api/identity.rs b/src/api/identity.rs index 2b1ddfb1..b09382ad 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -30,7 +30,7 @@ use crate::{ db::{ DbConn, models::{ - AuthRequest, AuthRequestId, Device, DeviceId, EventType, Invitation, OIDCCodeResponseError, + AuthRequest, AuthRequestId, Device, DeviceId, DeviceType, EventType, Invitation, OIDCCodeResponseError, OrganizationApiKey, OrganizationId, SendId, SsoAuth, SsoUser, TwoFactor, TwoFactorIncomplete, TwoFactorType, User, UserId, }, @@ -507,6 +507,39 @@ async fn password_login( authenticated_response(&user, &mut device, auth_tokens, twofactor_token, conn, ip).await } +async fn send_new_device_email(user: &User, device: &Device, ip: &ClientIp) -> EmptyResult { + if !CONFIG.mail_enabled() || !device.is_new() { + return Ok(()); + } + + let now = Utc::now().naive_utc(); + let device_type = DeviceType::from_i32(device.atype); + + if CONFIG.require_device_email() { + if let Err(e) = + mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device.name, device_type).await + { + error!("Error sending new device email: {e:#?}"); + err!( + "Could not send login notification email. Please contact your administrator.", + ErrorEvent { + event: EventType::UserFailedLogIn + } + ) + } + return Ok(()); + } + + let (address, ip, device_name) = (user.email.clone(), ip.ip.to_string(), device.name.clone()); + tokio::task::spawn(async move { + if let Err(e) = mail::send_new_device_logged_in(&address, &ip, &now, &device_name, device_type).await { + error!("Error sending new device email: {e:#?}"); + } + }); + + Ok(()) +} + async fn authenticated_response( user: &User, device: &mut Device, @@ -515,21 +548,7 @@ async fn authenticated_response( conn: &DbConn, ip: &ClientIp, ) -> JsonResult { - if CONFIG.mail_enabled() && device.is_new() { - let now = Utc::now().naive_utc(); - if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, device).await { - error!("Error sending new device email: {e:#?}"); - - if CONFIG.require_device_email() { - err!( - "Could not send login notification email. Please contact your administrator.", - ErrorEvent { - event: EventType::UserFailedLogIn - } - ) - } - } - } + send_new_device_email(user, device, ip).await?; // register push device if !device.is_new() { @@ -663,21 +682,7 @@ async fn user_api_key_login( let mut device = get_device(&data, conn, &user).await?; - if CONFIG.mail_enabled() && device.is_new() { - let now = Utc::now().naive_utc(); - if let Err(e) = mail::send_new_device_logged_in(&user.email, &ip.ip.to_string(), &now, &device).await { - error!("Error sending new device email: {e:#?}"); - - if CONFIG.require_device_email() { - err!( - "Could not send login notification email. Please contact your administrator.", - ErrorEvent { - event: EventType::UserFailedLogIn - } - ) - } - } - } + send_new_device_email(&user, &device, ip).await?; // --- // Disabled this variable, it was used to generate the JWT diff --git a/src/mail.rs b/src/mail.rs index a7e5e5ae..8b3b96d2 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -17,7 +17,7 @@ use crate::{ encode_jwt, generate_delete_claims, generate_emergency_access_invite_claims, generate_invite_claims, generate_verify_email_claims, }, - db::models::{Device, DeviceType, EmergencyAccessId, MembershipId, OrganizationId, User, UserId}, + db::models::{DeviceType, EmergencyAccessId, MembershipId, OrganizationId, User, UserId}, error::Error, util::upcase_first, }; @@ -514,7 +514,13 @@ pub async fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult send_email(address, &subject, body_html, body_text).await } -pub async fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTime, device: &Device) -> EmptyResult { +pub async fn send_new_device_logged_in( + address: &str, + ip: &str, + dt: &NaiveDateTime, + device_name: &str, + device_type: DeviceType, +) -> EmptyResult { let fmt = "%A, %B %_d, %Y at %r %Z"; let (subject, body_html, body_text) = get_text( "email/new_device_logged_in", @@ -522,8 +528,8 @@ pub async fn send_new_device_logged_in(address: &str, ip: &str, dt: &NaiveDateTi "url": CONFIG.domain(), "img_src": CONFIG._smtp_img_src(), "ip": ip, - "device_name": upcase_first(&device.name), - "device_type": DeviceType::from_i32(device.atype).to_string(), + "device_name": upcase_first(device_name), + "device_type": device_type.to_string(), "datetime": crate::util::format_naive_datetime_local(dt, fmt), }), )?;