fedimint_server_ui/
lnv2.rs

1use axum::extract::{Form, State};
2use axum::response::{IntoResponse, Redirect};
3use axum_extra::extract::cookie::CookieJar;
4use fedimint_core::util::SafeUrl;
5use fedimint_server_core::dashboard_ui::{DashboardApiModuleExt, DynDashboardApi};
6use maud::{Markup, html};
7
8use crate::{AuthState, check_auth};
9
10// Form for gateway management
11#[derive(serde::Deserialize)]
12pub struct GatewayForm {
13    pub gateway_url: SafeUrl,
14}
15
16// Function to render the Lightning V2 module UI section
17pub async fn render(lightning: &fedimint_lnv2_server::Lightning) -> Markup {
18    let gateways = lightning.gateways_ui().await;
19    let consensus_block_count = lightning.consensus_block_count_ui().await;
20    let consensus_unix_time = lightning.consensus_unix_time_ui().await;
21    let formatted_unix_time = chrono::DateTime::from_timestamp(consensus_unix_time as i64, 0)
22        .map(|dt| dt.to_rfc2822())
23        .unwrap_or("Invalid time".to_string());
24
25    html! {
26        div class="row gy-4 mt-2" {
27            div class="col-12" {
28                div class="card h-100" {
29                    div class="card-header dashboard-header" { "Lightning V2" }
30                    div class="card-body" {
31                        // Consensus status information
32                        div class="mb-4" {
33                            table
34                                class="table"
35                                id="lnv2-module-timers" hx-swap-oob=(true)
36                            {
37                                tr {
38                                    th { "Consensus Block Count" }
39                                    td { (consensus_block_count) }
40                                }
41                                tr {
42                                    th { "Consensus Unix Time" }
43                                    td { (formatted_unix_time) }
44                                }
45                            }
46                        }
47
48                        // Gateway management
49                        div {
50                            h5 { "Gateway Management" }
51                            // Add new gateway form
52                            div class="mb-4" {
53                                form action="/lnv2_gateway_add" method="post" class="row g-3" {
54                                    div class="col-md-9" {
55                                        div class="form-group" {
56                                            div class="text-muted mb-1" style="font-size: 0.875em;" {
57                                                "Please enter a valid URL starting with http:// or https://"
58                                            }
59                                            input
60                                                type="url"
61                                                class="form-control"
62                                                id="gateway-url"
63                                                name="gateway_url"
64                                                placeholder="Enter gateway URL"
65                                                required;
66                                        }
67                                    }
68                                    div class="col-md-3" {
69                                        div style="margin-top: 24px;" {
70                                            button type="submit" class="btn btn-primary w-100 form-control" { "Add Gateway" }
71                                        }
72                                    }
73                                }
74                            }
75
76                            // Gateway list
77                            @if gateways.is_empty() {
78                                div class="alert alert-info" { "No gateways configured yet." }
79                            } @else {
80                                div class="table-responsive" {
81                                    table class="table table-hover" {
82                                        thead {
83                                            tr {
84                                                th { "Gateway URL" }
85                                                th class="text-end" { "Actions" }
86                                            }
87                                        }
88                                        tbody {
89                                            @for gateway in &gateways {
90                                                tr {
91                                                    td {
92                                                        a href=(gateway.to_string()) target="_blank" { (gateway.to_string()) }
93                                                    }
94                                                    td class="text-end" {
95                                                        form action="/lnv2_gateway_remove" method="post" style="display: inline;" {
96                                                            input type="hidden" name="gateway_url" value=(gateway.to_string());
97                                                            button type="submit" class="btn btn-sm btn-danger" {
98                                                                "Remove"
99                                                            }
100                                                        }
101                                                    }
102                                                }
103                                            }
104                                        }
105                                    }
106                                }
107                            }
108                        }
109                    }
110                }
111            }
112        }
113    }
114}
115
116// Handler for adding a new gateway
117pub async fn add_gateway(
118    State(state): State<AuthState<DynDashboardApi>>,
119    jar: CookieJar,
120    Form(form): Form<GatewayForm>,
121) -> impl IntoResponse {
122    if !check_auth(&state.auth_cookie_name, &state.auth_cookie_value, &jar).await {
123        return Redirect::to("/login").into_response();
124    }
125
126    state
127        .api
128        .get_module::<fedimint_lnv2_server::Lightning>()
129        .expect("Route only mounted when Lightning V2 module exists")
130        .add_gateway_ui(form.gateway_url)
131        .await;
132
133    Redirect::to("/").into_response()
134}
135
136// Handler for removing a gateway
137pub async fn remove_gateway(
138    State(state): State<AuthState<DynDashboardApi>>,
139    jar: CookieJar,
140    Form(form): Form<GatewayForm>,
141) -> impl IntoResponse {
142    if !check_auth(&state.auth_cookie_name, &state.auth_cookie_value, &jar).await {
143        return Redirect::to("/login").into_response();
144    }
145
146    state
147        .api
148        .get_module::<fedimint_lnv2_server::Lightning>()
149        .expect("Route only mounted when Lightning V2 module exists")
150        .remove_gateway_ui(form.gateway_url)
151        .await;
152
153    Redirect::to("/").into_response()
154}