diff --git a/backend/spec/repo.md b/backend/spec/repo.md index e3a9bb8..998b56e 100644 --- a/backend/spec/repo.md +++ b/backend/spec/repo.md @@ -53,9 +53,13 @@ Notes: - Returns the hardcoded relay plans used by the system (`free`, `basic`, `growth`) - This is the source of truth for plan metadata exposed via API -## `pub fn list_relays(&self, tenant_id: Option<&str>) -> Result>` +## `pub fn list_relays(&self) -> Result>` -- Returns all matching relays +- Returns all relays + +## `pub fn list_relays_for_tenant(&self, tenant_id: &str) -> Result>` + +- Returns all relays belonging to the given tenant ## `pub fn get_relay(&self, id: &str) -> Result` @@ -82,7 +86,7 @@ Notes: - Sets relay status to `active` - Logs activity as `(activate_relay, relay_id)` -## `pub fn fail_relay_sync(&self, relay: &Relay, sync_error: String) -> Result<()>` +## `pub fn fail_relay_sync(&self, relay: &Relay, sync_error: &str) -> Result<()>` - Sets relay status to `inactive`, sets `sync_error` - Logs activity as `(fail_relay_sync, relay_id)` @@ -92,7 +96,11 @@ Notes: - Saves an `invoice` row and related `invoice_item` rows - Logs activity as `(create_invoice, invoice_id)` -## `pub fn list_invoices(tenant_id: Option<&str>) -> Result>` +## `pub fn list_invoices() -> Result>` + +- Returns all invoices + +## `pub fn list_invoices_for_tenant(tenant_id: &str) -> Result>` - Returns all matching invoices @@ -103,7 +111,7 @@ Notes: - Clears `error` if set - Logs activity as `(mark_invoice_paid, invoice_id)` -## `pub fn mark_invoice_attempted(&self, invoice_id: &str, error: Option<&str>) -> Result<()>` +## `pub fn mark_invoice_attempted(&self, invoice_id: &str, error: &str) -> Result<()>` - Sets `attempted_at` to now - Updates `error` if provided @@ -122,7 +130,11 @@ Notes: - Sets `closed_at` to now - Logs activity as `(mark_invoice_closed, invoice_id)` -## `pub fn list_activity(&self, since: &i64, tenant: Option<&str>) -> Result>` +## `pub fn list_activity(&self, since: &i64) -> Result>` + +- Returns all activity occuring after `since` + +## `pub fn list_activity_for_tenant(&self, tenant: &str, since: &i64) -> Result>` - Returns all activity occuring after `since` matching `tenant` diff --git a/backend/src/api.rs b/backend/src/api.rs index ede24d4..336bd44 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -454,7 +454,12 @@ async fn list_relays( Some(auth.as_str()) }; - match state.api.repo.list_relays(tenant_filter).await { + let relays = match tenant_filter { + Some(tenant) => state.api.repo.list_relays_for_tenant(tenant).await, + None => state.api.repo.list_relays().await, + }; + + match relays { Ok(relays) => ok(StatusCode::OK, relays), Err(e) => err( StatusCode::INTERNAL_SERVER_ERROR, @@ -747,7 +752,12 @@ async fn list_invoices( Some(auth.as_str()) }; - match state.api.repo.list_invoices(tenant_filter).await { + let invoices = match tenant_filter { + Some(tenant) => state.api.repo.list_invoices_for_tenant(tenant).await, + None => state.api.repo.list_invoices().await, + }; + + match invoices { Ok(invoices) => ok(StatusCode::OK, invoices), Err(e) => err( StatusCode::INTERNAL_SERVER_ERROR, diff --git a/backend/src/billing.rs b/backend/src/billing.rs index 78124c5..8ce39ce 100644 --- a/backend/src/billing.rs +++ b/backend/src/billing.rs @@ -40,7 +40,7 @@ impl Billing { pub async fn tick(&self) -> Result<()> { let mut since_guard = self.last_activity_at.lock().await; let since = *since_guard; - let activity = self.repo.list_activity(&since, None).await?; + let activity = self.repo.list_activity(&since).await?; for a in &activity { if matches!( a.activity_type.as_str(), @@ -70,7 +70,7 @@ impl Billing { return Ok(()); } - let relays = self.repo.list_relays(Some(&relay.tenant)).await?; + let relays = self.repo.list_relays_for_tenant(&relay.tenant).await?; let paid_active_count = relays .into_iter() .filter(|r| r.status == "active" && r.plan != "free") @@ -95,7 +95,7 @@ impl Billing { return Ok(()); } - let relays = self.repo.list_relays(Some(&tenant.pubkey)).await?; + let relays = self.repo.list_relays_for_tenant(&tenant.pubkey).await?; let active_paid_relays: Vec = relays .iter() .filter(|r| r.status == "active" && r.plan != "free") @@ -114,7 +114,7 @@ impl Billing { let usage_events = self .repo - .list_activity(&tenant.billing_anchor, Some(&tenant.pubkey)) + .list_activity_for_tenant(&tenant.pubkey, &tenant.billing_anchor) .await?; let invoice_id = uuid::Uuid::new_v4().to_string(); let mut items = Vec::new(); @@ -176,7 +176,7 @@ impl Billing { } async fn collect_outstanding(&self, tenant: &Tenant) -> Result<()> { - let invoices = self.repo.list_invoices(Some(&tenant.pubkey)).await?; + let invoices = self.repo.list_invoices_for_tenant(&tenant.pubkey).await?; let now = now_ts(); for invoice in invoices.into_iter().filter(|i| i.status == "pending") { diff --git a/backend/src/infra.rs b/backend/src/infra.rs index 1cda24f..5ab8a45 100644 --- a/backend/src/infra.rs +++ b/backend/src/infra.rs @@ -45,7 +45,7 @@ impl Infra { pub async fn tick(&self) -> Result<()> { let mut since_guard = self.last_activity_at.lock().await; let since = *since_guard; - let activity = self.repo.list_activity(&since, None).await?; + let activity = self.repo.list_activity(&since).await?; for a in activity { if a.resource_type == "relay" diff --git a/backend/src/repo.rs b/backend/src/repo.rs index 935585f..c543ea0 100644 --- a/backend/src/repo.rs +++ b/backend/src/repo.rs @@ -160,34 +160,35 @@ impl Repo { Ok(()) } - pub async fn list_relays(&self, tenant_id: Option<&str>) -> Result> { - let rows = if let Some(tenant) = tenant_id { - sqlx::query_as::<_, Relay>( - "SELECT id, tenant, schema, subdomain, plan, status, sync_error, - info_name, info_icon, info_description, - policy_public_join, policy_strip_signatures, - groups_enabled, management_enabled, blossom_enabled, - livekit_enabled, push_enabled - FROM relay - WHERE tenant = ? - ORDER BY id", - ) - .bind(tenant) - .fetch_all(&self.pool) - .await? - } else { - sqlx::query_as::<_, Relay>( - "SELECT id, tenant, schema, subdomain, plan, status, sync_error, - info_name, info_icon, info_description, - policy_public_join, policy_strip_signatures, - groups_enabled, management_enabled, blossom_enabled, - livekit_enabled, push_enabled - FROM relay - ORDER BY id", - ) - .fetch_all(&self.pool) - .await? - }; + pub async fn list_relays(&self) -> Result> { + let rows = sqlx::query_as::<_, Relay>( + "SELECT id, tenant, schema, subdomain, plan, status, sync_error, + info_name, info_icon, info_description, + policy_public_join, policy_strip_signatures, + groups_enabled, management_enabled, blossom_enabled, + livekit_enabled, push_enabled + FROM relay + ORDER BY id", + ) + .fetch_all(&self.pool) + .await?; + Ok(rows) + } + + pub async fn list_relays_for_tenant(&self, tenant_id: &str) -> Result> { + let rows = sqlx::query_as::<_, Relay>( + "SELECT id, tenant, schema, subdomain, plan, status, sync_error, + info_name, info_icon, info_description, + policy_public_join, policy_strip_signatures, + groups_enabled, management_enabled, blossom_enabled, + livekit_enabled, push_enabled + FROM relay + WHERE tenant = ? + ORDER BY id", + ) + .bind(tenant_id) + .fetch_all(&self.pool) + .await?; Ok(rows) } @@ -355,28 +356,29 @@ impl Repo { Ok(()) } - pub async fn list_invoices(&self, tenant_id: Option<&str>) -> Result> { - let rows = if let Some(tenant) = tenant_id { - sqlx::query_as::<_, Invoice>( - "SELECT id, tenant, status, created_at, attempted_at, error, closed_at, - sent_at, paid_at, bolt11, period_start, period_end - FROM invoice - WHERE tenant = ? - ORDER BY created_at DESC", - ) - .bind(tenant) - .fetch_all(&self.pool) - .await? - } else { - sqlx::query_as::<_, Invoice>( - "SELECT id, tenant, status, created_at, attempted_at, error, closed_at, - sent_at, paid_at, bolt11, period_start, period_end - FROM invoice - ORDER BY created_at DESC", - ) - .fetch_all(&self.pool) - .await? - }; + pub async fn list_invoices(&self) -> Result> { + let rows = sqlx::query_as::<_, Invoice>( + "SELECT id, tenant, status, created_at, attempted_at, error, closed_at, + sent_at, paid_at, bolt11, period_start, period_end + FROM invoice + ORDER BY created_at DESC", + ) + .fetch_all(&self.pool) + .await?; + Ok(rows) + } + + pub async fn list_invoices_for_tenant(&self, tenant_id: &str) -> Result> { + let rows = sqlx::query_as::<_, Invoice>( + "SELECT id, tenant, status, created_at, attempted_at, error, closed_at, + sent_at, paid_at, bolt11, period_start, period_end + FROM invoice + WHERE tenant = ? + ORDER BY created_at DESC", + ) + .bind(tenant_id) + .fetch_all(&self.pool) + .await?; Ok(rows) } @@ -453,29 +455,30 @@ impl Repo { Ok(()) } - pub async fn list_activity(&self, since: &i64, tenant: Option<&str>) -> Result> { - let rows = if let Some(tenant_pubkey) = tenant { - sqlx::query_as::<_, Activity>( - "SELECT id, tenant, created_at, activity_type, resource_type, resource_id - FROM activity - WHERE created_at > ? AND tenant = ? - ORDER BY created_at, id", - ) - .bind(since) - .bind(tenant_pubkey) - .fetch_all(&self.pool) - .await? - } else { - sqlx::query_as::<_, Activity>( - "SELECT id, tenant, created_at, activity_type, resource_type, resource_id - FROM activity - WHERE created_at > ? - ORDER BY created_at, id", - ) - .bind(since) - .fetch_all(&self.pool) - .await? - }; + pub async fn list_activity(&self, since: &i64) -> Result> { + let rows = sqlx::query_as::<_, Activity>( + "SELECT id, tenant, created_at, activity_type, resource_type, resource_id + FROM activity + WHERE created_at > ? + ORDER BY created_at, id", + ) + .bind(since) + .fetch_all(&self.pool) + .await?; + Ok(rows) + } + + pub async fn list_activity_for_tenant(&self, tenant: &str, since: &i64) -> Result> { + let rows = sqlx::query_as::<_, Activity>( + "SELECT id, tenant, created_at, activity_type, resource_type, resource_id + FROM activity + WHERE created_at > ? AND tenant = ? + ORDER BY created_at, id", + ) + .bind(since) + .bind(tenant) + .fetch_all(&self.pool) + .await?; Ok(rows) }