|
|
|
@ -10,7 +10,7 @@ use crate::{ |
|
|
|
auth::Headers, |
|
|
|
crypto, |
|
|
|
db::{ |
|
|
|
models::{EventType, TwoFactor, TwoFactorType, User, UserId}, |
|
|
|
models::{DeviceId, EventType, TwoFactor, TwoFactorType, User, UserId}, |
|
|
|
DbConn, |
|
|
|
}, |
|
|
|
error::{Error, MapResult}, |
|
|
|
@ -24,10 +24,12 @@ pub fn routes() -> Vec<Route> { |
|
|
|
#[derive(Deserialize)] |
|
|
|
#[serde(rename_all = "camelCase")] |
|
|
|
struct SendEmailLoginData { |
|
|
|
#[serde(alias = "DeviceIdentifier")] |
|
|
|
device_identifier: DeviceId, |
|
|
|
#[serde(alias = "Email")] |
|
|
|
email: String, |
|
|
|
email: Option<String>, |
|
|
|
#[serde(alias = "MasterPasswordHash")] |
|
|
|
master_password_hash: String, |
|
|
|
master_password_hash: Option<String>, |
|
|
|
} |
|
|
|
|
|
|
|
/// User is trying to login and wants to use email 2FA.
|
|
|
|
@ -36,25 +38,36 @@ struct SendEmailLoginData { |
|
|
|
async fn send_email_login(data: Json<SendEmailLoginData>, conn: DbConn) -> EmptyResult { |
|
|
|
let data: SendEmailLoginData = data.into_inner(); |
|
|
|
|
|
|
|
use crate::db::models::User; |
|
|
|
|
|
|
|
// Get the user
|
|
|
|
let Some(user) = User::find_by_mail(&data.email, &conn).await else { |
|
|
|
err!("Username or password is incorrect. Try again.") |
|
|
|
}; |
|
|
|
|
|
|
|
if !CONFIG._enable_email_2fa() { |
|
|
|
err!("Email 2FA is disabled") |
|
|
|
} |
|
|
|
|
|
|
|
// Check password
|
|
|
|
if !user.check_valid_password(&data.master_password_hash) { |
|
|
|
err!("Username or password is incorrect. Try again.") |
|
|
|
} |
|
|
|
// Get the user
|
|
|
|
let user = if let Some(email) = &data.email { |
|
|
|
let Some(master_password_hash) = &data.master_password_hash else { |
|
|
|
err!("No password hash has been submitted.") |
|
|
|
}; |
|
|
|
|
|
|
|
send_token(&user.uuid, &conn).await?; |
|
|
|
let Some(user) = User::find_by_mail(email, &conn).await else { |
|
|
|
err!("Username or password is incorrect. Try again.") |
|
|
|
}; |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
// Check password
|
|
|
|
if !user.check_valid_password(master_password_hash) { |
|
|
|
err!("Username or password is incorrect. Try again.") |
|
|
|
} |
|
|
|
|
|
|
|
user |
|
|
|
} else { |
|
|
|
// SSO login only sends device id, so we get the user by the most recently used device
|
|
|
|
let Some(user) = User::find_by_device(&data.device_identifier, &conn).await else { |
|
|
|
err!("Username or password is incorrect. Try again.") |
|
|
|
}; |
|
|
|
|
|
|
|
user |
|
|
|
}; |
|
|
|
|
|
|
|
send_token(&user.uuid, &conn).await |
|
|
|
} |
|
|
|
|
|
|
|
/// Generate the token, save the data for later verification and send email to user
|
|
|
|
|