Share owned host API state between HTTP hooks and native pages
This commit is contained in:
+26
-8
@@ -17,16 +17,34 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct Api<'a> {
|
||||
pub struct Api {
|
||||
pub cred: Arc<Cred>,
|
||||
script: cred::quickjs::QuickJs,
|
||||
pub passkeys: Mutex<Passkeys<'a>>,
|
||||
pub passkeys: Mutex<Passkeys<rusqlite::Connection>>,
|
||||
pub entry: EntryKey,
|
||||
requests: Mutex<HashMap<u32, (Instant, u32)>>,
|
||||
}
|
||||
impl<'a> Api<'a> {
|
||||
impl Api {
|
||||
/// Own the connection and ceremony state shared by both transports.
|
||||
pub fn open(
|
||||
cred: Arc<Cred>,
|
||||
host_dir: &std::path::Path,
|
||||
rp_id: &str,
|
||||
origin: &str,
|
||||
) -> anyhow::Result<Self> {
|
||||
let db = rusqlite::Connection::open(host_dir.join("cred.sqlite"))?;
|
||||
Ok(Self::new(
|
||||
cred,
|
||||
Passkeys::new(db, rp_id, origin)?,
|
||||
EntryKey::open(&host_dir.join("entry.key"))?,
|
||||
))
|
||||
}
|
||||
/// Passkeys owns the RP configuration. Its database must remain host-only.
|
||||
pub fn new(cred: impl Into<Arc<Cred>>, passkeys: Passkeys<'a>, entry: EntryKey) -> Self {
|
||||
pub fn new(
|
||||
cred: impl Into<Arc<Cred>>,
|
||||
passkeys: Passkeys<rusqlite::Connection>,
|
||||
entry: EntryKey,
|
||||
) -> Self {
|
||||
Self {
|
||||
cred: cred.into(),
|
||||
script: cred::quickjs::QuickJs::default(),
|
||||
@@ -113,10 +131,10 @@ fn request_view(request: cred::requests::Request) -> Result<Value> {
|
||||
}
|
||||
|
||||
/// Handle a request without a network transport. Errors contain only static error kinds.
|
||||
pub async fn handle(ctx: &Api<'_>, caller: Caller, request: Request<Bytes>) -> Response<Bytes> {
|
||||
pub async fn handle(ctx: &Api, caller: Caller, request: Request<Bytes>) -> Response<Bytes> {
|
||||
respond(ctx, caller, request)
|
||||
}
|
||||
fn respond(ctx: &Api<'_>, caller: Caller, request: Request<Bytes>) -> Response<Bytes> {
|
||||
fn respond(ctx: &Api, caller: Caller, request: Request<Bytes>) -> Response<Bytes> {
|
||||
let result = if request.method() == http::Method::GET {
|
||||
match pages::get(ctx, request.uri().path()) {
|
||||
Ok(Some(response)) => return response,
|
||||
@@ -143,7 +161,7 @@ fn respond(ctx: &Api<'_>, caller: Caller, request: Request<Bytes>) -> Response<B
|
||||
.body(Bytes::from(serde_json::to_vec(&body).expect("JSON value")))
|
||||
.expect("valid response")
|
||||
}
|
||||
fn route(ctx: &Api<'_>, caller: &Caller, request: Request<Bytes>) -> Result<Value> {
|
||||
fn route(ctx: &Api, caller: &Caller, request: Request<Bytes>) -> Result<Value> {
|
||||
let path: Vec<_> = request.uri().path().trim_matches('/').split('/').collect();
|
||||
let method = request.method().as_str();
|
||||
let body: Value = if request.body().is_empty() {
|
||||
@@ -206,7 +224,7 @@ mod tests {
|
||||
let db = rusqlite::Connection::open_in_memory()?;
|
||||
let api = Api::new(
|
||||
Cred::open(dir.path())?,
|
||||
Passkeys::new(&db, "localhost", "http://localhost:8080")?,
|
||||
Passkeys::new(db, "localhost", "http://localhost:8080")?,
|
||||
EntryKey::open(&dir.path().join("entry.key"))?,
|
||||
);
|
||||
let caller = Caller::default();
|
||||
|
||||
Reference in New Issue
Block a user