feat(api): add Leptos server functions bridging client and server
- Add src/api/ module with server functions for networks, hosts, applications - Each server function retrieves the pool via use_context::<AnyPool>() - Pool is injected via provide_context in two places in main.rs: * leptos_routes_with_context: for SSR renders and inline server fn calls * handle_server_fns_with_context on /api/*fn_name: for WASM client calls - create_host validates IP against network CIDR before inserting - create_network validates CIDR format before inserting Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
107
src/api/applications.rs
Normal file
107
src/api/applications.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
// api/applications.rs — Server functions for applications and their port associations
|
||||
|
||||
use leptos::prelude::*;
|
||||
|
||||
use crate::models::Application;
|
||||
|
||||
// ─── Queries ──────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Returns all applications ordered by name.
|
||||
#[server]
|
||||
pub async fn get_applications() -> Result<Vec<Application>, ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::list_applications(&pool)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
|
||||
/// Returns the port numbers associated with an application.
|
||||
#[server]
|
||||
pub async fn get_ports_for_application(
|
||||
application_id: i64,
|
||||
) -> Result<Vec<u16>, ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::list_ports_for_application(&pool, application_id)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
|
||||
// ─── Mutations ────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Creates a new application and returns the created record.
|
||||
#[server]
|
||||
pub async fn create_application(name: String) -> Result<Application, ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::create_application(&pool, &name)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
|
||||
/// Deletes an application and all its port associations.
|
||||
///
|
||||
/// Returns `true` if the application existed and was deleted.
|
||||
#[server]
|
||||
pub async fn delete_application(id: i64) -> Result<bool, ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::delete_application(&pool, id)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
|
||||
/// Associates a port number with an application.
|
||||
///
|
||||
/// If the association already exists, this is a no-op.
|
||||
#[server]
|
||||
pub async fn add_port_to_application(
|
||||
application_id: i64,
|
||||
port_number: u16,
|
||||
) -> Result<(), ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::add_port_to_application(&pool, application_id, port_number)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
|
||||
/// Removes a port association from an application.
|
||||
///
|
||||
/// If the association does not exist, this is a no-op.
|
||||
#[server]
|
||||
pub async fn remove_port_from_application(
|
||||
application_id: i64,
|
||||
port_number: u16,
|
||||
) -> Result<(), ServerFnError> {
|
||||
use sqlx::AnyPool;
|
||||
use crate::server::repository::applications as repo;
|
||||
|
||||
let pool = use_context::<AnyPool>()
|
||||
.ok_or_else(|| ServerFnError::new("Database pool not found in context"))?;
|
||||
|
||||
repo::remove_port_from_application(&pool, application_id, port_number)
|
||||
.await
|
||||
.map_err(|e| ServerFnError::new(e.to_string()))
|
||||
}
|
||||
Reference in New Issue
Block a user