extending Save to cache captcha responses
This commit is contained in:
parent
61ee89aee3
commit
b597c0b965
7 changed files with 141 additions and 29 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -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
89
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
42
src/cache/hashcache.rs
vendored
42
src/cache/hashcache.rs
vendored
|
@ -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
12
src/cache/mod.rs
vendored
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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()?;
|
||||
|
|
Loading…
Reference in a new issue