Fixed web ui. Added deprecation feature

This commit is contained in:
Ultradesu
2025-07-19 12:56:25 +03:00
parent e33910a2db
commit 45ac3fca51
9 changed files with 1055 additions and 533 deletions

View File

@@ -2,9 +2,10 @@ use actix_web::{web, HttpResponse, Result};
use log::info;
use rust_embed::RustEmbed;
use serde_json::json;
use tokio_postgres::Client;
use std::sync::Arc;
use crate::server::{get_keys_from_db, Flows};
use crate::db::ReconnectingDbClient;
use crate::server::Flows;
#[derive(RustEmbed)]
#[folder = "static/"]
@@ -20,12 +21,15 @@ pub async fn get_flows_api(allowed_flows: web::Data<Vec<String>>) -> Result<Http
pub async fn delete_key_by_server(
flows: web::Data<Flows>,
path: web::Path<(String, String)>,
db_client: web::Data<std::sync::Arc<Client>>,
db_client: web::Data<Arc<ReconnectingDbClient>>,
allowed_flows: web::Data<Vec<String>>,
) -> Result<HttpResponse> {
let (flow_id_str, server_name) = path.into_inner();
info!("API request to deprecate key for server '{}' in flow '{}'", server_name, flow_id_str);
info!(
"API request to deprecate key for server '{}' in flow '{}'",
server_name, flow_id_str
);
if !allowed_flows.contains(&flow_id_str) {
return Ok(HttpResponse::Forbidden().json(json!({
@@ -34,13 +38,19 @@ pub async fn delete_key_by_server(
}
// Deprecate in database
match crate::db::deprecate_key_by_server(&db_client, &server_name, &flow_id_str).await {
match db_client
.deprecate_key_by_server_reconnecting(server_name.clone(), flow_id_str.clone())
.await
{
Ok(deprecated_count) => {
if deprecated_count > 0 {
info!("Deprecated {} key(s) for server '{}' in flow '{}'", deprecated_count, server_name, flow_id_str);
info!(
"Deprecated {} key(s) for server '{}' in flow '{}'",
deprecated_count, server_name, flow_id_str
);
// Refresh the in-memory flows
let updated_flows = match get_keys_from_db(&db_client).await {
let updated_flows = match db_client.get_keys_from_db_reconnecting().await {
Ok(flows) => flows,
Err(e) => {
return Ok(HttpResponse::InternalServerError().json(json!({
@@ -62,11 +72,9 @@ pub async fn delete_key_by_server(
})))
}
}
Err(e) => {
Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to deprecate key: {}", e)
})))
}
Err(e) => Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to deprecate key: {}", e)
}))),
}
}
@@ -74,12 +82,15 @@ pub async fn delete_key_by_server(
pub async fn restore_key_by_server(
flows: web::Data<Flows>,
path: web::Path<(String, String)>,
db_client: web::Data<std::sync::Arc<Client>>,
db_client: web::Data<Arc<ReconnectingDbClient>>,
allowed_flows: web::Data<Vec<String>>,
) -> Result<HttpResponse> {
let (flow_id_str, server_name) = path.into_inner();
info!("API request to restore key for server '{}' in flow '{}'", server_name, flow_id_str);
info!(
"API request to restore key for server '{}' in flow '{}'",
server_name, flow_id_str
);
if !allowed_flows.contains(&flow_id_str) {
return Ok(HttpResponse::Forbidden().json(json!({
@@ -88,13 +99,19 @@ pub async fn restore_key_by_server(
}
// Restore in database
match crate::db::restore_key_by_server(&db_client, &server_name, &flow_id_str).await {
match db_client
.restore_key_by_server_reconnecting(server_name.clone(), flow_id_str.clone())
.await
{
Ok(restored_count) => {
if restored_count > 0 {
info!("Restored {} key(s) for server '{}' in flow '{}'", restored_count, server_name, flow_id_str);
info!(
"Restored {} key(s) for server '{}' in flow '{}'",
restored_count, server_name, flow_id_str
);
// Refresh the in-memory flows
let updated_flows = match get_keys_from_db(&db_client).await {
let updated_flows = match db_client.get_keys_from_db_reconnecting().await {
Ok(flows) => flows,
Err(e) => {
return Ok(HttpResponse::InternalServerError().json(json!({
@@ -116,11 +133,9 @@ pub async fn restore_key_by_server(
})))
}
}
Err(e) => {
Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to restore key: {}", e)
})))
}
Err(e) => Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to restore key: {}", e)
}))),
}
}
@@ -128,12 +143,15 @@ pub async fn restore_key_by_server(
pub async fn permanently_delete_key_by_server(
flows: web::Data<Flows>,
path: web::Path<(String, String)>,
db_client: web::Data<std::sync::Arc<Client>>,
db_client: web::Data<Arc<ReconnectingDbClient>>,
allowed_flows: web::Data<Vec<String>>,
) -> Result<HttpResponse> {
let (flow_id_str, server_name) = path.into_inner();
info!("API request to permanently delete key for server '{}' in flow '{}'", server_name, flow_id_str);
info!(
"API request to permanently delete key for server '{}' in flow '{}'",
server_name, flow_id_str
);
if !allowed_flows.contains(&flow_id_str) {
return Ok(HttpResponse::Forbidden().json(json!({
@@ -142,13 +160,19 @@ pub async fn permanently_delete_key_by_server(
}
// Permanently delete from database
match crate::db::permanently_delete_key_by_server(&db_client, &server_name, &flow_id_str).await {
match db_client
.permanently_delete_key_by_server_reconnecting(server_name.clone(), flow_id_str.clone())
.await
{
Ok(deleted_count) => {
if deleted_count > 0 {
info!("Permanently deleted {} key(s) for server '{}' in flow '{}'", deleted_count, server_name, flow_id_str);
info!(
"Permanently deleted {} key(s) for server '{}' in flow '{}'",
deleted_count, server_name, flow_id_str
);
// Refresh the in-memory flows
let updated_flows = match get_keys_from_db(&db_client).await {
let updated_flows = match db_client.get_keys_from_db_reconnecting().await {
Ok(flows) => flows,
Err(e) => {
return Ok(HttpResponse::InternalServerError().json(json!({
@@ -170,23 +194,21 @@ pub async fn permanently_delete_key_by_server(
})))
}
}
Err(e) => {
Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to delete key: {}", e)
})))
}
Err(e) => Ok(HttpResponse::InternalServerError().json(json!({
"error": format!("Failed to delete key: {}", e)
}))),
}
}
// Serve static files from embedded assets
pub async fn serve_static_file(path: web::Path<String>) -> Result<HttpResponse> {
let file_path = path.into_inner();
match StaticAssets::get(&file_path) {
Some(content) => {
let content_type = match std::path::Path::new(&file_path)
.extension()
.and_then(|s| s.to_str())
.and_then(|s| s.to_str())
{
Some("html") => "text/html; charset=utf-8",
Some("css") => "text/css; charset=utf-8",
@@ -201,22 +223,16 @@ pub async fn serve_static_file(path: web::Path<String>) -> Result<HttpResponse>
.content_type(content_type)
.body(content.data.as_ref().to_vec()))
}
None => {
Ok(HttpResponse::NotFound().body(format!("File not found: {}", file_path)))
}
None => Ok(HttpResponse::NotFound().body(format!("File not found: {}", file_path))),
}
}
// Serve the main web interface from embedded assets
pub async fn serve_web_interface() -> Result<HttpResponse> {
match StaticAssets::get("index.html") {
Some(content) => {
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(content.data.as_ref().to_vec()))
}
None => {
Ok(HttpResponse::NotFound().body("Web interface not found"))
}
Some(content) => Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(content.data.as_ref().to_vec())),
None => Ok(HttpResponse::NotFound().body("Web interface not found")),
}
}