use gloo_net::http::Request; use wasm_bindgen_futures::spawn_local; use yew::prelude::*; use yew_router::prelude::*; #[derive(Clone, Debug, PartialEq)] pub struct AuthState { pub is_authenticated: Option, pub is_admin: Option, } #[derive(Properties, PartialEq)] pub struct ProtectedRouteProps { pub children: Children, pub admin_page: bool, } #[component(ProtectedRoute)] pub fn protected_route(props: &ProtectedRouteProps) -> Html { let auth_state = use_state(|| AuthState { is_authenticated: None, is_admin: None, }); { let auth_state = auth_state.clone(); use_effect_with((), move |_| { let auth_state = auth_state.clone(); spawn_local(async move { match Request::get("/api/users/current") .credentials(web_sys::RequestCredentials::Include) .send() .await { Ok(resp) => { let status = resp.status(); web_sys::console::log_1(&format!("Auth check: status {}", status).into()); if status == 200 { let user_data: serde_json::Value = resp.json().await.unwrap_or_default(); let is_admin = user_data["data"]["is_admin"].as_bool(); auth_state.set(AuthState { is_authenticated: Some(true), is_admin, }); } else { auth_state.set(AuthState { is_authenticated: Some(false), is_admin: Some(false), }); } } Err(err) => { web_sys::console::log_1(&format!("Auth check error: {:?}", err).into()); auth_state.set(AuthState { is_authenticated: Some(false), is_admin: Some(false), }); } } }); || () }); } match (*auth_state) { AuthState { is_authenticated: None, .. } => html! {
{ "Loading..." }
}, AuthState { is_authenticated: Some(false), .. } => html! { to={crate::Route::Login}/> }, AuthState { is_authenticated: Some(true), is_admin: admin_flag, } => { if props.admin_page { match admin_flag { Some(true) => props.children.clone().into(), Some(false) => { html! { to={crate::Route::PermissionDenied}/> } } None => html! {
{ "Checking permissions..." }
}, } } else { props.children.clone().into() } } _ => html! {
{ "Checking permissions..." }
}, } }