From 23910167097fc27c19ae07b60ee4fa1faf6e7d2a Mon Sep 17 00:00:00 2001 From: Aidan Westphal Date: Sun, 1 Dec 2024 22:56:50 +0000 Subject: [PATCH] API Endpoints for managing friend requests, and a LOT of trait bound debugging... --- src/api/profile.rs | 176 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 1 deletion(-) diff --git a/src/api/profile.rs b/src/api/profile.rs index 9bf900f..8bc8878 100644 --- a/src/api/profile.rs +++ b/src/api/profile.rs @@ -17,9 +17,11 @@ cfg_if! { use crate::database::get_db_conn; use diesel::prelude::*; use diesel::dsl::count; + use diesel::dsl::exists; use crate::models::*; use crate::schema::*; + use chrono::prelude::*; use std::collections::HashMap; } } @@ -325,7 +327,6 @@ pub async fn friends(for_user_id: i32) ) .load(&mut db_con)?; - // leave out the password field for security let friend_list: Vec = friends.into_iter().map(|(user, created_at): (User, NaiveDateTime)| { FriendData { username: user.username, @@ -336,3 +337,176 @@ pub async fn friends(for_user_id: i32) Ok(friend_list) } + +/// Get a user's list of friend requests (outgoing) from the database +#[server(endpoint = "/profile/friend-requests-outgoing")] +pub async fn friend_requests_outgoing(for_user_id: i32) + -> Result, ServerFnError> +{ + let mut db_con = get_db_conn(); + + let friends = friend_requests::table + .filter(friend_requests::from_id.eq(for_user_id)) + .filter(friend_requests::from_id.ne(friend_requests::to_id)) + .inner_join(users::table.on(users::id.eq(friend_requests::to_id))) + .select((users::all_columns, friend_requests::created_at)) + .order(friend_requests::created_at.desc()) + .order(users::username.asc()) + .load(&mut db_con)?; + + let friend_list: Vec = friends.into_iter().map(|(user, created_at): (User, NaiveDateTime)| { + FriendData { + username: user.username, + created_at: created_at.into(), + user_id: user.id.unwrap() + } + }).collect(); + + Ok(friend_list) +} + +/// Get a user's list of friend requests (incoming) from the database +#[server(endpoint = "/profile/friend-requests-incoming")] +pub async fn friend_requests_incoming(for_user_id: i32) + -> Result, ServerFnError> +{ + let mut db_con = get_db_conn(); + + let friends = friend_requests::table + .filter(friend_requests::to_id.eq(for_user_id)) + .filter(friend_requests::from_id.ne(friend_requests::to_id)) + .inner_join(users::table.on(users::id.eq(friend_requests::from_id))) + .select((users::all_columns, friend_requests::created_at)) + .order(friend_requests::created_at.desc()) + .order(users::username.asc()) + .load(&mut db_con)?; + + let friend_list: Vec = friends.into_iter().map(|(user, created_at): (User, NaiveDateTime)| { + FriendData { + username: user.username, + created_at: created_at.into(), + user_id: user.id.unwrap() + } + }).collect(); + + Ok(friend_list) +} + +/// Send a friend request +#[server(endpoint = "/profile/send-friend-request")] +pub async fn send_friend_request(to_user_id: i32) + -> Result<(), ServerFnError> +{ + let mut db_con = get_db_conn(); + + // Get user id from session + let user = get_user().await + .map_err(|e| ServerFnError::::ServerError(format!("Error getting user: {}", e)))?; + + // Get current time for request + let timestamp: NaiveDateTime = Utc::now().naive_utc(); + + // Insert into database (if already exists, won't succeed due to primary key) + diesel::insert_into(crate::schema::friend_requests::table) + .values((friend_requests::created_at.eq(timestamp),friend_requests::from_id.eq(user.id.unwrap()),friend_requests::to_id.eq(to_user_id))) + .execute(&mut db_con) + .map_err(|e| { + let msg = format!("Error saving friend request to database: {}", e); + ServerFnError::::ServerError(msg) + })?; + + Ok(()) +} + +/// Remove an outgoing friend request +#[server(endpoint = "/profile/friend-requests-incoming")] +pub async fn delete_friend_request(to_user_id: i32) + -> Result<(), ServerFnError> +{ + let mut db_con = get_db_conn(); + + // Get user id from session + let user = get_user().await + .map_err(|e| ServerFnError::::ServerError(format!("Error getting user: {}", e)))?; + + // Delete the friend request + diesel::delete(friend_requests::table + .filter(friend_requests::from_id.eq(user.id.unwrap())) + .filter(friend_requests::to_id.eq(to_user_id)) + ).execute(&mut db_con)?; + + Ok(()) +} + +/// Remove an existing friendship +#[server(endpoint = "/profile/delete-friend")] +pub async fn delete_friend(for_user_id: i32) + -> Result<(), ServerFnError> +{ + let mut db_con = get_db_conn(); + + // Get user id from session + let user = get_user().await + .map_err(|e| ServerFnError::::ServerError(format!("Error getting user: {}", e)))?; + + // Delete the friend request + diesel::delete(friendships::table + .filter(friendships::friend_1_id.eq(user.id.unwrap())) + .filter(friendships::friend_2_id.eq(for_user_id)) + ).execute(&mut db_con)?; + + diesel::delete(friendships::table + .filter(friendships::friend_2_id.eq(user.id.unwrap())) + .filter(friendships::friend_1_id.eq(for_user_id)) + ).execute(&mut db_con)?; + + Ok(()) +} + +/// Accept a friend request +#[server(endpoint = "/profile/accept-friend-request")] +pub async fn accept_friend_request(to_user_id: i32) + -> Result<(), ServerFnError> +{ + let mut db_con = get_db_conn(); + + // Get user id from session + let user = get_user().await + .map_err(|e| ServerFnError::::ServerError(format!("Error getting user: {}", e)))?; + + // Get current time for request + let timestamp: NaiveDateTime = Utc::now().naive_utc(); + + // Make sure the person has received a friend request from the other person + let req = diesel::select(exists( + friend_requests::table + .filter(friend_requests::from_id.eq(user.id.unwrap())) + .filter(friend_requests::to_id.eq(to_user_id)) + )).get_result::(&mut db_con)?; + + if req == false { + Err(ServerFnError::::ServerError(format!("Error, the friend request does not exist!")))?; + } + + // Delete the friend requests + diesel::delete(friend_requests::table + .filter(friend_requests::from_id.eq(user.id.unwrap())) + .filter(friend_requests::to_id.eq(to_user_id)) + ).execute(&mut db_con)?; + + diesel::delete(friend_requests::table + .filter(friend_requests::to_id.eq(user.id.unwrap())) + .filter(friend_requests::from_id.eq(to_user_id)) + ).execute(&mut db_con)?; + + // Add the new friend request either direction + diesel::insert_into(crate::schema::friendships::table) + .values((friendships::created_at.eq(timestamp),friendships::friend_1_id.eq(user.id.unwrap()),friendships::friend_2_id.eq(to_user_id))) + .execute(&mut db_con) + .map_err(|e| { + let msg = format!("Error saving friendship to database: {}", e); + ServerFnError::::ServerError(msg) + })?; + + Ok(()) +} \ No newline at end of file