diff options
-rw-r--r-- | src/db.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 161 | ||||
-rw-r--r-- | src/posts.rs | 153 |
3 files changed, 166 insertions, 151 deletions
diff --git a/src/db.rs b/src/db.rs index d09ce21..0ad16ca 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,6 +1,7 @@ +use std::time; + use log::info; use rusqlite; -use std::time; const DB_PATH: &str = "/usr/local/clinte/clinte.db"; diff --git a/src/main.rs b/src/main.rs index b7d6f7a..2e760ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,10 @@ +use std::time; + #[macro_use] extern crate lazy_static; use clap; use log::info; -use std::io; -use std::time; -use users; mod db; mod logging; @@ -17,8 +16,12 @@ fn main() { .author("Ben Morrison (gbmor)") .about("Command-line community notices system") .subcommand(clap::SubCommand::with_name("post").about("Post a new notice")) - .subcommand(clap::SubCommand::with_name("update").about("Update a notice you've posted")) - .subcommand(clap::SubCommand::with_name("delete").about("Delete a notice you've posted")) + .subcommand( + clap::SubCommand::with_name("update_handler").about("Update a notice you've posted"), + ) + .subcommand( + clap::SubCommand::with_name("delete_handler").about("Delete a notice you've posted"), + ) .get_matches(); let start = time::Instant::now(); @@ -34,158 +37,24 @@ fn main() { if arg_matches.subcommand_matches("post").is_some() { info!("New post..."); - post(&db); - } else if arg_matches.subcommand_matches("update").is_some() { - let id: u32 = if let Some(val) = arg_matches.subcommand_matches("update") { + posts::create(&db); + } else if arg_matches.subcommand_matches("update_handler").is_some() { + let id: u32 = if let Some(val) = arg_matches.subcommand_matches("update_handler") { val.value_of("id").unwrap().parse().unwrap() } else { 0 }; info!("Updating post ..."); - update(&db, id); - } else if arg_matches.subcommand_matches("delete").is_some() { - let id: u32 = if let Some(val) = arg_matches.subcommand_matches("update") { + posts::update_handler(&db, id); + } else if arg_matches.subcommand_matches("delete_handler").is_some() { + let id: u32 = if let Some(val) = arg_matches.subcommand_matches("update_handler") { val.value_of("id").unwrap().parse().unwrap() } else { 0 }; info!("Deleting post"); - delete(&db, id); + posts::delete_handler(&db, id); } posts::display(&db); } - -// Make sure nobody encodes narsty characters -// into a message to negatively affect other -// users -fn str_to_utf8(str: &str) -> String { - str.chars() - .map(|c| { - let mut buf = [0; 4]; - c.encode_utf8(&mut buf).to_string() - }) - .collect::<String>() -} - -fn post(db: &db::Conn) { - let mut stmt = db - .conn - .prepare("INSERT INTO posts (title, author, body) VALUES (:title, :author, :body)") - .unwrap(); - - println!(); - println!("Title of the new post: "); - let mut title = String::new(); - io::stdin().read_line(&mut title).unwrap(); - let title = str_to_utf8(title.trim()); - let title = if title.len() > 30 { - &title[..30] - } else { - &title - }; - - println!(); - println!("Body of the new post: "); - let mut body = String::new(); - io::stdin().read_line(&mut body).unwrap(); - let body = str_to_utf8(body.trim()); - let body = if body.len() > 500 { - &body[..500] - } else { - &body - }; - - posts::new(&mut stmt, title, body).unwrap(); - - println!(); -} - -fn update(db: &db::Conn, id: u32) { - let cur_user = users::get_current_username() - .unwrap() - .into_string() - .unwrap(); - - let id_num_in = if id == 0 { - println!(); - println!("ID number of your post to edit?"); - let mut id_num_in = String::new(); - io::stdin().read_line(&mut id_num_in).unwrap(); - id_num_in.trim().parse().unwrap() - } else { - id - }; - - let mut get_stmt = db - .conn - .prepare("SELECT * FROM posts WHERE id = :id") - .unwrap(); - - let row = get_stmt - .query_row_named(&[(":id", &id_num_in)], |row| { - let title: String = row.get(1).unwrap(); - let author = row.get(2).unwrap(); - let body = row.get(3).unwrap(); - Ok(vec![title, author, body]) - }) - .unwrap(); - - if cur_user != row[1] { - println!(); - println!("Username mismatch - can't update post!"); - return; - } - - let mut new_title = String::new(); - let mut new_body = String::new(); - - println!("Updating post {}", id_num_in); - println!(); - println!("Title: {}\n\nBody: {}", row[0], row[2]); - println!(); - println!("Enter new title:"); - io::stdin().read_line(&mut new_title).unwrap(); - println!(); - println!("Enter new body:"); - io::stdin().read_line(&mut new_body).unwrap(); - println!(); - - posts::update(&new_title, &new_body, id_num_in, &db).unwrap(); -} - -fn delete(db: &db::Conn, id: u32) { - let cur_user = users::get_current_username() - .unwrap() - .into_string() - .unwrap(); - - let id_num_in: u32 = if id == 0 { - println!(); - println!("ID of the post to delete?"); - let mut id_num_in = String::new(); - io::stdin().read_line(&mut id_num_in).unwrap(); - id_num_in.trim().parse().unwrap() - } else { - id - }; - - let del_stmt = format!("DELETE FROM posts WHERE id = {}", id_num_in); - let get_stmt = format!("SELECT * FROM posts WHERE id = {}", id_num_in); - - let mut get_stmt = db.conn.prepare(&get_stmt).unwrap(); - let mut del_stmt = db.conn.prepare(&del_stmt).unwrap(); - - let user_in_post: String = get_stmt - .query_row(rusqlite::NO_PARAMS, |row| row.get(2)) - .unwrap(); - - if cur_user != user_in_post { - println!(); - println!("Users don't match. Can't delete!"); - println!(); - return; - } - - posts::exec_stmt_no_params(&mut del_stmt).unwrap(); -} diff --git a/src/posts.rs b/src/posts.rs index 77e24fc..f8b1d6c 100644 --- a/src/posts.rs +++ b/src/posts.rs @@ -1,11 +1,16 @@ -use crate::db; -use rusqlite; use std::error::Error; +use std::io; + +use rusqlite; use users; +use crate::db; + type Result<T> = std::result::Result<T, Box<dyn Error>>; -pub fn new(stmt: &mut rusqlite::Statement, title: &str, body: &str) -> Result<()> { +// Executes the sql statement that inserts a new post +// Broken off for unit testing. +pub fn exec_new(stmt: &mut rusqlite::Statement, title: &str, body: &str) -> Result<()> { let user = users::get_current_username() .unwrap() .into_string() @@ -15,6 +20,53 @@ pub fn new(stmt: &mut rusqlite::Statement, title: &str, body: &str) -> Result<() Ok(()) } +// Make sure nobody encodes narsty characters +// into a message to negatively affect other +// users +fn str_to_utf8(str: &str) -> String { + str.chars() + .map(|c| { + let mut buf = [0; 4]; + c.encode_utf8(&mut buf).to_string() + }) + .collect::<String>() +} + +// First handler for creating a new post. +pub fn create(db: &db::Conn) { + let mut stmt = db + .conn + .prepare("INSERT INTO posts (title, author, body) VALUES (:title, :author, :body)") + .unwrap(); + + println!(); + println!("Title of the new post: "); + let mut title = String::new(); + io::stdin().read_line(&mut title).unwrap(); + let title = str_to_utf8(title.trim()); + let title = if title.len() > 30 { + &title[..30] + } else { + &title + }; + + println!(); + println!("Body of the new post: "); + let mut body = String::new(); + io::stdin().read_line(&mut body).unwrap(); + let body = str_to_utf8(body.trim()); + let body = if body.len() > 500 { + &body[..500] + } else { + &body + }; + + exec_new(&mut stmt, title, body).unwrap(); + + println!(); +} + +// Shows the most recent posts. pub fn display(db: &db::Conn) { let mut stmt = db.conn.prepare("SELECT * FROM posts").unwrap(); let out = stmt @@ -49,6 +101,61 @@ pub fn display(db: &db::Conn) { } } +// First handler to update posts. +pub fn update_handler(db: &db::Conn, id: u32) { + let cur_user = users::get_current_username() + .unwrap() + .into_string() + .unwrap(); + + let id_num_in = if id == 0 { + println!(); + println!("ID number of your post to edit?"); + let mut id_num_in = String::new(); + io::stdin().read_line(&mut id_num_in).unwrap(); + id_num_in.trim().parse().unwrap() + } else { + id + }; + + let mut get_stmt = db + .conn + .prepare("SELECT * FROM posts WHERE id = :id") + .unwrap(); + + let row = get_stmt + .query_row_named(&[(":id", &id_num_in)], |row| { + let title: String = row.get(1).unwrap(); + let author = row.get(2).unwrap(); + let body = row.get(3).unwrap(); + Ok(vec![title, author, body]) + }) + .unwrap(); + + if cur_user != row[1] { + println!(); + println!("Username mismatch - can't update_handler post!"); + return; + } + + let mut new_title = String::new(); + let mut new_body = String::new(); + + println!("Updating post {}", id_num_in); + println!(); + println!("Title: {}\n\nBody: {}", row[0], row[2]); + println!(); + println!("Enter new title:"); + io::stdin().read_line(&mut new_title).unwrap(); + println!(); + println!("Enter new body:"); + io::stdin().read_line(&mut new_body).unwrap(); + println!(); + + update(&new_title, &new_body, id_num_in, &db).unwrap(); +} + +// Allows editing of posts - called by main::update pub fn update(new_title: &str, new_body: &str, id_num_in: u32, db: &db::Conn) -> Result<()> { let new_title = new_title.trim(); let new_body = new_body.trim(); @@ -64,12 +171,50 @@ pub fn update(new_title: &str, new_body: &str, id_num_in: u32, db: &db::Conn) -> Ok(()) } +// Helper to just run a sql statement. pub fn exec_stmt_no_params(stmt: &mut rusqlite::Statement) -> Result<()> { stmt.execute(rusqlite::NO_PARAMS)?; Ok(()) } +// First handler to remove a post +pub fn delete_handler(db: &db::Conn, id: u32) { + let cur_user = users::get_current_username() + .unwrap() + .into_string() + .unwrap(); + + let id_num_in: u32 = if id == 0 { + println!(); + println!("ID of the post to delete?"); + let mut id_num_in = String::new(); + io::stdin().read_line(&mut id_num_in).unwrap(); + id_num_in.trim().parse().unwrap() + } else { + id + }; + + let del_stmt = format!("DELETE FROM posts WHERE id = {}", id_num_in); + let get_stmt = format!("SELECT * FROM posts WHERE id = {}", id_num_in); + + let mut get_stmt = db.conn.prepare(&get_stmt).unwrap(); + let mut del_stmt = db.conn.prepare(&del_stmt).unwrap(); + + let user_in_post: String = get_stmt + .query_row(rusqlite::NO_PARAMS, |row| row.get(2)) + .unwrap(); + + if cur_user != user_in_post { + println!(); + println!("Users don't match. Can't delete!"); + println!(); + return; + } + + exec_stmt_no_params(&mut del_stmt).unwrap(); +} + #[cfg(test)] mod tests { use super::*; @@ -85,7 +230,7 @@ mod tests { let title = String::from("TEST TITLE"); - new(&mut stmt, &title, "TEST BODY").unwrap(); + exec_new(&mut stmt, &title, "TEST BODY").unwrap(); update("NEW TITLE", "TEST BODY", 1, &db).unwrap(); let mut stmt = db |