diff --git a/src/api/client/message.rs b/src/api/client/message.rs index 17bd56ca..4a7135b3 100644 --- a/src/api/client/message.rs +++ b/src/api/client/message.rs @@ -1,6 +1,6 @@ use axum::extract::State; use conduwuit::{ - Err, Result, at, + Err, Result, at, err, matrix::{ event::{Event, Matches}, pdu::PduCount, @@ -22,7 +22,7 @@ use conduwuit_service::{ }; use futures::{FutureExt, StreamExt, TryFutureExt, future::OptionFuture, pin_mut}; use ruma::{ - DeviceId, RoomId, UserId, + DeviceId, MilliSecondsSinceUnixEpoch, RoomId, UserId, api::{ Direction, client::{filter::RoomEventFilter, message::get_message_events}, @@ -78,6 +78,21 @@ pub(crate) async fn get_message_events_route( let room_id = &body.room_id; let filter = &body.filter; + if sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = body.sender_device(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } + if !services.rooms.metadata.exists(room_id).await { return Err!(Request(Forbidden("Room does not exist to this server"))); } diff --git a/src/api/client/read_marker.rs b/src/api/client/read_marker.rs index 145b8f09..fe02d710 100644 --- a/src/api/client/read_marker.rs +++ b/src/api/client/read_marker.rs @@ -121,6 +121,20 @@ pub(crate) async fn create_receipt_route( body: Ruma, ) -> Result { let sender_user = body.sender_user(); + if body.sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = body.sender_device(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } if matches!( &body.receipt_type, diff --git a/src/api/client/redact.rs b/src/api/client/redact.rs index 35fd2eec..e7b917aa 100644 --- a/src/api/client/redact.rs +++ b/src/api/client/redact.rs @@ -1,7 +1,8 @@ use axum::extract::State; -use conduwuit::{Err, Result, matrix::pdu::PduBuilder}; +use conduwuit::{Err, Result, err, matrix::pdu::PduBuilder}; use ruma::{ - api::client::redact::redact_event, events::room::redaction::RoomRedactionEventContent, + MilliSecondsSinceUnixEpoch, api::client::redact::redact_event, + events::room::redaction::RoomRedactionEventContent, }; use crate::Ruma; @@ -16,6 +17,20 @@ pub(crate) async fn redact_event_route( body: Ruma, ) -> Result { let sender_user = body.sender_user(); + if body.sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = body.sender_device(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } let body = &body.body; if services.users.is_suspended(sender_user).await? { // TODO: Users can redact their own messages while suspended diff --git a/src/api/client/send.rs b/src/api/client/send.rs index 7c5ea0c1..d708d88e 100644 --- a/src/api/client/send.rs +++ b/src/api/client/send.rs @@ -2,7 +2,10 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{Err, Result, err, matrix::pdu::PduBuilder, utils}; -use ruma::{api::client::message::send_message_event, events::MessageLikeEventType}; +use ruma::{ + MilliSecondsSinceUnixEpoch, api::client::message::send_message_event, + events::MessageLikeEventType, +}; use serde_json::from_str; use crate::Ruma; @@ -27,6 +30,21 @@ pub(crate) async fn send_message_event_route( return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } + if sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = sender_device.clone().unwrap(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } + // Forbid m.room.encrypted if encryption is disabled if MessageLikeEventType::RoomEncrypted == body.event_type && !services.config.allow_encryption { diff --git a/src/api/client/state.rs b/src/api/client/state.rs index 139d565b..fbc45e54 100644 --- a/src/api/client/state.rs +++ b/src/api/client/state.rs @@ -7,7 +7,7 @@ use conduwuit::{ use conduwuit_service::Services; use futures::{FutureExt, TryStreamExt}; use ruma::{ - OwnedEventId, RoomId, UserId, + MilliSecondsSinceUnixEpoch, OwnedEventId, RoomId, UserId, api::client::state::{get_state_events, get_state_events_for_key, send_state_event}, events::{ AnyStateEventContent, StateEventType, @@ -33,6 +33,20 @@ pub(crate) async fn send_state_event_for_key_route( body: Ruma, ) -> Result { let sender_user = body.sender_user(); + if body.sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = body.sender_device(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); diff --git a/src/api/client/sync/v5.rs b/src/api/client/sync/v5.rs index af510104..899e3d73 100644 --- a/src/api/client/sync/v5.rs +++ b/src/api/client/sync/v5.rs @@ -7,7 +7,7 @@ use std::{ use axum::extract::State; use conduwuit::{ - Err, Error, Result, at, error, extract_variant, is_equal_to, + Err, Error, Result, at, err, error, extract_variant, is_equal_to, matrix::{Event, TypeStateKey, pdu::PduCount}, trace, utils::{ @@ -25,7 +25,7 @@ use futures::{ pin_mut, }; use ruma::{ - DeviceId, OwnedEventId, OwnedRoomId, RoomId, UInt, UserId, + DeviceId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, RoomId, UInt, UserId, api::client::sync::sync_events::{self, DeviceLists, UnreadNotificationsCount}, directory::RoomTypeFilter, events::{ @@ -66,6 +66,19 @@ pub(crate) async fn sync_events_v5_route( debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted"); let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_device = body.sender_device.as_ref().expect("user is authenticated"); + + // Increment the "device last active" metadata + let mut device = services + .users + .get_device_metadata(sender_user, sender_device) + .await + .or_else(|_| err!(Request(NotFound("device {sender_device} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, sender_device, &device) + .await?; + let mut body = body.body; // Setup watchers, so if there's no response, we can wait for them diff --git a/src/api/client/typing.rs b/src/api/client/typing.rs index 14f7f3f2..d00792b1 100644 --- a/src/api/client/typing.rs +++ b/src/api/client/typing.rs @@ -1,6 +1,6 @@ use axum::extract::State; -use conduwuit::{Err, Result, utils, utils::math::Tried}; -use ruma::api::client::typing::create_typing_event; +use conduwuit::{Err, Result, err, utils, utils::math::Tried}; +use ruma::{MilliSecondsSinceUnixEpoch, api::client::typing::create_typing_event}; use crate::Ruma; @@ -13,6 +13,20 @@ pub(crate) async fn create_typing_event_route( ) -> Result { use create_typing_event::v3::Typing; let sender_user = body.sender_user(); + if body.sender_device.is_some() { + // Increment the "device last active" metadata + let device_id = body.sender_device(); + let mut device = services + .users + .get_device_metadata(sender_user, device_id) + .await + .or_else(|_| err!(Request(NotFound("device {device_id} not found?"))))?; + device.last_seen_ts = Some(MilliSecondsSinceUnixEpoch::now()); + services + .users + .update_device_metadata(sender_user, device_id, &device) + .await?; + } if sender_user != body.user_id && body.appservice_info.is_none() { return Err!(Request(Forbidden("You cannot update typing status of other users.")));