diff --git a/backend/src/handlers/auth.rs b/backend/src/handlers/auth.rs index 6b8d8d9..56cdab6 100644 --- a/backend/src/handlers/auth.rs +++ b/backend/src/handlers/auth.rs @@ -163,7 +163,8 @@ pub async fn get_current_user( "data": json!({ "id": user.id, "first_name": user.first_name, - "last_name": user.last_name + "last_name": user.last_name, + "is_admin": user.is_admin }) }); diff --git a/frontend/src/auth.rs b/frontend/src/auth.rs index fe06539..9afac06 100644 --- a/frontend/src/auth.rs +++ b/frontend/src/auth.rs @@ -5,22 +5,27 @@ use yew_router::prelude::*; #[derive(Clone, Debug, PartialEq)] pub struct AuthState { - pub is_authenticated: bool, + 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 is_authenticated = use_state(|| None::); + 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! {
{"Loading..."}
}, - Some(true) => props.children.clone().into(), - Some(false) => { - html! { - to={crate::Route::Login} /> + 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..." }
}, } } diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index a9cfd64..25e8bbb 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -1,7 +1,7 @@ -mod pages; mod auth; -use crate::pages::*; +mod pages; use crate::auth::ProtectedRoute; +use crate::pages::*; use yew::prelude::*; use yew_router::prelude::*; @@ -23,6 +23,8 @@ enum Route { AllUsers, #[at("/users/:id")] UserByID { id: i16 }, + #[at("/denied")] + PermissionDenied, #[not_found] #[at("/404")] NotFound, @@ -30,43 +32,44 @@ enum Route { fn switch(route: Route) -> Html { match route { - Route::Home => html! { - + Route::Home => html! { + }, Route::NotFound => html! { }, - Route::Ticket => html! { - - + Route::Ticket => html! { + + }, - Route::TicketById { id } => html! { - - + Route::TicketById { id } => html! { + + }, - Route::AllTickets => html! { - - + Route::AllTickets => html! { + + }, - Route::Register => html! { - - + Route::Register => html! { + + }, Route::Login => html! { }, Route::AllUsers => html! { - + }, - Route::UserByID { id } => html! { - - + Route::UserByID { id } => html! { + + }, + Route::PermissionDenied => html! { }, } } diff --git a/frontend/src/pages/basic_pages.rs b/frontend/src/pages/basic_pages.rs index 670e068..056eb48 100644 --- a/frontend/src/pages/basic_pages.rs +++ b/frontend/src/pages/basic_pages.rs @@ -28,3 +28,13 @@ pub fn not_found_component() -> Html { } } + +#[component(PermissionDenied)] +pub fn denied_component() -> Html { + html! { +
+

{ "Sie haben nicht die benötigten Rechte um diese Seite aufzurufen" }

+

{ "Wenn sie denken, dass dies ein Fehler ist kontaktieren sie Herrn Winter" }

+
+ } +} diff --git a/frontend/src/pages/user.rs b/frontend/src/pages/user.rs index 375e5b9..e20a925 100644 --- a/frontend/src/pages/user.rs +++ b/frontend/src/pages/user.rs @@ -4,6 +4,7 @@ use gloo_net::http::Request; use serde::{Deserialize, Serialize}; use wasm_bindgen_futures::spawn_local; use yew::prelude::*; +use yew_router::prelude::use_navigator; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct User { @@ -177,6 +178,7 @@ pub fn login_component() -> Html { let loading = use_state(|| false); let error = use_state(|| String::new()); let success = use_state(|| false); + let navigator = use_navigator().unwrap(); let onsubmit = { let username = username.clone(); @@ -184,6 +186,7 @@ pub fn login_component() -> Html { let loading = loading.clone(); let error = error.clone(); let success = success.clone(); + let navigator = navigator.clone(); Callback::from(move |e: SubmitEvent| { e.prevent_default(); @@ -192,6 +195,7 @@ pub fn login_component() -> Html { let loading = loading.clone(); let error = error.clone(); let success = success.clone(); + let navigator = navigator.clone(); loading.set(true); error.set(String::new()); @@ -211,7 +215,10 @@ pub fn login_component() -> Html { loading.set(false); match response { - Ok(r) if r.status() == 200 => success.set(true), + Ok(r) if r.status() == 200 => { + success.set(true); + navigator.push(&crate::Route::Home); + } Ok(r) => { let text = r.text().await.unwrap_or_else(|_| "unknown".into()); error.set(format!("HTTP {}: {}", r.status(), text)); @@ -242,7 +249,6 @@ pub fn login_component() -> Html { })} /> - if *success {

{"Logged in — cookie set by server"}

} if !error.is_empty() {

{(*error).clone()}

} }