feat(push): Add MSC4174 web push

This commit is contained in:
Erwan Leboucher authored and Ellis Git committed 2026-09-21 23:35:05 +00:00
1 parent dbcffe8af0
commit ed1e634579
23 files changed
+1864 -281

No files matched your search

+6
View File
@@ -13,6 +13,7 @@ use ruma::{
},
assign,
};
use serde_json::json;
use crate::Ruma;
@@ -55,5 +56,10 @@ pub(crate) async fn get_capabilities_route(
assign!(ProfileFieldsCapability::new(true), { disallowed: Some(services.oidc.restricted_profile_fields()) }),
);
capabilities.set(
"org.matrix.msc4174.webpush",
json!({ "enabled": true, "vapid": services.pusher.webpush_vapid_public_key() }),
)?;
Ok(get_capabilities::v3::Response::new(capabilities))
}
+77 -8
View File
@@ -1,13 +1,16 @@
use std::sync::LazyLock;
use axum::extract::State;
use conduwuit::{Err, Error, Result, err};
use conduwuit_service::Services;
use conduwuit::{Err, Error, Result, err, utils::IterStream};
use conduwuit_service::{Services, pusher::ActivationOutcome};
use futures::StreamExt;
use ruma::{
CanonicalJsonObject, CanonicalJsonValue,
api::{
client::push::{
delete_pushrule, get_pushers, get_pushrule, get_pushrule_actions,
get_pushrule_enabled, get_pushrules_all, get_pushrules_global_scope, set_pusher,
set_pushrule, set_pushrule_actions, set_pushrule_enabled,
delete_pushrule, get_pushrule, get_pushrule_actions, get_pushrule_enabled,
get_pushrules_all, get_pushrules_global_scope, set_pushrule, set_pushrule_actions,
set_pushrule_enabled,
},
error::ErrorKind,
},
@@ -20,6 +23,12 @@ use ruma::{
RemovePushRuleError, Ruleset,
},
};
use ruminuwuity::pushers::{
PusherKind,
ack::unstable as pushers_ack,
get_pushers::{self, v3::PusherWithActivation},
set_pusher,
};
use crate::Ruma;
@@ -460,7 +469,29 @@ pub(crate) async fn get_pushers_route(
) -> Result<get_pushers::v3::Response> {
let sender_user = body.identity.expect_sender_user()?;
Ok(get_pushers::v3::Response::new(services.pusher.get_pushers(sender_user).await))
let pushers = services
.pusher
.get_pushers(sender_user)
.await
.into_iter()
.stream()
.then(async |pusher| {
let activated = match pusher.kind {
| PusherKind::WebPush(_) => Some(
services
.pusher
.is_webpush_activated(sender_user, pusher.ids.pushkey.as_str())
.await,
),
| _ => None,
};
PusherWithActivation { pusher, activated }
})
.collect()
.await;
Ok(get_pushers::v3::Response::new(pushers))
}
/// # `POST /_matrix/client/r0/pushers/set`
@@ -475,12 +506,50 @@ pub(crate) async fn set_pushers_route(
let sender_user = body.identity.expect_sender_user()?;
let sender_device = body.identity.expect_sender_device()?;
services
let needs_activation = services
.pusher
.set_pusher(sender_user, sender_device, &body.action)
.await?;
Ok(set_pusher::v3::Response::new())
Ok(set_pusher::v3::Response::new(needs_activation))
}
pub(crate) async fn pushers_ack_route(
State(services): State<crate::State>,
body: Ruma<pushers_ack::Request>,
) -> Result<pushers_ack::Response> {
let sender_user = body.identity.expect_sender_user()?;
match services
.pusher
.activate_webpush_pusher(sender_user, &body.app_id, &body.ack_token)
.await?
{
| ActivationOutcome::Activated => Ok(pushers_ack::Response::new()),
| ActivationOutcome::NoSuchPusher => {
Err!(Request(NotFound("No pusher with this app ID exists.")))
},
| ActivationOutcome::UnknownToken => Err(Error::Request(
UNKNOWN_ACTIVATION_TOKEN.clone(),
"Unknown activation token.".into(),
http::StatusCode::BAD_REQUEST,
)),
| ActivationOutcome::Expired => Err(Error::Request(
EXPIRED_ACTIVATION_TOKEN.clone(),
"Activation token has expired.".into(),
http::StatusCode::BAD_REQUEST,
)),
}
}
static EXPIRED_ACTIVATION_TOKEN: LazyLock<ErrorKind> =
LazyLock::new(|| custom_error_kind("ORG.MATRIX.MSC4174_EXPIRED_ACTIVATION_TOKEN"));
static UNKNOWN_ACTIVATION_TOKEN: LazyLock<ErrorKind> =
LazyLock::new(|| custom_error_kind("ORG.MATRIX.MSC4174_UNKNOWN_ACTIVATION_TOKEN"));
fn custom_error_kind(errcode: &str) -> ErrorKind {
serde_json::from_value(serde_json::json!({ "errcode": errcode }))
.expect("errcode deserializes into an ErrorKind")
}
/// user somehow has bad push rules, these must always exist per spec.
+1
View File
@@ -171,6 +171,7 @@ pub fn build(router: Router<State>, state: State) -> Router<State> {
.ruma_route(&client::get_key_changes_route)
.ruma_route(&client::get_pushers_route)
.ruma_route(&client::set_pushers_route)
.ruma_route(&client::pushers_ack_route)
.ruma_route(&client::upgrade_room_route)
.ruma_route(&client::get_threads_route)
.ruma_route(&client::get_relating_events_with_rel_type_and_event_type_route)