feat: define internfaces to create,fetch and rm auth challenges

This commit is contained in:
Aravinth Manivannan 2023-06-13 19:23:23 +05:30
parent 78de0b266f
commit c53fe2e3ff
No known key found for this signature in database
GPG Key ID: AD9F0F08E855ED88
3 changed files with 82 additions and 0 deletions

View File

@ -15,6 +15,7 @@ serde = { version = "1", features = ["derive"]}
url = { version = "2.2.2", features = ["serde"] }
#libmcaptcha = { version = "0.2.2", git = "https://github.com/mCaptcha/libmcaptcha", features = ["minimal"], default-features = false, tag = "0.2.2"}
libmcaptcha = { branch = "master", git = "https://github.com/mCaptcha/libmcaptcha", features = ["full"] }
uuid = { version = "1.3.3", features = ["v4", "serde"] }
[features]
default = []

View File

@ -31,7 +31,10 @@
//! - [errors](crate::auth): error data structures used in this crate
//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting
//! connection from pool
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub use libmcaptcha::defense::Level;
@ -97,6 +100,64 @@ pub struct NameHash {
pub hash: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// Email challenge reason
pub enum ChallengeReason {
/// challenge created to verify a newly registered user
EmailVerification,
/// Challenge created to verify a password reset request
PasswordReset,
}
impl ChallengeReason {
pub fn to_str(&self) -> &'static str {
match self {
Self::EmailVerification => "email_verification",
Self::PasswordReset => "password_resset",
}
}
}
impl ToString for ChallengeReason {
fn to_string(&self) -> String {
self.to_str().into()
}
}
impl FromStr for ChallengeReason {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
for reason in [Self::PasswordReset, Self::EmailVerification].iter() {
if s == reason.to_str() {
return Ok(reason.clone());
}
}
Err(())
}
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
/// Email challenge
pub struct Challenge {
/// challenge unique identifier
pub challenge: Uuid,
/// reason why the challenge was create
pub reason: ChallengeReason,
}
impl Challenge {
/// create new Challenge instance for a given reason. Challenge text is auto-generated
pub fn new(reason: ChallengeReason) -> Self {
let challenge = Uuid::new_v4();
Self { challenge, reason }
}
/// Generate new ID (useful when ID clashes)
pub fn new_id(&mut self) {
self.challenge = Uuid::new_v4();
}
}
#[async_trait]
/// mCaptcha's database requirements. To implement support for $Database, kindly implement this
/// trait.
@ -250,6 +311,15 @@ pub trait MCDatabase: std::marker::Send + std::marker::Sync + CloneSPDatabase {
/// fetch PoWConfig confirms
async fn fetch_confirm(&self, user: &str, key: &str) -> DBResult<Vec<i64>>;
/// Record challenge in database
async fn new_challenge(&self, challenge: &mut Challenge) -> DBResult<()>;
/// Record challenge in database
async fn fetch_challenge(&self, challenge: &Challenge) -> DBResult<Challenge>;
/// Delete a challenge from database
async fn delete_challenge(&self, challenge: &Challenge) -> DBResult<()>;
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]

View File

@ -296,3 +296,14 @@ pub async fn database_works<'a, T: MCDatabase>(
db.delete_captcha(p.username, p.username).await.unwrap();
assert!(!db.captcha_exists(Some(p.username), c.key).await.unwrap());
}
/// test all challenge routines
pub async fn challenges_works<'a, T: MCDatabase>(db: &T) {
let mut challenge = Challenge::new(ChallengeReason::PasswordReset);
db.new_challenge(&mut challenge).await.unwrap();
db.new_challenge(&mut challenge).await.unwrap();
let c = db.fetch_challenge(&challenge).await.unwrap();
assert_eq!(c, challenge);
db.delete_challenge(&challenge).await.unwrap();
assert!(db.fetch_challenge(&challenge).await.is_err())
}