Skip to content
Snippets Groups Projects
push.rs 16.5 KiB
Newer Older
use crate::{database::DatabaseGuard, Error, Result, 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,
Jonas Platte's avatar
Jonas Platte committed
    events::{push_rules::PushRulesEvent, EventType},
Jonas Platte's avatar
Jonas Platte committed
    push::{ConditionalPushRuleInit, PatternedPushRuleInit, SimplePushRuleInit},
/// # `GET /_matrix/client/r0/pushrules`
///
/// Retrieves the push rules event for this user.
pub async fn get_pushrules_all_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<get_pushrules_all::Request>,
) -> Result<get_pushrules_all::Response> {
    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
Jonas Platte's avatar
Jonas Platte committed
    let event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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,
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
///
/// Retrieves a single specified push rule for this user.
pub async fn get_pushrule_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<get_pushrule::Request<'_>>,
) -> Result<get_pushrule::Response> {
    let sender_user = body.sender_user.as_ref().expect("user is authenticated");

Jonas Platte's avatar
Jonas Platte committed
    let event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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_
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.clone().into()),
        RuleKind::Underride => global
            .underride
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.clone().into()),
        RuleKind::Sender => global
            .sender
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.clone().into()),
        RuleKind::Room => global
            .room
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.clone().into()),
        RuleKind::Content => global
            .content
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.clone().into()),
Timo Kösters's avatar
Timo Kösters committed
        _ => None,
    };

    if let Some(rule) = rule {
        Ok(get_pushrule::Response { rule })
    } else {
        Err(Error::BadRequest(
            ErrorKind::NotFound,
            "Push rule not found.",
        ))
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
///
/// Creates a single specified push rule for this user.
pub async fn set_pushrule_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<set_pushrule::Request<'_>>,
) -> Result<set_pushrule::Response> {
    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
    let body = body.body;

    if body.scope != "global" {
        return Err(Error::BadRequest(
            ErrorKind::InvalidParam,
            "Scopes other than 'global' are not supported.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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 => {
Jonas Platte's avatar
Jonas Platte committed
            global.override_.replace(
                ConditionalPushRuleInit {
Jonas Platte's avatar
Jonas Platte committed
                    actions: body.actions,
                    default: false,
                    enabled: true,
Jonas Platte's avatar
Jonas Platte committed
                    rule_id: body.rule_id,
                    conditions: body.conditions,
                }
                .into(),
Jonas Platte's avatar
Jonas Platte committed
            );
        }
        RuleKind::Underride => {
Jonas Platte's avatar
Jonas Platte committed
            global.underride.replace(
                ConditionalPushRuleInit {
Jonas Platte's avatar
Jonas Platte committed
                    actions: body.actions,
                    default: false,
                    enabled: true,
Jonas Platte's avatar
Jonas Platte committed
                    rule_id: body.rule_id,
                    conditions: body.conditions,
                }
                .into(),
Jonas Platte's avatar
Jonas Platte committed
            );
        }
        RuleKind::Sender => {
Jonas Platte's avatar
Jonas Platte committed
            global.sender.replace(
                SimplePushRuleInit {
Jonas Platte's avatar
Jonas Platte committed
                    actions: body.actions,
                    default: false,
                    enabled: true,
Jonas Platte's avatar
Jonas Platte committed
                    rule_id: body.rule_id,
                }
                .into(),
Jonas Platte's avatar
Jonas Platte committed
            );
        }
        RuleKind::Room => {
Jonas Platte's avatar
Jonas Platte committed
            global.room.replace(
                SimplePushRuleInit {
Jonas Platte's avatar
Jonas Platte committed
                    actions: body.actions,
                    default: false,
                    enabled: true,
Jonas Platte's avatar
Jonas Platte committed
                    rule_id: body.rule_id,
                }
                .into(),
Jonas Platte's avatar
Jonas Platte committed
            );
        }
        RuleKind::Content => {
Jonas Platte's avatar
Jonas Platte committed
            global.content.replace(
                PatternedPushRuleInit {
Jonas Platte's avatar
Jonas Platte committed
                    actions: body.actions,
                    default: false,
                    enabled: true,
Jonas Platte's avatar
Jonas Platte committed
                    rule_id: body.rule_id,
                    pattern: body.pattern.unwrap_or_default(),
                }
                .into(),
Jonas Platte's avatar
Jonas Platte committed
            );
Timo Kösters's avatar
Timo Kösters committed
        _ => {}
    db.account_data
        .update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
    Ok(set_pushrule::Response {})
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
///
/// Gets the actions of a single specified push rule for this user.
pub async fn get_pushrule_actions_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<get_pushrule_actions::Request<'_>>,
) -> Result<get_pushrule_actions::Response> {
    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.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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_
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.actions.clone()),
        RuleKind::Underride => global
            .underride
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.actions.clone()),
        RuleKind::Sender => global
            .sender
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.actions.clone()),
        RuleKind::Room => global
            .room
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.actions.clone()),
        RuleKind::Content => global
            .content
Jonas Platte's avatar
Jonas Platte committed
            .get(body.rule_id.as_str())
            .map(|rule| rule.actions.clone()),
