From 814125d462279e1b8f8d7b82a26e3abe1dded9af Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Fri, 24 Jan 2025 15:31:10 -0500 Subject: [PATCH] feat: got sqlx working with axum and leptos --- Cargo.lock | 1 + sparse-server/Cargo.toml | 1 + sparse-server/src/app.rs | 2 -- sparse-server/src/db/user.rs | 3 -- sparse-server/src/lib.rs | 2 ++ sparse-server/src/users.rs | 61 +++++++++++++++++++++++++++++++++- sparse-server/src/webserver.rs | 12 ++++--- 7 files changed, 72 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d62d436..052482a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2810,6 +2810,7 @@ dependencies = [ "leptos_router", "pbkdf2", "rpassword", + "serde", "sha2", "sqlx", "structopt", diff --git a/sparse-server/Cargo.toml b/sparse-server/Cargo.toml index 81bbc84..5f274fb 100644 --- a/sparse-server/Cargo.toml +++ b/sparse-server/Cargo.toml @@ -36,6 +36,7 @@ rpassword = { version = "7.3", optional = true } pbkdf2 = { version = "0.12", features = ["simple", "sha2"], optional = true } sha2 = { version = "0.10", optional = true } hex = { version = "0.4", optional = true } +serde = "1.0" [features] hydrate = ["leptos/hydrate"] diff --git a/sparse-server/src/app.rs b/sparse-server/src/app.rs index 4188a33..d89be7d 100644 --- a/sparse-server/src/app.rs +++ b/sparse-server/src/app.rs @@ -63,8 +63,6 @@ pub fn App() -> impl IntoView { /// Renders the home page of your application. #[component] fn HomePage() -> impl IntoView { - use web_sys::WebSocket; - use std::sync::Arc; use leptos_use::{UseWebSocketReturn, use_websocket}; // Creates a reactive value to update the button diff --git a/sparse-server/src/db/user.rs b/sparse-server/src/db/user.rs index d18b822..44abd09 100644 --- a/sparse-server/src/db/user.rs +++ b/sparse-server/src/db/user.rs @@ -19,9 +19,6 @@ where let salt_string = hex::encode(salt.as_str().as_bytes()); let password_string = hex::encode(&key[..]); - tracing::debug!("New password hash: {password_string}"); - tracing::debug!("New password salt: {salt_string}"); - sqlx::query!( "UPDATE users SET password_hash = ?, password_salt = ? WHERE user_id = ?", password_string, diff --git a/sparse-server/src/lib.rs b/sparse-server/src/lib.rs index 6ff12ee..d5aa96b 100644 --- a/sparse-server/src/lib.rs +++ b/sparse-server/src/lib.rs @@ -2,6 +2,8 @@ pub mod app; pub mod users; +pub mod db; + #[cfg(feature = "hydrate")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn hydrate() { diff --git a/sparse-server/src/users.rs b/sparse-server/src/users.rs index 8795f5a..a198954 100644 --- a/sparse-server/src/users.rs +++ b/sparse-server/src/users.rs @@ -1,8 +1,67 @@ use leptos::prelude::*; +use serde::{Serialize, Deserialize}; +#[cfg(feature = "ssr")] +use { + sqlx::SqlitePool +}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct PubUser { + user_id: i64, + user_name: String +} + +#[server] +async fn list_users() -> Result, ServerFnError> { + use leptos::server_fn::error::NoCustomError; + + let pool = expect_context::(); + + let users = sqlx::query_as!( + PubUser, + "SELECT user_id, user_name FROM users" + ) + .fetch_all(&pool) + .await?; + + Ok(users) +} #[component] pub fn UserView() -> impl IntoView { + let user_list = Resource::new(|| (), |_| async move { list_users().await }); + view! { -

"User view"

+

"User list"

+ "Loading..."

} + > + "Errors loading users!"

+
    + {move || errors.get() + .into_iter() + .map(|(_, e)| view! {
  • {e.to_string()}
  • }) + .collect::>()} +
+ } + > + {move || Suspend::new(async move { + let users_res = user_list.await; + + users_res.map(|users| view! { +
    + {users + .into_iter() + .map(|user| view! { +
  • {user.user_id}": "{user.user_name}
  • + }) + .collect::>()} +
+ }) + })} +
+
} } diff --git a/sparse-server/src/webserver.rs b/sparse-server/src/webserver.rs index a84bb40..adea3d4 100644 --- a/sparse-server/src/webserver.rs +++ b/sparse-server/src/webserver.rs @@ -51,10 +51,14 @@ pub async fn serve_web(options: crate::cli::Options, db: SqlitePool) -> anyhow:: let app = Router::new() .route("/ws", axum::routing::any(websocket)) - .leptos_routes(&leptos_options, routes, { - let leptos_options = leptos_options.clone(); - move || shell(leptos_options.clone()) - }) + .leptos_routes_with_context( + &leptos_options, + routes, + move || provide_context(db.clone()), + { + let leptos_options = leptos_options.clone(); + move || shell(leptos_options.clone()) + }) .fallback(leptos_axum::file_and_error_handler(shell)) .with_state(leptos_options);