Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/monetize

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)
    }
}