extending Save to cache captcha responses

This commit is contained in:
Aravinth Manivannan 2021-04-09 17:28:04 +05:30
parent 61ee89aee3
commit b597c0b965
Signed by untrusted user: realaravinth
GPG Key ID: AD9F0F08E855ED88
7 changed files with 141 additions and 29 deletions

View File

@ -2,6 +2,16 @@
## Fixed
- a bug in `mCaptcha/pow_sha256` was causing errors in PoW computation
## Changed
- `Cache` became `CachePoW` (`HashCache` extension)
- `Retrieve` became `RetrievePoW`(`HashCache` extension)
- `DeleteString` became `DeletePoW` (`HashCache` extension)
- `Save` trait now requires three new message impls (`HashCache` extension_
## Added
- `HashCache` was extended to store captcha responses
## 0.1.2
## Changed
- actix upgraded to `0.11`

89
Cargo.lock generated
View File

@ -76,6 +76,15 @@ dependencies = [
"syn",
]
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "async-trait"
version = "0.1.48"
@ -87,6 +96,17 @@ dependencies = [
"syn",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "autocfg"
version = "1.0.1"
@ -341,6 +361,19 @@ dependencies = [
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -499,6 +532,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -615,7 +657,9 @@ dependencies = [
"actix-rt",
"derive_builder 0.9.0",
"derive_more",
"log",
"pow_sha256",
"pretty_env_logger",
"rand 0.8.3",
"serde",
"serde_json",
@ -806,6 +850,16 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"log",
]
[[package]]
name = "proc-macro2"
version = "1.0.26"
@ -920,6 +974,23 @@ dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "resolv-conf"
version = "0.7.0"
@ -1041,6 +1112,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.24"
@ -1260,6 +1340,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -16,6 +16,9 @@ actix = "0.10"
serde = "1.0.114"
serde_json = "1"
pretty_env_logger = "0.4"
log = "0.4"
derive_builder = "0.9"
derive_more = "0.99"

View File

@ -26,12 +26,16 @@ use crate::errors::*;
#[derive(Clone, Default)]
/// cache datastructure implementing [Save]
pub struct HashCache(HashMap<String, u32>);
pub struct HashCache {
difficulty_map: HashMap<String, u32>,
result_map: HashMap<String, String>,
}
impl HashCache {
// save [PoWConfig] to cache
fn save(&mut self, config: Cache) -> CaptchaResult<()> {
self.0.insert(config.string, config.difficulty_factor);
fn save(&mut self, config: CachePoW) -> CaptchaResult<()> {
self.difficulty_map
.insert(config.string, config.difficulty_factor);
Ok(())
}
@ -46,7 +50,7 @@ impl HashCache {
// delete [PoWConfig] from cache
fn remove(&mut self, string: &str) -> Option<u32> {
self.0.remove(string)
self.difficulty_map.remove(string)
}
}
@ -57,15 +61,15 @@ impl Actor for HashCache {
}
/// cache a PoWConfig
impl Handler<Cache> for HashCache {
type Result = MessageResult<Cache>;
fn handle(&mut self, msg: Cache, ctx: &mut Self::Context) -> Self::Result {
impl Handler<CachePoW> for HashCache {
type Result = MessageResult<CachePoW>;
fn handle(&mut self, msg: CachePoW, ctx: &mut Self::Context) -> Self::Result {
//use actix::clock::sleep;
use actix::clock::delay_for;
use std::time::Duration;
let addr = ctx.address();
let del_msg = DeleteString(msg.string.clone());
let del_msg = DeletePoW(msg.string.clone());
let duration: Duration = Duration::new(msg.duration.clone(), 0);
let wait_for = async move {
@ -81,18 +85,18 @@ impl Handler<Cache> for HashCache {
}
/// Delte a PoWConfig
impl Handler<DeleteString> for HashCache {
type Result = MessageResult<DeleteString>;
fn handle(&mut self, msg: DeleteString, _ctx: &mut Self::Context) -> Self::Result {
impl Handler<DeletePoW> for HashCache {
type Result = MessageResult<DeletePoW>;
fn handle(&mut self, msg: DeletePoW, _ctx: &mut Self::Context) -> Self::Result {
self.remove(&msg.0);
MessageResult(Ok(()))
}
}
/// Retrive PoW difficulty_factor for a PoW string
impl Handler<Retrive> for HashCache {
type Result = MessageResult<Retrive>;
fn handle(&mut self, msg: Retrive, _ctx: &mut Self::Context) -> Self::Result {
impl Handler<RetrivePoW> for HashCache {
type Result = MessageResult<RetrivePoW>;
fn handle(&mut self, msg: RetrivePoW, _ctx: &mut Self::Context) -> Self::Result {
MessageResult(self.retrive(msg.0))
}
}
@ -127,18 +131,22 @@ mod tests {
duration: DURATION,
};
let string = pow.string.clone();
let msg = Cache::new(&pow, &visitor_result);
let msg = CachePoW::new(&pow, &visitor_result);
addr.send(msg).await.unwrap().unwrap();
let cache_difficulty_factor = addr.send(Retrive(string.clone())).await.unwrap().unwrap();
let cache_difficulty_factor = addr
.send(RetrivePoW(string.clone()))
.await
.unwrap()
.unwrap();
assert_eq!(DIFFICULTY_FACTOR, cache_difficulty_factor.unwrap());
let duration: Duration = Duration::new(5, 0);
//sleep(DURATION + DURATION).await;
delay_for(duration + duration).await;
let expired_string = addr.send(Retrive(string)).await.unwrap().unwrap();
let expired_string = addr.send(RetrivePoW(string)).await.unwrap().unwrap();
assert_eq!(None, expired_string);
}
}

12
src/cache/mod.rs vendored
View File

@ -24,7 +24,7 @@ pub mod hashcache;
/// Describes actor handler trait impls that are required by a cache implementation
pub trait Save:
actix::Actor + actix::Handler<Retrive> + actix::Handler<Cache> + actix::Handler<DeleteString>
actix::Actor + actix::Handler<RetrivePoW> + actix::Handler<CachePoW> + actix::Handler<DeletePoW>
{
}
pub mod messages {
@ -40,15 +40,15 @@ pub mod messages {
/// Message to cache PoW difficulty factor and string
#[derive(Message, Serialize, Deserialize, Builder)]
#[rtype(result = "CaptchaResult<()>")]
pub struct Cache {
pub struct CachePoW {
pub string: String,
pub difficulty_factor: u32,
pub duration: u64,
}
impl Cache {
impl CachePoW {
pub fn new(p: &PoWConfig, v: &AddVisitorResult) -> Self {
CacheBuilder::default()
CachePoWBuilder::default()
.string(p.string.clone())
.difficulty_factor(v.difficulty_factor)
.duration(v.duration)
@ -61,11 +61,11 @@ pub mod messages {
/// string from the cache
#[derive(Message)]
#[rtype(result = "CaptchaResult<Option<u32>>")]
pub struct Retrive(pub String);
pub struct RetrivePoW(pub String);
/// Message to delete cached PoW difficulty factor and string
/// when they expire
#[derive(Message)]
#[rtype(result = "CaptchaResult<()>")]
pub struct DeleteString(pub String);
pub struct DeletePoW(pub String);
}

View File

@ -23,6 +23,7 @@ use std::time::Duration;
use actix::clock::delay_for;
use actix::dev::*;
use derive_builder::Builder;
use log::info;
use crate::mcaptcha::MCaptcha;
@ -111,7 +112,7 @@ impl Handler<CleanUp> for Master {
let sites = self.sites.clone();
let gc = self.gc;
let master = ctx.address();
println!("init cleanup up");
info!("init master actor cleanup up");
let task = async move {
for (id, (new, addr)) in sites.iter() {
use crate::mcaptcha::{GetCurrentVisitorCount, Stop};

View File

@ -37,11 +37,12 @@ pub struct System<T: Save> {
impl<T> System<T>
where
T: Save,
<T as actix::Actor>::Context: ToEnvelope<T, messages::Cache> + ToEnvelope<T, messages::Retrive>,
<T as actix::Actor>::Context:
ToEnvelope<T, messages::CachePoW> + ToEnvelope<T, messages::RetrivePoW>,
{
/// utility function to get difficulty factor of site `id` and cache it
pub async fn get_pow(&self, id: String) -> Option<PoWConfig> {
use crate::cache::messages::Cache;
use crate::cache::messages::CachePoW;
use crate::master::GetSite;
use crate::mcaptcha::AddVisitor;
@ -52,17 +53,17 @@ where
let mcaptcha = site_addr.unwrap().send(AddVisitor).await.unwrap();
let pow_config = PoWConfig::new(mcaptcha.difficulty_factor);
let cache_msg = Cache::new(&pow_config, &mcaptcha);
let cache_msg = CachePoW::new(&pow_config, &mcaptcha);
self.cache.send(cache_msg).await.unwrap().unwrap();
Some(pow_config)
}
/// utility function to verify [Work]
pub async fn verify_pow(&self, work: Work) -> CaptchaResult<bool> {
use crate::cache::messages::Retrive;
use crate::cache::messages::RetrivePoW;
let string = work.string.clone();
let msg = Retrive(string.clone());
let msg = RetrivePoW(string.clone());
let pow: PoW<String> = work.into();
let difficulty = self.cache.send(msg).await.unwrap()?;