diff --git a/src/master/embedded/counter.rs b/src/master/embedded/counter.rs index f6f83a0..7e41167 100644 --- a/src/master/embedded/counter.rs +++ b/src/master/embedded/counter.rs @@ -99,36 +99,6 @@ impl From for Counter { Counter(m) } } - -// impl Counter { -// /// increments the visitor count by one -// pub fn add_visitor(&mut self) { -// self.visitor_threshold += 1; -// if self.visitor_threshold > self.defense.visitor_threshold() { -// self.defense.tighten_up(); -// } else { -// self.defense.loosen_up(); -// } -// } -// -// /// decrements the visitor count by one -// pub fn decrement_visitor(&mut self) { -// if self.visitor_threshold > 0 { -// self.visitor_threshold -= 1; -// } -// } -// -// /// get current difficulty factor -// pub fn get_difficulty(&self) -> u32 { -// self.defense.get_difficulty() -// } -// -// /// get [Counter]'s lifetime -// pub fn get_duration(&self) -> u64 { -// self.duration -// } -// } - impl Actor for Counter { type Context = Context; } @@ -151,15 +121,6 @@ impl Handler for Counter { #[rtype(result = "AddVisitorResult")] pub struct AddVisitor; -//impl AddVisitorResult { -// fn new(m: &Counter) -> Self { -// AddVisitorResult { -// duration: m.0.get_duration(), -// difficulty_factor: m.0.get_difficulty(), -// } -// } -//} - impl Handler for Counter { type Result = MessageResult; diff --git a/src/master/embedded/master.rs b/src/master/embedded/master.rs index 9da880d..39af6de 100644 --- a/src/master/embedded/master.rs +++ b/src/master/embedded/master.rs @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -//! [Master] actor module that manages [Counter] actors +//! Embedded [Master] actor module that manages [Counter] actors use std::collections::BTreeMap; use std::sync::mpsc::channel; use std::time::Duration; diff --git a/src/master/embedded/mod.rs b/src/master/embedded/mod.rs index ecd66b1..8760af0 100644 --- a/src/master/embedded/mod.rs +++ b/src/master/embedded/mod.rs @@ -15,6 +15,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ - +//! Embedded master actor: manages counter and all mCaptcha stuff in-memory pub mod counter; pub mod master; diff --git a/src/master/mod.rs b/src/master/mod.rs index 269ad5d..eb8b3c0 100644 --- a/src/master/mod.rs +++ b/src/master/mod.rs @@ -16,7 +16,6 @@ * along with this program. If not, see . */ //! [Master] actor module that manages [MCaptcha] actors - use serde::{Deserialize, Serialize}; use crate::mcaptcha::*; @@ -34,6 +33,8 @@ pub trait Master: } #[derive(Serialize, Deserialize)] +/// [mCaptcha Redis module](https://github.com/mCaptcha/cache) uses this datatype for CAPTCHA +/// registration pub struct CreateMCaptcha { pub levels: Vec, pub duration: u64, @@ -49,6 +50,7 @@ pub struct AddVisitorResult { } impl AddVisitorResult { + /// create new [AddVisitorResult] from [MCaptcha] pub fn new(m: &MCaptcha) -> Self { AddVisitorResult { duration: m.get_duration(), @@ -59,6 +61,7 @@ impl AddVisitorResult { #[cfg(feature = "full")] pub mod messages { + //! Messages that a [super::Master] should respond to use std::sync::mpsc::Receiver; use actix::dev::*; diff --git a/src/master/redis/connection.rs b/src/master/redis/connection.rs index cfacc5d..a700a27 100644 --- a/src/master/redis/connection.rs +++ b/src/master/redis/connection.rs @@ -28,7 +28,7 @@ use crate::redis::RedisConnection; /// Redis instance with mCaptcha Redis module loaded pub struct MCaptchaRedis(Redis); -/// Redis instance with mCaptcha Redis module loaded +/// Connection to Redis instance with mCaptcha Redis module loaded pub struct MCaptchaRedisConnection(RedisConnection); const GET: &str = "MCAPTCHA_CACHE.GET"; @@ -40,6 +40,10 @@ const CAPTCHA_EXISTS: &str = "MCAPTCHA_CACHE.CAPTCHA_EXISTS"; const MODULE_NAME: &str = "mcaptcha_cahce"; impl MCaptchaRedis { + /// Get new [MCaptchaRedis]. Use this when executing commands that are + /// only supported by mCaptcha Redis module. Internally, when object + /// is created, checks are performed to check if the module is loaded and if + /// the required commands are available pub async fn new(redis: RedisConfig) -> CaptchaResult { let redis = Redis::new(redis).await?; let m = MCaptchaRedis(redis); @@ -47,13 +51,16 @@ impl MCaptchaRedis { Ok(m) } + /// Get connection to a Redis instance with mCaptcha Redis module loaded + /// + /// Uses interior mutability so look out for panics! pub fn get_client(&self) -> MCaptchaRedisConnection { MCaptchaRedisConnection(self.0.get_client()) } } impl MCaptchaRedisConnection { - pub async fn is_module_loaded(&self) -> CaptchaResult<()> { + async fn is_module_loaded(&self) -> CaptchaResult<()> { let modules: Vec> = self .0 .exec(redis::cmd("MODULE").arg(&["LIST"])) @@ -94,12 +101,14 @@ impl MCaptchaRedisConnection { Ok(()) } + /// Add visitor pub async fn add_visitor(&self, msg: AddVisitor) -> CaptchaResult> { let res: String = self.0.exec(redis::cmd(ADD_VISITOR).arg(&[msg.0])).await?; let res: AddVisitorResult = serde_json::from_str(&res).unwrap(); Ok(Some(res)) } + /// Register new mCaptcha with Redis pub async fn add_mcaptcha(&self, msg: AddSite) -> CaptchaResult<()> { let name = msg.id; let captcha: CreateMCaptcha = msg.mcaptcha.into(); @@ -110,6 +119,7 @@ impl MCaptchaRedisConnection { Ok(()) } + /// Check if an mCaptcha object is available in Redis pub async fn check_captcha_exists(&self, captcha: &str) -> CaptchaResult { let exists: usize = self .0 @@ -129,11 +139,13 @@ impl MCaptchaRedisConnection { } } + /// Delete an mCaptcha object from Redis pub async fn delete_captcha(&self, captcha: &str) -> CaptchaResult<()> { self.0.exec(redis::cmd(DEL).arg(&[captcha])).await?; Ok(()) } + /// Get number of visitors of an mCaptcha object from Redis pub async fn get_visitors(&self, captcha: &str) -> CaptchaResult { let visitors: usize = self.0.exec(redis::cmd(GET).arg(&[captcha])).await?; Ok(visitors) diff --git a/src/redis.rs b/src/redis.rs index 4c3f148..7f3e971 100644 --- a/src/redis.rs +++ b/src/redis.rs @@ -15,25 +15,28 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +//! Redis Client/Connection manager that can handle both single and clustered Redis Instances use std::cell::RefCell; use std::rc::Rc; use redis::cluster::ClusterClient; -use redis::FromRedisValue; -//use redis::cluster::ClusterConnection; use redis::Client; -//use redis::Connection; +use redis::FromRedisValue; use redis::{aio::Connection, cluster::ClusterConnection}; use crate::errors::*; +/// Client configuration #[derive(Clone)] pub enum RedisConfig { + /// Redis server URL Single(String), + /// List of URL of Redis nodes in cluster mode Cluster(Vec), } impl RedisConfig { + /// Create Redis connection pub fn connect(&self) -> RedisClient { match self { Self::Single(url) => { @@ -48,6 +51,7 @@ impl RedisConfig { } } +/// Redis connection - manages both single and clustered deployments pub enum RedisConnection { Single(Rc>), Cluster(Rc>), @@ -55,6 +59,7 @@ pub enum RedisConnection { impl RedisConnection { #[inline] + /// Get client. Uses interior mutability, so lookout for panics pub fn get_client(&self) -> Self { match self { Self::Single(con) => Self::Single(Rc::clone(&con)), @@ -62,6 +67,7 @@ impl RedisConnection { } } #[inline] + /// execute a redis command against a [Self] pub async fn exec(&self, cmd: &mut redis::Cmd) -> redis::RedisResult { match self { RedisConnection::Single(con) => cmd.query_async(&mut *con.borrow_mut()).await, @@ -71,17 +77,21 @@ impl RedisConnection { } #[derive(Clone)] +/// Client Configuration that can be used to get new connection shuld [RedisConnection] fail pub enum RedisClient { Single(Client), Cluster(ClusterClient), } +/// A Redis Client Object that encapsulates [RedisClient] and [RedisConnection]. +/// Use this when you need a Redis Client pub struct Redis { _client: RedisClient, connection: RedisConnection, } impl Redis { + /// create new [Redis]. Will try to connect to Redis instance specified in [RedisConfig] pub async fn new(redis: RedisConfig) -> CaptchaResult { let (_client, connection) = Self::connect(redis).await; let master = Self { @@ -91,6 +101,9 @@ impl Redis { Ok(master) } + /// Get client to do interact with Redis server. + /// + /// Uses Interior mutability so look out for panics pub fn get_client(&self) -> RedisConnection { self.connection.get_client() }