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_pusher, set_pushrule, set_pushrule_actions, set_pushrule_enabled, RuleKind, }, }, events::{push_rules, EventType}, push::{ConditionalPushRuleInit, PatternedPushRuleInit, SimplePushRuleInit}, }; #[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_ .get(body.rule_id.as_str()) .map(|rule| rule.clone().into()), RuleKind::Underride => global .underride .get(body.rule_id.as_str()) .map(|rule| rule.clone().into()), RuleKind::Sender => global .sender .get(body.rule_id.as_str()) .map(|rule| rule.clone().into()), RuleKind::Room => global .room .get(body.rule_id.as_str()) .map(|rule| rule.clone().into()), RuleKind::Content => global .content .get(body.rule_id.as_str()) .map(|rule| rule.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, req))] pub async fn set_pushrule_route( db: State<'_, Database>, req: Ruma>, ) -> ConduitResult { let sender_user = req.sender_user.as_ref().expect("user is authenticated"); let body = req.body; 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 => { global.override_.replace( ConditionalPushRuleInit { actions: body.actions, default: false, enabled: true, rule_id: body.rule_id, conditions: body.conditions, } .into(), ); } RuleKind::Underride => { global.underride.replace( ConditionalPushRuleInit { actions: body.actions, default: false, enabled: true, rule_id: body.rule_id, conditions: body.conditions, } .into(), ); } RuleKind::Sender => { global.sender.replace( SimplePushRuleInit { actions: body.actions, default: false, enabled: true, rule_id: body.rule_id, } .into(), ); } RuleKind::Room => { global.room.replace( SimplePushRuleInit { actions: body.actions, default: false, enabled: true, rule_id: body.rule_id, } .into(), ); } RuleKind::Content => { global.content.replace( PatternedPushRuleInit { actions: body.actions, default: false, enabled: true, rule_id: body.rule_id, pattern: body.pattern.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_ .get(body.rule_id.as_str()) .map(|rule| rule.actions.clone()), RuleKind::Underride => global .underride .get(body.rule_id.as_str()) .map(|rule| rule.actions.clone()), RuleKind::Sender => global .sender .get(body.rule_id.as_str()) .map(|rule| rule.actions.clone()), RuleKind::Room => global .room .get(body.rule_id.as_str()) .map(|rule| rule.actions.clone()), RuleKind::Content => global .content .get(body.rule_id.as_str()) .map(|rule| rule.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_.get(body.rule_id.as_str()).cloned() { rule.actions = body.actions.clone(); global.override_.replace(rule); } } RuleKind::Underride => { if let Some(mut rule) = global.underride.get(body.rule_id.as_str()).cloned() { rule.actions = body.actions.clone(); global.underride.replace(rule); } } RuleKind::Sender => { if let Some(mut rule) = global.sender.get(body.rule_id.as_str()).cloned() { rule.actions = body.actions.clone(); global.sender.replace(rule); } } RuleKind::Room => { if let Some(mut rule) = global.room.get(body.rule_id.as_str()).cloned() { rule.actions = body.actions.clone(); global.room.replace(rule); } } RuleKind::Content => { if let Some(mut rule) = global.content.get(body.rule_id.as_str()).cloned() { rule.actions = body.actions.clone(); global.content.replace(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.rule_id == body.rule_id) .map_or(false, |rule| rule.enabled), RuleKind::Underride => global .underride .iter() .find(|rule| rule.rule_id == body.rule_id) .map_or(false, |rule| rule.enabled), RuleKind::Sender => global .sender .iter() .find(|rule| rule.rule_id == body.rule_id) .map_or(false, |rule| rule.enabled), RuleKind::Room => global .room .iter() .find(|rule| rule.rule_id == body.rule_id) .map_or(false, |rule| rule.enabled), RuleKind::Content => global .content .iter() .find(|rule| rule.rule_id == body.rule_id) .map_or(false, |rule| rule.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_.get(body.rule_id.as_str()).cloned() { global.override_.remove(&rule); rule.enabled = body.enabled; global.override_.insert(rule); } } RuleKind::Underride => { if let Some(mut rule) = global.underride.get(body.rule_id.as_str()).cloned() { global.underride.remove(&rule); rule.enabled = body.enabled; global.underride.insert(rule); } } RuleKind::Sender => { if let Some(mut rule) = global.sender.get(body.rule_id.as_str()).cloned() { global.sender.remove(&rule); rule.enabled = body.enabled; global.sender.insert(rule); } } RuleKind::Room => { if let Some(mut rule) = global.room.get(body.rule_id.as_str()).cloned() { global.room.remove(&rule); rule.enabled = body.enabled; global.room.insert(rule); } } RuleKind::Content => { if let Some(mut rule) = global.content.get(body.rule_id.as_str()).cloned() { global.content.remove(&rule); rule.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_.get(body.rule_id.as_str()).cloned() { global.override_.remove(&rule); } } RuleKind::Underride => { if let Some(rule) = global.underride.get(body.rule_id.as_str()).cloned() { global.underride.remove(&rule); } } RuleKind::Sender => { if let Some(rule) = global.sender.get(body.rule_id.as_str()).cloned() { global.sender.remove(&rule); } } RuleKind::Room => { if let Some(rule) = global.room.get(body.rule_id.as_str()).cloned() { global.room.remove(&rule); } } RuleKind::Content => { if let Some(rule) = global.content.get(body.rule_id.as_str()).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", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn get_pushers_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); Ok(get_pushers::Response { pushers: db.pusher.get_pushers(sender_user)?, } .into()) } #[cfg_attr( feature = "conduit_bin", post("/_matrix/client/r0/pushers/set", data = "") )] #[tracing::instrument(skip(db, body))] pub async fn set_pushers_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let pusher = body.pusher.clone(); db.pusher.set_pusher(sender_user, pusher)?; db.flush().await?; Ok(set_pusher::Response::default().into()) }