use super::State; use crate::{ConduitResult, Database, Error, Ruma}; use ruma::{ api::client::{ error::ErrorKind, r0::push::{ delete_pushrule, get_pushers, get_pushrule, get_pushrule_actions, get_pushrule_enabled, get_pushrules_all, set_pushrule, set_pushrule_actions, set_pushrule_enabled, RuleKind, }, }, events::EventType, push::{ ConditionalPushRuleInit, ContentPushRule, OverridePushRule, PatternedPushRuleInit, RoomPushRule, SenderPushRule, SimplePushRuleInit, UnderridePushRule, }, }; #[cfg(feature = "conduit_bin")] use rocket::{delete, get, post, put}; #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/r0/pushrules", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_pushrules_all_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; Ok(get_pushrules_all::Response { global: event.content.global, } .into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_pushrule_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = event.content.global; let rule = match body.kind { RuleKind::Override => global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.clone().into()), RuleKind::Underride => global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.clone().into()), RuleKind::Sender => global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.clone().into()), RuleKind::Room => global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.clone().into()), RuleKind::Content => global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.clone().into()), RuleKind::_Custom(_) => None, }; if let Some(rule) = rule { Ok(get_pushrule::Response { rule }.into()) } else { Err(Error::BadRequest( ErrorKind::NotFound, "Push rule not found.", )) } } #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn set_pushrule_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; match body.kind { RuleKind::Override => { if let Some(rule) = global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.override_.remove(&rule); } global.override_.insert(OverridePushRule( ConditionalPushRuleInit { actions: body.actions.clone(), default: false, enabled: true, rule_id: body.rule_id.clone(), conditions: body.conditions.clone(), } .into(), )); } RuleKind::Underride => { if let Some(rule) = global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.underride.remove(&rule); } global.underride.insert(UnderridePushRule( ConditionalPushRuleInit { actions: body.actions.clone(), default: false, enabled: true, rule_id: body.rule_id.clone(), conditions: body.conditions.clone(), } .into(), )); } RuleKind::Sender => { if let Some(rule) = global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.sender.remove(&rule); } global.sender.insert(SenderPushRule( SimplePushRuleInit { actions: body.actions.clone(), default: false, enabled: true, rule_id: body.rule_id.clone(), } .into(), )); } RuleKind::Room => { if let Some(rule) = global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.room.remove(&rule); } global.room.insert(RoomPushRule( SimplePushRuleInit { actions: body.actions.clone(), default: false, enabled: true, rule_id: body.rule_id.clone(), } .into(), )); } RuleKind::Content => { if let Some(rule) = global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.content.remove(&rule); } global.content.insert(ContentPushRule( PatternedPushRuleInit { actions: body.actions.clone(), default: false, enabled: true, rule_id: body.rule_id.clone(), pattern: body.pattern.clone().unwrap_or_default(), } .into(), )); } RuleKind::_Custom(_) => {} } db.account_data.update( None, &sender_user, EventType::PushRules, &event, &db.globals, )?; db.flush().await?; Ok(set_pushrule::Response.into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/r0/pushrules/<_>/<_>/<_>/actions", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_pushrule_actions_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; let actions = match body.kind { RuleKind::Override => global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.actions.clone()), RuleKind::Underride => global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.actions.clone()), RuleKind::Sender => global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.actions.clone()), RuleKind::Room => global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.actions.clone()), RuleKind::Content => global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map(|rule| rule.0.actions.clone()), RuleKind::_Custom(_) => None, }; db.flush().await?; Ok(get_pushrule_actions::Response { actions: actions.unwrap_or_default(), } .into()) } #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/r0/pushrules/<_>/<_>/<_>/actions", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn set_pushrule_actions_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; match body.kind { RuleKind::Override => { if let Some(mut rule) = global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.override_.remove(&rule); rule.0.actions = body.actions.clone(); global.override_.insert(rule); } } RuleKind::Underride => { if let Some(mut rule) = global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.underride.remove(&rule); rule.0.actions = body.actions.clone(); global.underride.insert(rule); } } RuleKind::Sender => { if let Some(mut rule) = global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.sender.remove(&rule); rule.0.actions = body.actions.clone(); global.sender.insert(rule); } } RuleKind::Room => { if let Some(mut rule) = global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.room.remove(&rule); rule.0.actions = body.actions.clone(); global.room.insert(rule); } } RuleKind::Content => { if let Some(mut rule) = global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.content.remove(&rule); rule.0.actions = body.actions.clone(); global.content.insert(rule); } } RuleKind::_Custom(_) => {} }; db.account_data.update( None, &sender_user, EventType::PushRules, &event, &db.globals, )?; db.flush().await?; Ok(set_pushrule_actions::Response.into()) } #[cfg_attr( feature = "conduit_bin", get("/_matrix/client/r0/pushrules/<_>/<_>/<_>/enabled", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_pushrule_enabled_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; let enabled = match body.kind { RuleKind::Override => global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map_or(false, |rule| rule.0.enabled), RuleKind::Underride => global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map_or(false, |rule| rule.0.enabled), RuleKind::Sender => global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map_or(false, |rule| rule.0.enabled), RuleKind::Room => global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map_or(false, |rule| rule.0.enabled), RuleKind::Content => global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .map_or(false, |rule| rule.0.enabled), RuleKind::_Custom(_) => false, }; db.flush().await?; Ok(get_pushrule_enabled::Response { enabled }.into()) } #[cfg_attr( feature = "conduit_bin", put("/_matrix/client/r0/pushrules/<_>/<_>/<_>/enabled", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn set_pushrule_enabled_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; match body.kind { RuleKind::Override => { if let Some(mut rule) = global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.override_.remove(&rule); rule.0.enabled = body.enabled; global.override_.insert(rule); } } RuleKind::Underride => { if let Some(mut rule) = global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.underride.remove(&rule); rule.0.enabled = body.enabled; global.underride.insert(rule); } } RuleKind::Sender => { if let Some(mut rule) = global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.sender.remove(&rule); rule.0.enabled = body.enabled; global.sender.insert(rule); } } RuleKind::Room => { if let Some(mut rule) = global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.room.remove(&rule); rule.0.enabled = body.enabled; global.room.insert(rule); } } RuleKind::Content => { if let Some(mut rule) = global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.content.remove(&rule); rule.0.enabled = body.enabled; global.content.insert(rule); } } RuleKind::_Custom(_) => {} } db.account_data.update( None, &sender_user, EventType::PushRules, &event, &db.globals, )?; db.flush().await?; Ok(set_pushrule_enabled::Response.into()) } #[cfg_attr( feature = "conduit_bin", delete("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn delete_pushrule_route( db: State<'_, Database>, body: Ruma>, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); if body.scope != "global" { return Err(Error::BadRequest( ErrorKind::InvalidParam, "Scopes other than 'global' are not supported.", )); } let mut event = db .account_data .get::(None, &sender_user, EventType::PushRules)? .ok_or(Error::BadRequest( ErrorKind::NotFound, "PushRules event not found.", ))?; let global = &mut event.content.global; match body.kind { RuleKind::Override => { if let Some(rule) = global .override_ .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.override_.remove(&rule); } } RuleKind::Underride => { if let Some(rule) = global .underride .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.underride.remove(&rule); } } RuleKind::Sender => { if let Some(rule) = global .sender .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.sender.remove(&rule); } } RuleKind::Room => { if let Some(rule) = global .room .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.room.remove(&rule); } } RuleKind::Content => { if let Some(rule) = global .content .iter() .find(|rule| rule.0.rule_id == body.rule_id) .cloned() { global.content.remove(&rule); } } RuleKind::_Custom(_) => {} } db.account_data.update( None, &sender_user, EventType::PushRules, &event, &db.globals, )?; db.flush().await?; Ok(delete_pushrule::Response.into()) } #[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/pushers"))] #[tracing::instrument] pub async fn get_pushers_route() -> ConduitResult { Ok(get_pushers::Response { pushers: Vec::new(), } .into()) } #[cfg_attr(feature = "conduit_bin", post("/_matrix/client/r0/pushers/set"))] #[tracing::instrument(skip(db))] pub async fn set_pushers_route(db: State<'_, Database>) -> ConduitResult { db.flush().await?; Ok(get_pushers::Response { pushers: Vec::new(), } .into()) }