Skip to main content

fr_rust/linkv/
linkv.rs

1use crate::prelude::*;
2use rand::Rng;
3use deadpool_redis::redis::AsyncCommands; 
4
5// --- ERROR HANDLING ---
6
7// Add the import to your path where RedisManagerError is defined
8#[derive(thiserror::Error, Debug)]
9pub enum LinkVError {
10    #[error("Redis manager error: {0}")]
11    RedisManager(#[from] RedisManagerError),
12
13    #[error("Redis error: {0}")]
14    Redis(#[from] deadpool_redis::redis::RedisError),
15
16    #[error("Redis pool error: {0}")]
17    RedisPool(#[from] deadpool_redis::PoolError),
18}
19
20
21pub type Result<T> = std::result::Result<T, LinkVError>;
22
23// --- SERVICE IMPLEMENTATION ---
24
25#[derive(Clone)]
26pub struct LinkVConfig {
27    pub secret: String,
28    pub crypto: CryptoService,
29    pub redis: RedisManager,
30    pub ttl_secs: u64,
31}
32
33#[derive(Clone)]
34pub struct LinkV {
35    config: LinkVConfig,
36}
37
38impl LinkV {
39    pub fn new(config: LinkVConfig) -> Self {
40        Self { config }
41    }
42
43    pub async fn generate_token(&self, user_id: &str) -> Result<String> {
44        let mut token_bytes = vec![0u8; 256];
45        rand::rng().fill_bytes(&mut token_bytes);
46        let token = hex::encode(token_bytes);
47        let redis_key = format!("linkv:verify:{}:{}", user_id, token);
48        
49        let mut con = self.config.redis.get_connection().await?;
50        
51        // Force the type system to register the output as ()
52        let _res: () = con.set_ex(&redis_key, "1", self.config.ttl_secs).await?;
53        
54        Ok(token)
55    }
56
57    pub async fn verify_token(&self, user_id: &str, token: &str) -> Result<bool> {
58        let redis_key = format!("linkv:verify:{}:{}", user_id, token);
59        
60        let mut con = self.config.redis.get_connection().await?;
61        let is_valid: bool = con.exists(&redis_key).await?;
62        
63        if is_valid {
64            // Force the type system to register the output as ()
65            let _res: () = con.del(&redis_key).await?;
66            Ok(true)
67        } else {
68            Ok(false)
69        }
70    }
71}