From 351a9ba30c0db24532ca32b097c6ab9a1b247d2b Mon Sep 17 00:00:00 2001 From: shockrah Date: Wed, 29 Jul 2020 00:26:19 -0700 Subject: [PATCH] list channels and create channels behaving properly based on inputs, delete_channel not working just yet --- server/src/channels.rs | 92 +++++++++++++++++++++++++++++------------- server/src/db_types.rs | 8 +++- server/src/main.rs | 3 ++ 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/server/src/channels.rs b/server/src/channels.rs index d61ad85..dd50cf9 100644 --- a/server/src/channels.rs +++ b/server/src/channels.rs @@ -9,8 +9,9 @@ use mysql_async::prelude::{params, Queryable}; use serde_json::Value; -use crate::db_types::{UBigInt, VarChar, Integer}; +use crate::db_types::{DbError, UBigInt, VarChar, Integer}; +#[derive(Debug)] pub enum ChannelType { Voice, Text, @@ -59,9 +60,9 @@ pub struct Channel { kind: ChannelType } +#[derive(Debug)] struct InsertableChannel { name: String, - description: String, kind: ChannelType } @@ -70,11 +71,16 @@ impl Channel { * When our sql library queries things we generally get back tuples rather reasily * we can use this method to get something that makes more sense */ - fn from_tup(tup: (u64, String, String, i32)) -> Channel { + fn from_tup(tup: (UBigInt, VarChar, Option, Integer)) -> Channel { + let desc = match tup.2 { + Some(val) => val, + None => "None".into() + }; + Channel { id: tup.0, name: tup.1, - description: tup.2, + description: desc, kind: ChannelType::from_i32(tup.3) } } @@ -84,7 +90,7 @@ impl Channel { * { * "id": id, * "name": "", - * "description": "", + * "description": Option<"">, * "kind": kind * } */ @@ -106,8 +112,7 @@ impl Channel { async fn get_channels_vec(conn: Conn) -> Result, Error> { let rows_db = conn.prep_exec(r"SELECT * FROM channels", ()).await?; let (_, rows) = rows_db.map_and_drop(|row| { - let (id, name, desc, kind): (UBigInt, VarChar, VarChar, Integer) = mysql_async::from_row(row); - println!("{}, {}, {}, {}", id, name, desc, kind); + let (id, name, desc, kind): (UBigInt, VarChar, Option, Integer) = mysql_async::from_row(row); Channel::from_tup((id, name, desc, kind)) }).await?; @@ -150,19 +155,15 @@ pub async fn list_channels(pool: &Pool, response: &mut Response) { } } -fn parse_insert_channel_params(name_r: Option<&Value>, kind_r: Option<&Value>, desc_r: Option<&Value>) -> +fn parse_insert_channel_params(name_r: Option<&Value>, kind_r: Option<&Value>) -> Result { match (name_r, kind_r) { (Some(name), Some(kind)) => { - let desc: String = match desc_r { - Some(d) => d.as_str().unwrap().to_string(), // if this fails burn the server - None => "".into() - }; + let channel = InsertableChannel { name: name.to_string(), kind: ChannelType::from_i64_opt(kind.as_i64()), - description: desc }; Ok(channel) } @@ -172,16 +173,25 @@ fn parse_insert_channel_params(name_r: Option<&Value>, kind_r: Option<&Value>, d } } } -async fn insert_channel(pool: &Pool, channel: InsertableChannel) -> Result<(), Error> { - let conn = pool.get_conn().await?; - conn.batch_exec( - r"INSERT INTO channels (name, kind, description) VALUES (:name, :kind, :description)", - params!{ - "name" => channel.name, - "kind" => channel.kind.as_i32(), - "description" => channel.description, - }).await?; - Ok(()) +async fn insert_channel(pool: &Pool, channel: InsertableChannel) -> Result<(), DbError> { + if let Ok(conn) = pool.get_conn().await { + let db_result: Result = conn.drop_exec( + "INSERT INTO channels (name, kind) VALUES (:name, 0)", + mysql_async::params!{ "name" => channel.name } + ).await; + match db_result { + Ok(_) => Ok(()), + Err(e) => { + match e { + Error::Server(_) => Err(DbError::BadParam("Couldn't process input somehow")), + _ => Err(DbError::Internal) + } + } + } + } + else { + Err(DbError::Connection("Could not connect to database at all")) + } } pub async fn create_channel(pool: &Pool, response: &mut Response, params: Value) { @@ -189,16 +199,44 @@ pub async fn create_channel(pool: &Pool, response: &mut Response, params: * Create a channel base on a few parameters that may or may not be there */ let name_r = params.get("name"); - let desc_r = params.get("description"); let kind_r = params.get("kind"); - match parse_insert_channel_params(name_r, kind_r, desc_r) { + match parse_insert_channel_params(name_r, kind_r) { Ok(channel) => { match insert_channel(pool, channel).await { Ok(_) => *response.status_mut() = StatusCode::OK, - Err(_) => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR + Err(dbe) => { + // Todo: add some form of loggin off the back of these values + match dbe { + DbError::BadParam(_msg) => *response.status_mut() = StatusCode::BAD_REQUEST, + DbError::Connection(_msg) => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR, + DbError::Internal => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR + } + } } }, Err(_) => *response.status_mut() = StatusCode::BAD_REQUEST } -} \ No newline at end of file +} + +async fn db_delete_channel(pool: &Pool, name: &Value) -> Result<(), Error> { + let conn = pool.get_conn().await?; + let q = "DELETE FROM channels WHERE name = :name"; + let p = params!{ "name" => name.as_str().unwrap() }; + conn.batch_exec(q, p).await?; + Ok(()) +} +pub async fn delete_channel(pool: &Pool, response: &mut Response, params: Value) { + // make sure we have the right parameters provided + if let Some(name) = params.get("name") { + match db_delete_channel(pool, name).await { + Ok(_) => *response.status_mut() = StatusCode::OK, + Err(e) => { + println!("delete_chanel sql error :\n{}", e); + } + } + } + else { + *response.status_mut() = StatusCode::BAD_REQUEST; + } +} diff --git a/server/src/db_types.rs b/server/src/db_types.rs index becbf2e..e1d15ee 100644 --- a/server/src/db_types.rs +++ b/server/src/db_types.rs @@ -4,4 +4,10 @@ pub type UInteger = u32; pub type UBigInt = u64; pub type BigInt = i64; -pub type VarChar = String; \ No newline at end of file +pub type VarChar = String; + +pub enum DbError { + BadParam(&'static str), + Connection(&'static str), + Internal +} diff --git a/server/src/main.rs b/server/src/main.rs index 0256b6b..45c2c6d 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -47,6 +47,7 @@ async fn route_dispatcher(pool: &Pool, resp: &mut Response, meth: &Method, }, (&Method::GET, routes::CHANNELS_LIST) => channels::list_channels(pool, resp).await, (&Method::POST, routes::CHANNELS_CREATE) => channels::create_channel(pool, resp, params).await, + (&Method::POST, routes::CHANNELS_DELETE) => channels::delete_channel(pool, resp, params).await, (&Method::POST, routes::MESSAGE_SEND) => messages::send_message(pool, resp, params).await, _ => { @@ -63,6 +64,7 @@ async fn route_dispatcher(pool: &Pool, resp: &mut Response, meth: &Method, println!("Dynamic part: {}", route.dynamic); } else { + println!("NOT FOUND: {}: {}", meth, path); *resp.status_mut() = StatusCode::NOT_FOUND } } @@ -96,6 +98,7 @@ async fn main_responder(request: Request) -> Result, hyper: } } else { + println!("PARSER: Parameter parsing failed"); *response.status_mut() = StatusCode::BAD_REQUEST; } Ok(response)