Add plan model

This commit is contained in:
Jon Staab
2026-03-26 12:35:48 -07:00
parent 05437ef113
commit 1b3fe346f5
7 changed files with 128 additions and 11 deletions
+32
View File
@@ -76,6 +76,8 @@ impl Api {
};
let app = Router::new()
.route("/plans", get(list_plans))
.route("/plans/:id", get(get_plan))
.route("/tenants", get(list_tenants).post(create_tenant))
.route("/tenants/:pubkey", get(get_tenant))
.route("/tenants/:pubkey/billing", put(update_tenant_billing))
@@ -323,6 +325,36 @@ async fn list_tenants(
}
}
async fn list_plans(
State(state): State<AppState>,
headers: HeaderMap,
method: Method,
uri: Uri,
) -> Response {
if let Err(e) = extract_auth_pubkey(&headers, &method, &uri, &state.api.host) {
return auth_fail_response(e);
}
ok(StatusCode::OK, Repo::list_plans())
}
async fn get_plan(
State(state): State<AppState>,
headers: HeaderMap,
method: Method,
uri: Uri,
Path(id): Path<String>,
) -> Response {
if let Err(e) = extract_auth_pubkey(&headers, &method, &uri, &state.api.host) {
return auth_fail_response(e);
}
match Repo::list_plans().into_iter().find(|p| p.id == id) {
Some(plan) => ok(StatusCode::OK, plan),
None => err(StatusCode::NOT_FOUND, "not-found", "plan not found"),
}
}
async fn get_tenant(
State(state): State<AppState>,
headers: HeaderMap,
+3 -3
View File
@@ -125,7 +125,7 @@ impl Billing {
if hours <= 0 {
continue;
}
let plan_monthly = self.repo.get_relay_plan_amount_sats(&relay.plan).await?;
let plan_monthly = self.repo.get_relay_plan_sats(&relay.plan).await?;
if plan_monthly <= 0 {
continue;
}
@@ -228,7 +228,7 @@ impl Billing {
Ok(())
}
async fn make_bolt11(&self, amount_sats: i64) -> Result<String> {
async fn make_bolt11(&self, sats: i64) -> Result<String> {
if self.nwc_url.trim().is_empty() {
anyhow::bail!("NWC_URL not configured")
}
@@ -236,7 +236,7 @@ impl Billing {
let uri = nostr_sdk::nips::nip47::NostrWalletConnectURI::parse(&self.nwc_url)?;
let req = nostr_sdk::nips::nip47::Request::make_invoice(
nostr_sdk::nips::nip47::MakeInvoiceRequest {
amount: (amount_sats as u64) * 1_000,
amount: (sats as u64) * 1_000,
description: Some("Caravel relay invoice".to_string()),
description_hash: None,
expiry: None,
+10
View File
@@ -10,6 +10,16 @@ pub struct Activity {
pub resource_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Plan {
pub id: String,
pub name: String,
pub sats: i64,
pub members: Option<i64>,
pub blossom: bool,
pub livekit: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct Tenant {
pub pubkey: String,
+36 -8
View File
@@ -7,7 +7,7 @@ use sqlx::{
sqlite::{SqliteConnectOptions, SqlitePoolOptions},
};
use crate::models::{Activity, Invoice, InvoiceItem, Relay, Tenant};
use crate::models::{Activity, Invoice, InvoiceItem, Plan, Relay, Tenant};
#[derive(Clone)]
pub struct Repo {
@@ -502,15 +502,43 @@ impl Repo {
Ok(count)
}
pub async fn get_relay_plan_amount_sats(&self, plan: &str) -> Result<i64> {
let sats = match plan {
"free" => 0,
"basic" => 10_000,
"growth" => 50_000,
_ => 0,
};
pub async fn get_relay_plan_sats(&self, plan: &str) -> Result<i64> {
let sats = Self::list_plans()
.into_iter()
.find(|p| p.id == plan)
.map(|p| p.sats)
.unwrap_or(0);
Ok(sats)
}
pub fn list_plans() -> Vec<Plan> {
vec![
Plan {
id: "free".to_string(),
name: "Free".to_string(),
sats: 0,
members: Some(10),
blossom: false,
livekit: false,
},
Plan {
id: "basic".to_string(),
name: "Basic".to_string(),
sats: 10_000,
members: Some(100),
blossom: true,
livekit: true,
},
Plan {
id: "growth".to_string(),
name: "Growth".to_string(),
sats: 50_000,
members: None,
blossom: true,
livekit: true,
},
]
}
}
fn normalize_sqlite_url(url: &str) -> String {