moved mcaptcha into embedded
This commit is contained in:
parent
e7dd8bff63
commit
cc88c69fc6
8 changed files with 168 additions and 122 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,5 +1,9 @@
|
|||
## 0.1.4
|
||||
|
||||
## Added:
|
||||
|
||||
- `Master` trait: provides methods to manage mcaptcha
|
||||
|
||||
## Changed:
|
||||
|
||||
- `PoWConfig` has an extra field to send internal `PoW` salt to clients.
|
||||
|
@ -11,9 +15,14 @@
|
|||
- `master::Master` is moved to `master::embedded::master` in preparation
|
||||
for Redis based implementation.
|
||||
|
||||
- `crate::mcaptcha` is moved to `master::embedded::mcaptcha` in preparation
|
||||
- `crate::mcaptcha` is moved to `master::embedded::counter` in preparation
|
||||
for Redis based implementation.
|
||||
|
||||
- `AddSite` message for `Master` now requires an instance of
|
||||
`crate::master::MCaptcha`. In the case of
|
||||
`crate::master::embedded::master`, it automatically starts `Counter`
|
||||
actor.
|
||||
|
||||
## 0.1.3
|
||||
|
||||
## Added
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use libmcaptcha::{
|
||||
cache::{messages::VerifyCaptchaResult, HashCache},
|
||||
master::embedded::master::{AddSiteBuilder, Master},
|
||||
master::embedded::master::Master,
|
||||
master::AddSiteBuilder,
|
||||
pow::{ConfigBuilder, Work},
|
||||
system::SystemBuilder,
|
||||
DefenseBuilder, LevelBuilder, MCaptchaBuilder,
|
||||
|
@ -75,8 +76,7 @@ async fn main() -> std::io::Result<()> {
|
|||
.duration(30)
|
||||
// .cache(cache)
|
||||
.build()
|
||||
.unwrap()
|
||||
.start();
|
||||
.unwrap();
|
||||
|
||||
// unique value identifying an MCaptcha actor
|
||||
let mcaptcha_name = "batsense.net";
|
||||
|
@ -84,7 +84,7 @@ async fn main() -> std::io::Result<()> {
|
|||
// add MCaptcha to Master
|
||||
let msg = AddSiteBuilder::default()
|
||||
.id(mcaptcha_name.into())
|
||||
.addr(mcaptcha.clone())
|
||||
.mcaptcha(mcaptcha)
|
||||
.build()
|
||||
.unwrap();
|
||||
system.master.send(msg).await.unwrap();
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -48,7 +48,8 @@
|
|||
//! ```rust
|
||||
//! use libmcaptcha::{
|
||||
//! cache::{messages::VerifyCaptchaResult, HashCache},
|
||||
//! master::embedded::master::{AddSiteBuilder, Master},
|
||||
//! master::embedded::master:: Master,
|
||||
//! master::AddSiteBuilder,
|
||||
//! pow::{ConfigBuilder, Work},
|
||||
//! system::SystemBuilder,
|
||||
//! DefenseBuilder, LevelBuilder, MCaptchaBuilder,
|
||||
|
@ -123,8 +124,7 @@
|
|||
//! .duration(30)
|
||||
//! // .cache(cache)
|
||||
//! .build()
|
||||
//! .unwrap()
|
||||
//! .start();
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! // unique value identifying an MCaptcha actor
|
||||
//! let mcaptcha_name = "batsense.net";
|
||||
|
@ -132,7 +132,7 @@
|
|||
//! // add MCaptcha to Master
|
||||
//! let msg = AddSiteBuilder::default()
|
||||
//! .id(mcaptcha_name.into())
|
||||
//! .addr(mcaptcha.clone())
|
||||
//! .mcaptcha(mcaptcha)
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! system.master.send(msg).await.unwrap();
|
||||
|
@ -196,4 +196,5 @@ mod utils;
|
|||
pub use crate::cache::hashcache::HashCache;
|
||||
|
||||
pub use defense::{Defense, DefenseBuilder, LevelBuilder};
|
||||
pub use master::embedded::mcaptcha::{MCaptcha, MCaptchaBuilder};
|
||||
pub use master::embedded::counter::Counter;
|
||||
pub use master::MCaptchaBuilder;
|
||||
|
|
|
@ -15,11 +15,17 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//! MCaptcha actor module that manages defense levels
|
||||
//! Counter actor module that manages defense levels
|
||||
//!
|
||||
//! ## Usage:
|
||||
//! ```rust
|
||||
//! use libmcaptcha::{master::embedded::mcaptcha::AddVisitor, MCaptchaBuilder, cache::HashCache, LevelBuilder, DefenseBuilder};
|
||||
//! use libmcaptcha::{
|
||||
//! master::embedded::counter::{Counter, AddVisitor},
|
||||
//! master::MCaptchaBuilder,
|
||||
//! cache::HashCache,
|
||||
//! LevelBuilder,
|
||||
//! DefenseBuilder
|
||||
//! };
|
||||
//! // traits from actix needs to be in scope for starting actor
|
||||
//! use actix::prelude::*;
|
||||
//!
|
||||
|
@ -55,18 +61,20 @@
|
|||
//! .build()
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! // create and start MCaptcha actor
|
||||
//! // create and start Counter actor
|
||||
//! //let cache = HashCache::default().start();
|
||||
//! let mcaptcha = MCaptchaBuilder::default()
|
||||
//! .defense(defense)
|
||||
//! // leaky bucket algorithm's emission interval
|
||||
//! .duration(30)
|
||||
//! .build()
|
||||
//! .unwrap()
|
||||
//! .start();
|
||||
//! .unwrap();
|
||||
//!
|
||||
//! let counter: Counter = mcaptcha.into();
|
||||
//! let counter = counter.start();
|
||||
//!
|
||||
//! // increment count when user visits protected routes
|
||||
//! mcaptcha.send(AddVisitor).await.unwrap();
|
||||
//! counter.send(AddVisitor).await.unwrap();
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
|
@ -78,72 +86,29 @@ use std::time::Duration;
|
|||
use actix::dev::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
defense::Defense,
|
||||
errors::{CaptchaError, CaptchaResult},
|
||||
master::AddVisitorResult,
|
||||
};
|
||||
|
||||
/// Builder for [MCaptcha]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MCaptchaBuilder {
|
||||
visitor_threshold: u32,
|
||||
defense: Option<Defense>,
|
||||
duration: Option<u64>,
|
||||
}
|
||||
|
||||
impl Default for MCaptchaBuilder {
|
||||
fn default() -> Self {
|
||||
MCaptchaBuilder {
|
||||
visitor_threshold: 0,
|
||||
defense: None,
|
||||
duration: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::master::MCaptcha;
|
||||
use crate::{defense::Defense, master::AddVisitorResult};
|
||||
|
||||
/// This struct represents the mCaptcha state and is used
|
||||
/// to configure leaky-bucket lifetime and manage defense
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MCaptcha {
|
||||
pub struct Counter {
|
||||
visitor_threshold: u32,
|
||||
defense: Defense,
|
||||
duration: u64,
|
||||
}
|
||||
|
||||
impl MCaptchaBuilder {
|
||||
/// set defense
|
||||
pub fn defense(&mut self, d: Defense) -> &mut Self {
|
||||
self.defense = Some(d);
|
||||
self
|
||||
}
|
||||
|
||||
/// set duration
|
||||
pub fn duration(&mut self, d: u64) -> &mut Self {
|
||||
self.duration = Some(d);
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds new [MCaptcha]
|
||||
pub fn build(&mut self) -> CaptchaResult<MCaptcha> {
|
||||
if self.duration.is_none() {
|
||||
Err(CaptchaError::PleaseSetValue("duration".into()))
|
||||
} else if self.defense.is_none() {
|
||||
Err(CaptchaError::PleaseSetValue("defense".into()))
|
||||
} else if self.duration <= Some(0) {
|
||||
Err(CaptchaError::CaptchaDurationZero)
|
||||
} else {
|
||||
let m = MCaptcha {
|
||||
duration: self.duration.unwrap(),
|
||||
defense: self.defense.clone().unwrap(),
|
||||
visitor_threshold: self.visitor_threshold,
|
||||
};
|
||||
Ok(m)
|
||||
}
|
||||
impl From<MCaptcha> for Counter {
|
||||
fn from(m: MCaptcha) -> Counter {
|
||||
let m = Counter {
|
||||
duration: m.duration,
|
||||
defense: m.defense,
|
||||
visitor_threshold: m.visitor_threshold,
|
||||
};
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
impl MCaptcha {
|
||||
impl Counter {
|
||||
/// increments the visitor count by one
|
||||
pub fn add_visitor(&mut self) {
|
||||
self.visitor_threshold += 1;
|
||||
|
@ -166,12 +131,12 @@ impl MCaptcha {
|
|||
self.defense.get_difficulty()
|
||||
}
|
||||
|
||||
/// get [MCaptcha]'s lifetime
|
||||
/// get [Counter]'s lifetime
|
||||
pub fn get_duration(&self) -> u64 {
|
||||
self.duration
|
||||
}
|
||||
}
|
||||
impl Actor for MCaptcha {
|
||||
impl Actor for Counter {
|
||||
type Context = Context<Self>;
|
||||
}
|
||||
|
||||
|
@ -180,7 +145,7 @@ impl Actor for MCaptcha {
|
|||
#[rtype(result = "()")]
|
||||
struct DeleteVisitor;
|
||||
|
||||
impl Handler<DeleteVisitor> for MCaptcha {
|
||||
impl Handler<DeleteVisitor> for Counter {
|
||||
type Result = ();
|
||||
fn handle(&mut self, _msg: DeleteVisitor, _ctx: &mut Self::Context) -> Self::Result {
|
||||
self.decrement_visitor();
|
||||
|
@ -194,7 +159,7 @@ impl Handler<DeleteVisitor> for MCaptcha {
|
|||
pub struct AddVisitor;
|
||||
|
||||
impl AddVisitorResult {
|
||||
fn new(m: &MCaptcha) -> Self {
|
||||
fn new(m: &Counter) -> Self {
|
||||
AddVisitorResult {
|
||||
duration: m.get_duration(),
|
||||
difficulty_factor: m.get_difficulty(),
|
||||
|
@ -202,7 +167,7 @@ impl AddVisitorResult {
|
|||
}
|
||||
}
|
||||
|
||||
impl Handler<AddVisitor> for MCaptcha {
|
||||
impl Handler<AddVisitor> for Counter {
|
||||
type Result = MessageResult<AddVisitor>;
|
||||
|
||||
fn handle(&mut self, _: AddVisitor, ctx: &mut Self::Context) -> Self::Result {
|
||||
|
@ -228,7 +193,7 @@ impl Handler<AddVisitor> for MCaptcha {
|
|||
#[rtype(result = "u32")]
|
||||
pub struct GetCurrentVisitorCount;
|
||||
|
||||
impl Handler<GetCurrentVisitorCount> for MCaptcha {
|
||||
impl Handler<GetCurrentVisitorCount> for Counter {
|
||||
type Result = MessageResult<GetCurrentVisitorCount>;
|
||||
|
||||
fn handle(&mut self, _: GetCurrentVisitorCount, _ctx: &mut Self::Context) -> Self::Result {
|
||||
|
@ -236,12 +201,12 @@ impl Handler<GetCurrentVisitorCount> for MCaptcha {
|
|||
}
|
||||
}
|
||||
|
||||
/// Message to stop [MCaptcha]
|
||||
/// Message to stop [Counter]
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct Stop;
|
||||
|
||||
impl Handler<Stop> for MCaptcha {
|
||||
impl Handler<Stop> for Counter {
|
||||
type Result = ();
|
||||
|
||||
fn handle(&mut self, _: Stop, ctx: &mut Self::Context) -> Self::Result {
|
||||
|
@ -253,6 +218,8 @@ impl Handler<Stop> for MCaptcha {
|
|||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::defense::*;
|
||||
use crate::errors::*;
|
||||
use crate::master::MCaptchaBuilder;
|
||||
|
||||
// constants for testing
|
||||
// (visitor count, level)
|
||||
|
@ -260,7 +227,7 @@ pub mod tests {
|
|||
pub const LEVEL_2: (u32, u32) = (500, 500);
|
||||
pub const DURATION: u64 = 5;
|
||||
|
||||
type MyActor = Addr<MCaptcha>;
|
||||
type MyActor = Addr<Counter>;
|
||||
|
||||
pub fn get_defense() -> Defense {
|
||||
DefenseBuilder::default()
|
||||
|
@ -286,13 +253,17 @@ pub mod tests {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
async fn race(addr: Addr<MCaptcha>, count: (u32, u32)) {
|
||||
async fn race(addr: Addr<Counter>, count: (u32, u32)) {
|
||||
for _ in 0..count.0 as usize - 1 {
|
||||
let _ = addr.send(AddVisitor).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_counter() -> MCaptcha {
|
||||
pub fn get_counter() -> Counter {
|
||||
get_mcaptcha().into()
|
||||
}
|
||||
|
||||
pub fn get_mcaptcha() -> MCaptcha {
|
||||
MCaptchaBuilder::default()
|
||||
.defense(get_defense())
|
||||
.duration(DURATION)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//! [Master] actor module that manages [MCaptcha] actors
|
||||
//! [Master] actor module that manages [Counter] actors
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::time::Duration;
|
||||
|
@ -23,30 +23,28 @@ use std::time::Duration;
|
|||
//use actix::clock::sleep;
|
||||
use actix::clock::delay_for;
|
||||
use actix::dev::*;
|
||||
use derive_builder::Builder;
|
||||
use log::info;
|
||||
|
||||
use super::mcaptcha::MCaptcha;
|
||||
use crate::master::AddVisitor;
|
||||
use super::counter::Counter;
|
||||
use crate::master::Master as MasterTrait;
|
||||
use crate::master::{AddSite, AddVisitor};
|
||||
|
||||
/// This Actor manages the [MCaptcha] actors.
|
||||
/// A service can have several [MCaptcha] actors with
|
||||
/// This Actor manages the [Counter] actors.
|
||||
/// A service can have several [Counter] actors with
|
||||
/// varying [Defense][crate::defense::Defense] configurations
|
||||
/// so a "master" actor is needed to manage them all
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Master {
|
||||
sites: BTreeMap<String, (Option<()>, Addr<MCaptcha>)>,
|
||||
sites: BTreeMap<String, (Option<()>, Addr<Counter>)>,
|
||||
gc: u64,
|
||||
}
|
||||
|
||||
impl MasterTrait for Master {}
|
||||
|
||||
impl Master {
|
||||
/// add [MCaptcha] actor to [Master]
|
||||
pub fn add_site(&mut self, details: AddSite) {
|
||||
self.sites
|
||||
.insert(details.id, (None, details.addr.to_owned()));
|
||||
/// add [Counter] actor to [Master]
|
||||
pub fn add_site(&mut self, addr: Addr<Counter>, id: String) {
|
||||
self.sites.insert(id, (None, addr.to_owned()));
|
||||
}
|
||||
|
||||
/// create new master
|
||||
|
@ -58,8 +56,8 @@ impl Master {
|
|||
}
|
||||
}
|
||||
|
||||
/// get [MCaptcha] actor from [Master]
|
||||
pub fn get_site<'a, 'b>(&'a mut self, id: &'b str) -> Option<Addr<MCaptcha>> {
|
||||
/// get [Counter] actor from [Master]
|
||||
pub fn get_site<'a, 'b>(&'a mut self, id: &'b str) -> Option<Addr<Counter>> {
|
||||
let mut r = None;
|
||||
if let Some((read_val, addr)) = self.sites.get_mut(id) {
|
||||
r = Some(addr.clone());
|
||||
|
@ -68,7 +66,7 @@ impl Master {
|
|||
r
|
||||
}
|
||||
|
||||
/// remvoes [MCaptcha] actor from [Master]
|
||||
/// remvoes [Counter] actor from [Master]
|
||||
pub fn rm_site(&mut self, id: &str) {
|
||||
self.sites.remove(id);
|
||||
}
|
||||
|
@ -99,7 +97,7 @@ impl Handler<AddVisitor> for Master {
|
|||
let fut = async move {
|
||||
let config = addr
|
||||
.unwrap()
|
||||
.send(super::mcaptcha::AddVisitor)
|
||||
.send(super::counter::AddVisitor)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -112,9 +110,9 @@ impl Handler<AddVisitor> for Master {
|
|||
}
|
||||
}
|
||||
|
||||
/// Message to get an [MCaptcha] actor from master
|
||||
/// Message to get an [Counter] actor from master
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "Option<Addr<MCaptcha>>")]
|
||||
#[rtype(result = "Option<Addr<Counter>>")]
|
||||
pub struct GetSite(pub String);
|
||||
|
||||
impl Handler<GetSite> for Master {
|
||||
|
@ -130,7 +128,7 @@ impl Handler<GetSite> for Master {
|
|||
}
|
||||
}
|
||||
|
||||
/// Message to clean up master of [MCaptcha] actors with zero visitor count
|
||||
/// Message to clean up master of [Counter] actors with zero visitor count
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct CleanUp;
|
||||
|
@ -145,7 +143,7 @@ impl Handler<CleanUp> for Master {
|
|||
info!("init master actor cleanup up");
|
||||
let task = async move {
|
||||
for (id, (new, addr)) in sites.iter() {
|
||||
use super::mcaptcha::{GetCurrentVisitorCount, Stop};
|
||||
use super::counter::{GetCurrentVisitorCount, Stop};
|
||||
let visitor_count = addr.send(GetCurrentVisitorCount).await.unwrap();
|
||||
println!("{}", visitor_count);
|
||||
if visitor_count == 0 && new.is_some() {
|
||||
|
@ -165,7 +163,7 @@ impl Handler<CleanUp> for Master {
|
|||
}
|
||||
}
|
||||
|
||||
/// Message to delete [MCaptcha] actor
|
||||
/// Message to delete [Counter] actor
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct RemoveSite(pub String);
|
||||
|
@ -178,43 +176,38 @@ impl Handler<RemoveSite> for Master {
|
|||
}
|
||||
}
|
||||
|
||||
/// Message to add an [MCaptcha] actor to [Master]
|
||||
#[derive(Message, Builder)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct AddSite {
|
||||
pub id: String,
|
||||
pub addr: Addr<MCaptcha>,
|
||||
}
|
||||
|
||||
impl Handler<AddSite> for Master {
|
||||
type Result = ();
|
||||
|
||||
fn handle(&mut self, m: AddSite, _ctx: &mut Self::Context) -> Self::Result {
|
||||
self.add_site(m);
|
||||
let counter: Counter = m.mcaptcha.into();
|
||||
let addr = counter.start();
|
||||
self.add_site(addr, m.id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::master::embedded::mcaptcha::tests::*;
|
||||
use crate::master::embedded::counter::tests::*;
|
||||
use crate::master::AddSiteBuilder;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn master_actor_works() {
|
||||
let addr = Master::new(1).start();
|
||||
|
||||
let id = "yo";
|
||||
let mcaptcha = get_counter().start();
|
||||
let mcaptcha = get_mcaptcha();
|
||||
let msg = AddSiteBuilder::default()
|
||||
.id(id.into())
|
||||
.addr(mcaptcha.clone())
|
||||
.mcaptcha(mcaptcha.clone())
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
addr.send(msg).await.unwrap();
|
||||
|
||||
let mcaptcha_addr = addr.send(GetSite(id.into())).await.unwrap();
|
||||
assert_eq!(mcaptcha_addr, Some(mcaptcha));
|
||||
assert!(mcaptcha_addr.is_some());
|
||||
|
||||
let addr_doesnt_exist = addr.send(GetSite("a".into())).await.unwrap();
|
||||
assert!(addr_doesnt_exist.is_none());
|
||||
|
|
|
@ -16,5 +16,5 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
pub mod counter;
|
||||
pub mod master;
|
||||
pub mod mcaptcha;
|
||||
|
|
|
@ -19,12 +19,18 @@
|
|||
use std::sync::mpsc::Receiver;
|
||||
|
||||
use actix::dev::*;
|
||||
use derive_builder::Builder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod embedded;
|
||||
|
||||
use crate::defense::Defense;
|
||||
use crate::errors::*;
|
||||
|
||||
/// Describes actor handler trait impls that are required by a cache implementation
|
||||
pub trait Master: actix::Actor + actix::Handler<AddVisitor> {}
|
||||
pub trait Master: actix::Actor + actix::Handler<AddVisitor> + actix::Handler<AddSite> {}
|
||||
|
||||
//+ actix::Handler<AddSite>
|
||||
|
||||
/// Message to add visitor to an [MCaptcha] actor
|
||||
#[derive(Message)]
|
||||
|
@ -39,3 +45,68 @@ pub struct AddVisitorResult {
|
|||
pub duration: u64,
|
||||
pub difficulty_factor: u32,
|
||||
}
|
||||
|
||||
/// Message to add an [Counter] actor to [Master]
|
||||
#[derive(Message, Builder)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct AddSite {
|
||||
pub id: String,
|
||||
pub mcaptcha: MCaptcha,
|
||||
}
|
||||
|
||||
/// Builder for [MCaptcha]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MCaptchaBuilder {
|
||||
visitor_threshold: u32,
|
||||
defense: Option<Defense>,
|
||||
duration: Option<u64>,
|
||||
}
|
||||
|
||||
impl Default for MCaptchaBuilder {
|
||||
fn default() -> Self {
|
||||
MCaptchaBuilder {
|
||||
visitor_threshold: 0,
|
||||
defense: None,
|
||||
duration: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MCaptchaBuilder {
|
||||
/// set defense
|
||||
pub fn defense(&mut self, d: Defense) -> &mut Self {
|
||||
self.defense = Some(d);
|
||||
self
|
||||
}
|
||||
|
||||
/// set duration
|
||||
pub fn duration(&mut self, d: u64) -> &mut Self {
|
||||
self.duration = Some(d);
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds new [MCaptcha]
|
||||
pub fn build(self: &mut MCaptchaBuilder) -> CaptchaResult<MCaptcha> {
|
||||
if self.duration.is_none() {
|
||||
Err(CaptchaError::PleaseSetValue("duration".into()))
|
||||
} else if self.defense.is_none() {
|
||||
Err(CaptchaError::PleaseSetValue("defense".into()))
|
||||
} else if self.duration <= Some(0) {
|
||||
Err(CaptchaError::CaptchaDurationZero)
|
||||
} else {
|
||||
let m = MCaptcha {
|
||||
duration: self.duration.unwrap(),
|
||||
defense: self.defense.clone().unwrap(),
|
||||
visitor_threshold: self.visitor_threshold,
|
||||
};
|
||||
Ok(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct MCaptcha {
|
||||
visitor_threshold: u32,
|
||||
defense: Defense,
|
||||
duration: u64,
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ where
|
|||
+ ToEnvelope<T, CacheResult>
|
||||
+ ToEnvelope<T, VerifyCaptchaResult>,
|
||||
X: Master,
|
||||
<X as actix::Actor>::Context: ToEnvelope<X, crate::master::AddVisitor>,
|
||||
<X as actix::Actor>::Context:
|
||||
ToEnvelope<X, crate::master::AddVisitor> + ToEnvelope<X, crate::master::AddSite>,
|
||||
{
|
||||
/// utility function to get difficulty factor of site `id` and cache it
|
||||
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
|
||||
|
@ -123,21 +124,21 @@ mod tests {
|
|||
use super::System;
|
||||
use super::*;
|
||||
use crate::cache::HashCache;
|
||||
use crate::master::embedded::counter::tests::*;
|
||||
use crate::master::embedded::master::Master;
|
||||
use crate::master::embedded::master::*;
|
||||
use crate::master::embedded::mcaptcha::tests::*;
|
||||
use crate::master::*;
|
||||
|
||||
const MCAPTCHA_NAME: &str = "batsense.net";
|
||||
|
||||
async fn boostrap_system(gc: u64) -> System<HashCache, Master> {
|
||||
let master = Master::new(gc).start();
|
||||
let mcaptcha = get_counter().start();
|
||||
let mcaptcha = get_mcaptcha();
|
||||
let pow = get_config();
|
||||
|
||||
let cache = HashCache::default().start();
|
||||
let msg = AddSiteBuilder::default()
|
||||
.id(MCAPTCHA_NAME.into())
|
||||
.addr(mcaptcha.clone())
|
||||
.mcaptcha(mcaptcha)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
|
Loading…
Reference in a new issue