Compare commits

...

2 Commits

3 changed files with 51 additions and 6 deletions

View File

@ -93,7 +93,7 @@ impl Account {
Err(e) => Err(Error::new(e)), Err(e) => Err(Error::new(e)),
} }
} }
pub async fn from_email(pool: &MySqlPool, email: &String) -> Result<Option<Self>> { pub async fn from_email(pool: &MySqlPool, email: &String) -> Result<Option<Self>> {
match sqlx::query!(r#"SELECT * FROM Accounts WHERE email = ?;"#, email) match sqlx::query!(r#"SELECT * FROM Accounts WHERE email = ?;"#, email)
.fetch_one(pool) .fetch_one(pool)
@ -115,4 +115,14 @@ impl Account {
Err(e) => Err(Error::new(e)), Err(e) => Err(Error::new(e)),
} }
} }
pub async fn check_password(&self, password: String) -> Result<bool> {
let hash = PasswordHash::new(self.password.as_str())
.map_err(|_| anyhow::Error::msg("Failed to parse the password hash"))?;
match Pbkdf2.verify_password(password.as_bytes(), &hash) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}
} }

View File

@ -33,7 +33,10 @@ pub async fn register(
return Ok(data::RegisterResponse::Blocked); return Ok(data::RegisterResponse::Blocked);
} }
if Account::from_username(pool, &request.username).await?.is_some() { if Account::from_username(pool, &request.username)
.await?
.is_some()
{
return Ok(data::RegisterResponse::Conflict( return Ok(data::RegisterResponse::Conflict(
data::RegisterConflict::Username, data::RegisterConflict::Username,
)); ));
@ -59,7 +62,10 @@ pub async fn register(
SmtpClientBuilder::new(&std::env::var("SMTP_HOST_URL")?, 465) SmtpClientBuilder::new(&std::env::var("SMTP_HOST_URL")?, 465)
.implicit_tls(true) .implicit_tls(true)
.credentials(mail_send::Credentials::Plain { username: &std::env::var("SMTP_USER")?, secret: &std::env::var("SMTP_PASSWORD")? }) .credentials(mail_send::Credentials::Plain {
username: &std::env::var("SMTP_USER")?,
secret: &std::env::var("SMTP_PASSWORD")?,
})
.connect() .connect()
.await? .await?
.send(message) .send(message)
@ -78,6 +84,13 @@ pub async fn verify(
return Ok(data::VerifyResponse::Blocked); return Ok(data::VerifyResponse::Blocked);
} }
let token = match VerificationToken::check(pool, request.token).await? {
Some(t) => t,
None => return Ok(data::VerifyResponse::TokenUnknown),
};
token.apply(pool).await?;
Ok(data::VerifyResponse::Success) Ok(data::VerifyResponse::Success)
} }
@ -89,10 +102,19 @@ pub async fn authenticate(
return Ok(data::AuthenticateResponse::Blocked); return Ok(data::AuthenticateResponse::Blocked);
} }
let account = match Account::from_username(pool, &request.username).await? {
Some(a) => a,
None => return Ok(data::AuthenticateResponse::UserNotFound),
};
if !account.check_password(request.password).await? {
return Ok(data::AuthenticateResponse::WrongPassword);
}
let token = AuthToken::new(pool, account.id, chrono::Duration::days(7)).await?;
Ok(data::AuthenticateResponse::Success( Ok(data::AuthenticateResponse::Success(
data::AuthenticateSuccess { data::AuthenticateSuccess { token: token.token },
token: "not_a_valid_token".to_string(),
},
)) ))
} }

View File

@ -1,3 +1,4 @@
use crate::accounts::Account;
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use sqlx::{mysql::MySqlPool, types::chrono as sqlx_chrono}; use sqlx::{mysql::MySqlPool, types::chrono as sqlx_chrono};
@ -159,4 +160,16 @@ impl VerificationToken {
Err(e) => Err(Error::new(e)), Err(e) => Err(Error::new(e)),
} }
} }
pub async fn apply(&self, pool: &MySqlPool) -> Result<()> {
sqlx::query!(r#"DELETE FROM VerificationTokens WHERE token = ?;"#, self.token)
.execute(pool)
.await?;
sqlx::query!(r#"UPDATE Accounts SET verified=true WHERE id = ?;"#, self.account)
.execute(pool)
.await?;
Ok(())
}
} }