Files
RustProxy/src/admin/preferences_columns.rs
T

188 lines
4.8 KiB
Rust

const LIVE_LOG_COLUMNS: &[&str] = &[
"time",
"request",
"host",
"source_ip",
"vhost",
"backend",
"status",
"duration",
"cache",
"outcome",
"transport",
"websocket",
"upstream_error",
];
const FILE_LOG_COLUMN_MAX: usize = 64;
const BACKEND_TABLE_COLUMNS: &[&str] = &[
"vhost",
"backend",
"status",
"active",
"requests",
"errors",
"latency",
"traffic",
"generation",
"generationRequests",
"generationAge",
"rotations",
"lastFailure",
"lastRecovery",
];
const VHOST_LIST_SORT_COLUMNS: &[&str] = &[
"id",
"hostname",
"status",
"listeners",
"certificate",
"backends",
];
const DOCKER_VHOST_SORT_COLUMNS: &[&str] = &[
"service",
"hostname",
"status",
"backend",
"scheme",
"published",
];
const REDIRECT_LIST_SORT_COLUMNS: &[&str] = &[
"id",
"name",
"hostname",
"status",
"target",
"rules",
"listeners",
"certificate",
];
const NOTFOUND_LIST_SORT_COLUMNS: &[&str] = &[
"id",
"name",
"hostname",
"status",
"mode",
"listeners",
"certificate",
];
const STREAM_LIST_SORT_COLUMNS: &[&str] = &[
"name",
"id",
"protocol",
"listen",
"upstream",
"status",
"maxConnections",
"idleTimeout",
];
#[derive(serde::Deserialize)]
struct DashboardWidgetDefinition {
id: String,
default_hidden: bool,
display_type: String,
}
static DASHBOARD_WIDGETS: std::sync::LazyLock<Vec<DashboardWidgetDefinition>> =
std::sync::LazyLock::new(|| {
serde_json::from_str(include_str!("web/dashboard-widgets.json"))
.expect("invalid bundled Overview Cards registry")
});
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct DashboardDefaultPreset {
dashboard_widgets: Vec<String>,
dashboard_hidden_widgets: Vec<String>,
dashboard_density: String,
overview_samples: u16,
}
static DASHBOARD_DEFAULT_PRESET: std::sync::LazyLock<DashboardDefaultPreset> =
std::sync::LazyLock::new(|| {
let preset: DashboardDefaultPreset =
serde_json::from_str(include_str!("web/dashboard-defaults.json"))
.expect("invalid factory Overview layout preset");
let registry = DASHBOARD_WIDGETS
.iter()
.map(|w| w.id.as_str())
.collect::<std::collections::HashSet<_>>();
let order = preset
.dashboard_widgets
.iter()
.map(String::as_str)
.collect::<std::collections::HashSet<_>>();
let hidden = preset
.dashboard_hidden_widgets
.iter()
.map(String::as_str)
.collect::<std::collections::HashSet<_>>();
assert_eq!(
order.len(),
preset.dashboard_widgets.len(),
"duplicate factory widget ID"
);
assert_eq!(
hidden.len(),
preset.dashboard_hidden_widgets.len(),
"duplicate hidden factory widget ID"
);
assert!(
order.is_subset(&registry) && hidden.is_subset(&order),
"unknown widget in factory layout"
);
assert!(
matches!(
preset.dashboard_density.as_str(),
"normal" | "compact" | "ultra"
),
"invalid factory density"
);
assert!(
matches!(preset.overview_samples, 60 | 120 | 300 | 600),
"invalid factory sample count"
);
preset
});
fn valid_dashboard_span(display_type: &str, span: u8) -> bool {
match display_type {
"table" => matches!(span, 6 | 12),
"panel" => matches!(span, 4 | 6 | 12),
"chart" => matches!(span, 3 | 4 | 6 | 12),
_ => matches!(span, 2 | 3 | 4 | 6 | 12),
}
}
fn valid_dashboard_sizes(sizes: &Option<std::collections::BTreeMap<String, u8>>) -> bool {
sizes.as_ref().is_none_or(|sizes| {
sizes.len() <= DASHBOARD_WIDGETS.len()
&& sizes.iter().all(|(id, span)| {
DASHBOARD_WIDGETS.iter().any(|widget| {
widget.id == *id && valid_dashboard_span(&widget.display_type, *span)
})
})
})
}
fn default_hidden_dashboard_widgets() -> Vec<String> {
let mut hidden = DASHBOARD_DEFAULT_PRESET.dashboard_hidden_widgets.clone();
for widget in DASHBOARD_WIDGETS.iter() {
if !DASHBOARD_DEFAULT_PRESET
.dashboard_widgets
.contains(&widget.id)
&& widget.default_hidden
{
hidden.push(widget.id.clone());
}
}
hidden
}
fn default_admin_dashboard_widgets() -> Vec<String> {
let mut order = DASHBOARD_DEFAULT_PRESET.dashboard_widgets.clone();
for widget in DASHBOARD_WIDGETS.iter() {
if !order.contains(&widget.id) {
order.push(widget.id.clone());
}
}
order
}