Skip to content

Commit d877ecb

Browse files
committed
feat(base): Remember when a user explicitly accepted an invite
1 parent 7394b34 commit d877ecb

File tree

4 files changed

+55
-2
lines changed

4 files changed

+55
-2
lines changed

crates/matrix-sdk-base/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ All notable changes to this project will be documented in this file.
66

77
## [Unreleased] - ReleaseDate
88

9+
### Features
10+
- The `RoomInfo` now remembers when an invite was explicitly accepted when the
11+
`BaseClient::room_joined()` method was called. A new getter for this
12+
timestamp exists, the `RoomInfo::invite_accepted_at()` method returns this
13+
timestamp.
14+
([#5333](https://github.com/matrix-org/matrix-rust-sdk/pull/5333))
15+
916
### Refactor
1017

1118
- The cached `ServerCapabilities` has been renamed to `ServerInfo` and

crates/matrix-sdk-base/src/client.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,12 +434,30 @@ impl BaseClient {
434434
let _sync_lock = self.sync_lock().lock().await;
435435

436436
let mut room_info = room.clone_info();
437+
438+
// If our previous state was an invite and we're now in the joined state, this
439+
// means that the user has explicitly accepted the invite. Let's
440+
// remember when this has happened.
441+
//
442+
// This is somewhat of a workaround for our lack of cryptographic membership.
443+
// Later on we will decide if historic room keys should be accepted
444+
// based on this info. If a user has accepted an invite and we receive a room
445+
// key bundle shortly after, we might accept it. If we don't do
446+
// this, the homeserver could trick us into accepting any historic room key
447+
// bundle.
448+
if room.state() == RoomState::Invited {
449+
room_info.set_invite_accepted_now();
450+
}
451+
437452
room_info.mark_as_joined();
438453
room_info.mark_state_partially_synced();
439454
room_info.mark_members_missing(); // the own member event changed
455+
440456
let mut changes = StateChanges::default();
441457
changes.add_room(room_info.clone());
458+
442459
self.state_store.save_changes(&changes).await?; // Update the store
460+
443461
room.set_room_info(room_info, RoomInfoNotableUpdateReasons::MEMBERSHIP);
444462
}
445463

crates/matrix-sdk-base/src/room/room_info.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ use ruma::{
4646
},
4747
room::RoomType,
4848
serde::Raw,
49-
EventId, MxcUri, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId,
50-
RoomAliasId, RoomId, RoomVersionId, UserId,
49+
EventId, MilliSecondsSinceUnixEpoch, MxcUri, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId,
50+
OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomVersionId, UserId,
5151
};
5252
use serde::{Deserialize, Serialize};
5353
use tracing::{debug, field::debug, info, instrument, warn};
@@ -464,6 +464,14 @@ pub struct RoomInfo {
464464
/// more accurate than relying on the latest event.
465465
#[serde(default)]
466466
pub(crate) recency_stamp: Option<u64>,
467+
468+
/// A timestamp remembering when we observed the user accepting an invite on
469+
/// this current device.
470+
///
471+
/// This is useful to remember if the user accepted this a join on this
472+
/// specific client.
473+
#[serde(default, skip_serializing_if = "Option::is_none")]
474+
pub(crate) invite_accepted_at: Option<MilliSecondsSinceUnixEpoch>,
467475
}
468476

469477
impl RoomInfo {
@@ -486,6 +494,7 @@ impl RoomInfo {
486494
cached_display_name: None,
487495
cached_user_defined_notification_mode: None,
488496
recency_stamp: None,
497+
invite_accepted_at: None,
489498
}
490499
}
491500

@@ -749,6 +758,22 @@ impl RoomInfo {
749758
self.summary.invited_member_count = count;
750759
}
751760

761+
/// Mark that the user has accepted an invite and remember when this has
762+
/// happened using a timestamp set to [`MilliSecondsSinceUnixEpoch::now()`].
763+
pub(crate) fn set_invite_accepted_now(&mut self) {
764+
self.invite_accepted_at = Some(MilliSecondsSinceUnixEpoch::now());
765+
}
766+
767+
/// Returns the timestamp when an invite to this room has been accepted by
768+
/// this specific client.
769+
///
770+
/// # Returns
771+
/// - `Some` if the invite has been accepted by this specific client.
772+
/// - `None` if the invite has not been accepted
773+
pub fn invite_accepted_at(&self) -> Option<MilliSecondsSinceUnixEpoch> {
774+
self.invite_accepted_at
775+
}
776+
752777
/// Updates the room heroes.
753778
pub(crate) fn update_heroes(&mut self, heroes: Vec<RoomHero>) {
754779
self.summary.room_heroes = heroes;
@@ -1221,6 +1246,7 @@ mod tests {
12211246
cached_display_name: None,
12221247
cached_user_defined_notification_mode: None,
12231248
recency_stamp: Some(42),
1249+
invite_accepted_at: None,
12241250
};
12251251

12261252
let info_json = json!({
@@ -1277,6 +1303,7 @@ mod tests {
12771303
"pending": []
12781304
},
12791305
"recency_stamp": 42,
1306+
"invite_accepted_at": null,
12801307
});
12811308

12821309
assert_eq!(serde_json::to_value(info).unwrap(), info_json);

crates/matrix-sdk-base/src/store/migration_helpers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ impl RoomInfoV1 {
121121
cached_display_name: None,
122122
cached_user_defined_notification_mode: None,
123123
recency_stamp: None,
124+
invite_accepted_at: None,
124125
}
125126
}
126127
}

0 commit comments

Comments
 (0)