diff --git a/projects/session_auth_axum/Cargo.toml b/projects/session_auth_axum/Cargo.toml index f7694dce1..f681d4395 100644 --- a/projects/session_auth_axum/Cargo.toml +++ b/projects/session_auth_axum/Cargo.toml @@ -30,23 +30,21 @@ sqlx = { version = "0.8.0", features = [ ], optional = true } thiserror = "1.0" wasm-bindgen = "0.2.0" -axum_session_auth = { version = "0.14.0", features = [ - "sqlite-rustls", -], optional = true } -axum_session = { version = "0.14.0", features = [ - "sqlite-rustls", -], optional = true } +axum_session_auth = { version = "0.14.0", features = [], optional = true } +axum_session = { version = "0.14.0", features = [], optional = true } +axum_session_sqlx = { version = "0.3.0", features = [ "sqlite", "tls-rustls"], optional = true } bcrypt = { version = "0.15.0", optional = true } async-trait = { version = "0.1.0", optional = true } [features] default = ["ssr"] -hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"] +hydrate = ["leptos/hydrate"] ssr = [ "dep:axum", "dep:tower", "dep:tower-http", "dep:tokio", + "dep:axum_session_sqlx", "dep:axum_session_auth", "dep:axum_session", "dep:async-trait", diff --git a/projects/session_auth_axum/src/auth.rs b/projects/session_auth_axum/src/auth.rs index c6c212b5e..40e704f9d 100644 --- a/projects/session_auth_axum/src/auth.rs +++ b/projects/session_auth_axum/src/auth.rs @@ -28,9 +28,8 @@ impl Default for User { #[cfg(feature = "ssr")] pub mod ssr { pub use super::{User, UserPasshash}; - pub use axum_session_auth::{ - Authentication, HasPermission, SessionSqlitePool, - }; + pub use axum_session_auth::{Authentication, HasPermission}; + use axum_session_sqlx::SessionSqlitePool; pub use sqlx::SqlitePool; pub use std::collections::HashSet; pub type AuthSession = axum_session_auth::AuthSession< diff --git a/projects/session_auth_axum/src/error_template.rs b/projects/session_auth_axum/src/error_template.rs index a60429af4..33bc18822 100644 --- a/projects/session_auth_axum/src/error_template.rs +++ b/projects/session_auth_axum/src/error_template.rs @@ -8,10 +8,10 @@ use leptos_axum::ResponseOptions; #[component] pub fn ErrorTemplate( #[prop(optional)] outside_errors: Option, - #[prop(optional)] errors: Option>, + #[prop(optional)] errors: Option>, ) -> impl IntoView { let errors = match outside_errors { - Some(e) => RwSignal::new(e), + Some(e) => ArcRwSignal::new(e), None => match errors { Some(e) => e, None => panic!("No Errors found and we expected errors!"), diff --git a/projects/session_auth_axum/src/fallback.rs b/projects/session_auth_axum/src/fallback.rs deleted file mode 100644 index 66b2a5ffe..000000000 --- a/projects/session_auth_axum/src/fallback.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::{error_template::ErrorTemplate, errors::TodoAppError}; -use axum::{ - body::Body, - extract::State, - http::{Request, Response, StatusCode, Uri}, - response::{IntoResponse, Response as AxumResponse}, -}; -use leptos::{view, Errors, LeptosOptions}; -use tower::ServiceExt; -use tower_http::services::ServeDir; - -pub async fn file_and_error_handler( - uri: Uri, - State(options): State, - req: Request, -) -> AxumResponse { - let root = options.site_root.clone(); - let res = get_static_file(uri.clone(), &root).await.unwrap(); - - if res.status() == StatusCode::OK { - res.into_response() - } else { - let mut errors = Errors::default(); - errors.insert_with_default_key(TodoAppError::NotFound); - let handler = leptos_axum::render_app_to_stream( - options.to_owned(), - move || view! {}, - ); - handler(req).await.into_response() - } -} - -async fn get_static_file( - uri: Uri, - root: &str, -) -> Result, (StatusCode, String)> { - let req = Request::builder() - .uri(uri.clone()) - .body(Body::empty()) - .unwrap(); - // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` - // This path is relative to the cargo root - match ServeDir::new(root).oneshot(req).await { - Ok(res) => Ok(res.into_response()), - Err(err) => Err(( - StatusCode::INTERNAL_SERVER_ERROR, - format!("Something went wrong: {err}"), - )), - } -} diff --git a/projects/session_auth_axum/src/lib.rs b/projects/session_auth_axum/src/lib.rs index 09cb6a6a3..146d2fc62 100644 --- a/projects/session_auth_axum/src/lib.rs +++ b/projects/session_auth_axum/src/lib.rs @@ -2,8 +2,6 @@ pub mod auth; pub mod error_template; pub mod errors; #[cfg(feature = "ssr")] -pub mod fallback; -#[cfg(feature = "ssr")] pub mod state; pub mod todo; @@ -14,5 +12,5 @@ pub fn hydrate() { _ = console_log::init_with_level(log::Level::Debug); console_error_panic_hook::set_once(); - leptos::mount_to_body(TodoApp); + leptos::mount::hydrate_body(TodoApp); } diff --git a/projects/session_auth_axum/src/main.rs b/projects/session_auth_axum/src/main.rs index 2f9fe34ca..9ceea32b3 100644 --- a/projects/session_auth_axum/src/main.rs +++ b/projects/session_auth_axum/src/main.rs @@ -7,14 +7,16 @@ use axum::{ Router, }; use axum_session::{SessionConfig, SessionLayer, SessionStore}; -use axum_session_auth::{AuthConfig, AuthSessionLayer, SessionSqlitePool}; -use leptos::{get_configuration, logging::log, provide_context}; +use axum_session_auth::{AuthConfig, AuthSessionLayer}; +use axum_session_sqlx::SessionSqlitePool; +use leptos::{ + config::get_configuration, logging::log, prelude::provide_context, +}; use leptos_axum::{ generate_route_list, handle_server_fns_with_context, LeptosRoutes, }; use session_auth_axum::{ auth::{ssr::AuthSession, User}, - fallback::file_and_error_handler, state::AppState, todo::*, }; @@ -40,19 +42,19 @@ async fn server_fn_handler( async fn leptos_routes_handler( auth_session: AuthSession, - State(app_state): State, + state: State, req: Request, ) -> Response { + let State(app_state) = state.clone(); let handler = leptos_axum::render_route_with_context( - app_state.leptos_options.clone(), app_state.routes.clone(), move || { provide_context(auth_session.clone()); provide_context(app_state.pool.clone()); }, - TodoApp, + move || shell(app_state.leptos_options.clone()), ); - handler(req).await.into_response() + handler(state, req).await.into_response() } #[tokio::main] @@ -111,7 +113,7 @@ async fn main() { get(server_fn_handler).post(server_fn_handler), ) .leptos_routes_with_handler(routes, get(leptos_routes_handler)) - .fallback(file_and_error_handler) + .fallback(leptos_axum::file_and_error_handler::(shell)) .layer( AuthSessionLayer::::new( Some(pool.clone()), diff --git a/projects/session_auth_axum/src/state.rs b/projects/session_auth_axum/src/state.rs index 89ddaf777..9fc3752a4 100644 --- a/projects/session_auth_axum/src/state.rs +++ b/projects/session_auth_axum/src/state.rs @@ -1,6 +1,6 @@ use axum::extract::FromRef; -use leptos::LeptosOptions; -use leptos_router::RouteListing; +use leptos::prelude::LeptosOptions; +use leptos_axum::AxumRouteListing; use sqlx::SqlitePool; /// This takes advantage of Axum's SubStates feature by deriving FromRef. This is the only way to have more than one @@ -9,5 +9,5 @@ use sqlx::SqlitePool; pub struct AppState { pub leptos_options: LeptosOptions, pub pool: SqlitePool, - pub routes: Vec, + pub routes: Vec, } diff --git a/projects/session_auth_axum/src/todo.rs b/projects/session_auth_axum/src/todo.rs index a2f91401d..70b7c8b7c 100644 --- a/projects/session_auth_axum/src/todo.rs +++ b/projects/session_auth_axum/src/todo.rs @@ -1,7 +1,7 @@ use crate::{auth::*, error_template::ErrorTemplate}; use leptos::prelude::*; use leptos_meta::*; -use leptos_router::*; +use leptos_router::{components::*, *}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -109,13 +109,33 @@ pub async fn delete_todo(id: u16) -> Result<(), ServerFnError> { .map(|_| ())?) } +pub fn shell(options: LeptosOptions) -> impl IntoView { + view! { + + + + + + + + + + + + + + + + } +} + #[component] pub fn TodoApp() -> impl IntoView { - let login = create_server_action::(); - let logout = create_server_action::(); - let signup = create_server_action::(); + let login = ServerAction::::new(); + let logout = ServerAction::::new(); + let signup = ServerAction::::new(); - let user = create_resource( + let user = Resource::new( move || { ( login.version().get(), @@ -128,8 +148,6 @@ pub fn TodoApp() -> impl IntoView { provide_meta_context(); view! { - -
@@ -149,7 +167,7 @@ pub fn TodoApp() -> impl IntoView { ", " {format!("Login error: {}", e)} } - .into_view() + .into_any() } Ok(None) => { view! { @@ -159,7 +177,7 @@ pub fn TodoApp() -> impl IntoView { ", " "Logged out." } - .into_view() + .into_any() } Ok(Some(user)) => { view! { @@ -169,7 +187,7 @@ pub fn TodoApp() -> impl IntoView { {format!("Logged in as: {} ({})", user.username, user.id)} } - .into_view() + .into_any() } }) }} @@ -178,13 +196,15 @@ pub fn TodoApp() -> impl IntoView {

- + // Route - - }/> - }/> - + }/> + }/> + "Settings" @@ -193,7 +213,7 @@ pub fn TodoApp() -> impl IntoView { } /> - +
} @@ -201,12 +221,12 @@ pub fn TodoApp() -> impl IntoView { #[component] pub fn Todos() -> impl IntoView { - let add_todo = create_server_multi_action::(); - let delete_todo = create_server_action::(); + let add_todo = ServerMultiAction::::new(); + let delete_todo = ServerAction::::new(); let submissions = add_todo.submissions(); // list of todos is loaded from the server in reaction to changes - let todos = create_resource( + let todos = Resource::new( move || (add_todo.version().get(), delete_todo.version().get()), move |_| get_todos(), ); @@ -231,11 +251,11 @@ pub fn Todos() -> impl IntoView { view! {
"Server Error: " {e.to_string()}
} - .into_view() + .into_any() } Ok(todos) => { if todos.is_empty() { - view! {

"No tasks were found."

}.into_view() + view! {

"No tasks were found."

}.into_any() } else { todos .into_iter() @@ -252,10 +272,11 @@ pub fn Todos() -> impl IntoView { } }) .collect_view() + .into_any() } } }) - .unwrap_or_default() + .unwrap_or(().into_any()) } }; let pending_todos = move || { @@ -266,7 +287,7 @@ pub fn Todos() -> impl IntoView { .map(|submission| { view! {
  • - {move || submission.input.get().map(|data| data.title)} + {move || submission.input().get().map(|data| data.title)}
  • } }) @@ -282,9 +303,7 @@ pub fn Todos() -> impl IntoView { } #[component] -pub fn Login( - action: Action>, -) -> impl IntoView { +pub fn Login(action: ServerAction) -> impl IntoView { view! {

    "Log In"

    @@ -317,9 +336,7 @@ pub fn Login( } #[component] -pub fn Signup( - action: Action>, -) -> impl IntoView { +pub fn Signup(action: ServerAction) -> impl IntoView { view! {

    "Sign Up"

    @@ -362,9 +379,7 @@ pub fn Signup( } #[component] -pub fn Logout( - action: Action>, -) -> impl IntoView { +pub fn Logout(action: ServerAction) -> impl IntoView { view! {