diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-09-18 01:27:47 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-09-18 12:17:46 -0400 |
| commit | cce6662d635bb2115f9f2a7bab92cc105166e761 (patch) | |
| tree | 9d1edfea364a3b72cf40c78d67ce05e3e68c84df /src/login/app.rs | |
| parent | 921f38a73e5d58a5a6077477a8b52d2705798f55 (diff) | |
App methods now return errors that allow not-found cases to be distinguished.
Diffstat (limited to 'src/login/app.rs')
| -rw-r--r-- | src/login/app.rs | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/src/login/app.rs b/src/login/app.rs index aec072c..f0e0571 100644 --- a/src/login/app.rs +++ b/src/login/app.rs @@ -3,9 +3,9 @@ use sqlx::sqlite::SqlitePool; use super::repo::auth::Provider as _; use crate::{ clock::DateTime, - error::BoxedError, password::StoredHash, repo::{ + error::NotFound as _, login::{Login, Provider as _}, token::Provider as _, }, @@ -25,7 +25,7 @@ impl<'a> Logins<'a> { name: &str, password: &str, login_at: DateTime, - ) -> Result<Option<String>, BoxedError> { + ) -> Result<String, LoginError> { let mut tx = self.db.begin().await?; let login = if let Some((login, stored_hash)) = tx.auth().for_name(name).await? { @@ -41,39 +41,53 @@ impl<'a> Logins<'a> { Some(tx.logins().create(name, &password_hash).await?) }; - // If `login` is Some, then we have an identity and can issue a token. - // If `login` is None, then neither creating a new login nor - // authenticating an existing one succeeded, and we must reject the - // login attempt. - let token = if let Some(login) = login { - Some(tx.tokens().issue(&login, login_at).await?) - } else { - None - }; - + let login = login.ok_or(LoginError::Rejected)?; + let token = tx.tokens().issue(&login, login_at).await?; tx.commit().await?; Ok(token) } - pub async fn validate( - &self, - secret: &str, - used_at: DateTime, - ) -> Result<Option<Login>, BoxedError> { + pub async fn validate(&self, secret: &str, used_at: DateTime) -> Result<Login, ValidateError> { let mut tx = self.db.begin().await?; tx.tokens().expire(used_at).await?; - let login = tx.tokens().validate(secret, used_at).await?; + let login = tx + .tokens() + .validate(secret, used_at) + .await + .not_found(|| ValidateError::InvalidToken)?; tx.commit().await?; Ok(login) } - pub async fn logout(&self, secret: &str) -> Result<(), BoxedError> { + pub async fn logout(&self, secret: &str) -> Result<(), ValidateError> { let mut tx = self.db.begin().await?; - tx.tokens().revoke(secret).await?; + tx.tokens() + .revoke(secret) + .await + .not_found(|| ValidateError::InvalidToken)?; + tx.commit().await?; Ok(()) } } + +#[derive(Debug, thiserror::Error)] +pub enum LoginError { + #[error("invalid login")] + Rejected, + #[error("database error: {0}")] + DatabaseError(#[from] sqlx::Error), + #[error("password hash error: {0}")] + PasswordHashError(#[from] password_hash::Error), +} + +#[derive(Debug, thiserror::Error)] +pub enum ValidateError { + #[error("invalid token")] + InvalidToken, + #[error("database error: {0}")] + DatabaseError(#[from] sqlx::Error), +} |
