mcatcha duration greater than 0, fixes #2

This commit is contained in:
Aravinth Manivannan 2021-03-14 16:17:26 +05:30
parent f401124d9f
commit 5264430936
Signed by: realaravinth
GPG Key ID: AD9F0F08E855ED88
2 changed files with 87 additions and 4 deletions

View File

@ -34,6 +34,10 @@ pub enum CaptchaError {
#[display(fmt = "difficulty factor must be greater than zero")]
DifficultyFactorZero,
/// captcha cooldown duration must be greater than 0
#[display(fmt = "difficulty factor must be greater than zero")]
CaptchaDurationZero,
/// Difficulty factor must be set
#[display(fmt = "Set difficulty factor")]
SetDifficultyFactor,
@ -63,6 +67,10 @@ pub enum CaptchaError {
/// isn't in cache
#[display(fmt = "String now found")]
StringNotFound,
/// Used in builder structs when a value is not set
#[display(fmt = "Please set value: {}", _0)]
PleaseSetValue(#[error(not(source))] String),
}
/// [Result] datatype for m_captcha

View File

@ -75,20 +75,72 @@
use std::time::Duration;
use actix::dev::*;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use crate::defense::Defense;
use crate::{
defense::Defense,
errors::{CaptchaError, CaptchaResult},
};
/// 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,
}
}
}
/// This struct represents the mCaptcha state and is used
/// to configure leaky-bucket lifetime and manage defense
#[derive(Clone, Debug, Builder)]
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct MCaptcha {
#[builder(default = "0", setter(skip))]
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 MCaptcha {
/// increments the visitor count by one
pub fn add_visitor(&mut self) {
@ -256,4 +308,27 @@ pub mod tests {
mcaptcha = addr.send(Visitor).await.unwrap();
assert_eq!(mcaptcha.difficulty_factor, LEVEL_1.1);
}
#[test]
fn test_mcatcptha_builder() {
let defense = get_defense();
let m = MCaptchaBuilder::default()
.duration(0)
.defense(defense.clone())
.build();
assert_eq!(m.err(), Some(CaptchaError::CaptchaDurationZero));
let m = MCaptchaBuilder::default().duration(30).build();
assert_eq!(
m.err(),
Some(CaptchaError::PleaseSetValue("defense".into()))
);
let m = MCaptchaBuilder::default().defense(defense.clone()).build();
assert_eq!(
m.err(),
Some(CaptchaError::PleaseSetValue("duration".into()))
);
}
}