summaryrefslogtreecommitdiff
path: root/src/login/app.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/login/app.rs')
-rw-r--r--src/login/app.rs54
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),
+}