diff --git a/services/user/Chainmail/service/src/event_query_helpers.rs b/services/user/Chainmail/service/src/event_query_helpers.rs index cd7c1c82e..e626cce77 100644 --- a/services/user/Chainmail/service/src/event_query_helpers.rs +++ b/services/user/Chainmail/service/src/event_query_helpers.rs @@ -4,18 +4,18 @@ use crate::helpers::validate_user; use psibase::services::r_events::Wrapper as REventsSvc; -use psibase::{HttpReply, HttpRequest}; - -fn make_query(req: &HttpRequest, sql: String) -> HttpRequest { - return HttpRequest { - host: req.host.clone(), - rootHost: req.rootHost.clone(), - method: String::from("POST"), - target: String::from("/sql"), - contentType: String::from("application/sql"), - body: sql.into(), - }; -} +use psibase::{Hex, HttpReply, HttpRequest}; + +// fn make_query(req: &HttpRequest, sql: String) -> HttpRequest { +// return HttpRequest { +// host: req.host.clone(), +// rootHost: req.rootHost.clone(), +// method: String::from("POST"), +// target: String::from("/sql"), +// contentType: String::from("application/sql"), +// body: sql.into(), +// }; +// } fn parse_query(query: &str) -> HashMap { let mut params: HashMap = HashMap::new(); @@ -28,46 +28,47 @@ fn parse_query(query: &str) -> HashMap { params } -fn get_where_clause_from_sender_receiver_params(params: HashMap) -> Option { - let mut s_clause = String::new(); - let s_opt = params.get("sender"); - if let Some(s) = s_opt { - if !validate_user(s) { - return None; - } - s_clause = format!("sender = '{}'", s); - } - - let mut r_clause = String::new(); - let r_opt = params.get(&String::from("receiver")); - if let Some(r) = r_opt { - if !validate_user(r) { - return None; - } - r_clause = format!("receiver = '{}'", r); - } - - if s_opt.is_none() && r_opt.is_none() { - return None; - } - - let mut where_clause: String = String::from("WHERE "); - if s_opt.is_some() { - where_clause += s_clause.as_str(); - } - if s_opt.is_some() && r_opt.is_some() { - where_clause += " AND "; - } - if r_opt.is_some() { - where_clause += r_clause.as_str(); - } - - Some(where_clause) -} +// fn get_where_clause_from_sender_receiver_params(params: HashMap) -> Option { +// let mut s_clause = String::new(); +// let s_opt = params.get("sender"); +// if let Some(s) = s_opt { +// if !validate_user(s) { +// return None; +// } +// s_clause = format!("sender = '{}'", s); +// } + +// let mut r_clause = String::new(); +// let r_opt = params.get(&String::from("receiver")); +// if let Some(r) = r_opt { +// if !validate_user(r) { +// return None; +// } +// r_clause = format!("receiver = '{}'", r); +// } + +// if s_opt.is_none() && r_opt.is_none() { +// return None; +// } + +// let mut where_clause: String = String::from("WHERE "); +// if s_opt.is_some() { +// where_clause += s_clause.as_str(); +// } +// if s_opt.is_some() && r_opt.is_some() { +// where_clause += " AND "; +// } +// if r_opt.is_some() { +// where_clause += r_clause.as_str(); +// } + +// Some(where_clause) +// } pub fn serve_rest_api(request: &HttpRequest) -> Option { if request.method == "GET" { - if !request.target.starts_with("/messages") { + println!("request.target = {}", request.target); + if !request.target.starts_with("/api/messages") { return None; } @@ -79,33 +80,93 @@ pub fn serve_rest_api(request: &HttpRequest) -> Option { let query = request.target.split_at(query_start + 1).1; let params = parse_query(query); + println!("params: {:#?}", params); + + let mut s_clause = String::new(); + let s_opt = params.get("sender"); + println!("sender: {:#?}", s_opt); + if let Some(s) = s_opt { + if !validate_user(s) { + return None; + } + s_clause = format!("sender = '{}'", s); + } + + let mut r_clause = String::new(); + let r_opt = params.get(&String::from("receiver")); + println!("receiver: {:#?}", r_opt); + if let Some(r) = r_opt { + if !validate_user(r) { + return None; + } + r_clause = format!("receiver = '{}'", r); + } - let where_clause: String; - let mq: HttpRequest; - // handle id param requests (for specific message) - if params.contains_key("id") { - where_clause = format!("WHERE CONCAT(receiver, rowid) = {}", params.get("id")?); - - mq = make_query( - request, - format!( - "SELECT * - FROM \"history.chainmail.sent\" {} ORDER BY ROWID", - where_clause - ), - ); - // handle receiver or sender param requests - } else { - where_clause = get_where_clause_from_sender_receiver_params(params)?; - - mq = make_query( - request, - format!("SELECT * - FROM \"history.chainmail.sent\" AS sent - LEFT JOIN \"history.chainmail.archive\" AS archive ON CONCAT(sent.receiver, sent.rowid) = archive.event_id {} ORDER BY ROWID", where_clause), - ); + if s_opt.is_none() && r_opt.is_none() { + return None; + } + + let archived_requested = match params.get(&String::from("archived")) { + Some(arch) => arch == "true", + None => false, + }; + println!("archived_requested: {}", archived_requested); + + let mut where_clause_sender_receiver: String = String::from(""); + if s_opt.is_some() { + where_clause_sender_receiver += s_clause.as_str(); + } + if s_opt.is_some() && r_opt.is_some() { + where_clause_sender_receiver += " AND "; + } + if r_opt.is_some() { + where_clause_sender_receiver += r_clause.as_str(); } - return REventsSvc::call().serveSys(mq); + println!("where-clause: {}", where_clause_sender_receiver); + + /* TASKS + * x- clean this up so chainmail shows sent/received messages instead of [] + * x- send a couple of archive actions so 'alice test 2' and 'bob test 1' are archived + * x- tweak this sql until I can retrieve archived an not archived messages properly + */ + + // let archived_msgs_query = "SELECT DISTINCT sent.rowid as msg_id, sent.* FROM \"history.chainmail.sent\" AS sent INNER JOIN \"history.chainmail.archive\" AS archive ON CONCAT(sent.receiver, sent.rowid) = archive.event_id"; + // let not_archvied_msgs_query = "SELECT DISTINCT sent.rowid as msg_id, archive.event_id, sent.* FROM \"history.chainmail.sent\" AS sent LEFT JOIN \"history.chainmail.archive\" AS archive ON CONCAT(sent.receiver, sent.rowid) = archive.event_id WHERE event_id IS NULL"; + + // Select from all sent emails *not archived* where receiver/send are as query params specify + let select_clause = format!("DISTINCT sent.rowid as msg_id, archive.event_id, sent.*"); + let from_clause = format!("\"history.chainmail.sent\" AS sent LEFT JOIN \"history.chainmail.archive\" AS archive ON CONCAT(sent.receiver, sent.rowid) = archive.event_id" ); + let where_clause_archived_or_not = format!( + "archive.event_id IS {} NULL", + if archived_requested { "NOT" } else { "" } + ); + let order_by_clause = "sent.ROWID"; + + let sql_query_str = format!( + "SELECT {} FROM {} WHERE {} {} {} ORDER BY {}", + select_clause, + from_clause, + where_clause_archived_or_not, + if s_opt.is_some() || r_opt.is_some() { + "AND" + } else { + "" + }, + where_clause_sender_receiver, + order_by_clause + ); + + println!("query: {}", sql_query_str); + + let query_response = REventsSvc::call().sqlQuery(sql_query_str); + println!("query_response: {}", query_response); + + return Some(HttpReply { + status: 200, + contentType: request.contentType.clone(), + headers: vec![], + body: Hex(query_response.as_bytes().to_vec()), + }); } return None; } diff --git a/services/user/Chainmail/service/src/lib.rs b/services/user/Chainmail/service/src/lib.rs index 2256fd827..57b5952e0 100644 --- a/services/user/Chainmail/service/src/lib.rs +++ b/services/user/Chainmail/service/src/lib.rs @@ -11,8 +11,8 @@ mod service { use psibase::services::events::Wrapper as EventsSvc; use psibase::services::sites::Wrapper as SitesSvc; use psibase::{ - anyhow, check, create_schema, get_sender, serve_simple_ui, AccountNumber, DbId, Fracpack, - HttpReply, HttpRequest, MethodNumber, Table, ToSchema, + anyhow, check, create_schema, get_sender, AccountNumber, DbId, Fracpack, HttpReply, + HttpRequest, MethodNumber, Table, ToSchema, }; use serde::{Deserialize, Serialize}; @@ -93,6 +93,6 @@ mod service { #[allow(non_snake_case)] fn serveSys(request: HttpRequest) -> Option { None.or_else(|| serve_rest_api(&request)) - .or_else(|| serve_simple_ui::(&request)) + // .or_else(|| serve_simple_ui::(&request)) } }