diff --git a/Cargo.lock b/Cargo.lock
index 6c70fe2..fecdbcd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -197,6 +197,7 @@ checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
+ "axum-macros",
"base64",
"bytes",
"futures-util",
@@ -249,23 +250,38 @@ dependencies = [
]
[[package]]
-name = "axum-login"
-version = "0.16.0"
+name = "axum-extra"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5260ed0ecc8ace8e7e61a7406672faba598c8a86b8f4742fcdde0ddc979a318f"
+checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04"
dependencies = [
- "async-trait",
"axum",
- "form_urlencoded",
+ "axum-core",
+ "bytes",
+ "cookie",
+ "fastrand",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "mime",
+ "multer",
+ "pin-project-lite",
"serde",
- "subtle",
- "thiserror 1.0.69",
- "tower-cookies",
+ "tower 0.5.2",
"tower-layer",
"tower-service",
- "tower-sessions",
- "tracing",
- "urlencoding",
+]
+
+[[package]]
+name = "axum-macros"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.96",
]
[[package]]
@@ -724,7 +740,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
- "serde",
]
[[package]]
@@ -1841,7 +1856,6 @@ checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
- "serde",
]
[[package]]
@@ -2533,28 +2547,6 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "rmp"
-version = "0.8.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4"
-dependencies = [
- "byteorder",
- "num-traits",
- "paste",
-]
-
-[[package]]
-name = "rmp-serde"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db"
-dependencies = [
- "byteorder",
- "rmp",
- "serde",
-]
-
[[package]]
name = "rpassword"
version = "7.3.1"
@@ -2962,9 +2954,8 @@ name = "sparse-server"
version = "0.1.0"
dependencies = [
"anyhow",
- "async-trait",
"axum",
- "axum-login",
+ "axum-extra",
"axum-server",
"cfg-if",
"chrono",
@@ -2986,13 +2977,10 @@ dependencies = [
"sqlx",
"structopt",
"thiserror 1.0.69",
- "time",
"tokio",
"tokio-stream",
"tower 0.4.13",
"tower-http 0.5.2",
- "tower-sessions",
- "tower-sessions-sqlx-store",
"tracing",
"tracing-subscriber",
"wasm-bindgen",
@@ -3067,7 +3055,6 @@ dependencies = [
"sha2",
"smallvec",
"thiserror 2.0.11",
- "time",
"tokio",
"tokio-stream",
"tracing",
@@ -3152,7 +3139,6 @@ dependencies = [
"sqlx-core",
"stringprep",
"thiserror 2.0.11",
- "time",
"tracing",
"whoami",
]
@@ -3191,7 +3177,6 @@ dependencies = [
"sqlx-core",
"stringprep",
"thiserror 2.0.11",
- "time",
"tracing",
"whoami",
]
@@ -3216,7 +3201,6 @@ dependencies = [
"serde",
"serde_urlencoded",
"sqlx-core",
- "time",
"tracing",
"url",
]
@@ -3640,23 +3624,6 @@ dependencies = [
"tracing",
]
-[[package]]
-name = "tower-cookies"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fd0118512cf0b3768f7fcccf0bef1ae41d68f2b45edc1e77432b36c97c56c6d"
-dependencies = [
- "async-trait",
- "axum-core",
- "cookie",
- "futures-util",
- "http",
- "parking_lot",
- "pin-project-lite",
- "tower-layer",
- "tower-service",
-]
-
[[package]]
name = "tower-http"
version = "0.5.2"
@@ -3721,71 +3688,6 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
-[[package]]
-name = "tower-sessions"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65856c81ee244e0f8a55ab0f7b769b72fbde387c235f0a73cd97c579818d05eb"
-dependencies = [
- "async-trait",
- "http",
- "time",
- "tokio",
- "tower-cookies",
- "tower-layer",
- "tower-service",
- "tower-sessions-core",
- "tower-sessions-memory-store",
- "tracing",
-]
-
-[[package]]
-name = "tower-sessions-core"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb6abbfcaf6436ec5a772cd9f965401da12db793e404ae6134eac066fa5a04f3"
-dependencies = [
- "async-trait",
- "axum-core",
- "base64",
- "futures",
- "http",
- "parking_lot",
- "rand",
- "serde",
- "serde_json",
- "thiserror 1.0.69",
- "time",
- "tokio",
- "tracing",
-]
-
-[[package]]
-name = "tower-sessions-memory-store"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fad75660c8afbe74f4e7cbbe8e9090171a056b57370ea4d7d5e9eb3e4af3092"
-dependencies = [
- "async-trait",
- "time",
- "tokio",
- "tower-sessions-core",
-]
-
-[[package]]
-name = "tower-sessions-sqlx-store"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdd38eba51214e99accab78f6b7c8e273e90a9cb57575e86b592c60074e182d7"
-dependencies = [
- "async-trait",
- "rmp-serde",
- "sqlx",
- "thiserror 1.0.69",
- "time",
- "tower-sessions-core",
-]
-
[[package]]
name = "tracing"
version = "0.1.41"
@@ -3973,12 +3875,6 @@ dependencies = [
"percent-encoding",
]
-[[package]]
-name = "urlencoding"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
-
[[package]]
name = "utf-8"
version = "0.7.6"
diff --git a/flake.nix b/flake.nix
index c1b79cf..c4162ae 100644
--- a/flake.nix
+++ b/flake.nix
@@ -87,6 +87,11 @@
rust-analyzer
zls
+ # Debuggers
+ gdb
+ pwndbg
+ gdbgui
+
# Cargo lint tools
taplo
cargo-deny
diff --git a/sparse-server/Cargo.toml b/sparse-server/Cargo.toml
index f1950c6..0be0c2b 100644
--- a/sparse-server/Cargo.toml
+++ b/sparse-server/Cargo.toml
@@ -9,13 +9,14 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
leptos = { version = "^0.7", features = ["nightly"] }
leptos_router = { version = "^0.7", features = ["nightly"] }
-axum = { version = "^0.7", features = ["ws"], optional = true }
+axum = { version = "^0.7", features = ["ws", "macros"], optional = true }
+axum-extra = { version = "^0.9", features = ["cookie"], optional = true }
console_error_panic_hook = "0.1"
leptos_axum = { version = "^0.7", optional = true }
leptos_meta = { version = "^0.7" }
tokio = { version = "1", features = ["rt-multi-thread", "signal"], optional = true }
tower = { version = "0.4", optional = true }
-tower-http = { version = "0.5", features = ["fs", "compression-br", "compression-deflate", "compression-gzip", "compression-zstd"], optional = true }
+tower-http = { version = "0.5", features = ["fs", "compression-br", "compression-deflate", "compression-gzip", "compression-zstd", "trace"], optional = true }
wasm-bindgen = "0.2"
thiserror = "1"
http = "1"
@@ -33,28 +34,20 @@ codee = "0.2"
sqlx = { version = "0.8", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "sqlx-sqlite"], optional = true }
chrono = { version = "0.4", features = ["serde"] }
rpassword = { version = "7.3", optional = true }
-pbkdf2 = { version = "0.12", features = ["simple", "sha2"], optional = true }
+pbkdf2 = { version = "0.12", features = ["simple", "sha2", "std"], optional = true }
sha2 = { version = "0.10", optional = true }
hex = { version = "0.4", optional = true }
serde = "1.0"
-axum-login = { version = "0.16.0", optional = true }
-async-trait = "0.1.85"
cfg-if = "1.0.0"
-tower-sessions = { version = "0.13.0", optional = true }
-tower-sessions-sqlx-store = { version = "0.14.0", features = ["sqlite"], optional = true }
-time = { version = "0.3.37", optional = true }
[features]
hydrate = ["leptos/hydrate", "chrono/wasmbind"]
ssr = [
"dep:axum",
- "dep:axum-login",
+ "dep:axum-extra",
"dep:tokio",
- "dep:time",
"dep:tower",
"dep:tower-http",
- "dep:tower-sessions",
- "dep:tower-sessions-sqlx-store",
"dep:leptos_axum",
"dep:axum-server",
"dep:tracing-subscriber",
diff --git a/sparse-server/migrations/20250129045406_readd_sessions.sql b/sparse-server/migrations/20250129045406_readd_sessions.sql
new file mode 100644
index 0000000..3cacce5
--- /dev/null
+++ b/sparse-server/migrations/20250129045406_readd_sessions.sql
@@ -0,0 +1,8 @@
+CREATE TABLE sessions (
+ session_id char(64) NOT NULL,
+ user_id int NOT NULL,
+ expires int NOT NULL,
+
+ PRIMARY KEY (session_id),
+ FOREIGN KEY (user_id) REFERENCES users
+);
diff --git a/sparse-server/src/app.rs b/sparse-server/src/app.rs
index ddcdc74..460a589 100644
--- a/sparse-server/src/app.rs
+++ b/sparse-server/src/app.rs
@@ -2,6 +2,7 @@ use leptos::prelude::*;
use leptos_meta::{provide_meta_context, MetaTags, Stylesheet, Title};
use leptos_router::{
components::{A, Route, Router, Routes},
+ hooks::use_query_map,
path
};
use serde::{Serialize, Deserialize};
@@ -21,56 +22,38 @@ pub async fn test_retrieve() -> Result {
Ok(since_the_epoch)
}
-#[derive(Clone, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct User {
user_id: i64,
user_name: String,
}
#[server]
-async fn me() -> Result
}
- >
- "Loaded time:"
- {move || {
- loaded_time.get()
- .map(|time| match time {
- Ok(t) => view! { {format!("{}", t)}
},
- Err(_) => view! { {"Error!".to_string()}
}
- })
- }}
- "Requested time:"
-
- {move || pending.get().then_some("Loading...")}
- {move || match requested_time.get() {
- Some(t) => {
- leptos::logging::log!("updating time display");
- view! { {t}
}
- },
- None => view! { {"N/A".to_string()}
}
- }}
-
- "Messages"
-
-
- {move || messages
- .get()
- .iter()
- .map(|message| view! { {message.clone()}
})
- .collect::>()}
+ "Welcome to sparse!"
}
}
diff --git a/sparse-server/src/db/user.rs b/sparse-server/src/db/user.rs
index a0fe834..ce3aa3e 100644
--- a/sparse-server/src/db/user.rs
+++ b/sparse-server/src/db/user.rs
@@ -1,3 +1,11 @@
+use leptos::{prelude::expect_context, server_fn::error::NoCustomError};
+use leptos_axum::{extract, ResponseOptions};
+use leptos::prelude::ServerFnError;
+use pbkdf2::{Pbkdf2, password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, rand_core::{OsRng, RngCore}, SaltString}};
+use sqlx::SqlitePool;
+
+use crate::error::Error;
+
#[derive(Clone)]
pub struct User {
pub user_id: i64,
@@ -6,13 +14,6 @@ pub struct User {
pub last_active: Option
}
-use async_trait::async_trait;
-use pbkdf2::{Pbkdf2, password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, rand_core::OsRng, SaltString}};
-use axum_login::{AuthUser, AuthnBackend, UserId};
-use sqlx::SqlitePool;
-
-use crate::error::Error;
-
impl std::fmt::Debug for User {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("User")
@@ -23,27 +24,16 @@ impl std::fmt::Debug for User {
}
}
-impl AuthUser for User {
- type Id = i64;
-
- fn id(&self) -> Self::Id {
- self.user_id
- }
-
- fn session_auth_hash(&self) -> &[u8] {
- self.password_hash.as_bytes()
- }
-}
-
async fn hash_password(pass: &[u8]) -> Result {
Ok(tokio::task::spawn_blocking({
let pass = pass.to_owned();
let salt = SaltString::generate(&mut OsRng);
- move || Pbkdf2.hash_password(
- &*pass,
- &salt,
- ).map(|hash| hash.to_string())
+ move ||
+ Pbkdf2.hash_password(
+ &*pass,
+ &salt,
+ ).map(|hash| hash.serialize().as_str().to_string())
}).await??)
}
@@ -114,67 +104,149 @@ where
Ok(())
}
-#[derive(Clone)]
-pub struct Backend(SqlitePool);
+const SESSION_ID_KEY: &'static str = "session_id";
+const SESSION_AGE: i64 = 30 * 60;
-impl Backend {
- pub fn new(db: SqlitePool) -> Self {
- Self(db)
- }
-}
+pub async fn create_auth_session(username: String, password: String) -> Result<(), ServerFnError> {
+ use axum_extra::extract::cookie::{Cookie, SameSite};
+ use axum::http::{header, HeaderValue};
-#[async_trait]
-impl AuthnBackend for Backend {
- type User = User;
- type Credentials = (String, String);
- type Error = Error;
+ let db = expect_context::();
+ let resp = expect_context::();
- async fn authenticate(
- &self,
- creds: Self::Credentials
- ) -> Result