From bdf8f86ba5fe8e2d19923784136d6df1c049d5f6 Mon Sep 17 00:00:00 2001 From: rasul Date: Tue, 28 Apr 2020 09:32:39 -0500 Subject: [PATCH] Move the pass and name checks to its own module outside the Game struct. This way it can be called from methods that are not members of Game such as the password set command. It does require some global variables and an initializion to get setup from the configuration. --- src/check.rs | 90 ++++++++++++++++++++++++++++++++++++++++ src/game/check_player.rs | 70 ------------------------------- src/game/mod.rs | 3 +- src/game/new.rs | 4 ++ src/game/state/login.rs | 15 +++---- src/lib.rs | 1 + src/main.rs | 1 + 7 files changed, 105 insertions(+), 79 deletions(-) create mode 100644 src/check.rs delete mode 100644 src/game/check_player.rs diff --git a/src/check.rs b/src/check.rs new file mode 100644 index 0000000..cbd52e4 --- /dev/null +++ b/src/check.rs @@ -0,0 +1,90 @@ +use std::cell::RefCell; + +use crate::config::Player; + +// this global stuff is so that we can load up the config and check stuff without +// being part of the Game struct +thread_local! { + pub static NAME_MIN: RefCell = RefCell::new(0); + pub static NAME_MAX: RefCell = RefCell::new(0); + pub static NAME_CHARS: RefCell<&'static str> = RefCell::new(""); + pub static PASS_MIN: RefCell = RefCell::new(0); + pub static PASS_MAX: RefCell = RefCell::new(0); + pub static PASS_CHARS: RefCell<&'static str> = RefCell::new(""); +} + +/// Return value for check functions +#[derive(Debug)] +pub enum PlayerCheck { + /// The value checks out + Ok(String), + + /// There is one or more issues + Err(Vec), +} + +pub fn init(config: &Player) { + NAME_MIN.with(|n| *n.borrow_mut() = config.name_min); + NAME_MAX.with(|n| *n.borrow_mut() = config.name_max); + NAME_CHARS.with(|n| *n.borrow_mut() = Box::leak(config.name_chars.clone().into_boxed_str())); + PASS_MIN.with(|p| *p.borrow_mut() = config.pass_min); + PASS_MAX.with(|p| *p.borrow_mut() = config.pass_max); + PASS_CHARS.with(|p| *p.borrow_mut() = Box::leak(config.pass_chars.clone().into_boxed_str())); +} + +/// Check the player name to ensure it meets guidelines +pub fn player_name>(name: S) -> PlayerCheck { + let name = name.into(); + let name = name.trim(); + let mut err_vec = Vec::::new(); + + if name.len() < NAME_MIN.with(|n| *n.borrow()) { + err_vec.push(format!("{} character minimum", NAME_MIN.with(|n| *n.borrow()))); + } else if name.len() > NAME_MAX.with(|n| *n.borrow()) { + err_vec.push(format!("{} character maximum", NAME_MAX.with(|n| *n.borrow()))); + } + + for c in name.chars() { + if !NAME_CHARS.with(|n| *n.borrow()).contains(&c.to_string()) { + err_vec.push(format!( + "Allowed characters are: {}", + NAME_CHARS.with(|n| *n.borrow()) + )); + break; + } + } + + if !err_vec.is_empty() { + PlayerCheck::Err(err_vec) + } else { + PlayerCheck::Ok(name.into()) + } +} + +/// Check the password to ensure it meets password requirements +pub fn player_password>(password: S) -> PlayerCheck { + let password = password.into(); + let mut err_vec = Vec::::new(); + + if password.len() < PASS_MIN.with(|p| *p.borrow()) { + err_vec.push(format!("{} character minimum", PASS_MIN.with(|p| *p.borrow()))); + } else if password.len() > PASS_MAX.with(|p| *p.borrow()) { + err_vec.push(format!("{} character maximum", PASS_MAX.with(|p| *p.borrow()))); + } + + for c in password.chars() { + if !PASS_CHARS.with(|p| *p.borrow()).contains(&c.to_string()) { + err_vec.push(format!( + "Allowed characters are: {}", + PASS_CHARS.with(|p| *p.borrow()) + )); + break; + } + } + + if err_vec.is_empty() { + PlayerCheck::Ok(password.into()) + } else { + PlayerCheck::Err(err_vec) + } +} diff --git a/src/game/check_player.rs b/src/game/check_player.rs deleted file mode 100644 index 3f5968d..0000000 --- a/src/game/check_player.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::game::Game; - -/// Return value for check functions -#[derive(Debug)] -pub enum PlayerCheck { - /// The value checks out - Ok(String), - - /// There is one or more issues - Err(Vec), -} - -impl Game { - /// Check the player name to ensure it meets guidelines - pub fn check_player_name>(&self, name: S) -> PlayerCheck { - let name = name.into(); - let name = name.trim(); - let mut err_vec = Vec::::new(); - - if name.len() < self.config.player.name_min { - err_vec.push(format!("{} character minimum", self.config.player.name_min)); - } else if name.len() > self.config.player.name_max { - err_vec.push(format!("{} character maximum", self.config.player.name_max)); - } - - for c in name.chars() { - if !self.config.player.name_chars.contains(&c.to_string()) { - err_vec.push(format!( - "Allowed characters are: {}", - self.config.player.name_chars - )); - break; - } - } - - if !err_vec.is_empty() { - PlayerCheck::Err(err_vec) - } else { - PlayerCheck::Ok(name.into()) - } - } - - /// Check the password to ensure it meets password requirements - pub fn check_player_password>(&self, password: S) -> PlayerCheck { - let password = password.into(); - let mut err_vec = Vec::::new(); - - if password.len() < self.config.player.pass_min { - err_vec.push(format!("{} character minimum", self.config.player.pass_min)); - } else if password.len() > self.config.player.pass_max { - err_vec.push(format!("{} character maximum", self.config.player.pass_max)); - } - - for c in password.chars() { - if !self.config.player.pass_chars.contains(&c.to_string()) { - err_vec.push(format!( - "Allowed characters are: {}", - self.config.player.pass_chars - )); - break; - } - } - - if err_vec.is_empty() { - PlayerCheck::Ok(password.into()) - } else { - PlayerCheck::Err(err_vec) - } - } -} diff --git a/src/game/mod.rs b/src/game/mod.rs index 2d5902c..1929e22 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,4 +1,3 @@ -mod check_player; #[allow(clippy::module_inception)] mod game; mod handle_events; @@ -7,5 +6,5 @@ mod new; mod process_recv_message; mod state; -pub use check_player::*; +//pub use check_player::*; pub use game::Game; diff --git a/src/game/new.rs b/src/game/new.rs index 2bb1b08..2908952 100644 --- a/src/game/new.rs +++ b/src/game/new.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, VecDeque}; use log::{debug, info}; use mio::{Events, Interest, Poll, Token}; +use crate::check; use crate::client::Client; use crate::config::Config; use crate::database::Db; @@ -21,6 +22,9 @@ impl Game { try_print(logger::init(log_level), "Unable to initialize logger")?; debug!("Initialized logging facility"); + debug!("Setting up check config"); + check::init(&config.player); + debug!("Opening database"); let db = Db::open(&config.database)?; diff --git a/src/game/state/login.rs b/src/game/state/login.rs index 4c616e1..ea07507 100644 --- a/src/game/state/login.rs +++ b/src/game/state/login.rs @@ -1,8 +1,9 @@ use chrono::Utc; use mio::Token; +use crate::check; use crate::command::Command; -use crate::game::{Game, PlayerCheck}; +use crate::game::Game; use crate::log_error; use crate::password::Password; use crate::player::Player; @@ -19,8 +20,8 @@ impl Game { if message.is_empty() { send_queue.push(token, "\n\nUsername: ", false, None); } else { - match self.check_player_name(message) { - PlayerCheck::Ok(name) => match self.db.find_player_by_name(&name) { + match check::player_name(message) { + check::PlayerCheck::Ok(name) => match self.db.find_player_by_name(&name) { Ok(Some(_)) => { send_queue.push( token, @@ -41,7 +42,7 @@ impl Game { send_queue.push(token, "\nError\n\nUsername: ", false, None); } }, - PlayerCheck::Err(err) => { + check::PlayerCheck::Err(err) => { send_queue.push(token, "\nInvalid username:\n", false, None); for line in err { send_queue.push(token, format!("{}\n", line), false, None); @@ -81,8 +82,8 @@ impl Game { Some(State::Login(Login::Username)), ); } else { - match self.check_player_password(message) { - PlayerCheck::Ok(pass) => { + match check::player_password(message) { + check::PlayerCheck::Ok(pass) => { match Password::new(pass) { Ok(password) => send_queue.push( token, @@ -105,7 +106,7 @@ impl Game { }, }; } - PlayerCheck::Err(err) => { + check::PlayerCheck::Err(err) => { send_queue.push(token, "\nInvalid password:\n", false, None); for line in err { send_queue.push(token, format!("{}\n", line), false, None); diff --git a/src/lib.rs b/src/lib.rs index 8d80e8f..34fece4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ //! The Rude Mud +pub mod check; pub mod client; pub mod command; pub mod config; diff --git a/src/main.rs b/src/main.rs index 612cddc..c5502ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod check; mod client; mod command; mod config;