97 lines
3.2 KiB
Rust
97 lines
3.2 KiB
Rust
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<bool>,
|
|
pub is_admin: Option<bool>,
|
|
}
|
|
|
|
#[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! { <div>{ "Loading..." } </div> },
|
|
AuthState {
|
|
is_authenticated: Some(false),
|
|
..
|
|
} => html! {
|
|
<Redirect<crate::Route> 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! { <Redirect<crate::Route> to={crate::Route::PermissionDenied}/> }
|
|
}
|
|
None => html! { <div>{ "Checking permissions..." }</div> },
|
|
}
|
|
} else {
|
|
props.children.clone().into()
|
|
}
|
|
}
|
|
_ => html! { <div>{ "Checking permissions..." }</div> },
|
|
}
|
|
}
|