89 lines
2.9 KiB
Rust
89 lines
2.9 KiB
Rust
use dioxus::prelude::*;
|
|
|
|
use crate::models::user::{User, UserCredentials};
|
|
use crate::util::error::Result;
|
|
|
|
cfg_if::cfg_if! {
|
|
if #[cfg(feature = "server")] {
|
|
|
|
use dioxus::server::axum::Extension;
|
|
|
|
use crate::server::{auth::{AuthSession, create_user}, config::Config, database::DbPool};
|
|
use crate::util::error::{AuthError, Contextualize, Error, ErrorType};
|
|
|
|
}
|
|
}
|
|
|
|
#[post("/api/v1/auth/signup", mut auth: Extension<AuthSession>, db_pool: Extension<DbPool>, config: Extension<Config>)]
|
|
pub async fn signup(credentials: UserCredentials) -> Result<User> {
|
|
if !config.auth.open_signup {
|
|
return Err(Error::message_here("Signup is disabled"));
|
|
}
|
|
|
|
// Don't allow signup when already logged in
|
|
if auth.user.is_some() {
|
|
return Err(Error::message_here("Log out before creating an account"));
|
|
}
|
|
|
|
let hashed_creds = credentials
|
|
.try_hash()
|
|
.map_err(|e| Error::message_here(e.to_string()))
|
|
.err_context("Error hashing new user credentials")?;
|
|
|
|
let mut db_conn = db_pool
|
|
.get()
|
|
.await
|
|
.err_context("Failed to get database pool connection")?;
|
|
|
|
let new_user = create_user(&mut db_conn, &hashed_creds)
|
|
.await
|
|
.err_context("Error creating user")?;
|
|
|
|
// Don't return this to the client, logging in immediately isn't strictly necessary
|
|
if let Err(e) = auth.login(&new_user).await {
|
|
tracing::warn!("Failed to log in user after creating: {e}");
|
|
}
|
|
|
|
Ok(new_user.into())
|
|
}
|
|
|
|
#[post("/api/v1/auth/login", mut auth: Extension<AuthSession>)]
|
|
pub async fn login(credentials: UserCredentials) -> Result<User> {
|
|
let db_user = match auth.authenticate(credentials).await {
|
|
Ok(Some(db_user)) => Ok(db_user),
|
|
Ok(None) => Err(Error::new_here(ErrorType::Auth(
|
|
AuthError::InvalidCredentials,
|
|
))),
|
|
Err(axum_login::Error::Session(e)) => Err(Error::new_here(ErrorType::Auth(
|
|
AuthError::Error(format!("Session error: {e}")),
|
|
))),
|
|
Err(axum_login::Error::Backend(e)) => Err(e),
|
|
}
|
|
.err_context("Error authenticating")?;
|
|
|
|
auth.login(&db_user)
|
|
.await
|
|
.map_err(|e| Error::new_here(ErrorType::Auth(AuthError::Error(e.to_string()))))
|
|
.err_context("Error logging in")?;
|
|
|
|
Ok(db_user.into())
|
|
}
|
|
|
|
#[post("/api/v1/auth/logout", mut auth: Extension<AuthSession>)]
|
|
pub async fn logout() -> Result<()> {
|
|
match auth.logout().await {
|
|
Ok(_) => Ok(()),
|
|
Err(axum_login::Error::Session(e)) => Err(Error::new_here(ErrorType::Auth(
|
|
AuthError::Error(format!("Session error: {e}")),
|
|
))),
|
|
Err(axum_login::Error::Backend(e)) => Err(e),
|
|
}
|
|
.err_context("Error logging out")
|
|
}
|
|
|
|
/// Retrieve the currently logged-in user, or `None` if unauthenticated
|
|
#[get("/api/v1/auth/user", auth: Extension<AuthSession>)]
|
|
pub async fn get_user() -> Result<Option<User>> {
|
|
Ok(auth.user.clone().map(Into::into))
|
|
}
|