crates/lake-product/src/site.rs
//! **The Lake's buy site**: `monetize_site_buy::BuySite`, filled for the Lake. The
//! shared relay (`monetize_site_buy::relay`) does every buy door; a site answers only who asks,
//! the actor ticket (the Lake mints none), the held caps and the paid sign-up's account. Gunnar's (`GunnarSite`)
//! and Holger's (holger-estate-front `buy.rs`) answer the same five questions.
use std::collections::BTreeMap;
use axum::http::{HeaderMap, StatusCode};
use monetize_site_buy::{Account, BuySite, Buyer, Refusal, Who};
use crate::say;
/// The header the bench signs a person in with (`x-lake-user: acme`). A real site reads its
/// session cookie or bearer here and never trusts a header.
pub const USER_HEADER: &str = "x-lake-user";
pub struct LakeSite {
/// The Lake's boxes.
pub boxes: crate::installer::Boxes,
pub origin: String,
}
impl BuySite for LakeSite {
fn origin(&self) -> String {
self.origin.clone()
}
fn product_word(&self) -> String {
"Lake".into()
}
async fn who(&self, headers: &HeaderMap) -> Result<Who, Refusal> {
let user = headers
.get(USER_HEADER)
.and_then(|v| v.to_str().ok())
.unwrap_or_default()
.to_string();
say("site", "who", "relay", &format!("user={user:?}"));
Ok(if user.is_empty() {
Who::Visitor
} else {
Who::Person(Buyer {
account: user,
..Default::default()
})
})
}
/// **No actor ticket**: the Lake mints none (owner rule: the Lake stays thin), so a door that
/// needs one is refused and a door that reads without one answers what it shows anyone.
async fn ticket(
&self,
_headers: &HeaderMap,
buyer: &Buyer,
purpose: &str,
_caps: &BTreeMap<String, u64>,
) -> Result<Vec<u8>, Refusal> {
say(
"site",
"ticket",
"relay",
&format!(
"account={} purpose={purpose}: the Lake mints no actor tickets",
buyer.account
),
);
Err(Refusal::new(
StatusCode::FORBIDDEN,
"the Lake mints no actor tickets".to_string(),
))
}
async fn held_caps(
&self,
_headers: &HeaderMap,
buyer: &Buyer,
) -> Result<BTreeMap<String, u64>, Refusal> {
say(
"site",
"held_caps",
"relay",
&format!("account={}", buyer.account),
);
Ok(BTreeMap::new())
}
async fn signup_account(&self, user: &str) -> Result<Account, Refusal> {
say("site", "signup_account", "relay", &format!("user={user}"));
Ok(Account::NoPasskey)
}
}