main
use cache::CacheConn;
use config::redis::RedisConfig;
use crate::error::InternalError;
#[derive(Clone)]
pub struct NonceStore {
conn: CacheConn,
}
impl NonceStore {
pub fn from_conn(conn: CacheConn) -> Self {
Self { conn }
}
pub async fn connect(config: &RedisConfig, _prefix: &str) -> Result<Self, InternalError> {
let conn = CacheConn::init(config)
.await
.map_err(|error| InternalError::Config(format!("redis: {error}")))?;
Ok(Self::from_conn(conn))
}
/// `SET key 1 NX EX ttl`:第一次出现返回 true,重放返回 false。
pub async fn accept(&self, key: &str, ttl_secs: u64) -> Result<bool, InternalError> {
let mut conn = self.conn.clone();
let result: Option<String> = redis::cmd("SET")
.arg(key)
.arg("1")
.arg("NX")
.arg("EX")
.arg(ttl_secs.max(1))
.query_async(&mut conn)
.await?;
Ok(result.is_some())
}
}
pub fn key(audience: &str, nonce: &str) -> String {
format!("event:identity:nonce:{audience}:{nonce}")
}