feat: notifications, simple permission systems

This commit is contained in:
timokoesters 2020-05-01 20:26:57 +02:00
parent 169dbe6c37
commit b02c568941
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
6 changed files with 506 additions and 126 deletions

View file

@ -8,10 +8,12 @@ use ruma_client_api::{
account::register,
alias::get_alias,
capabilities::get_capabilities,
client_exchange::send_event_to_device,
config::{get_global_account_data, set_global_account_data},
directory::{self, get_public_rooms_filtered},
filter::{self, create_filter, get_filter},
keys::{get_keys, upload_keys},
media::get_media_config,
membership::{
forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias,
leave_room,
@ -21,7 +23,7 @@ use ruma_client_api::{
profile::{
get_avatar_url, get_display_name, get_profile, set_avatar_url, set_display_name,
},
push::get_pushrules_all,
push::{self, get_pushrules_all, set_pushrule, set_pushrule_enabled},
read_marker::set_read_marker,
room::create_room,
session::{get_login_types, login},
@ -40,7 +42,6 @@ use serde_json::json;
use std::{
collections::BTreeMap,
convert::{TryFrom, TryInto},
path::PathBuf,
time::{Duration, SystemTime},
};
@ -238,9 +239,86 @@ pub fn get_capabilities_route(
#[get("/_matrix/client/r0/pushrules")]
pub fn get_pushrules_all_route() -> MatrixResult<get_pushrules_all::Response> {
// TODO
MatrixResult(Ok(get_pushrules_all::Response {
global: BTreeMap::new(),
}))
let mut global = BTreeMap::new();
global.insert(
push::RuleKind::Underride,
vec![push::PushRule {
actions: vec![
push::Action::Notify,
push::Action::SetTweak {
kind: push::TweakKind::Highlight,
value: Some(false.into()),
},
],
default: true,
enabled: true,
rule_id: ".m.rule.message".to_owned(),
conditions: Some(vec![push::PushCondition::EventMatch {
key: "type".to_owned(),
pattern: "m.room.message".to_owned(),
}]),
pattern: None,
}],
);
MatrixResult(Ok(get_pushrules_all::Response { global }))
}
#[put(
"/_matrix/client/r0/pushrules/<_scope>/<_kind>/<_rule_id>",
data = "<body>"
)]
pub fn set_pushrule_route(
data: State<Data>,
body: Ruma<set_pushrule::Request>,
_scope: String,
_kind: String,
_rule_id: String,
) -> MatrixResult<set_pushrule::Response> {
// TODO
let user_id = body.user_id.clone().expect("user is authenticated");
data.room_userdata_update(
None,
&user_id,
EduEvent::PushRules(ruma_events::push_rules::PushRulesEvent {
content: ruma_events::push_rules::PushRulesEventContent {
global: ruma_events::push_rules::Ruleset {
content: vec![],
override_rules: vec![],
room: vec![],
sender: vec![],
underride: vec![ruma_events::push_rules::ConditionalPushRule {
actions: vec![
ruma_events::push_rules::Action::Notify,
ruma_events::push_rules::Action::SetTweak(
ruma_events::push_rules::Tweak::Highlight { value: false },
),
],
default: true,
enabled: true,
rule_id: ".m.rule.message".to_owned(),
conditions: vec![ruma_events::push_rules::PushCondition::EventMatch(
ruma_events::push_rules::EventMatchCondition {
key: "type".to_owned(),
pattern: "m.room.message".to_owned(),
},
)],
}],
},
},
}),
);
MatrixResult(Ok(set_pushrule::Response))
}
#[put("/_matrix/client/r0/pushrules/<_scope>/<_kind>/<_rule_id>/enabled")]
pub fn set_pushrule_enabled_route(
_scope: String,
_kind: String,
_rule_id: String,
) -> MatrixResult<set_pushrule_enabled::Response> {
// TODO
MatrixResult(Ok(set_pushrule_enabled::Response))
}
#[get(
@ -284,7 +362,6 @@ pub fn set_global_account_data_route(
_user_id: String,
_type: String,
) -> MatrixResult<set_global_account_data::Response> {
// TODO
MatrixResult(Ok(set_global_account_data::Response))
}
@ -485,8 +562,20 @@ pub fn set_read_marker_route(
_room_id: String,
) -> MatrixResult<set_read_marker::Response> {
let user_id = body.user_id.clone().expect("user is authenticated");
// TODO: Fully read
data.room_userdata_update(
Some(&body.room_id),
&user_id,
EduEvent::FullyRead(ruma_events::fully_read::FullyReadEvent {
content: ruma_events::fully_read::FullyReadEventContent {
event_id: body.fully_read.clone(),
},
room_id: Some(body.room_id.clone()),
}),
);
if let Some(event) = &body.read_receipt {
data.room_read_set(&body.room_id, &user_id, event);
let mut user_receipts = BTreeMap::new();
user_receipts.insert(
user_id.clone(),
@ -564,6 +653,8 @@ pub fn create_room_route(
Some("".to_owned()),
);
data.room_join(&room_id, &user_id);
data.pdu_append(
room_id.clone(),
user_id.clone(),
@ -604,8 +695,6 @@ pub fn create_room_route(
);
}
data.room_join(&room_id, &user_id);
for user in &body.invite {
data.room_invite(&user_id, &room_id, user);
}
@ -855,17 +944,22 @@ pub fn create_message_event_route(
_txn_id: String,
body: Ruma<create_message_event::Request>,
) -> MatrixResult<create_message_event::Response> {
let user_id = body.user_id.clone().expect("user is authenticated");
let mut unsigned = serde_json::Map::new();
unsigned.insert("transaction_id".to_owned(), body.txn_id.clone().into());
let event_id = data.pdu_append(
body.room_id.clone(),
body.user_id.clone().expect("user is authenticated"),
body.event_type.clone(),
body.json_body.clone(),
Some(unsigned),
None,
);
let event_id = data
.pdu_append(
body.room_id.clone(),
user_id.clone(),
body.event_type.clone(),
body.json_body.clone(),
Some(unsigned),
None,
)
.expect("message events are always okay");
MatrixResult(Ok(create_message_event::Response { event_id }))
}
@ -880,16 +974,21 @@ pub fn create_state_event_for_key_route(
_state_key: String,
body: Ruma<create_state_event_for_key::Request>,
) -> MatrixResult<create_state_event_for_key::Response> {
let user_id = body.user_id.clone().expect("user is authenticated");
// Reponse of with/without key is the same
let event_id = data.pdu_append(
if let Some(event_id) = data.pdu_append(
body.room_id.clone(),
body.user_id.clone().expect("user is authenticated"),
body.event_type.clone(),
body.json_body.clone(),
None,
Some(body.state_key.clone()),
);
MatrixResult(Ok(create_state_event_for_key::Response { event_id }))
) {
MatrixResult(Ok(create_state_event_for_key::Response { event_id }))
} else {
panic!("TODO: error missing permissions");
}
}
#[put(
@ -902,16 +1001,21 @@ pub fn create_state_event_for_empty_key_route(
_event_type: String,
body: Ruma<create_state_event_for_empty_key::Request>,
) -> MatrixResult<create_state_event_for_empty_key::Response> {
let user_id = body.user_id.clone().expect("user is authenticated");
// Reponse of with/without key is the same
let event_id = data.pdu_append(
if let Some(event_id) = data.pdu_append(
body.room_id.clone(),
body.user_id.clone().expect("user is authenticated"),
body.event_type.clone(),
body.json_body,
body.json_body.clone(),
None,
Some("".to_owned()),
);
MatrixResult(Ok(create_state_event_for_empty_key::Response { event_id }))
) {
MatrixResult(Ok(create_state_event_for_empty_key::Response { event_id }))
} else {
panic!("TODO: error missing permissions");
}
}
#[get("/_matrix/client/r0/sync", data = "<body>")]
@ -919,7 +1023,7 @@ pub fn sync_route(
data: State<Data>,
body: Ruma<sync_events::Request>,
) -> MatrixResult<sync_events::Response> {
std::thread::sleep(Duration::from_millis(300));
std::thread::sleep(Duration::from_millis(1500));
let user_id = body.user_id.clone().expect("user is authenticated");
let next_batch = data.last_pdu_index().to_string();
@ -932,7 +1036,7 @@ pub fn sync_route(
.unwrap_or(0);
for room_id in joined_roomids {
let pdus = data.pdus_since(&room_id, since);
let mut pdus = data.pdus_since(&room_id, since);
let mut send_member_count = false;
let mut send_full_state = false;
@ -946,6 +1050,25 @@ pub fn sync_route(
}
}
let notification_count = if let Some(last_read) = data.room_read_get(&room_id, &user_id) {
Some((data.pdus_since(&room_id, last_read).len() as u32).into())
} else {
None
};
// They /sync response doesn't always return all messages, so we say the output is
// limited unless there are enough events
let mut limited = true;
pdus = pdus.split_off(pdus.len().checked_sub(10).unwrap_or_else(|| {
limited = false;
0
}));
let prev_batch = pdus
.first()
.and_then(|e| data.pdu_get_count(&e.event_id))
.map(|c| c.to_string());
let room_events = pdus
.into_iter()
.map(|pdu| pdu.to_room_event())
@ -957,7 +1080,13 @@ pub fn sync_route(
joined_rooms.insert(
room_id.clone().try_into().unwrap(),
sync_events::JoinedRoom {
account_data: sync_events::AccountData { events: Vec::new() },
account_data: sync_events::AccountData {
events: data
.room_userdata_since(Some(&room_id), &user_id, since)
.into_iter()
.map(|(_, v)| v)
.collect(),
},
summary: sync_events::RoomSummary {
heroes: Vec::new(),
joined_member_count: if send_member_count {
@ -973,11 +1102,11 @@ pub fn sync_route(
},
unread_notifications: sync_events::UnreadNotificationsCount {
highlight_count: None,
notification_count: None,
notification_count,
},
timeline: sync_events::Timeline {
limited: None,
prev_batch: Some(since.to_string()),
limited: if limited { Some(limited) } else { None },
prev_batch,
events: room_events,
},
// TODO: state before timeline
@ -1042,6 +1171,13 @@ pub fn sync_route(
invite: invited_rooms,
},
presence: sync_events::Presence { events: Vec::new() },
account_data: sync_events::AccountData {
events: data
.room_userdata_since(None, &user_id, since)
.into_iter()
.map(|(_, v)| v)
.collect(),
},
device_lists: Default::default(),
device_one_time_keys_count: Default::default(),
to_device: sync_events::ToDevice { events: Vec::new() },
@ -1059,14 +1195,23 @@ pub fn get_message_events_route(
}
if let Ok(from) = body.from.clone().parse() {
let pdus = data.pdus_until(&body.room_id, from);
let pdus = data.pdus_until(
&body.room_id,
from,
body.limit.map(|l| l.try_into().unwrap()).unwrap_or(10),
);
let prev_batch = pdus
.last()
.and_then(|e| data.pdu_get_count(&e.event_id))
.map(|c| c.to_string());
let room_events = pdus
.into_iter()
.map(|pdu| pdu.to_room_event())
.collect::<Vec<_>>();
MatrixResult(Ok(get_message_events::Response {
start: Some(body.from.clone()),
end: None,
end: prev_batch,
chunk: room_events,
state: Vec::new(),
}))
@ -1099,6 +1244,23 @@ pub fn publicised_groups_route() -> MatrixResult<create_message_event::Response>
}))
}
#[put("/_matrix/client/r0/sendToDevice/<_event_type>/<_txn_id>")]
pub fn send_event_to_device_route(
_event_type: String,
_txn_id: String,
) -> MatrixResult<send_event_to_device::Response> {
// TODO
MatrixResult(Ok(send_event_to_device::Response))
}
#[get("/_matrix/media/r0/config")]
pub fn get_media_config_route() -> MatrixResult<get_media_config::Response> {
// TODO
MatrixResult(Ok(get_media_config::Response {
upload_size: 0_u32.into(),
}))
}
#[options("/<_segments..>")]
pub fn options_route(
_segments: rocket::http::uri::Segments,

View file

@ -1,11 +1,15 @@
use crate::{utils, Database, PduEvent};
use ruma_events::{collections::only::Event as EduEvent, EventJson, EventType};
use crate::{database::COUNTER, utils, Database, PduEvent};
use ruma_events::{
collections::only::Event as EduEvent, room::power_levels::PowerLevelsEventContent, EventJson,
EventType,
};
use ruma_federation_api::RoomV3Pdu;
use ruma_identifiers::{EventId, RoomId, UserId};
use serde_json::json;
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
mem,
};
pub struct Data {
@ -189,7 +193,14 @@ impl Data {
}
pub fn room_join(&self, room_id: &RoomId, user_id: &UserId) -> bool {
if !self.room_exists(room_id) {
if !self.room_exists(room_id)
&& !self
.db
.userid_joinroomids
.get_iter(user_id.to_string().as_bytes())
.values()
.any(|r| r.unwrap() == room_id.to_string().as_bytes())
{
return false;
}
@ -249,8 +260,7 @@ impl Data {
/// Check if a room exists by looking for PDUs in that room.
pub fn room_exists(&self, room_id: &RoomId) -> bool {
// Create the first part of the full pdu id
let mut prefix = vec![b'd'];
prefix.extend_from_slice(room_id.to_string().as_bytes());
let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
if let Some((key, _)) = self.db.pduid_pdu.get_gt(&prefix).unwrap() {
@ -397,13 +407,14 @@ impl Data {
.collect()
}
pub fn room_pdu_first(&self, room_id: &RoomId, pdu_index: u64) -> bool {
let mut pdu_id = vec![b'd'];
pdu_id.extend_from_slice(room_id.to_string().as_bytes());
pdu_id.push(0xff);
pdu_id.extend_from_slice(&pdu_index.to_be_bytes());
self.db.pduid_pdu.get_lt(&pdu_id).unwrap().is_none()
pub fn pdu_get_count(&self, event_id: &EventId) -> Option<u64> {
self.db
.eventid_pduid
.get(event_id.to_string().as_bytes())
.unwrap()
.map(|pdu_id| {
utils::u64_from_bytes(&pdu_id[pdu_id.len() - mem::size_of::<u64>()..pdu_id.len()])
})
}
pub fn pdu_get(&self, event_id: &EventId) -> Option<RoomV3Pdu> {
@ -459,7 +470,39 @@ impl Data {
content: serde_json::Value,
unsigned: Option<serde_json::Map<String, serde_json::Value>>,
state_key: Option<String>,
) -> EventId {
) -> Option<EventId> {
// Is the event authorized?
if state_key.is_some() {
if let Some(pdu) = self
.room_state(&room_id)
.get(&(EventType::RoomPowerLevels, "".to_owned()))
{
let power_levels = serde_json::from_value::<EventJson<PowerLevelsEventContent>>(
pdu.content.clone(),
)
.unwrap()
.deserialize()
.unwrap();
match event_type {
EventType::RoomMember => {
// Member events are okay for now (TODO)
}
_ if power_levels
.users
.get(&sender)
.unwrap_or(&power_levels.users_default)
<= &0.into() =>
{
// Not authorized
return None;
}
// User has sufficient power
_ => {}
}
}
}
// prev_events are the leaves of the current graph. This method removes all leaves from the
// room and replaces them with our event
// TODO: Make sure this isn't called twice in parallel
@ -523,22 +566,19 @@ impl Data {
self.pdu_leaves_replace(&room_id, &pdu.event_id);
// The new value will need a new index. We store the last used index in 'n'
// The count will go up regardless of the room_id
// This is also the next_batch/since value
// Increment the last index and use that
let index = utils::u64_from_bytes(
&self
.db
.pduid_pdu
.update_and_fetch(b"n", utils::increment)
.global
.update_and_fetch(COUNTER, utils::increment)
.unwrap()
.unwrap(),
);
let mut pdu_id = vec![b'd'];
pdu_id.extend_from_slice(room_id.to_string().as_bytes());
let mut pdu_id = room_id.to_string().as_bytes().to_vec();
pdu_id.push(0xff); // Add delimiter so we don't find rooms starting with the same id
pdu_id.extend_from_slice(&index.to_be_bytes());
@ -564,7 +604,9 @@ impl Data {
.unwrap();
}
pdu.event_id
self.room_read_set(&room_id, &sender, &pdu.event_id);
Some(pdu.event_id)
}
/// Returns a vector of all PDUs in a room.
@ -573,12 +615,11 @@ impl Data {
}
pub fn last_pdu_index(&self) -> u64 {
let count_key: Vec<u8> = vec![b'n'];
utils::u64_from_bytes(
&self
.db
.pduid_pdu
.get(&count_key)
.global
.get(&COUNTER)
.unwrap()
.unwrap_or_else(|| (&0_u64.to_be_bytes()).into()),
)
@ -586,15 +627,23 @@ impl Data {
/// Returns a vector of all events in a room that happened after the event with id `since`.
pub fn pdus_since(&self, room_id: &RoomId, since: u64) -> Vec<PduEvent> {
// Create the first part of the full pdu id
let mut pdu_id = room_id.to_string().as_bytes().to_vec();
pdu_id.push(0xff); // Add delimiter so we don't find rooms starting with the same id
pdu_id.extend_from_slice(&(since).to_be_bytes());
self.pdus_since_pduid(room_id, pdu_id)
}
/// Returns a vector of all events in a room that happened after the event with id `since`.
pub fn pdus_since_pduid(&self, room_id: &RoomId, pdu_id: Vec<u8>) -> Vec<PduEvent> {
let mut pdus = Vec::new();
// Create the first part of the full pdu id
let mut prefix = vec![b'd'];
prefix.extend_from_slice(room_id.to_string().as_bytes());
let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
let mut current = prefix.clone();
current.extend_from_slice(&since.to_be_bytes());
let mut current = pdu_id;
while let Some((key, value)) = self.db.pduid_pdu.get_gt(&current).unwrap() {
if key.starts_with(&prefix) {
@ -608,19 +657,18 @@ impl Data {
pdus
}
pub fn pdus_until(&self, room_id: &RoomId, until: u64) -> Vec<PduEvent> {
pub fn pdus_until(&self, room_id: &RoomId, until: u64, max: u32) -> Vec<PduEvent> {
let mut pdus = Vec::new();
// Create the first part of the full pdu id
let mut prefix = vec![b'd'];
prefix.extend_from_slice(room_id.to_string().as_bytes());
let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff); // Add delimiter so we don't find rooms starting with the same id
let mut current = prefix.clone();
current.extend_from_slice(&until.to_be_bytes());
while let Some((key, value)) = self.db.pduid_pdu.get_lt(&current).unwrap() {
if key.starts_with(&prefix) {
if pdus.len() < max as usize && key.starts_with(&prefix) {
current = key.to_vec();
pdus.push(serde_json::from_slice(&value).expect("pdu in db is valid"));
} else {
@ -670,8 +718,8 @@ impl Data {
let index = utils::u64_from_bytes(
&self
.db
.pduid_pdu
.update_and_fetch(b"n", utils::increment)
.global
.update_and_fetch(COUNTER, utils::increment)
.unwrap()
.unwrap(),
);
@ -695,17 +743,14 @@ impl Data {
prefix.push(0xff);
let mut current = prefix.clone();
current.extend_from_slice(&since.to_be_bytes());
current.extend_from_slice(&(since + 1).to_be_bytes());
while let Some((key, value)) = self.db.roomlatestid_roomlatest.get_gt(&current).unwrap() {
if key.starts_with(&prefix) {
current = key.to_vec();
room_latests.push(
serde_json::from_slice::<EventJson<EduEvent>>(&value)
.expect("room_latest in db is valid")
.deserialize()
.expect("room_latest in db is valid")
.into(),
.expect("room_latest in db is valid"),
);
} else {
break;
@ -715,6 +760,11 @@ impl Data {
room_latests
}
/// Returns a vector of the most recent read_receipts in a room that happened after the event with id `since`.
pub fn roomlatests_all(&self, room_id: &RoomId) -> Vec<EventJson<EduEvent>> {
self.roomlatests_since(room_id, 0)
}
pub fn roomactive_add(&self, event: EduEvent, room_id: &RoomId, timeout: u64) {
let mut prefix = room_id.to_string().as_bytes().to_vec();
prefix.push(0xff);
@ -737,8 +787,8 @@ impl Data {
let index = utils::u64_from_bytes(
&self
.db
.pduid_pdu
.update_and_fetch(b"n", utils::increment)
.global
.update_and_fetch(COUNTER, utils::increment)
.unwrap()
.unwrap(),
);
@ -790,10 +840,7 @@ impl Data {
current = key.to_vec();
room_actives.push(
serde_json::from_slice::<EventJson<EduEvent>>(&value)
.expect("room_active in db is valid")
.deserialize()
.expect("room_active in db is valid")
.into(),
.expect("room_active in db is valid"),
);
} else {
break;
@ -813,6 +860,158 @@ impl Data {
}
}
pub fn room_userdata_update(
&self,
room_id: Option<&RoomId>,
user_id: &UserId,
event: EduEvent,
) {
let mut prefix = room_id
.map(|r| r.to_string())
.unwrap_or_default()
.as_bytes()
.to_vec();
prefix.push(0xff);
prefix.extend_from_slice(&user_id.to_string().as_bytes());
prefix.push(0xff);
// Start with last
if let Some(mut current) = self
.db
.roomuserdataid_accountdata
.scan_prefix(&prefix)
.keys()
.next_back()
.map(|c| c.unwrap())
{
// Remove old entry (there should be at most one)
loop {
if !current.starts_with(&prefix) {
// We're in another room or user
break;
}
if current.rsplit(|&b| b == 0xff).nth(2).unwrap() == user_id.to_string().as_bytes()
{
// This is the old room_latest
self.db.roomuserdataid_accountdata.remove(current).unwrap();
break;
}
// Else, try the event before that
if let Some((k, _)) = self.db.roomuserdataid_accountdata.get_lt(current).unwrap() {
current = k;
} else {
break;
}
}
}
// Increment the last index and use that
let index = utils::u64_from_bytes(
&self
.db
.global
.update_and_fetch(COUNTER, utils::increment)
.unwrap()
.unwrap(),
);
let mut key = prefix;
key.extend_from_slice(&index.to_be_bytes());
let json = serde_json::to_value(&event).unwrap();
key.extend_from_slice(json["type"].as_str().unwrap().as_bytes());
self.db
.roomuserdataid_accountdata
.insert(key, &*json.to_string())
.unwrap();
}
pub fn room_userdata_get(
&self,
room_id: Option<&RoomId>,
user_id: &UserId,
kind: &str,
) -> Option<EventJson<EduEvent>> {
self.room_userdata_all(room_id, user_id).remove(kind)
}
pub fn room_userdata_since(
&self,
room_id: Option<&RoomId>,
user_id: &UserId,
since: u64,
) -> HashMap<String, EventJson<EduEvent>> {
let mut userdata = HashMap::new();
let mut prefix = room_id
.map(|r| r.to_string())
.unwrap_or_default()
.as_bytes()
.to_vec();
prefix.push(0xff);
prefix.extend_from_slice(&user_id.to_string().as_bytes());
prefix.push(0xff);
let mut current = prefix.clone();
current.extend_from_slice(&(since + 1).to_be_bytes());
while let Some((key, value)) = self.db.roomuserdataid_accountdata.get_gt(&current).unwrap()
{
if key.starts_with(&prefix) {
current = key.to_vec();
let json = serde_json::from_slice::<serde_json::Value>(&value).unwrap();
userdata.insert(
json["type"].as_str().unwrap().to_owned(),
serde_json::from_value::<EventJson<EduEvent>>(json)
.expect("userdata in db is valid"),
);
} else {
break;
}
}
userdata
}
pub fn room_userdata_all(
&self,
room_id: Option<&RoomId>,
user_id: &UserId,
) -> HashMap<String, EventJson<EduEvent>> {
self.room_userdata_since(room_id, user_id, 0)
}
pub fn room_read_set(
&self,
room_id: &RoomId,
user_id: &UserId,
event_id: &EventId,
) -> Option<()> {
let mut key = room_id.to_string().as_bytes().to_vec();
key.push(0xff);
key.extend_from_slice(&user_id.to_string().as_bytes());
self.db
.roomuserid_lastread
.insert(key, &self.pdu_get_count(event_id)?.to_be_bytes())
.unwrap();
Some(())
}
pub fn room_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Option<u64> {
let mut key = room_id.to_string().as_bytes().to_vec();
key.push(0xff);
key.extend_from_slice(&user_id.to_string().as_bytes());
self.db
.roomuserid_lastread
.get(key)
.unwrap()
.map(|v| utils::u64_from_bytes(&v))
}
pub fn debug(&self) {
self.db.debug();
}

View file

@ -5,6 +5,8 @@ use std::fs::remove_dir_all;
pub struct MultiValue(sled::Tree);
pub const COUNTER: &str = "c";
impl MultiValue {
/// Get an iterator over all values.
pub fn iter_all(&self) -> sled::Iter {
@ -67,22 +69,24 @@ pub struct Database {
pub userid_deviceids: MultiValue,
pub userdeviceid_token: sled::Tree,
pub token_userid: sled::Tree,
pub pduid_pdu: sled::Tree, // PduId = 'd' + RoomId + Since (global since counter is at 'n')
pub pduid_pdu: sled::Tree, // PduId = RoomId + Count
pub eventid_pduid: sled::Tree,
pub roomid_pduleaves: MultiValue,
pub roomstateid_pdu: sled::Tree, // Room + StateType + StateKey
pub roomuserdataid_accountdata: sled::Tree, // RoomUserDataId = Room + User + Count + Type
pub roomuserid_lastread: sled::Tree, // RoomUserId = Room + User
pub roomid_joinuserids: MultiValue,
pub roomid_inviteuserids: MultiValue,
pub userid_joinroomids: MultiValue,
pub userid_inviteroomids: MultiValue,
pub userid_leftroomids: MultiValue,
// EDUs:
pub roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Since + UserId TODO: Types
pub roomactiveid_roomactive: sled::Tree, // Typing, RoomActiveId = TimeoutTime + Since
pub globalallid_globalall: sled::Tree, // ToDevice, GlobalAllId = UserId + Since
pub globallatestid_globallatest: sled::Tree, // Presence, GlobalLatestId = Since + Type + UserId
pub roomlatestid_roomlatest: sled::Tree, // Read Receipts, RoomLatestId = RoomId + Count + UserId TODO: Types
pub roomactiveid_roomactive: sled::Tree, // Typing, RoomActiveId = TimeoutTime + Count
pub globalallid_globalall: sled::Tree, // ToDevice, GlobalAllId = UserId + Count
pub globallatestid_globallatest: sled::Tree, // Presence, GlobalLatestId = Count + Type + UserId
pub keypair: ruma_signatures::Ed25519KeyPair,
_db: sled::Db,
pub global: sled::Db,
}
impl Database {
@ -116,6 +120,8 @@ impl Database {
eventid_pduid: db.open_tree("eventid_pduid").unwrap(),
roomid_pduleaves: MultiValue(db.open_tree("roomid_pduleaves").unwrap()),
roomstateid_pdu: db.open_tree("roomstateid_pdu").unwrap(),
roomuserdataid_accountdata: db.open_tree("roomuserdataid_accountdata").unwrap(),
roomuserid_lastread: db.open_tree("roomuserid_lastread").unwrap(),
roomid_joinuserids: MultiValue(db.open_tree("roomid_joinuserids").unwrap()),
roomid_inviteuserids: MultiValue(db.open_tree("roomid_inviteuserids").unwrap()),
userid_joinroomids: MultiValue(db.open_tree("userid_joinroomids").unwrap()),
@ -132,7 +138,7 @@ impl Database {
"key1".to_owned(),
)
.unwrap(),
_db: db,
global: db,
}
}

View file

@ -29,6 +29,8 @@ fn setup_rocket() -> rocket::Rocket {
client_server::login_route,
client_server::get_capabilities_route,
client_server::get_pushrules_all_route,
client_server::set_pushrule_route,
client_server::set_pushrule_enabled_route,
client_server::get_filter_route,
client_server::create_filter_route,
client_server::set_global_account_data_route,
@ -61,6 +63,8 @@ fn setup_rocket() -> rocket::Rocket {
client_server::get_message_events_route,
client_server::turn_server_route,
client_server::publicised_groups_route,
client_server::send_event_to_device_route,
client_server::get_media_config_route,
client_server::options_route,
server_server::well_known_server,
server_server::get_server_version,