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")] #[display(fmt = "difficulty factor must be greater than zero")]
DifficultyFactorZero, DifficultyFactorZero,
/// captcha cooldown duration must be greater than 0
#[display(fmt = "difficulty factor must be greater than zero")]
CaptchaDurationZero,
/// Difficulty factor must be set /// Difficulty factor must be set
#[display(fmt = "Set difficulty factor")] #[display(fmt = "Set difficulty factor")]
SetDifficultyFactor, SetDifficultyFactor,
@ -63,6 +67,10 @@ pub enum CaptchaError {
/// isn't in cache /// isn't in cache
#[display(fmt = "String now found")] #[display(fmt = "String now found")]
StringNotFound, 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 /// [Result] datatype for m_captcha

View File

@ -75,20 +75,72 @@
use std::time::Duration; use std::time::Duration;
use actix::dev::*; 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 /// This struct represents the mCaptcha state and is used
/// to configure leaky-bucket lifetime and manage defense /// to configure leaky-bucket lifetime and manage defense
#[derive(Clone, Debug, Builder)] #[derive(Clone, Serialize, Deserialize, Debug)]
pub struct MCaptcha { pub struct MCaptcha {
#[builder(default = "0", setter(skip))]
visitor_threshold: u32, visitor_threshold: u32,
defense: Defense, defense: Defense,
duration: u64, 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 { impl MCaptcha {
/// increments the visitor count by one /// increments the visitor count by one
pub fn add_visitor(&mut self) { pub fn add_visitor(&mut self) {
@ -256,4 +308,27 @@ pub mod tests {
mcaptcha = addr.send(Visitor).await.unwrap(); mcaptcha = addr.send(Visitor).await.unwrap();
assert_eq!(mcaptcha.difficulty_factor, LEVEL_1.1); 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()))
);
}
} }