diff --git a/core/notifications/src/account_notification_settings/entity.rs b/core/notifications/src/account_notification_settings/entity.rs index 696240134c..d7e47c0f1e 100644 --- a/core/notifications/src/account_notification_settings/entity.rs +++ b/core/notifications/src/account_notification_settings/entity.rs @@ -14,6 +14,9 @@ pub enum AccountNotificationSettingsEvent { ChannelDisabled { channel: NotificationChannel, }, + ChannelEnabled { + channel: NotificationChannel, + }, } impl EntityEvent for AccountNotificationSettingsEvent { @@ -37,13 +40,31 @@ impl EsEntity for AccountNotificationSettings { impl AccountNotificationSettings { pub fn disable_channel(&mut self, channel: NotificationChannel) { - // check if its already disabled -> NoOp + if !self.is_channel_enabled(channel) { + return; + } self.events .push(AccountNotificationSettingsEvent::ChannelDisabled { channel }); } - pub fn project>(&self) -> T { - self.events.project() + pub fn enable_channel(&mut self, channel: NotificationChannel) { + if self.is_channel_enabled(channel) { + return; + } + self.events + .push(AccountNotificationSettingsEvent::ChannelEnabled { channel }); + } + + pub fn is_channel_enabled(&self, channel: NotificationChannel) -> bool { + self.events.iter().fold(true, |acc, event| match event { + AccountNotificationSettingsEvent::ChannelDisabled { channel: c } if c == &channel => { + false + } + AccountNotificationSettingsEvent::ChannelEnabled { channel: c } if c == &channel => { + true + } + _ => acc, + }) } } @@ -69,3 +90,45 @@ impl TryFrom> for AccountNotifica builder.events(events).build() } } + +#[cfg(test)] +mod tests { + use super::*; + + fn initial_events() -> EntityEvents { + let id = AccountNotificationSettingsId::new(); + EntityEvents::init( + id, + [AccountNotificationSettingsEvent::Initialized { + id, + galoy_account_id: GaloyAccountId::from("galoy_id".to_string()), + }], + ) + } + + #[test] + fn channel_is_initially_enabled() { + let events = initial_events(); + let settings = AccountNotificationSettings::try_from(events).expect("Could not hydrate"); + assert!(settings.is_channel_enabled(NotificationChannel::Push)); + } + + #[test] + fn can_disable_channel() { + let events = initial_events(); + let mut settings = + AccountNotificationSettings::try_from(events).expect("Could not hydrate"); + settings.disable_channel(NotificationChannel::Push); + assert!(!settings.is_channel_enabled(NotificationChannel::Push)); + } + + #[test] + fn can_reenable_channel() { + let events = initial_events(); + let mut settings = + AccountNotificationSettings::try_from(events).expect("Could not hydrate"); + settings.disable_channel(NotificationChannel::Push); + settings.enable_channel(NotificationChannel::Push); + assert!(settings.is_channel_enabled(NotificationChannel::Push)); + } +} diff --git a/core/notifications/src/app/mod.rs b/core/notifications/src/app/mod.rs index d2eacae7a9..6eac00e1e7 100644 --- a/core/notifications/src/app/mod.rs +++ b/core/notifications/src/app/mod.rs @@ -1,7 +1,6 @@ mod config; mod error; -use es_entity::EsEntityProjection; use sqlx::{Pool, Postgres}; use crate::{account_notification_settings::*, primitives::*}; @@ -26,13 +25,11 @@ impl NotificationsApp { } } - pub async fn disable_channel_on_account< - T: EsEntityProjection, - >( + pub async fn disable_channel_on_account( &self, account_id: GaloyAccountId, channel: NotificationChannel, - ) -> Result { + ) -> Result { let mut account_settings = if let Some(settings) = self.settings.find_for_account_id(account_id).await? { settings @@ -42,6 +39,6 @@ impl NotificationsApp { }; account_settings.disable_channel(channel); self.settings.persist(&mut account_settings).await?; - Ok(account_settings.project()) + Ok(account_settings) } } diff --git a/core/notifications/src/graphql/convert.rs b/core/notifications/src/graphql/convert.rs index 401305aaec..f75955e2a9 100644 --- a/core/notifications/src/graphql/convert.rs +++ b/core/notifications/src/graphql/convert.rs @@ -1,10 +1,14 @@ -use es_entity::EsEntityProjection; - use super::types::NotificationSettingsAlt; -use crate::account_notification_settings::*; +use crate::{account_notification_settings::*, primitives::*}; -impl EsEntityProjection for NotificationSettingsAlt { - fn apply(&mut self, _: &AccountNotificationSettingsEvent) -> Self { +impl From for NotificationSettingsAlt { + fn from(settings: AccountNotificationSettings) -> Self { + // NotificationSettingsAlt { + // push: NotificationChannelSettingsAlt { + // enabled: settings.is_channel_enabled(NotificationChannel::Push), + // disabled_categories: settings.dissabled_categories_for(NotificationChannel::Push), + // }, + // } unimplemented!() } } diff --git a/core/notifications/src/graphql/schema.rs b/core/notifications/src/graphql/schema.rs index 95f2bc7d66..bf21ebc331 100644 --- a/core/notifications/src/graphql/schema.rs +++ b/core/notifications/src/graphql/schema.rs @@ -52,11 +52,11 @@ impl Mutation { return Err("Permission denied".into()); } let app = ctx.data_unchecked::(); - let res: NotificationSettingsAlt = app + let settings = app .disable_channel_on_account(GaloyAccountId::from(subject.id.clone()), input.channel) .await?; Ok(AccountUpdateNotificationSettingsPayloadAlt { - notification_settings: res, + notification_settings: NotificationSettingsAlt::from(settings), }) } } diff --git a/core/notifications/src/graphql/types.rs b/core/notifications/src/graphql/types.rs index a99a6ae382..9036bd7910 100644 --- a/core/notifications/src/graphql/types.rs +++ b/core/notifications/src/graphql/types.rs @@ -7,17 +7,6 @@ pub(super) struct NotificationSettingsAlt { pub push: NotificationChannelSettingsAlt, } -impl Default for NotificationSettingsAlt { - fn default() -> Self { - Self { - push: NotificationChannelSettingsAlt { - enabled: true, - disabled_categories: vec![], - }, - } - } -} - #[derive(SimpleObject)] pub(super) struct NotificationChannelSettingsAlt { pub enabled: bool, diff --git a/lib/es-entity-rs/src/events.rs b/lib/es-entity-rs/src/events.rs index 28f588f8d4..870166204f 100644 --- a/lib/es-entity-rs/src/events.rs +++ b/lib/es-entity-rs/src/events.rs @@ -21,13 +21,6 @@ pub trait EsEntity: TryFrom::Event>, Error = Ent type Event: EntityEvent; } -pub trait EsEntityProjection -where - Self: Default, -{ - fn apply(&mut self, event: &E) -> Self; -} - pub struct EntityEvents { entity_id: ::EntityId, persisted_events: Vec, @@ -53,16 +46,6 @@ where self.new_events.push(event); } - pub fn project>(&self) -> P { - self.persisted_events - .iter() - .chain(self.new_events.iter()) - .fold(P::default(), |mut acc, event| { - acc = acc.apply(event); - acc - }) - } - pub async fn persist( &mut self, tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,