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);