add user conv impl
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use axum::{
|
||||
Json, extract::{
|
||||
FromRequest,FromRequestParts, State,
|
||||
FromRequest,FromRequestParts, State, Path,
|
||||
|
||||
}, http::StatusCode, response::{IntoResponse, sse::KeepAlive}
|
||||
|
||||
};
|
||||
//use axum::extract::ws::Message;
|
||||
use chrono::NaiveDateTime;
|
||||
use rusqlite::{Name, params};
|
||||
use rusqlite::{Name, Statement, params};
|
||||
use rusqlite::OptionalExtension;
|
||||
use serde::Serialize;
|
||||
use serde_json::{json, to_value};
|
||||
|
||||
@@ -56,58 +57,189 @@ pub async fn add_user_to_conv(
|
||||
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get(){
|
||||
let mut conn = match pool.get(){
|
||||
Ok(conn) => conn,
|
||||
Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error"))
|
||||
};
|
||||
|
||||
let mut statement = match conn.prepare(
|
||||
"SELECT 1 FROM conversation WHERE creator_id = ?1 AND id = ?2" ,
|
||||
){
|
||||
Ok(statement) => statement,
|
||||
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "prepare failed".to_string())
|
||||
let is_creator = match conn
|
||||
.query_row(
|
||||
"SELECT 1 FROM conversation WHERE creator_id = ?1 AND id = ?2",
|
||||
params![user_id, payload.conv_id],
|
||||
|_| Ok(()),
|
||||
)
|
||||
.optional()
|
||||
{
|
||||
Ok(Some(_)) => true,
|
||||
Ok(None) => false,
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Creator check failed".to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match statement.exists(params![user_id, payload.conv_id]) {
|
||||
Ok(true) => {
|
||||
//user is creator
|
||||
}
|
||||
Ok(false) => {
|
||||
//user is not the creator
|
||||
return (StatusCode::FORBIDDEN, "Not the creato of the conversation".to_string())
|
||||
}
|
||||
Err(_) => {
|
||||
return(StatusCode::INTERNAL_SERVER_ERROR, "Query failed".to_string())
|
||||
}
|
||||
|
||||
if !is_creator {
|
||||
return (
|
||||
StatusCode::FORBIDDEN,
|
||||
"Not the creator of the conversation".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
for target_id in &payload.users {
|
||||
let rows_inserted = match conn.execute(
|
||||
"INSERT INTO conversation_participants (conversation_id, user_id) VALUES (?1, ?2)",
|
||||
params![payload.conv_id, target_id],
|
||||
) {
|
||||
Ok(n) => n,
|
||||
Err(err) => {
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, format!("Err adding user {}: {}", target_id, err));
|
||||
}
|
||||
};
|
||||
|
||||
if rows_inserted == 0 {
|
||||
return (StatusCode::NOT_FOUND, format!("Could not add user {}", target_id));
|
||||
//fix this
|
||||
let existing: HashSet<u32> = {
|
||||
let mut stmt = match conn.prepare(
|
||||
"SELECT user_id FROM conversation_participants WHERE conversation_id = ?1",
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Prepare participants stmt failed".to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match stmt.query_map(params![payload.conv_id], |row| row.get(0)) {
|
||||
Ok(rows) => rows.filter_map(Result::ok).collect(),
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Query participants failed".to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}; // ← stmt dropped HERE
|
||||
|
||||
let payload_users: HashSet<u32> = payload.users.into_iter().collect();
|
||||
|
||||
let to_add: Vec<u32> = payload_users
|
||||
.difference(&existing)
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
let to_remove : Vec<u32> = existing
|
||||
.difference(&payload_users)
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
let tx = match conn.transaction() {
|
||||
Ok(t) => t,
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Transaction start failed for update conv participants".to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
for user_id in to_add {
|
||||
if let Err(err) = tx.execute(
|
||||
"INSERT INTO conversation_participants (conversation_id, user_id)
|
||||
VALUES (?1, ?2)",
|
||||
params![payload.conv_id, user_id],
|
||||
) {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Insert failed for {}: {}", user_id, err),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for user_id in to_remove {
|
||||
if let Err(err) = tx.execute(
|
||||
"DELETE FROM conversation_participants
|
||||
WHERE conversation_id = ?1 AND user_id = ?2",
|
||||
params![payload.conv_id, user_id],
|
||||
) {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Delete failed for {}: {}", user_id, err),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(_) = tx.commit() {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Transaction commit failed".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
return (StatusCode::OK, "ok".to_string());
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct Get
|
||||
|
||||
*/
|
||||
|
||||
pub async fn get_conv_users(
|
||||
State(state): State<AppState>,
|
||||
AuthClaims{user_id, hotel_id}: AuthClaims,
|
||||
Path(conv_id): Path<(i32)>,
|
||||
) -> impl IntoResponse {
|
||||
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get (){
|
||||
Ok(c)=> c,
|
||||
Err(err)=> return (StatusCode::INTERNAL_SERVER_ERROR, format!("Error opening pol connection : {err}") )
|
||||
};
|
||||
|
||||
|
||||
let mut stmt = match conn.prepare(
|
||||
"SELECT conversation_id, name FROM conversation_participants WHERE user_id = ?1",
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(e) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Prepare failed: {}", e)),
|
||||
};
|
||||
|
||||
//fix this
|
||||
let existing: HashSet<u32> = {
|
||||
let mut stmt = match conn.prepare(
|
||||
"SELECT user_id FROM conversation_participants WHERE conversation_id = ?1",
|
||||
) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Prepare participants stmt failed".to_string(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
match stmt.query_map(params![conv_id], |row| row.get(0)) {
|
||||
Ok(rows) => rows.filter_map(Result::ok).collect(),
|
||||
Err(_) => {
|
||||
return (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Query participants failed".to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}; // ← stmt dropped HERE
|
||||
|
||||
let present: Vec<u32> = existing
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
match serde_json::to_string(&present) {
|
||||
Ok(json) => (StatusCode::OK, json),
|
||||
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Serialization failed: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_message(
|
||||
State(state): State<AppState>,
|
||||
AuthClaims {user_id, hotel_id}: AuthClaims,
|
||||
SendMessagePayload(payload):SendMessagePayload
|
||||
) -> impl IntoResponse {
|
||||
|
||||
//TODO: make sur the convid is valid
|
||||
let pool = state.hotel_pools.get_pool(hotel_id);
|
||||
|
||||
let conn = match pool.get(){
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn chat_routes() -> Router<AppState> {
|
||||
.route("/add_users_conv", put(add_user_to_conv))
|
||||
.route("/send_message", post(send_message))
|
||||
.route("/get_conv", post(get_convs))
|
||||
.route("/get_message", get(get_message))
|
||||
.route("/get_message", post(get_message))
|
||||
.route("/hotel_users", post(get_hotel_users))
|
||||
|
||||
.route("/get_conv_users/{conv_id}", post(get_conv_users))
|
||||
}
|
||||
Reference in New Issue
Block a user