Compare commits

..

4 Commits

Author SHA1 Message Date
spinline
09a4c69282 fix(auth): fix MsgPack serialization by adding missing feature in backend and reverting to individual arguments
All checks were successful
Build MIPS Binary / build (push) Successful in 5m15s
2026-02-11 22:03:46 +03:00
spinline
a877e0c393 chore: remove db files from git and update gitignore
All checks were successful
Build MIPS Binary / build (push) Successful in 5m13s
2026-02-11 21:54:15 +03:00
spinline
fd65df2962 fix(setup): add logging and error details for setup debugging
Some checks failed
Build MIPS Binary / build (push) Has been cancelled
2026-02-11 21:53:53 +03:00
spinline
9d160a7ef5 fix(ui): use thread_local for toast signal to fix context issue
All checks were successful
Build MIPS Binary / build (push) Successful in 5m12s
2026-02-11 21:43:06 +03:00
9 changed files with 65 additions and 15 deletions

6
.gitignore vendored
View File

@@ -8,3 +8,9 @@ backend.log
.runner .runner
.env .env
backend/.env backend/.env
*.db
*.db-shm
*.db-wal
*.sqlite
*.sqlite-shm
*.sqlite-wal

1
Cargo.lock generated
View File

@@ -3761,6 +3761,7 @@ dependencies = [
"struct-patch", "struct-patch",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"tracing",
"utoipa", "utoipa",
] ]

View File

@@ -44,6 +44,6 @@ tower_governor = "0.8.0"
governor = "0.10.4" governor = "0.10.4"
# Leptos # Leptos
leptos = { version = "0.8.15", features = ["nightly"] } leptos = { version = "0.8.15", features = ["nightly", "msgpack"] }
leptos_axum = { version = "0.8.7" } leptos_axum = { version = "0.8.7" }
jsonwebtoken = "9" jsonwebtoken = "9"

View File

@@ -41,7 +41,8 @@ pub fn Setup() -> impl IntoView {
} }
Err(e) => { Err(e) => {
log::error!("Setup failed: {:?}", e); log::error!("Setup failed: {:?}", e);
error.1.set(Some("Kurulum sırasında bir hata oluştu".to_string())); // Hatanın sadece mesaj kısmını almaya çalışalım, yoksa full struct basılabilir
error.1.set(Some(format!("Hata: {}", e)));
loading.1.set(false); loading.1.set(false);
} }
} }

View File