Timo Kösters's avatar
Timo Kösters committed
        _ => None,

    Ok(get_pushrule_actions::Response {
        actions: actions.unwrap_or_default(),
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
///
/// Sets the actions of a single specified push rule for this user.
pub async fn set_pushrule_actions_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<set_pushrule_actions::Request<'_>>,
) -> Result<set_pushrule_actions::Response> {
    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.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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 => {
Jonas Platte's avatar
Jonas Platte committed
            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 => {
Jonas Platte's avatar
Jonas Platte committed
            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 => {
Jonas Platte's avatar
Jonas Platte committed
            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 => {
Jonas Platte's avatar
Jonas Platte committed
            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 => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.content.get(body.rule_id.as_str()).cloned() {
                rule.actions = body.actions.clone();
                global.content.replace(rule);
Timo Kösters's avatar
Timo Kösters committed
        _ => {}
    db.account_data
        .update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
    Ok(set_pushrule_actions::Response {})
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
///
/// Gets the enabled status of a single specified push rule for this user.
pub async fn get_pushrule_enabled_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<get_pushrule_enabled::Request<'_>>,
) -> Result<get_pushrule_enabled::Response> {
    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.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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()
Jonas Platte's avatar
Jonas Platte committed
            .find(|rule| rule.rule_id == body.rule_id)
            .map_or(false, |rule| rule.enabled),
        RuleKind::Underride => global
            .underride
            .iter()
Jonas Platte's avatar
Jonas Platte committed
            .find(|rule| rule.rule_id == body.rule_id)
            .map_or(false, |rule| rule.enabled),
        RuleKind::Sender => global
            .sender
            .iter()
Jonas Platte's avatar
Jonas Platte committed
            .find(|rule| rule.rule_id == body.rule_id)
            .map_or(false, |rule| rule.enabled),
        RuleKind::Room => global
            .room
            .iter()
Jonas Platte's avatar
Jonas Platte committed
            .find(|rule| rule.rule_id == body.rule_id)
            .map_or(false, |rule| rule.enabled),
        RuleKind::Content => global
            .content
            .iter()
Jonas Platte's avatar
Jonas Platte committed
            .find(|rule| rule.rule_id == body.rule_id)
            .map_or(false, |rule| rule.enabled),
Timo Kösters's avatar
Timo Kösters committed
        _ => false,
    Ok(get_pushrule_enabled::Response { enabled })
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
///
/// Sets the enabled status of a single specified push rule for this user.
pub async fn set_pushrule_enabled_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<set_pushrule_enabled::Request<'_>>,
) -> Result<set_pushrule_enabled::Response> {
    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.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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 => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.override_.get(body.rule_id.as_str()).cloned() {
                global.override_.remove(&rule);
Jonas Platte's avatar
Jonas Platte committed
                rule.enabled = body.enabled;
                global.override_.insert(rule);
            }
        }
        RuleKind::Underride => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.underride.get(body.rule_id.as_str()).cloned() {
                global.underride.remove(&rule);
Jonas Platte's avatar
Jonas Platte committed
                rule.enabled = body.enabled;
                global.underride.insert(rule);
            }
        }
        RuleKind::Sender => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.sender.get(body.rule_id.as_str()).cloned() {
                global.sender.remove(&rule);
Jonas Platte's avatar
Jonas Platte committed
                rule.enabled = body.enabled;
                global.sender.insert(rule);
            }
        }
        RuleKind::Room => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.room.get(body.rule_id.as_str()).cloned() {
                global.room.remove(&rule);
Jonas Platte's avatar
Jonas Platte committed
                rule.enabled = body.enabled;
                global.room.insert(rule);
            }
        }
        RuleKind::Content => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(mut rule) = global.content.get(body.rule_id.as_str()).cloned() {
                global.content.remove(&rule);
Jonas Platte's avatar
Jonas Platte committed
                rule.enabled = body.enabled;
                global.content.insert(rule);
            }
        }
Timo Kösters's avatar
Timo Kösters committed
        _ => {}
    db.account_data
        .update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
    Ok(set_pushrule_enabled::Response {})
/// # `DELETE /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
///
/// Deletes a single specified push rule for this user.
pub async fn delete_pushrule_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<delete_pushrule::Request<'_>>,
) -> Result<delete_pushrule::Response> {
    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.",
        ));
    }

Jonas Platte's avatar
Jonas Platte committed
    let mut event: PushRulesEvent = db
        .account_data
Jonas Platte's avatar
Jonas Platte committed
        .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 => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(rule) = global.override_.get(body.rule_id.as_str()).cloned() {
                global.override_.remove(&rule);
            }
        }
        RuleKind::Underride => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(rule) = global.underride.get(body.rule_id.as_str()).cloned() {
                global.underride.remove(&rule);
            }
        }
        RuleKind::Sender => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(rule) = global.sender.get(body.rule_id.as_str()).cloned() {
                global.sender.remove(&rule);
            }
        }
        RuleKind::Room => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(rule) = global.room.get(body.rule_id.as_str()).cloned() {
                global.room.remove(&rule);
            }
        }
        RuleKind::Content => {
Jonas Platte's avatar
Jonas Platte committed
            if let Some(rule) = global.content.get(body.rule_id.as_str()).cloned() {
                global.content.remove(&rule);
            }
        }
Timo Kösters's avatar
Timo Kösters committed
        _ => {}
    db.account_data
        .update(None, sender_user, EventType::PushRules, &event, &db.globals)?;
    Ok(delete_pushrule::Response {})
/// # `GET /_matrix/client/r0/pushers`
///
/// Gets all currently active pushers for the sender user.
pub async fn get_pushers_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<get_pushers::Request>,
) -> Result<get_pushers::Response> {
    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
    Ok(get_pushers::Response {
        pushers: db.pusher.get_pushers(sender_user)?,
/// # `POST /_matrix/client/r0/pushers/set`
///
/// Adds a pusher for the sender user.
///
/// - TODO: Handle `append`
pub async fn set_pushers_route(
Jonathan de Jong's avatar
Jonathan de Jong committed
    db: DatabaseGuard,
    body: Ruma<set_pusher::Request>,
) -> Result<set_pusher::Response> {
    let sender_user = body.sender_user.as_ref().expect("user is authenticated");
    let pusher = body.pusher.clone();

    db.pusher.set_pusher(sender_user, pusher)?;
    Ok(set_pusher::Response::default())