diff options
Diffstat (limited to 'src/token/app.rs')
| -rw-r--r-- | src/token/app.rs | 118 |
1 files changed, 4 insertions, 114 deletions
diff --git a/src/token/app.rs b/src/token/app.rs index a7a843d..fb5d712 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -8,15 +8,9 @@ use sqlx::sqlite::SqlitePool; use super::{ Broadcaster, Event as TokenEvent, Secret, Token, extract::Identity, - repo::{self, Provider as _, auth::Provider as _}, -}; -use crate::{ - clock::DateTime, - db::NotFound as _, - name::{self, Name}, - password::Password, - user::{User, repo::Provider as _}, + repo::{self, Provider as _}, }; +use crate::{clock::DateTime, db::NotFound as _, name}; pub struct Tokens<'a> { db: &'a SqlitePool, @@ -28,100 +22,20 @@ impl<'a> Tokens<'a> { Self { db, token_events } } - pub async fn login( - &self, - name: &Name, - password: &Password, - login_at: &DateTime, - ) -> Result<Secret, LoginError> { - let mut tx = self.db.begin().await?; - let (user, stored_hash) = tx - .auth() - .for_name(name) - .await - .optional()? - .ok_or(LoginError::Rejected)?; - // Split the transaction here to avoid holding the tx open (potentially blocking - // other writes) while we do the fairly expensive task of verifying the - // password. It's okay if the token issuance transaction happens some notional - // amount of time after retrieving the login, as inserting the token will fail - // if the account is deleted during that time. - tx.commit().await?; - - let user = user.as_snapshot().ok_or(LoginError::Rejected)?; - - if stored_hash.verify(password)? { - let mut tx = self.db.begin().await?; - let (token, secret) = Token::generate(&user, login_at); - tx.tokens().create(&token, &secret).await?; - tx.commit().await?; - - Ok(secret) - } else { - Err(LoginError::Rejected) - } - } - - pub async fn change_password( - &self, - user: &User, - password: &Password, - to: &Password, - changed_at: &DateTime, - ) -> Result<Secret, LoginError> { - let mut tx = self.db.begin().await?; - let (user, stored_hash) = tx - .auth() - .for_user(user) - .await - .optional()? - .ok_or(LoginError::Rejected)?; - // Split the transaction here to avoid holding the tx open (potentially blocking - // other writes) while we do the fairly expensive task of verifying the - // password. It's okay if the token issuance transaction happens some notional - // amount of time after retrieving the login, as inserting the token will fail - // if the account is deleted during that time. - tx.commit().await?; - - if !stored_hash.verify(password)? { - return Err(LoginError::Rejected); - } - - let user_snapshot = user.as_snapshot().ok_or(LoginError::Rejected)?; - let to_hash = to.hash()?; - - let mut tx = self.db.begin().await?; - tx.users().set_password(&user, &to_hash).await?; - - let tokens = tx.tokens().revoke_all(&user).await?; - let (token, secret) = Token::generate(&user_snapshot, changed_at); - tx.tokens().create(&token, &secret).await?; - - tx.commit().await?; - - for event in tokens.into_iter().map(TokenEvent::Revoked) { - self.token_events.broadcast(event); - } - - Ok(secret) - } - pub async fn validate( &self, secret: &Secret, used_at: &DateTime, ) -> Result<Identity, ValidateError> { let mut tx = self.db.begin().await?; - let (token, user) = tx + let (token, login) = tx .tokens() .validate(secret, used_at) .await .not_found(|| ValidateError::InvalidToken)?; tx.commit().await?; - let user = user.as_snapshot().ok_or(ValidateError::LoginDeleted)?; - - Ok(Identity { token, user }) + Ok(Identity { token, login }) } pub async fn limit_stream<S, E>( @@ -208,33 +122,9 @@ impl<'a> Tokens<'a> { } #[derive(Debug, thiserror::Error)] -pub enum LoginError { - #[error("invalid login")] - Rejected, - #[error(transparent)] - Database(#[from] sqlx::Error), - #[error(transparent)] - Name(#[from] name::Error), - #[error(transparent)] - PasswordHash(#[from] password_hash::Error), -} - -impl From<repo::auth::LoadError> for LoginError { - fn from(error: repo::auth::LoadError) -> Self { - use repo::auth::LoadError; - match error { - LoadError::Database(error) => error.into(), - LoadError::Name(error) => error.into(), - } - } -} - -#[derive(Debug, thiserror::Error)] pub enum ValidateError { #[error("invalid token")] InvalidToken, - #[error("user deleted")] - LoginDeleted, #[error(transparent)] Database(#[from] sqlx::Error), #[error(transparent)] |
