Compare commits
4 Commits
04ca8abce9
...
62a7103423
| Author | SHA1 | Date | |
|---|---|---|---|
|
62a7103423
|
|||
|
d028636e43
|
|||
|
7ca7056fac
|
|||
|
ab90cd81f9
|
@@ -8,12 +8,45 @@ if #[cfg(feature = "server")] {
|
|||||||
|
|
||||||
use dioxus::server::axum::Extension;
|
use dioxus::server::axum::Extension;
|
||||||
|
|
||||||
use crate::server::auth::AuthSession;
|
use crate::server::{auth::{AuthSession, create_user}, config::Config, database::DbPool};
|
||||||
use crate::util::error::{AuthError, Contextualize, Error, ErrorType};
|
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::new_here(ErrorType::Auth(AuthError::Unauthorized)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow signup when already logged in
|
||||||
|
if auth.user.is_some() {
|
||||||
|
return Err(Error::new_here(ErrorType::Auth(AuthError::Unauthorized)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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>)]
|
#[post("/api/v1/auth/login", mut auth: Extension<AuthSession>)]
|
||||||
pub async fn login(credentials: UserCredentials) -> Result<User> {
|
pub async fn login(credentials: UserCredentials) -> Result<User> {
|
||||||
let db_user = match auth.authenticate(credentials).await {
|
let db_user = match auth.authenticate(credentials).await {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use diesel::prelude::*;
|
|||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use tower_sessions_redis_store::RedisStore;
|
use tower_sessions_redis_store::RedisStore;
|
||||||
|
|
||||||
use crate::models::user::{DbUser, UserCredentials};
|
use crate::models::user::{DbUser, HashedUserCredentials, UserCredentials};
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
database::{DbConn, DbPool},
|
database::{DbConn, DbPool},
|
||||||
key_val_store::KeyValPool,
|
key_val_store::KeyValPool,
|
||||||
@@ -76,6 +76,17 @@ impl AuthnBackend for AuthBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn create_user(
|
||||||
|
db_conn: &mut DbConn,
|
||||||
|
credentials: &HashedUserCredentials,
|
||||||
|
) -> Result<DbUser> {
|
||||||
|
diesel::insert_into(crate::schema::users::table)
|
||||||
|
.values(credentials)
|
||||||
|
.get_result(db_conn)
|
||||||
|
.await
|
||||||
|
.err_context("Error creating user")
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_user_by_id(db_conn: &mut DbConn, id: i32) -> Result<Option<DbUser>> {
|
pub async fn get_user_by_id(db_conn: &mut DbConn, id: i32) -> Result<Option<DbUser>> {
|
||||||
crate::schema::users::table
|
crate::schema::users::table
|
||||||
.find(id)
|
.find(id)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ async fn router_setup() -> Result<Router> {
|
|||||||
let auth_layer = build_auth_layer(db_pool.clone(), key_val_pool);
|
let auth_layer = build_auth_layer(db_pool.clone(), key_val_pool);
|
||||||
|
|
||||||
let router = dioxus::server::router(App)
|
let router = dioxus::server::router(App)
|
||||||
|
.layer(Extension(config))
|
||||||
.layer(Extension(db_pool))
|
.layer(Extension(db_pool))
|
||||||
.layer(auth_layer);
|
.layer(auth_layer);
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,9 @@ impl From<ServerFnError> for Error {
|
|||||||
impl dioxus_fullstack::AsStatusCode for Error {
|
impl dioxus_fullstack::AsStatusCode for Error {
|
||||||
fn as_status_code(&self) -> StatusCode {
|
fn as_status_code(&self) -> StatusCode {
|
||||||
match &self.source {
|
match &self.source {
|
||||||
ErrorType::Auth(AuthError::InvalidCredentials) => StatusCode::UNAUTHORIZED,
|
ErrorType::Auth(AuthError::InvalidCredentials | AuthError::Unauthorized) => {
|
||||||
|
StatusCode::UNAUTHORIZED
|
||||||
|
}
|
||||||
ErrorType::Database(msg) if *msg == (diesel::result::Error::NotFound).to_string() => {
|
ErrorType::Database(msg) if *msg == (diesel::result::Error::NotFound).to_string() => {
|
||||||
StatusCode::NOT_FOUND
|
StatusCode::NOT_FOUND
|
||||||
}
|
}
|
||||||
@@ -343,4 +345,7 @@ pub enum AuthError {
|
|||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Error(String),
|
Error(String),
|
||||||
|
|
||||||
|
#[error("Unauthorized")]
|
||||||
|
Unauthorized,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user