use askama_axum::IntoResponse; use axum::{ extract::{Path, State}, response::Redirect, Extension, }; use chrono::Utc; ///User related structs and functions use serde::{Deserialize, Serialize}; use sqlx::{prelude::FromRow, SqlitePool}; use crate::middlewares::is_authorized; #[derive(Default, Clone, Debug, FromRow, Serialize, Deserialize)] pub struct UserData { pub id: i64, pub created_at: i64, pub created_by: i64, pub updated_at: i64, pub updated_by: i64, pub email: String, pub name: String, pub family_name: String, pub given_name: String, } #[derive(Serialize, Deserialize)] pub struct RoleData { pub id: i64, pub created_at: i64, pub created_by: i64, pub updated_at: i64, pub updated_by: i64, pub name: String, pub description: String, } #[derive(Default, Clone, Debug, FromRow, Serialize, Deserialize)] pub struct UserRoles { pub id: i64, pub created_at: i64, pub created_by: i64, pub updated_at: i64, pub updated_by: i64, pub user_id: i64, pub role_id: i64, } #[derive(Default, Clone, Debug, FromRow, Serialize, Deserialize)] pub struct UserRolesDisplay { pub id: i64, pub created_at: i64, pub created_by: i64, pub updated_at: i64, pub updated_by: i64, pub user_id: i64, pub user_name: String, pub role_id: i64, pub role_name: String, } #[derive(Default, Clone, Debug, FromRow, Serialize, Deserialize)] pub struct UserWishlistItem { pub id: i64, pub created_at: i64, pub created_by: i64, pub updated_at: i64, pub updated_by: i64, pub user_id: i64, pub item: String, pub item_url: String, pub purchased_by: i64, 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( r#"SELECT id, created_at, created_by, updated_at, updated_by, user_id, role_id FROM user_roles WHERE user_id = ?"# ) .bind(user_id) .fetch_all(db_pool) .await .unwrap(); user_roles } */ pub async fn get_user_roles_display(user_id: i64, db_pool: &SqlitePool) -> Vec { // Get user roles let user_roles = sqlx::query_as( r#"select ur.id, u.id as user_id, u.name as user_name, r.id as role_id, r.name as role_name, r.created_at, r.created_by, r.updated_at, r.updated_by from roles r join user_roles ur on ur.role_id = r.id join users u on u.id = ur.user_id WHERE ur.user_id = ?"# ) .bind(user_id) .fetch_all(db_pool) .await .unwrap(); user_roles } pub async fn get_other_roles_display(user_id: i64, db_pool: &SqlitePool) -> Vec { // Get roles user does not have let user_roles = sqlx::query_as( r#"select 0 as id, r.created_at, r.created_by, r.updated_at, r.updated_by, ? as user_id, '' as user_name, r.id as role_id, r.name as role_name from roles r where r.id not in (select ur.role_id from user_roles ur where ur.user_id = ?)"# ) .bind(user_id.clone()) .bind(user_id) .fetch_all(db_pool) .await .unwrap(); user_roles } pub async fn add_user_role( Path((user_id, role_id)): Path<(i64, i64)>, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { if is_authorized("/roles", user_data.clone(), db_pool.clone()).await { let now = Utc::now().timestamp(); sqlx::query("INSERT INTO user_roles (created_at, created_by, updated_at, updated_by, user_id, role_id) VALUES (?, ?, ?, ?, ?, ?)") .bind(now)// Created now .bind(user_data.as_ref().unwrap().id)// Created by current user .bind(now) // Updated now .bind(user_data.as_ref().unwrap().id) // Updated by current user .bind(user_id) .bind(role_id) .execute(&db_pool) .await .unwrap(); // TODO - send email to user regarding role changes let redirect_url = format!("/users/{user_id}"); Redirect::to(&redirect_url).into_response() } else { Redirect::to("/").into_response() } } pub async fn delete_user_role( Path((user_id, user_role_id)): Path<(i64, i64)>, State(db_pool): State, Extension(user_data): Extension>, ) -> impl IntoResponse { if is_authorized("/roles", user_data, db_pool.clone()).await { sqlx::query("DELETE FROM user_roles WHERE id = ?") .bind(user_role_id) .execute(&db_pool) .await .unwrap(); let redirect_url = format!("/users/{user_id}"); Redirect::to(&redirect_url).into_response() } else { Redirect::to("/").into_response() } } pub async fn get_user_wishlist_items(user_id: i64, db_pool: &SqlitePool) -> Vec { // Get wish list items for the user let user_wishlist_items = sqlx::query_as( r#"select id, created_at, created_by, updated_at, updated_by, user_id, item, item_url, purchased_by, received_at from wishlist_items where user_id = ?"# ) .bind(user_id) .fetch_all(db_pool) .await .unwrap(); user_wishlist_items }