Rework browser sessions
This commit is contained in:
30
src/db/cf.rs
30
src/db/cf.rs
@@ -1,6 +1,5 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
// use cached::{stores::TimedCache, Cached};
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use matchit::Node;
|
||||
use std::collections::HashMap;
|
||||
@@ -109,7 +108,6 @@ impl DBClient for CFClient {
|
||||
.map_err(|e| anyhow!("Failed to serialize client entry: {}", e))?,
|
||||
)
|
||||
.map_err(|e| anyhow!("Failed to build KV put: {}", e))?
|
||||
// TODO put some sort of expiration for dynamic registration
|
||||
.execute()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to put KV: {}", e))?;
|
||||
@@ -202,4 +200,32 @@ impl DBClient for CFClient {
|
||||
code => Err(anyhow!("Error fetching from Durable Object: {}", code)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()> {
|
||||
self.ctx
|
||||
.kv(KV_NAMESPACE)
|
||||
.map_err(|e| anyhow!("Failed to get KV store: {}", e))?
|
||||
.put(
|
||||
&format!("{}/{}", KV_SESSION_PREFIX, id),
|
||||
serde_json::to_string(&entry)
|
||||
.map_err(|e| anyhow!("Failed to serialize client entry: {}", e))?,
|
||||
)
|
||||
.map_err(|e| anyhow!("Failed to build KV put: {}", e))?
|
||||
.expiration_ttl(SESSION_LIFETIME)
|
||||
.execute()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to put KV: {}", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>> {
|
||||
Ok(self
|
||||
.ctx
|
||||
.kv(KV_NAMESPACE)
|
||||
.map_err(|e| anyhow!("Failed to get KV store: {}", e))?
|
||||
.get(&format!("{}/{}", KV_SESSION_PREFIX, id))
|
||||
.json()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to get KV: {}", e))?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ mod cf;
|
||||
pub use cf::CFClient;
|
||||
|
||||
const KV_CLIENT_PREFIX: &str = "clients";
|
||||
const KV_SESSION_PREFIX: &str = "sessions";
|
||||
pub const ENTRY_LIFETIME: usize = 30;
|
||||
pub const SESSION_LIFETIME: u64 = 300; // 5min
|
||||
pub const SESSION_COOKIE_NAME: &str = "session";
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct CodeEntry {
|
||||
@@ -33,6 +36,14 @@ pub struct ClientEntry {
|
||||
pub access_token: Option<RegistrationAccessToken>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct SessionEntry {
|
||||
pub siwe_nonce: String,
|
||||
pub oidc_nonce: Option<Nonce>,
|
||||
pub secret: String,
|
||||
pub signin_count: u64,
|
||||
}
|
||||
|
||||
// Using a trait to easily pass async functions with async_trait
|
||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||
@@ -42,4 +53,6 @@ pub trait DBClient {
|
||||
async fn delete_client(&self, client_id: String) -> Result<()>;
|
||||
async fn set_code(&self, code: String, code_entry: CodeEntry) -> Result<()>;
|
||||
async fn get_code(&self, code: String) -> Result<Option<CodeEntry>>;
|
||||
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()>;
|
||||
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>>;
|
||||
}
|
||||
|
||||
@@ -98,4 +98,40 @@ impl DBClient for RedisClient {
|
||||
.map_err(|e| anyhow!("Failed to deserialize code: {}", e))?;
|
||||
Ok(Some(code_entry))
|
||||
}
|
||||
|
||||
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()> {
|
||||
let mut conn = self
|
||||
.pool
|
||||
.get()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to get connection to database: {}", e))?;
|
||||
|
||||
conn.set_ex(
|
||||
format!("{}/{}", KV_SESSION_PREFIX, id),
|
||||
serde_json::to_string(&entry)
|
||||
.map_err(|e| anyhow!("Failed to serialize session entry: {}", e))?,
|
||||
SESSION_LIFETIME.try_into().unwrap(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to set kv: {}", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>> {
|
||||
let mut conn = self
|
||||
.pool
|
||||
.get()
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to get connection to database: {}", e))?;
|
||||
let entry: Option<String> = conn
|
||||
.get(format!("{}/{}", KV_SESSION_PREFIX, id))
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to get kv: {}", e))?;
|
||||
if let Some(e) = entry {
|
||||
Ok(serde_json::from_str(&e)
|
||||
.map_err(|e| anyhow!("Failed to deserialize session entry: {}", e))?)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user