From e723f6a0538625d86931bc3205ea6d4a79365678 Mon Sep 17 00:00:00 2001 From: Chris Jean-Marie Date: Tue, 29 Oct 2024 19:29:22 +0000 Subject: [PATCH] Added logged in user roles to API --- backend/src/main.rs | 2 +- backend/src/routes.rs | 74 +++++++++++++++++++++---------- backend/src/user.rs | 12 +++-- backend/src/wishlist.rs | 37 ++++++++++++---- backend/templates/authorized.html | 6 ++- backend/templates/user.html | 14 +++--- 6 files changed, 99 insertions(+), 46 deletions(-) diff --git a/backend/src/main.rs b/backend/src/main.rs index 3a9a53b..4a1410e 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -54,7 +54,7 @@ async fn main() { .route("/useradmin", get(useradmin)) .route("/users/:user_id", get(user_profile)) .route("/roles/:user_id/:role_id/add", get(add_user_role)) - .route("/roles/:user_role_id/delete", get(delete_user_role)) + .route("/roles/:user_id/:user_role_id/delete", get(delete_user_role)) .route("/wishlists", get(wishlists)) .route("/userwishlist/:user_id", get(user_wishlist)) .route("/userwishlist/add/:user_id", get(user_wishlist_add).post(user_wishlist_add_item)) diff --git a/backend/src/routes.rs b/backend/src/routes.rs index 2b9dcd0..d6f5efb 100644 --- a/backend/src/routes.rs +++ b/backend/src/routes.rs @@ -19,6 +19,7 @@ struct ProfileTemplate { logged_in: bool, name: String, user: UserData, + user_roles: Vec, } #[derive(Template)] @@ -26,9 +27,10 @@ struct ProfileTemplate { struct UserProfileTemplate { logged_in: bool, name: String, - user: UserData, user_roles: Vec, - non_user_roles: Vec, + profile: UserData, + profile_roles: Vec, + non_profile_roles: Vec, } struct HtmlTemplate(T); @@ -61,15 +63,15 @@ struct IndexTemplate { struct DashboardTemplate { logged_in: bool, name: String, + user_roles: Vec, } pub async fn index( State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { - let user_name = user_data.as_ref().map(|s| s.name.clone()); - let logged_in = user_name.is_some(); - let name = user_name.unwrap_or_default(); + let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); + let logged_in = user_data.is_some(); if is_authorized("/dashboard", user_data, db_pool).await { Redirect::to("/dashboard").into_response() @@ -83,12 +85,15 @@ pub async fn dashboard( State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { - let user_name = user_data.as_ref().map(|s| s.name.clone()); - let logged_in = user_name.is_some(); - let name = user_name.unwrap_or_default(); + let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); + let logged_in = user_data.is_some(); - if is_authorized("/dashboard", user_data, db_pool).await { - let template = DashboardTemplate { logged_in, name }; + if is_authorized("/dashboard", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + + let template = DashboardTemplate { logged_in, name, user_roles }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() @@ -101,20 +106,24 @@ pub async fn profile( Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. - let user_name = user_data.as_ref().map(|s| s.name.clone()); - let logged_in = user_name.is_some(); - let name = user_name.unwrap_or_default(); + let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); + let logged_in = user_data.is_some(); if logged_in { // Extract the user data. let user = user_data.as_ref().unwrap().clone(); - if is_authorized("/profile", user_data, db_pool).await { - // Create the profile template. + if is_authorized("/profile", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + + // Create the profile template. let template = ProfileTemplate { logged_in, name, user: user.clone(), + user_roles, }; return HtmlTemplate(template).into_response(); } else { @@ -131,9 +140,9 @@ pub async fn user_profile( Extension(user_data): Extension>, ) -> impl IntoResponse { // Extract the user's name from the user data. - let user_name = user_data.as_ref().map(|s| s.name.clone()); + let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + let name = user_data.as_ref().map(|s| s.name.clone()).unwrap_or_default(); let logged_in = user_data.is_some(); - let name = user_name.unwrap_or_default(); // Extract the user data. let user = sqlx::query_as!(UserData, "SELECT * FROM users WHERE id = ?", user_id) @@ -142,19 +151,23 @@ pub async fn user_profile( .unwrap(); if is_authorized("/users", user_data, db_pool.clone()).await { + // Get logged in user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + // Get user roles - let user_roles = get_user_roles_display(user_id, &db_pool.clone()).await; + let profile_roles = get_user_roles_display(user_id, &db_pool.clone()).await; // Get roles user does not have - let non_user_roles = get_other_roles_display(user_id, &db_pool.clone()).await; + let non_profile_roles = get_other_roles_display(user_id, &db_pool.clone()).await; // Create the profile template. let template = UserProfileTemplate { logged_in, name, - user: user, user_roles, - non_user_roles, + profile: user, + profile_roles, + non_profile_roles, }; return HtmlTemplate(template).into_response(); } else { @@ -168,6 +181,7 @@ struct UserAdminTemplate { logged_in: bool, name: String, users: Vec, + user_roles: Vec, } pub async fn useradmin( @@ -183,11 +197,17 @@ pub async fn useradmin( .await .unwrap(); - if is_authorized("/useradmin", user_data, db_pool).await { + let user_id = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + + if is_authorized("/useradmin", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(user_id, &db_pool.clone()).await; + let template = UserAdminTemplate { logged_in, name, users, + user_roles, }; HtmlTemplate(template).into_response() } else { @@ -232,6 +252,7 @@ pub async fn contact(Extension(user_data): Extension>) -> impl struct CottageCalendarTemplate { logged_in: bool, name: String, + user_roles: Vec, } pub async fn cottagecalendar( @@ -242,8 +263,13 @@ pub async fn cottagecalendar( let logged_in = user_name.is_some(); let name = user_name.unwrap_or_default(); - if is_authorized("/cottagecalendar", user_data, db_pool).await { - let template = CottageCalendarTemplate { logged_in, name }; + let user_id = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + + if is_authorized("/cottagecalendar", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(user_id, &db_pool.clone()).await; + + let template = CottageCalendarTemplate { logged_in, name, user_roles }; HtmlTemplate(template).into_response() } else { Redirect::to("/").into_response() diff --git a/backend/src/user.rs b/backend/src/user.rs index e3b0057..cee1fd6 100644 --- a/backend/src/user.rs +++ b/backend/src/user.rs @@ -74,7 +74,7 @@ pub struct UserWishlistItem { pub received_at: i64, } -/* +/* pub async fn get_user_roles(user_id: i64, db_pool: &SqlitePool) -> Vec { // Get user roles let user_roles = sqlx::query_as( @@ -142,7 +142,7 @@ pub async fn add_user_role( } pub async fn delete_user_role( - Path(user_role_id): Path, + Path((user_id, user_role_id)): Path<(i64, i64)>, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { @@ -152,8 +152,12 @@ pub async fn delete_user_role( .execute(&db_pool) .await .unwrap(); + + let redirect_url = format!("/users/{user_id}"); + Redirect::to(&redirect_url).into_response() + } else { + Redirect::to("/").into_response() } - Redirect::to("/").into_response() } pub async fn get_user_wishlist_items(user_id: i64, db_pool: &SqlitePool) -> Vec { @@ -167,4 +171,4 @@ pub async fn get_user_wishlist_items(user_id: i64, db_pool: &SqlitePool) -> Vec< .unwrap(); user_wishlist_items -} \ No newline at end of file +} diff --git a/backend/src/wishlist.rs b/backend/src/wishlist.rs index 9e6a2cf..b42fa6c 100644 --- a/backend/src/wishlist.rs +++ b/backend/src/wishlist.rs @@ -6,7 +6,7 @@ use http::StatusCode; use serde::Deserialize; use sqlx::{SqlitePool, Row}; -use crate::{middlewares::is_authorized, user::{get_user_wishlist_items, UserData, UserWishlistItem}}; +use crate::{middlewares::is_authorized, user::{get_user_roles_display, get_user_wishlist_items, UserData, UserWishlistItem}}; struct HtmlTemplate(T); @@ -31,6 +31,7 @@ where struct WishListsTemplate { logged_in: bool, name: String, + user_roles: Vec, users: Vec, } @@ -47,11 +48,17 @@ pub async fn wishlists( .await .unwrap(); - if is_authorized("/userwishlists", user_data, db_pool).await { - let template = WishListsTemplate { - logged_in, - name, - users, + let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + + if is_authorized("/userwishlists", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + + let template = WishListsTemplate { + logged_in, + name, + users, + user_roles, }; HtmlTemplate(template).into_response() } else { @@ -66,6 +73,7 @@ struct UserWishListTemplate { name: String, my_wishlist: bool, user: UserData, + user_roles: Vec, user_wishlist_items: Vec, } @@ -89,8 +97,11 @@ pub async fn user_wishlist( .await .unwrap(); - if is_authorized("/wishlist", user_data, db_pool.clone()).await { - // Get user wishlist + if is_authorized("/wishlist", user_data, db_pool.clone()).await { + // Get user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + + // Get user wishlist let user_wishlist_items = get_user_wishlist_items(user_id, &db_pool.clone()).await; // Is viewed and viewing user the same (my wishlist)? @@ -102,6 +113,7 @@ pub async fn user_wishlist( name, my_wishlist, user: user, + user_roles, user_wishlist_items, }; return HtmlTemplate(template).into_response(); @@ -116,6 +128,7 @@ struct UserWishListAddTemplate { logged_in: bool, name: String, user: UserData, + user_roles: Vec, user_wishlist_items: Vec, } @@ -135,8 +148,13 @@ pub async fn user_wishlist_add( .await .unwrap(); + let userid = user_data.as_ref().map(|s| s.id.clone()).unwrap_or_default(); + if is_authorized("/wishlist", user_data, db_pool.clone()).await { - // Get user roles + // Get user roles + let user_roles = get_user_roles_display(userid, &db_pool.clone()).await; + + // Get user wishlist items let user_wishlist_items = get_user_wishlist_items(user_id, &db_pool.clone()).await; // Create the wishlist template. @@ -144,6 +162,7 @@ pub async fn user_wishlist_add( logged_in, name, user: user, + user_roles, user_wishlist_items, }; return HtmlTemplate(template).into_response(); diff --git a/backend/templates/authorized.html b/backend/templates/authorized.html index d80efc1..1c8500a 100644 --- a/backend/templates/authorized.html +++ b/backend/templates/authorized.html @@ -7,10 +7,14 @@

Menu

+ {% for user_role in user_roles %} + {% if user_role.role_name == "admin" %} +
  • User Administration
  • + {% endif %} + {% endfor %}
    {% block center %}{% endblock center %} diff --git a/backend/templates/user.html b/backend/templates/user.html index a5cdd45..c6ae1fc 100644 --- a/backend/templates/user.html +++ b/backend/templates/user.html @@ -2,10 +2,10 @@ {% block title %}User Profile{% endblock %} {% block center %}

    User Profile

    -Full name: {{ user.name }}
    -Given name: {{ user.given_name }}
    -Family name: {{ user.family_name }}
    -Your email address: {{ user.email }}
    +Full name: {{ profile.name }}
    +Given name: {{ profile.given_name }}
    +Family name: {{ profile.family_name }}
    +Your email address: {{ profile.email }}

    User Roles

    @@ -18,13 +18,13 @@ Your email address: {{ user.email }}
    - {% for user_role in user_roles %} + {% for user_role in profile_roles %} {{ user_role.role_name }} - Delete + Delete {% endfor %} - {% for non_user_role in non_user_roles %} + {% for non_user_role in non_profile_roles %} {{ non_user_role.role_name }} Add