feat: got sqlx working with axum and leptos

This commit is contained in:
Andrew Rioux 2025-01-24 15:31:10 -05:00
parent 8695685eb3
commit 814125d462
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
7 changed files with 72 additions and 10 deletions

1
Cargo.lock generated
View File

@ -2810,6 +2810,7 @@ dependencies = [
"leptos_router", "leptos_router",
"pbkdf2", "pbkdf2",
"rpassword", "rpassword",
"serde",
"sha2", "sha2",
"sqlx", "sqlx",
"structopt", "structopt",

View File

@ -36,6 +36,7 @@ rpassword = { version = "7.3", optional = true }
pbkdf2 = { version = "0.12", features = ["simple", "sha2"], optional = true } pbkdf2 = { version = "0.12", features = ["simple", "sha2"], optional = true }
sha2 = { version = "0.10", optional = true } sha2 = { version = "0.10", optional = true }
hex = { version = "0.4", optional = true } hex = { version = "0.4", optional = true }
serde = "1.0"
[features] [features]
hydrate = ["leptos/hydrate"] hydrate = ["leptos/hydrate"]

View File

@ -63,8 +63,6 @@ pub fn App() -> impl IntoView {
/// Renders the home page of your application. /// Renders the home page of your application.
#[component] #[component]
fn HomePage() -> impl IntoView { fn HomePage() -> impl IntoView {
use web_sys::WebSocket;
use std::sync::Arc;
use leptos_use::{UseWebSocketReturn, use_websocket}; use leptos_use::{UseWebSocketReturn, use_websocket};
// Creates a reactive value to update the button // Creates a reactive value to update the button

View File

@ -19,9 +19,6 @@ where
let salt_string = hex::encode(salt.as_str().as_bytes()); let salt_string = hex::encode(salt.as_str().as_bytes());
let password_string = hex::encode(&key[..]); let password_string = hex::encode(&key[..]);
tracing::debug!("New password hash: {password_string}");
tracing::debug!("New password salt: {salt_string}");
sqlx::query!( sqlx::query!(
"UPDATE users SET password_hash = ?, password_salt = ? WHERE user_id = ?", "UPDATE users SET password_hash = ?, password_salt = ? WHERE user_id = ?",
password_string, password_string,

View File

@ -2,6 +2,8 @@ pub mod app;
pub mod users; pub mod users;
pub mod db;
#[cfg(feature = "hydrate")] #[cfg(feature = "hydrate")]
#[wasm_bindgen::prelude::wasm_bindgen] #[wasm_bindgen::prelude::wasm_bindgen]
pub fn hydrate() { pub fn hydrate() {

View File

@ -1,8 +1,67 @@
use leptos::prelude::*; 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<Vec<PubUser>, ServerFnError> {
use leptos::server_fn::error::NoCustomError;
let pool = expect_context::<SqlitePool>();
let users = sqlx::query_as!(
PubUser,
"SELECT user_id, user_name FROM users"
)
.fetch_all(&pool)
.await?;
Ok(users)
}
#[component] #[component]
pub fn UserView() -> impl IntoView { pub fn UserView() -> impl IntoView {
let user_list = Resource::new(|| (), |_| async move { list_users().await });
view! { view! {
<p>"User view"</p> <h1>"User list"</h1>
<Suspense
fallback=move || view! { <p>"Loading..."</p> }
>
<ErrorBoundary
fallback=|errors| view! {
<p>"Errors loading users!"</p>
<ul>
{move || errors.get()
.into_iter()
.map(|(_, e)| view! { <li>{e.to_string()}</li> })
.collect::<Vec<_>>()}
</ul>
}
>
{move || Suspend::new(async move {
let users_res = user_list.await;
users_res.map(|users| view! {
<ul>
{users
.into_iter()
.map(|user| view! {
<li>{user.user_id}": "{user.user_name}</li>
})
.collect::<Vec<_>>()}
</ul>
})
})}
</ErrorBoundary>
</Suspense>
} }
} }

View File

@ -51,10 +51,14 @@ pub async fn serve_web(options: crate::cli::Options, db: SqlitePool) -> anyhow::
let app = Router::new() let app = Router::new()
.route("/ws", axum::routing::any(websocket)) .route("/ws", axum::routing::any(websocket))
.leptos_routes(&leptos_options, routes, { .leptos_routes_with_context(
let leptos_options = leptos_options.clone(); &leptos_options,
move || shell(leptos_options.clone()) 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)) .fallback(leptos_axum::file_and_error_handler(shell))
.with_state(leptos_options); .with_state(leptos_options);