Gate push toggle on backend notification method

Add a GET /api/config endpoint exposing the front-end-facing backend
configuration (currently the notification delivery method, grouped under
a nested "notifications" object so the shape can grow). The settings
screen fetches it on init and only shows the per-device push toggle when
the backend method is "push" (and the platform supports push, which keeps
it off the browser).

Also fold in related push-notifications cleanups: fix the Android app
label ("frontend" -> "OOTT") so the notification permission dialog reads
correctly, remove the completed push_notifications.md plan, and update
TODO.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-06-08 17:26:53 -04:00
co-authored by Claude Opus 4.8
parent bef1a2987d
commit 1d85ec6f83
14 changed files with 209 additions and 299 deletions
+1
View File
@@ -1,3 +1,4 @@
pub mod config;
pub mod device_events;
pub mod devices;
pub mod notifications;
+17
View File
@@ -0,0 +1,17 @@
use serde::Serialize;
use utoipa::ToSchema;
// Front-end-facing view of the backend configuration. Only the settings the UI
// needs to adapt itself are exposed here, grouped by area so the shape can grow
// without breaking existing fields. Today it carries just the notification
// method, which gates the per-device push toggle in the settings screen.
#[derive(Clone, Serialize, ToSchema)]
pub struct Config {
pub notifications: NotificationConfig,
}
#[derive(Clone, Serialize, ToSchema)]
pub struct NotificationConfig {
// The configured delivery method (e.g. "push", "pushover", "none").
pub method: String,
}
+7
View File
@@ -1,6 +1,7 @@
use std::error::Error;
use std::path::{Path, PathBuf};
use crate::model::config::{Config, NotificationConfig};
use crate::model::device_events::{DeviceEvent, DeviceEventScanner, DeviceEventType};
use crate::model::devices::{Device, DeviceListResponse, DeviceSummary};
use crate::model::notifications::{Notification, NotificationListResponse, NotificationType};
@@ -29,6 +30,7 @@ use utoipa::openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme};
use utoipa_swagger_ui::SwaggerUi;
pub mod arp_scanner;
pub mod config;
pub mod device_events;
pub mod devices;
pub mod dhcp_scanner;
@@ -50,6 +52,7 @@ pub mod utils;
),
paths(
test_api,
config::read,
devices::list,
devices::summary,
devices::read,
@@ -71,6 +74,8 @@ pub mod utils;
snmp_scanner::status,
),
components(schemas(
Config,
NotificationConfig,
Device,
DeviceListResponse,
DeviceSummary,
@@ -90,6 +95,7 @@ pub mod utils;
)),
modifiers(&SecurityAddon),
tags(
(name = "config", description = "Front-end configuration"),
(name = "devices", description = "Device management"),
(name = "notifications", description = "Notification management"),
(name = "push_tokens", description = "Push notification token registration"),
@@ -163,6 +169,7 @@ pub async fn serve() -> Result<(), Box<dyn Error>> {
let router = Router::new()
.route("/api/test", get(test_api))
.route("/api/config", get(config::read))
.route("/api/devices", get(devices::list))
.route("/api/devices", put(devices::register))
.route("/api/devices/summary", get(devices::summary))
+41
View File
@@ -0,0 +1,41 @@
use axum::Json;
use crate::model::config::{Config, NotificationConfig};
use crate::settings::get_settings;
#[utoipa::path(
get,
path = "/api/config",
tag = "config",
responses(
(status = 200, description = "Front-end configuration", body = Config),
),
security(("bearer_auth" = []))
)]
pub async fn read() -> Json<Config> {
let settings = get_settings();
Json(Config {
notifications: NotificationConfig {
method: settings.notifications.method.clone(),
},
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests_common;
#[tokio::test]
async fn config_reports_the_configured_notification_method() {
tests_common::setup().await;
let Json(config) = read().await;
assert_eq!(
config.notifications.method,
get_settings().notifications.method,
"The endpoint should echo the backend's configured notification method"
);
}
}