admin pages

Pages can now be locked behind admin privileges
This commit is contained in:
2026-05-01 16:47:42 +02:00
parent 802e5876f7
commit fdd2e2a757
5 changed files with 94 additions and 36 deletions

View File

@@ -5,22 +5,27 @@ use yew_router::prelude::*;
#[derive(Clone, Debug, PartialEq)]
pub struct AuthState {
pub is_authenticated: bool,
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 is_authenticated = use_state(|| None::<bool>);
let auth_state = use_state(|| AuthState {
is_authenticated: None,
is_admin: None,
});
{
let is_authenticated = is_authenticated.clone();
let auth_state = auth_state.clone();
use_effect_with((), move |_| {
let is_authenticated = is_authenticated.clone();
let auth_state = auth_state.clone();
spawn_local(async move {
match Request::get("/api/users/current")
.credentials(web_sys::RequestCredentials::Include)
@@ -31,14 +36,27 @@ pub fn protected_route(props: &ProtectedRouteProps) -> Html {
let status = resp.status();
web_sys::console::log_1(&format!("Auth check: status {}", status).into());
if status == 200 {
is_authenticated.set(Some(true));
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 {
is_authenticated.set(Some(false));
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());
is_authenticated.set(Some(false));
auth_state.set(AuthState {
is_authenticated: Some(false),
is_admin: Some(false),
});
}
}
});
@@ -46,13 +64,33 @@ pub fn protected_route(props: &ProtectedRouteProps) -> Html {
});
}
match *is_authenticated {
None => html! { <div>{"Loading..."}</div> },
Some(true) => props.children.clone().into(),
Some(false) => {
html! {
<Redirect<crate::Route> to={crate::Route::Login} />
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> },
}
}