@@ -138,8 +138,18 @@ pub fn SonnerList(
} }
} }
// Thread local storage for global access without Context
thread_local! {
static TOASTS: std::cell::RefCell<Option<RwSignal<Vec<ToastData>>>> = std::cell::RefCell::new(None);
}
pub fn provide_toaster() { pub fn provide_toaster() {
let toasts = RwSignal::new(Vec::<ToastData>::new()); let toasts = RwSignal::new(Vec::<ToastData>::new());
// Set global thread_local
TOASTS.with(|t| *t.borrow_mut() = Some(toasts));
// Also provide context for components
provide_context(ToasterStore { toasts }); provide_context(ToasterStore { toasts });
} }
@@ -191,7 +201,9 @@ pub fn Toaster(#[prop(default = SonnerPosition::default())] position: SonnerPosi
// Global Helper Functions // Global Helper Functions
pub fn toast(title: impl Into<String>, variant: ToastType) { pub fn toast(title: impl Into<String>, variant: ToastType) {
if let Some(store) = use_context::<ToasterStore>() { let signal_opt = TOASTS.with(|t| *t.borrow());
if let Some(toasts) = signal_opt {
let id = js_sys::Math::random().to_bits(); let id = js_sys::Math::random().to_bits();
let new_toast = ToastData { let new_toast = ToastData {
id, id,
@@ -201,18 +213,16 @@ pub fn toast(title: impl Into<String>, variant: ToastType) {
duration: 4000, duration: 4000,
}; };
store.toasts.update(|t| t.push(new_toast.clone())); toasts.update(|t| t.push(new_toast.clone()));
// Auto remove after duration // Auto remove after duration
let duration = new_toast.duration; let duration = new_toast.duration;
leptos::task::spawn_local(async move { leptos::task::spawn_local(async move {
gloo_timers::future::TimeoutFuture::new(duration as u32).await; gloo_timers::future::TimeoutFuture::new(duration as u32).await;
if let Some(store) = use_context::<ToasterStore>() { toasts.update(|vec| vec.retain(|t| t.id != id));
store.toasts.update(|vec| vec.retain(|t| t.id != id));
}
}); });
} else { } else {
gloo_console::warn!("ToasterStore not found. Make sure <Toaster /> is mounted."); gloo_console::warn!("ToasterStore not found (global static). Make sure provide_toaster() is called.");
} }
} }

View File

@@ -10,6 +10,7 @@ struct-patch = "0.5"
rmp-serde = "1.3" rmp-serde = "1.3"
bytes = "1" bytes = "1"
http = "1" http = "1"
tracing = "0.1"
# Leptos 0.8.7 # Leptos 0.8.7
leptos = { version = "0.8.15", features = ["nightly", "msgpack"] } leptos = { version = "0.8.15", features = ["nightly", "msgpack"] }

View File

@@ -28,8 +28,17 @@ impl Db {
} }
async fn run_migrations(&self) -> Result<()> { async fn run_migrations(&self) -> Result<()> {
sqlx::migrate!("./migrations").run(&self.pool).await?; tracing::info!("Starting database migrations...");
Ok(()) match sqlx::migrate!("./migrations").run(&self.pool).await {
Ok(_) => {
tracing::info!("Database migrations completed successfully.");
Ok(())
}
Err(e) => {
tracing::error!("Database migration failed: {}", e);
Err(e.into())
}
}
} }
// --- User Operations --- // --- User Operations ---

View File

@@ -24,9 +24,19 @@ pub struct SetupStatus {
pub async fn get_setup_status() -> Result<SetupStatus, ServerFnError> { pub async fn get_setup_status() -> Result<SetupStatus, ServerFnError> {
use crate::DbContext; use crate::DbContext;
let db_context = use_context::<DbContext>().ok_or_else(|| ServerFnError::new("DB Context missing"))?; tracing::info!("Checking setup status...");
let db_context = use_context::<DbContext>().ok_or_else(|| {
tracing::error!("DB Context missing in GetSetupStatus");
ServerFnError::new("DB Context missing")
})?;
let has_users = db_context.db.has_users().await let has_users = db_context.db.has_users().await
.map_err(|e| ServerFnError::new(format!("DB error: {}", e)))?; .map_err(|e| {
tracing::error!("DB error in GetSetupStatus: {}", e);
ServerFnError::new(format!("DB error: {}", e))
})?;
tracing::info!("Setup status: completed={}", has_users);
Ok(SetupStatus { Ok(SetupStatus {
completed: has_users, completed: has_users,
@@ -37,21 +47,33 @@ pub async fn get_setup_status() -> Result<SetupStatus, ServerFnError> {
pub async fn setup(username: String, password: String) -> Result<(), ServerFnError> { pub async fn setup(username: String, password: String) -> Result<(), ServerFnError> {
use crate::DbContext; use crate::DbContext;
let db_context = use_context::<DbContext>().ok_or_else(|| ServerFnError::new("DB Context missing"))?; tracing::info!("Attempting setup for user: {}", username);
let db_context = use_context::<DbContext>().ok_or_else(|| {
tracing::error!("DB Context missing in Setup");
ServerFnError::new("DB Context missing")
})?;
// Check if setup is already done // Check if setup is already done
let has_users = db_context.db.has_users().await.unwrap_or(false); let has_users = db_context.db.has_users().await.unwrap_or(false);
if has_users { if has_users {
tracing::warn!("Setup attempt blocked: Setup already completed");
return Err(ServerFnError::new("Setup already completed")); return Err(ServerFnError::new("Setup already completed"));
} }
// Hash password (low cost for MIPS) // Hash password (low cost for MIPS)
let password_hash = bcrypt::hash(&password, 6) let password_hash = bcrypt::hash(&password, 6)
.map_err(|_| ServerFnError::new("Hashing error"))?; .map_err(|e| {
tracing::error!("Hashing error: {}", e);
ServerFnError::new("Hashing error")
})?;
db_context.db.create_user(&username, &password_hash).await db_context.db.create_user(&username, &password_hash).await
.map_err(|e| ServerFnError::new(format!("DB error: {}", e)))?; .map_err(|e| {
tracing::error!("Failed to create user: {}", e);
ServerFnError::new(format!("DB error: {}", e))
})?;
tracing::info!("Setup completed successfully for user: {}", username);
Ok(()) Ok(())
} }

Binary file not shown.