use axum::extract::FromRef;
use slave_framework::database::Db;
use crate::base::error::{AppError, AppResult};
use crate::base::state::AppState;
use crate::modules::user::models::user::User;
/// Business rules for managing user accounts.
#[derive(Debug, Clone)]
pub struct UserService {
db: Db,
}
impl FromRef<AppState> for UserService {
fn from_ref(state: &AppState) -> Self {
Self {
db: state.db.clone(),
}
}
}
impl UserService {
pub async fn list(&self) -> AppResult<Vec<User>> {
let users: Vec<User> = self
.db
.query(format!("SELECT {} FROM user ORDER BY id", User::FIELDS))
.await?
.take(0)?;
Ok(users)
}
pub async fn find(&self, id: i64) -> AppResult<User> {
let user: Option<User> = self
.db
.query(format!(
"SELECT {} FROM type::record('user', $id)",
User::FIELDS
))
.bind(("id", id))
.await?
.take(0)?;
user.ok_or_else(|| AppError::NotFound(format!("user {id}")))
}
/// Deletes `id` on behalf of `acting_user_id`, who may not delete
/// themselves. Their roles and memberships are deleted with them.
pub async fn delete(&self, id: i64, acting_user_id: i64) -> AppResult<()> {
if id == acting_user_id {
return Err(AppError::Conflict(
"you cannot delete your own account".into(),
));
}
self.find(id).await?;
self.db
.query("DELETE type::record('user', $id)")
.bind(("id", id))
.await?
.check()?;
Ok(())
}
}