lyrs/src/state.rs

77 lines
1.7 KiB
Rust
Raw Normal View History

2024-05-17 13:55:16 -05:00
use crate::{
db::{self, Data},
prelude::*,
user::{self, User},
2024-05-17 13:55:16 -05:00
};
use axum::async_trait;
use axum_login::{AuthnBackend, UserId};
use redact::Secret;
use serde::Deserialize;
2024-05-17 12:00:37 -05:00
use thiserror::Error;
2024-05-14 12:28:27 -05:00
#[derive(Clone)]
pub struct State {
2024-05-20 11:35:39 -05:00
pub db: Data,
2024-05-14 12:28:27 -05:00
}
impl State {
2024-05-20 11:35:39 -05:00
pub async fn try_new() -> Result<Self, NewStateError> {
2024-05-17 12:00:37 -05:00
Ok(Self {
2024-05-20 11:35:39 -05:00
db: Data::try_new()?,
2024-05-17 12:00:37 -05:00
})
2024-05-14 12:28:27 -05:00
}
}
2024-05-15 16:48:23 -05:00
#[derive(Error, Debug)]
pub enum NewStateError {
2024-05-17 12:00:37 -05:00
#[error("database error: {0}")]
2024-05-20 11:35:39 -05:00
Database(#[from] db::Error),
2024-05-15 16:48:23 -05:00
}
#[derive(Deserialize, Debug, Clone)]
pub struct Creds {
pub username: String,
pub password: Secret<String>,
}
#[derive(Error, Debug)]
pub enum AuthError {
#[error("user error: {0}")]
User(#[from] user::Error),
#[error("data error: {0}")]
Db(#[from] db::Error),
#[error("data error: {0}")]
Argon2(#[from] argon2::password_hash::Error),
}
#[async_trait]
impl AuthnBackend for State {
type User = User;
type Credentials = Creds;
type Error = AuthError;
async fn authenticate(
&self,
Creds { username, password }: Self::Credentials,
) -> Result<Option<Self::User>, Self::Error> {
if let Some(user) = self.db.get::<String, User>(User::tree(), username)? {
if let Err(err) = user.verify(password.expose_secret()) {
Err(err.into())
} else {
Ok(Some(user))
}
} else {
Ok(None)
}
}
async fn get_user(&self, username: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {
match self.db.get::<&str, User>(User::tree(), username)? {
Some(user) => Ok(Some(user)),
None => Ok(None),
}
}
}