diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0e0ca6c5..f0148a41a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ [Full Changelog](In progress) +### Push +- Add `listSubscriptionReq` and `SubscriptionRequest` to list informations used to subscribe. May be used to subscribe to another pusher + # v137.0 (_2025-03-03_) ## ✨ What's New ✨ diff --git a/components/push/src/internal/push_manager.rs b/components/push/src/internal/push_manager.rs index 86681f5bc3..f1d335a01e 100644 --- a/components/push/src/internal/push_manager.rs +++ b/components/push/src/internal/push_manager.rs @@ -20,7 +20,9 @@ use crate::internal::communications::{Connection, PersistedRateLimiter}; use crate::internal::config::PushConfiguration; use crate::internal::crypto::KeyV1 as Key; use crate::internal::storage::{PushRecord, Storage}; -use crate::{KeyInfo, PushSubscriptionChanged, SubscriptionInfo, SubscriptionResponse}; +use crate::{ + KeyInfo, PushSubscriptionChanged, SubscriptionInfo, SubscriptionRequest, SubscriptionResponse, +}; use super::crypto::{Cryptography, PushPayload}; const UPDATE_RATE_LIMITER_INTERVAL: u64 = 24 * 60 * 60; // 24 hours. @@ -35,6 +37,15 @@ impl From for KeyInfo { } } +impl From for SubscriptionRequest { + fn from(record: PushRecord) -> Self { + SubscriptionRequest { + scope: record.scope, + app_server_key: record.app_server_key, + } + } +} + impl From for PushSubscriptionChanged { fn from(record: PushRecord) -> Self { PushSubscriptionChanged { @@ -156,6 +167,15 @@ impl PushManager { .transpose() } + pub fn list_subscription_req(&self) -> Result> { + Ok(self + .store + .get_record_list()? + .into_iter() + .map(SubscriptionRequest::from) + .collect()) + } + pub fn unsubscribe(&mut self, scope: &str) -> Result { let (uaid, auth) = self.ensure_auth_pair()?; let record = self.store.get_record_by_scope(scope)?; diff --git a/components/push/src/internal/storage/db.rs b/components/push/src/internal/storage/db.rs index e78b5665eb..e047d8ae21 100644 --- a/components/push/src/internal/storage/db.rs +++ b/components/push/src/internal/storage/db.rs @@ -17,6 +17,8 @@ pub trait Storage: Sized { fn get_record_by_scope(&self, scope: &str) -> Result>; + fn get_record_list(&self) -> Result>; + fn put_record(&self, record: &PushRecord) -> Result; fn delete_record(&self, chid: &str) -> Result; @@ -118,6 +120,19 @@ impl Storage for PushDb { self.try_query_row(&query, &[(":scope", scope)], PushRecord::from_row, false) } + fn get_record_list(&self) -> Result> { + let query = format!( + "SELECT {common_cols} + FROM push_record", + common_cols = schema::COMMON_COLS, + ); + self.query_rows_and_then( + &query, + [], + |row| -> Result { Ok(PushRecord::from_row(row)?) }, + ) + } + fn put_record(&self, record: &PushRecord) -> Result { log::debug!( "adding push subscription for scope '{}', channel '{}', endpoint '{}'", diff --git a/components/push/src/lib.rs b/components/push/src/lib.rs index 2f84dc5bba..e4749357da 100644 --- a/components/push/src/lib.rs +++ b/components/push/src/lib.rs @@ -281,6 +281,20 @@ impl PushManager { self.internal.lock().unwrap().get_subscription(scope) } + /// List existing subscription requests + /// Contains scope and application server key from existing subscriptions + /// + /// # Returns + /// The list of existing [`SubscriptionRequest`] + /// + /// # Errors + /// Returns an error if: + /// - An error occurred accessing the PushManagers's persistent storage + #[handle_error(PushError)] + pub fn list_subscription_req(&self) -> ApiResult> { + self.internal.lock().unwrap().list_subscription_req() + } + /// Unsubscribe from given channelID, ending that subscription for the user. /// /// # Arguments @@ -381,6 +395,13 @@ impl PushManager { } } +/// Fields needed to do a subscription request: the scope and the application server key +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct SubscriptionRequest { + pub scope: String, + pub app_server_key: Option, +} + /// Key Information that can be used to encrypt payloads. These are encoded as base64 /// so will need to be decoded before they can actually be used as keys. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/components/push/src/push.udl b/components/push/src/push.udl index 71084ddce0..e496a79cc3 100644 --- a/components/push/src/push.udl +++ b/components/push/src/push.udl @@ -63,6 +63,27 @@ interface PushManager { [Throws=PushApiError] SubscriptionResponse? get_subscription([ByRef] string scope); + /// List existing scopes + /// + /// # Returns + /// The list of subscribed scopes + /// + /// # Errors + /// Returns an error if: + /// - An error occurred accessing the PushManagers's persistent storage + + /// List existing subscription requests + /// Contains scope and application server key from existing subscriptions + /// + /// # Returns + /// The list of existing [`SubscriptionRequest`] + /// + /// # Errors + /// Returns an error if: + /// - An error occurred accessing the PushManagers's persistent storage + [Throws=PushApiError] + sequence list_subscription_req(); + /// Unsubscribe from given scope, ending that subscription for the user. /// /// # Arguments @@ -141,6 +162,11 @@ interface PushManager { DecryptResponse decrypt(record payload); }; +/// Fields needed to do a subscription request: the scope and the application server key +dictionary SubscriptionRequest { + string scope; + string? app_server_key; +}; /// Key Information that can be used to encrypt payloads dictionary KeyInfo { string auth;