mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Report delivered device count from the test-notification endpoint
POST /api/notifications/test previously returned a blanket 200 even when there
were no registered devices, so a test that reached nobody looked like a success.
push::send now returns the number of devices the relay confirmed delivery to, and
the endpoint returns it as {"delivered": N}. Settings shows "sent to N device(s)"
on success and an explicit "No devices are registered..." warning when N is 0,
which is the case that previously masqueraded as success.
Backend, API and widget tests updated; clippy and dart analyze clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
0075072196
commit
475edcb2cf
@@ -18,10 +18,10 @@ pub use delivery::run_delivery;
|
||||
pub use error::DeliveryError;
|
||||
|
||||
/// Send a one-off test push to every registered device through the push relay. Used by the app's
|
||||
/// "Send test notification" button to verify end-to-end push delivery. Unlike scan-driven
|
||||
/// notifications it is not persisted to the notifications list, and it is a no-op (still `Ok`) when
|
||||
/// no devices are registered.
|
||||
pub async fn send_test_push() -> Result<(), DeliveryError> {
|
||||
/// "Send test notification" button to verify end-to-end push delivery. Returns the number of devices
|
||||
/// the relay confirmed delivery to (0 when none are registered). Unlike scan-driven notifications it
|
||||
/// is not persisted to the notifications list.
|
||||
pub async fn send_test_push() -> Result<usize, DeliveryError> {
|
||||
let config = crate::settings::get_settings()
|
||||
.notifications
|
||||
.push
|
||||
|
||||
@@ -48,13 +48,14 @@ fn dead_tokens(results: &[RelayTokenResult]) -> Vec<String> {
|
||||
|
||||
/// Deliver a notification to all registered devices through the project-operated push relay. Loads
|
||||
/// the stored tokens, forwards only the already-sanitized title/body, and prunes any tokens the
|
||||
/// relay reports as dead. Best-effort: a relay/network failure returns an error (logged by the
|
||||
/// caller) but never loses the event, which is already persisted in the notifications table.
|
||||
pub async fn send(config: &Push, title: String, body: String) -> Result<(), DeliveryError> {
|
||||
/// relay reports as dead. Returns the number of devices the relay confirmed delivery to. Best-effort:
|
||||
/// a relay/network failure returns an error (logged by the caller) but never loses the event, which
|
||||
/// is already persisted in the notifications table.
|
||||
pub async fn send(config: &Push, title: String, body: String) -> Result<usize, DeliveryError> {
|
||||
let stored = db::run_blocking(db::push_tokens::list).await?;
|
||||
if stored.is_empty() {
|
||||
debug!("No push tokens registered; nothing to deliver via the push relay");
|
||||
return Ok(());
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let request = RelayRequest {
|
||||
@@ -80,7 +81,12 @@ pub async fn send(config: &Push, title: String, body: String) -> Result<(), Deli
|
||||
db::run_blocking(move || db::push_tokens::delete_many(&dead)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
let delivered = parsed
|
||||
.results
|
||||
.iter()
|
||||
.filter(|result| result.status == "ok")
|
||||
.count();
|
||||
Ok(delivered)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -143,7 +149,8 @@ mod tests {
|
||||
let config = Push {
|
||||
relay_url: format!("http://{addr}/v1/push"),
|
||||
};
|
||||
send(&config, "title".into(), "body".into()).await.unwrap();
|
||||
let delivered = send(&config, "title".into(), "body".into()).await.unwrap();
|
||||
assert_eq!(delivered, 1, "Only the live token should count as delivered");
|
||||
|
||||
let all = db::push_tokens::list().unwrap();
|
||||
assert!(
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::model::notifications::{Notification, NotificationListResponse, Notifi
|
||||
use crate::model::push_tokens::{PushPlatform, PushToken};
|
||||
use crate::settings::get_settings;
|
||||
use crate::web_server::devices::{RegisterDevicePayload, UpdateDevicePayload};
|
||||
use crate::web_server::notifications::TestNotificationResponse;
|
||||
use crate::web_server::push_tokens::RegisterPushTokenPayload;
|
||||
use crate::web_server::scanner_status::{
|
||||
ActiveScannerStatusResponse, PassiveScannerStatusResponse,
|
||||
@@ -83,6 +84,7 @@ pub mod utils;
|
||||
Notification,
|
||||
NotificationListResponse,
|
||||
NotificationType,
|
||||
TestNotificationResponse,
|
||||
PushToken,
|
||||
PushPlatform,
|
||||
RegisterPushTokenPayload,
|
||||
|
||||
@@ -7,6 +7,8 @@ use axum::{
|
||||
response::IntoResponse,
|
||||
};
|
||||
use log::error;
|
||||
use serde::Serialize;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::{
|
||||
db, notifications,
|
||||
@@ -14,6 +16,12 @@ use crate::{
|
||||
web_server::utils,
|
||||
};
|
||||
|
||||
/// Result of a test-notification request: how many devices the relay confirmed delivery to.
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct TestNotificationResponse {
|
||||
pub delivered: usize,
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/notifications/{id}",
|
||||
@@ -123,20 +131,17 @@ pub async fn mark_all_as_old() -> impl IntoResponse {
|
||||
path = "/api/notifications/test",
|
||||
tag = "notifications",
|
||||
responses(
|
||||
(status = 200, description = "Test notification dispatched to the push relay"),
|
||||
(status = 200, description = "Test notification dispatched", body = TestNotificationResponse),
|
||||
(status = 500, description = "Internal server error"),
|
||||
),
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn send_test() -> impl IntoResponse {
|
||||
pub async fn send_test() -> Result<Json<TestNotificationResponse>, StatusCode> {
|
||||
match notifications::send_test_push().await {
|
||||
Ok(()) => (StatusCode::OK, "Test notification sent"),
|
||||
Ok(delivered) => Ok(Json(TestNotificationResponse { delivered })),
|
||||
Err(err) => {
|
||||
error!("Error sending test push notification: {err}");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Error sending test notification, check your logs",
|
||||
)
|
||||
Err(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +211,9 @@ mod tests {
|
||||
db::push_tokens::delete_many(&tokens).unwrap();
|
||||
}
|
||||
|
||||
let response = send_test().await.into_response();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let result = send_test()
|
||||
.await
|
||||
.expect("test send should succeed when no devices are registered");
|
||||
assert_eq!(result.0.delivered, 0, "No devices means nothing delivered");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user