resolve the last few relevant pedantic clippy lints
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
fa71dd4b4c
commit
48d1a3af3c
20 changed files with 464 additions and 560 deletions
|
@ -12,9 +12,8 @@ use crate::{services, Error, Result, Ruma};
|
||||||
/// - A user can only access their own filters
|
/// - A user can only access their own filters
|
||||||
pub async fn get_filter_route(body: Ruma<get_filter::v3::Request>) -> Result<get_filter::v3::Response> {
|
pub async fn get_filter_route(body: Ruma<get_filter::v3::Request>) -> Result<get_filter::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let filter = match services().users.get_filter(sender_user, &body.filter_id)? {
|
let Some(filter) = services().users.get_filter(sender_user, &body.filter_id)? else {
|
||||||
Some(filter) => filter,
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Filter not found."));
|
||||||
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Filter not found.")),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(get_filter::v3::Response::new(filter))
|
Ok(get_filter::v3::Response::new(filter))
|
||||||
|
|
|
@ -387,36 +387,33 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
while let Some((server, response)) = futures.next().await {
|
while let Some((server, response)) = futures.next().await {
|
||||||
match response {
|
if let Ok(Ok(response)) = response {
|
||||||
Ok(Ok(response)) => {
|
for (user, masterkey) in response.master_keys {
|
||||||
for (user, masterkey) in response.master_keys {
|
let (master_key_id, mut master_key) = services().users.parse_master_key(&user, &masterkey)?;
|
||||||
let (master_key_id, mut master_key) = services().users.parse_master_key(&user, &masterkey)?;
|
|
||||||
|
|
||||||
if let Some(our_master_key) =
|
if let Some(our_master_key) =
|
||||||
services()
|
services()
|
||||||
.users
|
.users
|
||||||
.get_key(&master_key_id, sender_user, &user, &allowed_signatures)?
|
.get_key(&master_key_id, sender_user, &user, &allowed_signatures)?
|
||||||
{
|
{
|
||||||
let (_, our_master_key) = services().users.parse_master_key(&user, &our_master_key)?;
|
let (_, our_master_key) = services().users.parse_master_key(&user, &our_master_key)?;
|
||||||
master_key.signatures.extend(our_master_key.signatures);
|
master_key.signatures.extend(our_master_key.signatures);
|
||||||
}
|
|
||||||
let json = serde_json::to_value(master_key).expect("to_value always works");
|
|
||||||
let raw = serde_json::from_value(json).expect("Raw::from_value always works");
|
|
||||||
services().users.add_cross_signing_keys(
|
|
||||||
&user, &raw, &None, &None,
|
|
||||||
false, /* Dont notify. A notification would trigger another key request resulting in an
|
|
||||||
* endless loop */
|
|
||||||
)?;
|
|
||||||
master_keys.insert(user, raw);
|
|
||||||
}
|
}
|
||||||
|
let json = serde_json::to_value(master_key).expect("to_value always works");
|
||||||
|
let raw = serde_json::from_value(json).expect("Raw::from_value always works");
|
||||||
|
services().users.add_cross_signing_keys(
|
||||||
|
&user, &raw, &None, &None,
|
||||||
|
false, /* Dont notify. A notification would trigger another key request resulting in an
|
||||||
|
* endless loop */
|
||||||
|
)?;
|
||||||
|
master_keys.insert(user, raw);
|
||||||
|
}
|
||||||
|
|
||||||
self_signing_keys.extend(response.self_signing_keys);
|
self_signing_keys.extend(response.self_signing_keys);
|
||||||
device_keys.extend(response.device_keys);
|
device_keys.extend(response.device_keys);
|
||||||
},
|
} else {
|
||||||
_ => {
|
back_off(server.to_owned()).await;
|
||||||
back_off(server.to_owned()).await;
|
failures.insert(server.to_string(), json!({}));
|
||||||
failures.insert(server.to_string(), json!({}));
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -788,13 +788,12 @@ async fn request_url_preview(url: &str) -> Result<UrlPreviewData> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let content_type = match response
|
let Some(content_type) = response
|
||||||
.headers()
|
.headers()
|
||||||
.get(reqwest::header::CONTENT_TYPE)
|
.get(reqwest::header::CONTENT_TYPE)
|
||||||
.and_then(|x| x.to_str().ok())
|
.and_then(|x| x.to_str().ok())
|
||||||
{
|
else {
|
||||||
Some(ct) => ct,
|
return Err(Error::BadRequest(ErrorKind::Unknown, "Unknown Content-Type"));
|
||||||
None => return Err(Error::BadRequest(ErrorKind::Unknown, "Unknown Content-Type")),
|
|
||||||
};
|
};
|
||||||
let data = match content_type {
|
let data = match content_type {
|
||||||
html if html.starts_with("text/html") => download_html(client, url).await?,
|
html if html.starts_with("text/html") => download_html(client, url).await?,
|
||||||
|
|
|
@ -669,17 +669,15 @@ pub(crate) async fn join_room_by_id_helper(
|
||||||
"There is a signed event. This room is probably using restricted joins. Adding signature \
|
"There is a signed event. This room is probably using restricted joins. Adding signature \
|
||||||
to our event"
|
to our event"
|
||||||
);
|
);
|
||||||
let (signed_event_id, signed_value) =
|
let Ok((signed_event_id, signed_value)) =
|
||||||
match gen_event_id_canonical_json(signed_raw, &room_version_id) {
|
gen_event_id_canonical_json(signed_raw, &room_version_id)
|
||||||
Ok(t) => t,
|
else {
|
||||||
Err(_) => {
|
// Event could not be converted to canonical json
|
||||||
// Event could not be converted to canonical json
|
return Err(Error::BadRequest(
|
||||||
return Err(Error::BadRequest(
|
ErrorKind::InvalidParam,
|
||||||
ErrorKind::InvalidParam,
|
"Could not convert event to canonical json.",
|
||||||
"Could not convert event to canonical json.",
|
));
|
||||||
));
|
};
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if signed_event_id != event_id {
|
if signed_event_id != event_id {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
|
@ -753,9 +751,8 @@ pub(crate) async fn join_room_by_id_helper(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pdu| validate_and_add_event_id(pdu, &room_version_id, &pub_key_map))
|
.map(|pdu| validate_and_add_event_id(pdu, &room_version_id, &pub_key_map))
|
||||||
{
|
{
|
||||||
let (event_id, value) = match result.await {
|
let Ok((event_id, value)) = result.await else {
|
||||||
Ok(t) => t,
|
continue;
|
||||||
Err(_) => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| {
|
let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| {
|
||||||
|
@ -783,9 +780,8 @@ pub(crate) async fn join_room_by_id_helper(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pdu| validate_and_add_event_id(pdu, &room_version_id, &pub_key_map))
|
.map(|pdu| validate_and_add_event_id(pdu, &room_version_id, &pub_key_map))
|
||||||
{
|
{
|
||||||
let (event_id, value) = match result.await {
|
let Ok((event_id, value)) = result.await else {
|
||||||
Ok(t) => t,
|
continue;
|
||||||
Err(_) => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services()
|
services()
|
||||||
|
@ -1104,15 +1100,13 @@ pub(crate) async fn join_room_by_id_helper(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(signed_raw) = send_join_response.room_state.event {
|
if let Some(signed_raw) = send_join_response.room_state.event {
|
||||||
let (signed_event_id, signed_value) = match gen_event_id_canonical_json(&signed_raw, &room_version_id) {
|
let Ok((signed_event_id, signed_value)) = gen_event_id_canonical_json(&signed_raw, &room_version_id)
|
||||||
Ok(t) => t,
|
else {
|
||||||
Err(_) => {
|
// Event could not be converted to canonical json
|
||||||
// Event could not be converted to canonical json
|
return Err(Error::BadRequest(
|
||||||
return Err(Error::BadRequest(
|
ErrorKind::InvalidParam,
|
||||||
ErrorKind::InvalidParam,
|
"Could not convert event to canonical json.",
|
||||||
"Could not convert event to canonical json.",
|
));
|
||||||
));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if signed_event_id != event_id {
|
if signed_event_id != event_id {
|
||||||
|
@ -1311,15 +1305,12 @@ pub(crate) async fn invite_helper(
|
||||||
|
|
||||||
// We do not add the event_id field to the pdu here because of signature and
|
// We do not add the event_id field to the pdu here because of signature and
|
||||||
// hashes checks
|
// hashes checks
|
||||||
let (event_id, value) = match gen_event_id_canonical_json(&response.event, &room_version_id) {
|
let Ok((event_id, value)) = gen_event_id_canonical_json(&response.event, &room_version_id) else {
|
||||||
Ok(t) => t,
|
// Event could not be converted to canonical json
|
||||||
Err(_) => {
|
return Err(Error::BadRequest(
|
||||||
// Event could not be converted to canonical json
|
ErrorKind::InvalidParam,
|
||||||
return Err(Error::BadRequest(
|
"Could not convert event to canonical json.",
|
||||||
ErrorKind::InvalidParam,
|
));
|
||||||
"Could not convert event to canonical json.",
|
|
||||||
));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if *pdu.event_id != *event_id {
|
if *pdu.event_id != *event_id {
|
||||||
|
|
|
@ -21,14 +21,11 @@ pub async fn report_event_route(body: Ruma<report_content::v3::Request>) -> Resu
|
||||||
info!("Received /report request by user {}", sender_user);
|
info!("Received /report request by user {}", sender_user);
|
||||||
|
|
||||||
// check if we know about the reported event ID or if it's invalid
|
// check if we know about the reported event ID or if it's invalid
|
||||||
let pdu = match services().rooms.timeline.get_pdu(&body.event_id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu(&body.event_id)? else {
|
||||||
Some(pdu) => pdu,
|
return Err(Error::BadRequest(
|
||||||
_ => {
|
ErrorKind::NotFound,
|
||||||
return Err(Error::BadRequest(
|
"Event ID is not known to us or Event ID is invalid",
|
||||||
ErrorKind::NotFound,
|
));
|
||||||
"Event ID is not known to us or Event ID is invalid",
|
|
||||||
))
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// check if the room ID from the URI matches the PDU's room ID
|
// check if the room ID from the URI matches the PDU's room ID
|
||||||
|
|
|
@ -314,28 +314,23 @@ async fn sync_helper(
|
||||||
None => HashMap::new(),
|
None => HashMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let left_event_id = match services().rooms.state_accessor.room_state_get_id(
|
let Some(left_event_id) = services().rooms.state_accessor.room_state_get_id(
|
||||||
&room_id,
|
&room_id,
|
||||||
&StateEventType::RoomMember,
|
&StateEventType::RoomMember,
|
||||||
sender_user.as_str(),
|
sender_user.as_str(),
|
||||||
)? {
|
)?
|
||||||
Some(e) => e,
|
else {
|
||||||
None => {
|
error!("Left room but no left state event");
|
||||||
error!("Left room but no left state event");
|
continue;
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let left_shortstatehash = match services()
|
let Some(left_shortstatehash) = services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.pdu_shortstatehash(&left_event_id)?
|
.pdu_shortstatehash(&left_event_id)?
|
||||||
{
|
else {
|
||||||
Some(s) => s,
|
error!("Leave event has no state");
|
||||||
None => {
|
continue;
|
||||||
error!("Leave event has no state");
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut left_state_ids = services()
|
let mut left_state_ids = services()
|
||||||
|
@ -616,9 +611,7 @@ async fn load_joined_room(
|
||||||
|
|
||||||
// Database queries:
|
// Database queries:
|
||||||
|
|
||||||
let current_shortstatehash = if let Some(s) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? else {
|
||||||
s
|
|
||||||
} else {
|
|
||||||
error!("Room {} has no state", room_id);
|
error!("Room {} has no state", room_id);
|
||||||
return Err(Error::BadDatabase("Room has no state"));
|
return Err(Error::BadDatabase("Room has no state"));
|
||||||
};
|
};
|
||||||
|
@ -736,12 +729,9 @@ async fn load_joined_room(
|
||||||
.get_statekey_from_short(shortstatekey)?;
|
.get_statekey_from_short(shortstatekey)?;
|
||||||
|
|
||||||
if event_type != StateEventType::RoomMember {
|
if event_type != StateEventType::RoomMember {
|
||||||
let pdu = match services().rooms.timeline.get_pdu(&id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? else {
|
||||||
Some(pdu) => pdu,
|
error!("Pdu in state not found: {}", id);
|
||||||
None => {
|
continue;
|
||||||
error!("Pdu in state not found: {}", id);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
state_events.push(pdu);
|
state_events.push(pdu);
|
||||||
|
|
||||||
|
@ -755,12 +745,9 @@ async fn load_joined_room(
|
||||||
// TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565
|
// TODO: Delete the following line when this is resolved: https://github.com/vector-im/element-web/issues/22565
|
||||||
|| (cfg!(feature = "element_hacks") && *sender_user == state_key)
|
|| (cfg!(feature = "element_hacks") && *sender_user == state_key)
|
||||||
{
|
{
|
||||||
let pdu = match services().rooms.timeline.get_pdu(&id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? else {
|
||||||
Some(pdu) => pdu,
|
error!("Pdu in state not found: {}", id);
|
||||||
None => {
|
continue;
|
||||||
error!("Pdu in state not found: {}", id);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This check is in case a bad user ID made it into the database
|
// This check is in case a bad user ID made it into the database
|
||||||
|
@ -812,12 +799,9 @@ async fn load_joined_room(
|
||||||
|
|
||||||
for (key, id) in current_state_ids {
|
for (key, id) in current_state_ids {
|
||||||
if full_state || since_state_ids.get(&key) != Some(&id) {
|
if full_state || since_state_ids.get(&key) != Some(&id) {
|
||||||
let pdu = match services().rooms.timeline.get_pdu(&id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? else {
|
||||||
Some(pdu) => pdu,
|
error!("Pdu in state not found: {}", id);
|
||||||
None => {
|
continue;
|
||||||
error!("Pdu in state not found: {}", id);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if pdu.kind == TimelineEventType::RoomMember {
|
if pdu.kind == TimelineEventType::RoomMember {
|
||||||
|
@ -1209,9 +1193,7 @@ pub async fn sync_events_v4_route(
|
||||||
);
|
);
|
||||||
|
|
||||||
for room_id in &all_joined_rooms {
|
for room_id in &all_joined_rooms {
|
||||||
let current_shortstatehash = if let Some(s) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? else {
|
||||||
s
|
|
||||||
} else {
|
|
||||||
error!("Room {} has no state", room_id);
|
error!("Room {} has no state", room_id);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -1272,12 +1254,9 @@ pub async fn sync_events_v4_route(
|
||||||
|
|
||||||
for (key, id) in current_state_ids {
|
for (key, id) in current_state_ids {
|
||||||
if since_state_ids.get(&key) != Some(&id) {
|
if since_state_ids.get(&key) != Some(&id) {
|
||||||
let pdu = match services().rooms.timeline.get_pdu(&id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu(&id)? else {
|
||||||
Some(pdu) => pdu,
|
error!("Pdu in state not found: {}", id);
|
||||||
None => {
|
continue;
|
||||||
error!("Pdu in state not found: {}", id);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
if pdu.kind == TimelineEventType::RoomMember {
|
if pdu.kind == TimelineEventType::RoomMember {
|
||||||
if let Some(state_key) = &pdu.state_key {
|
if let Some(state_key) = &pdu.state_key {
|
||||||
|
|
|
@ -84,82 +84,60 @@ where
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let (sender_user, sender_device, sender_servername, from_appservice) = if let Some(info) =
|
let (sender_user, sender_device, sender_servername, from_appservice) =
|
||||||
appservice_registration
|
if let Some(info) = appservice_registration {
|
||||||
{
|
match metadata.authentication {
|
||||||
match metadata.authentication {
|
AuthScheme::AccessToken => {
|
||||||
AuthScheme::AccessToken => {
|
let user_id = query_params.user_id.map_or_else(
|
||||||
let user_id = query_params.user_id.map_or_else(
|
|| {
|
||||||
|| {
|
UserId::parse_with_server_name(
|
||||||
UserId::parse_with_server_name(
|
info.registration.sender_localpart.as_str(),
|
||||||
info.registration.sender_localpart.as_str(),
|
services().globals.server_name(),
|
||||||
services().globals.server_name(),
|
)
|
||||||
)
|
.unwrap()
|
||||||
.unwrap()
|
},
|
||||||
},
|
|s| UserId::parse(s).unwrap(),
|
||||||
|s| UserId::parse(s).unwrap(),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
debug!("User ID: {:?}", user_id);
|
debug!("User ID: {:?}", user_id);
|
||||||
|
|
||||||
if !services().users.exists(&user_id)? {
|
if !services().users.exists(&user_id)? {
|
||||||
return Err(Error::BadRequest(ErrorKind::Forbidden, "User does not exist."));
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "User does not exist."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if appservice is allowed to be that user
|
|
||||||
(Some(user_id), None, None, true)
|
|
||||||
},
|
|
||||||
AuthScheme::AccessTokenOptional | AuthScheme::AppserviceToken => {
|
|
||||||
let user_id = query_params.user_id.map_or_else(
|
|
||||||
|| {
|
|
||||||
UserId::parse_with_server_name(
|
|
||||||
info.registration.sender_localpart.as_str(),
|
|
||||||
services().globals.server_name(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
},
|
|
||||||
|s| UserId::parse(s).unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
debug!("User ID: {:?}", user_id);
|
|
||||||
|
|
||||||
if !services().users.exists(&user_id)? {
|
|
||||||
(None, None, None, true)
|
|
||||||
} else {
|
|
||||||
// TODO: Check if appservice is allowed to be that user
|
// TODO: Check if appservice is allowed to be that user
|
||||||
(Some(user_id), None, None, true)
|
(Some(user_id), None, None, true)
|
||||||
}
|
},
|
||||||
},
|
AuthScheme::AccessTokenOptional | AuthScheme::AppserviceToken => {
|
||||||
AuthScheme::ServerSignatures | AuthScheme::None => (None, None, None, true),
|
let user_id = query_params.user_id.map_or_else(
|
||||||
}
|
|| {
|
||||||
} else {
|
UserId::parse_with_server_name(
|
||||||
match metadata.authentication {
|
info.registration.sender_localpart.as_str(),
|
||||||
AuthScheme::AccessToken => {
|
services().globals.server_name(),
|
||||||
let token = match token {
|
)
|
||||||
Some(token) => token,
|
.unwrap()
|
||||||
_ => return Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token.")),
|
},
|
||||||
};
|
|s| UserId::parse(s).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
match services().users.find_from_token(token)? {
|
debug!("User ID: {:?}", user_id);
|
||||||
None => {
|
|
||||||
return Err(Error::BadRequest(
|
if !services().users.exists(&user_id)? {
|
||||||
ErrorKind::UnknownToken {
|
(None, None, None, true)
|
||||||
soft_logout: false,
|
} else {
|
||||||
},
|
// TODO: Check if appservice is allowed to be that user
|
||||||
"Unknown access token.",
|
(Some(user_id), None, None, true)
|
||||||
))
|
}
|
||||||
},
|
},
|
||||||
Some((user_id, device_id)) => {
|
AuthScheme::ServerSignatures | AuthScheme::None => (None, None, None, true),
|
||||||
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
}
|
||||||
},
|
} else {
|
||||||
}
|
match metadata.authentication {
|
||||||
},
|
AuthScheme::AccessToken => {
|
||||||
AuthScheme::AccessTokenOptional => {
|
let Some(token) = token else {
|
||||||
let token = token.unwrap_or("");
|
return Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token."));
|
||||||
|
};
|
||||||
|
|
||||||
if token.is_empty() {
|
|
||||||
(None, None, None, false)
|
|
||||||
} else {
|
|
||||||
match services().users.find_from_token(token)? {
|
match services().users.find_from_token(token)? {
|
||||||
None => {
|
None => {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
|
@ -173,112 +151,13 @@ where
|
||||||
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
AuthScheme::AccessTokenOptional => {
|
||||||
// treat non-appservice registrations as None authentication
|
let token = token.unwrap_or("");
|
||||||
AuthScheme::AppserviceToken => (None, None, None, false),
|
|
||||||
AuthScheme::ServerSignatures => {
|
|
||||||
if !services().globals.allow_federation() {
|
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
|
||||||
}
|
|
||||||
|
|
||||||
let TypedHeader(Authorization(x_matrix)) = parts
|
|
||||||
.extract::<TypedHeader<Authorization<XMatrix>>>()
|
|
||||||
.await
|
|
||||||
.map_err(|e| {
|
|
||||||
warn!("Missing or invalid Authorization header: {}", e);
|
|
||||||
|
|
||||||
let msg = match e.reason() {
|
|
||||||
TypedHeaderRejectionReason::Missing => "Missing Authorization header.",
|
|
||||||
TypedHeaderRejectionReason::Error(_) => "Invalid X-Matrix signatures.",
|
|
||||||
_ => "Unknown header-related error",
|
|
||||||
};
|
|
||||||
|
|
||||||
Error::BadRequest(ErrorKind::Forbidden, msg)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let origin_signatures =
|
|
||||||
BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig))]);
|
|
||||||
|
|
||||||
let signatures = BTreeMap::from_iter([(
|
|
||||||
x_matrix.origin.as_str().to_owned(),
|
|
||||||
CanonicalJsonValue::Object(origin_signatures),
|
|
||||||
)]);
|
|
||||||
|
|
||||||
let server_destination = services().globals.server_name().as_str().to_owned();
|
|
||||||
|
|
||||||
if let Some(destination) = x_matrix.destination.as_ref() {
|
|
||||||
if destination != &server_destination {
|
|
||||||
return Err(Error::BadRequest(ErrorKind::Forbidden, "Invalid authorization."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut request_map = BTreeMap::from_iter([
|
|
||||||
("method".to_owned(), CanonicalJsonValue::String(parts.method.to_string())),
|
|
||||||
("uri".to_owned(), CanonicalJsonValue::String(parts.uri.to_string())),
|
|
||||||
(
|
|
||||||
"origin".to_owned(),
|
|
||||||
CanonicalJsonValue::String(x_matrix.origin.as_str().to_owned()),
|
|
||||||
),
|
|
||||||
("destination".to_owned(), CanonicalJsonValue::String(server_destination)),
|
|
||||||
("signatures".to_owned(), CanonicalJsonValue::Object(signatures)),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if let Some(json_body) = &json_body {
|
|
||||||
request_map.insert("content".to_owned(), json_body.clone());
|
|
||||||
};
|
|
||||||
|
|
||||||
let keys_result = services()
|
|
||||||
.rooms
|
|
||||||
.event_handler
|
|
||||||
.fetch_signing_keys_for_server(&x_matrix.origin, vec![x_matrix.key.clone()])
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let keys = match keys_result {
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to fetch signing keys: {}", e);
|
|
||||||
return Err(Error::BadRequest(ErrorKind::Forbidden, "Failed to fetch signing keys."));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let pub_key_map = BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]);
|
|
||||||
|
|
||||||
match ruma::signatures::verify_json(&pub_key_map, &request_map) {
|
|
||||||
Ok(()) => (None, None, Some(x_matrix.origin), false),
|
|
||||||
Err(e) => {
|
|
||||||
warn!(
|
|
||||||
"Failed to verify json request from {}: {}\n{:?}",
|
|
||||||
x_matrix.origin, e, request_map
|
|
||||||
);
|
|
||||||
|
|
||||||
if parts.uri.to_string().contains('@') {
|
|
||||||
warn!(
|
|
||||||
"Request uri contained '@' character. Make sure your reverse proxy gives Conduit \
|
|
||||||
the raw uri (apache: use nocanon)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Err(Error::BadRequest(
|
|
||||||
ErrorKind::Forbidden,
|
|
||||||
"Failed to verify X-Matrix signatures.",
|
|
||||||
));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
AuthScheme::None => match parts.uri.path() {
|
|
||||||
// allow_public_room_directory_without_auth
|
|
||||||
"/_matrix/client/v3/publicRooms" | "/_matrix/client/r0/publicRooms" => {
|
|
||||||
if !services()
|
|
||||||
.globals
|
|
||||||
.config
|
|
||||||
.allow_public_room_directory_without_auth
|
|
||||||
{
|
|
||||||
let token = match token {
|
|
||||||
Some(token) => token,
|
|
||||||
_ => return Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token.")),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if token.is_empty() {
|
||||||
|
(None, None, None, false)
|
||||||
|
} else {
|
||||||
match services().users.find_from_token(token)? {
|
match services().users.find_from_token(token)? {
|
||||||
None => {
|
None => {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
|
@ -292,14 +171,132 @@ where
|
||||||
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
(None, None, None, false)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => (None, None, None, false),
|
// treat non-appservice registrations as None authentication
|
||||||
},
|
AuthScheme::AppserviceToken => (None, None, None, false),
|
||||||
}
|
AuthScheme::ServerSignatures => {
|
||||||
};
|
if !services().globals.allow_federation() {
|
||||||
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
|
}
|
||||||
|
|
||||||
|
let TypedHeader(Authorization(x_matrix)) = parts
|
||||||
|
.extract::<TypedHeader<Authorization<XMatrix>>>()
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
warn!("Missing or invalid Authorization header: {}", e);
|
||||||
|
|
||||||
|
let msg = match e.reason() {
|
||||||
|
TypedHeaderRejectionReason::Missing => "Missing Authorization header.",
|
||||||
|
TypedHeaderRejectionReason::Error(_) => "Invalid X-Matrix signatures.",
|
||||||
|
_ => "Unknown header-related error",
|
||||||
|
};
|
||||||
|
|
||||||
|
Error::BadRequest(ErrorKind::Forbidden, msg)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let origin_signatures =
|
||||||
|
BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig))]);
|
||||||
|
|
||||||
|
let signatures = BTreeMap::from_iter([(
|
||||||
|
x_matrix.origin.as_str().to_owned(),
|
||||||
|
CanonicalJsonValue::Object(origin_signatures),
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let server_destination = services().globals.server_name().as_str().to_owned();
|
||||||
|
|
||||||
|
if let Some(destination) = x_matrix.destination.as_ref() {
|
||||||
|
if destination != &server_destination {
|
||||||
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Invalid authorization."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut request_map = BTreeMap::from_iter([
|
||||||
|
("method".to_owned(), CanonicalJsonValue::String(parts.method.to_string())),
|
||||||
|
("uri".to_owned(), CanonicalJsonValue::String(parts.uri.to_string())),
|
||||||
|
(
|
||||||
|
"origin".to_owned(),
|
||||||
|
CanonicalJsonValue::String(x_matrix.origin.as_str().to_owned()),
|
||||||
|
),
|
||||||
|
("destination".to_owned(), CanonicalJsonValue::String(server_destination)),
|
||||||
|
("signatures".to_owned(), CanonicalJsonValue::Object(signatures)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if let Some(json_body) = &json_body {
|
||||||
|
request_map.insert("content".to_owned(), json_body.clone());
|
||||||
|
};
|
||||||
|
|
||||||
|
let keys_result = services()
|
||||||
|
.rooms
|
||||||
|
.event_handler
|
||||||
|
.fetch_signing_keys_for_server(&x_matrix.origin, vec![x_matrix.key.clone()])
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let keys = match keys_result {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to fetch signing keys: {}", e);
|
||||||
|
return Err(Error::BadRequest(ErrorKind::Forbidden, "Failed to fetch signing keys."));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let pub_key_map = BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]);
|
||||||
|
|
||||||
|
match ruma::signatures::verify_json(&pub_key_map, &request_map) {
|
||||||
|
Ok(()) => (None, None, Some(x_matrix.origin), false),
|
||||||
|
Err(e) => {
|
||||||
|
warn!(
|
||||||
|
"Failed to verify json request from {}: {}\n{:?}",
|
||||||
|
x_matrix.origin, e, request_map
|
||||||
|
);
|
||||||
|
|
||||||
|
if parts.uri.to_string().contains('@') {
|
||||||
|
warn!(
|
||||||
|
"Request uri contained '@' character. Make sure your reverse proxy gives \
|
||||||
|
Conduit the raw uri (apache: use nocanon)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::Forbidden,
|
||||||
|
"Failed to verify X-Matrix signatures.",
|
||||||
|
));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AuthScheme::None => match parts.uri.path() {
|
||||||
|
// allow_public_room_directory_without_auth
|
||||||
|
"/_matrix/client/v3/publicRooms" | "/_matrix/client/r0/publicRooms" => {
|
||||||
|
if !services()
|
||||||
|
.globals
|
||||||
|
.config
|
||||||
|
.allow_public_room_directory_without_auth
|
||||||
|
{
|
||||||
|
let Some(token) = token else {
|
||||||
|
return Err(Error::BadRequest(ErrorKind::MissingToken, "Missing access token."));
|
||||||
|
};
|
||||||
|
|
||||||
|
match services().users.find_from_token(token)? {
|
||||||
|
None => {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::UnknownToken {
|
||||||
|
soft_logout: false,
|
||||||
|
},
|
||||||
|
"Unknown access token.",
|
||||||
|
))
|
||||||
|
},
|
||||||
|
Some((user_id, device_id)) => {
|
||||||
|
(Some(user_id), Some(OwnedDeviceId::from(device_id)), None, false)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, None, None, false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (None, None, None, false),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut http_request = Request::builder().uri(parts.uri).method(parts.method);
|
let mut http_request = Request::builder().uri(parts.uri).method(parts.method);
|
||||||
*http_request.headers_mut().unwrap() = parts.headers;
|
*http_request.headers_mut().unwrap() = parts.headers;
|
||||||
|
|
|
@ -429,74 +429,64 @@ async fn find_actual_destination(destination: &'_ ServerName) -> (FedDest, FedDe
|
||||||
FedDest::Named(host.to_owned(), port.to_owned())
|
FedDest::Named(host.to_owned(), port.to_owned())
|
||||||
} else {
|
} else {
|
||||||
debug!("Requesting well known for {destination}");
|
debug!("Requesting well known for {destination}");
|
||||||
match request_well_known(destination.as_str()).await {
|
if let Some(delegated_hostname) = request_well_known(destination.as_str()).await {
|
||||||
Some(delegated_hostname) => {
|
debug!("3: A .well-known file is available");
|
||||||
debug!("3: A .well-known file is available");
|
hostname = add_port_to_hostname(&delegated_hostname).into_uri_string();
|
||||||
hostname = add_port_to_hostname(&delegated_hostname).into_uri_string();
|
match get_ip_with_port(&delegated_hostname) {
|
||||||
match get_ip_with_port(&delegated_hostname) {
|
Some(host_and_port) => host_and_port, // 3.1: IP literal in .well-known file
|
||||||
Some(host_and_port) => host_and_port, // 3.1: IP literal in .well-known file
|
None => {
|
||||||
None => {
|
if let Some(pos) = delegated_hostname.find(':') {
|
||||||
if let Some(pos) = delegated_hostname.find(':') {
|
debug!("3.2: Hostname with port in .well-known file");
|
||||||
debug!("3.2: Hostname with port in .well-known file");
|
|
||||||
|
|
||||||
let (host, port) = delegated_hostname.split_at(pos);
|
let (host, port) = delegated_hostname.split_at(pos);
|
||||||
query_and_cache_override(host, host, port.parse::<u16>().unwrap_or(8448)).await;
|
query_and_cache_override(host, host, port.parse::<u16>().unwrap_or(8448)).await;
|
||||||
|
|
||||||
FedDest::Named(host.to_owned(), port.to_owned())
|
FedDest::Named(host.to_owned(), port.to_owned())
|
||||||
} else {
|
} else {
|
||||||
debug!("Delegated hostname has no port in this branch");
|
debug!("Delegated hostname has no port in this branch");
|
||||||
if let Some(hostname_override) = query_srv_record(&delegated_hostname).await {
|
if let Some(hostname_override) = query_srv_record(&delegated_hostname).await {
|
||||||
debug!("3.3: SRV lookup successful");
|
debug!("3.3: SRV lookup successful");
|
||||||
|
|
||||||
let force_port = hostname_override.port();
|
let force_port = hostname_override.port();
|
||||||
query_and_cache_override(
|
query_and_cache_override(
|
||||||
&delegated_hostname,
|
&delegated_hostname,
|
||||||
&hostname_override.hostname(),
|
&hostname_override.hostname(),
|
||||||
force_port.unwrap_or(8448),
|
force_port.unwrap_or(8448),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(port) = force_port {
|
if let Some(port) = force_port {
|
||||||
FedDest::Named(delegated_hostname, format!(":{port}"))
|
FedDest::Named(delegated_hostname, format!(":{port}"))
|
||||||
} else {
|
|
||||||
add_port_to_hostname(&delegated_hostname)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debug!("3.4: No SRV records, just use the hostname from .well-known");
|
|
||||||
query_and_cache_override(&delegated_hostname, &delegated_hostname, 8448).await;
|
|
||||||
add_port_to_hostname(&delegated_hostname)
|
add_port_to_hostname(&delegated_hostname)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
debug!("4: No .well-known or an error occured");
|
|
||||||
match query_srv_record(&destination_str).await {
|
|
||||||
Some(hostname_override) => {
|
|
||||||
debug!("4: SRV record found");
|
|
||||||
|
|
||||||
let force_port = hostname_override.port();
|
|
||||||
query_and_cache_override(
|
|
||||||
&hostname,
|
|
||||||
&hostname_override.hostname(),
|
|
||||||
force_port.unwrap_or(8448),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if let Some(port) = force_port {
|
|
||||||
FedDest::Named(hostname.clone(), format!(":{port}"))
|
|
||||||
} else {
|
} else {
|
||||||
add_port_to_hostname(&hostname)
|
debug!("3.4: No SRV records, just use the hostname from .well-known");
|
||||||
|
query_and_cache_override(&delegated_hostname, &delegated_hostname, 8448).await;
|
||||||
|
add_port_to_hostname(&delegated_hostname)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => {
|
},
|
||||||
debug!("5: No SRV record found");
|
}
|
||||||
query_and_cache_override(&destination_str, &destination_str, 8448).await;
|
} else {
|
||||||
add_port_to_hostname(&destination_str)
|
debug!("4: No .well-known or an error occured");
|
||||||
},
|
if let Some(hostname_override) = query_srv_record(&destination_str).await {
|
||||||
|
debug!("4: SRV record found");
|
||||||
|
|
||||||
|
let force_port = hostname_override.port();
|
||||||
|
query_and_cache_override(&hostname, &hostname_override.hostname(), force_port.unwrap_or(8448))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Some(port) = force_port {
|
||||||
|
FedDest::Named(hostname.clone(), format!(":{port}"))
|
||||||
|
} else {
|
||||||
|
add_port_to_hostname(&hostname)
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
|
debug!("5: No SRV record found");
|
||||||
|
query_and_cache_override(&destination_str, &destination_str, 8448).await;
|
||||||
|
add_port_to_hostname(&destination_str)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -776,15 +766,12 @@ pub fn parse_incoming_pdu(pdu: &RawJsonValue) -> Result<(OwnedEventId, Canonical
|
||||||
|
|
||||||
let room_version_id = services().rooms.state.get_room_version(&room_id)?;
|
let room_version_id = services().rooms.state.get_room_version(&room_id)?;
|
||||||
|
|
||||||
let (event_id, value) = match gen_event_id_canonical_json(pdu, &room_version_id) {
|
let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
||||||
Ok(t) => t,
|
// Event could not be converted to canonical json
|
||||||
Err(_) => {
|
return Err(Error::BadRequest(
|
||||||
// Event could not be converted to canonical json
|
ErrorKind::InvalidParam,
|
||||||
return Err(Error::BadRequest(
|
"Could not convert event to canonical json.",
|
||||||
ErrorKind::InvalidParam,
|
));
|
||||||
"Could not convert event to canonical json.",
|
|
||||||
));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
Ok((event_id, value, room_id))
|
Ok((event_id, value, room_id))
|
||||||
}
|
}
|
||||||
|
@ -1379,12 +1366,13 @@ pub async fn get_room_state_route(body: Ruma<get_room_state::v1::Request>) -> Re
|
||||||
|
|
||||||
Ok(get_room_state::v1::Response {
|
Ok(get_room_state::v1::Response {
|
||||||
auth_chain: auth_chain_ids
|
auth_chain: auth_chain_ids
|
||||||
.filter_map(|id| match services().rooms.timeline.get_pdu_json(&id).ok()? {
|
.filter_map(|id| {
|
||||||
Some(json) => Some(PduEvent::convert_to_outgoing_federation_event(json)),
|
if let Some(json) = services().rooms.timeline.get_pdu_json(&id).ok()? {
|
||||||
None => {
|
Some(PduEvent::convert_to_outgoing_federation_event(json))
|
||||||
|
} else {
|
||||||
error!("Could not find event json for {id} in db.");
|
error!("Could not find event json for {id} in db.");
|
||||||
None
|
None
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
pdus,
|
pdus,
|
||||||
|
@ -1623,15 +1611,12 @@ async fn create_join_event(
|
||||||
// We do not add the event_id field to the pdu here because of signature and
|
// We do not add the event_id field to the pdu here because of signature and
|
||||||
// hashes checks
|
// hashes checks
|
||||||
let room_version_id = services().rooms.state.get_room_version(room_id)?;
|
let room_version_id = services().rooms.state.get_room_version(room_id)?;
|
||||||
let (event_id, value) = match gen_event_id_canonical_json(pdu, &room_version_id) {
|
let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
||||||
Ok(t) => t,
|
// Event could not be converted to canonical json
|
||||||
Err(_) => {
|
return Err(Error::BadRequest(
|
||||||
// Event could not be converted to canonical json
|
ErrorKind::InvalidParam,
|
||||||
return Err(Error::BadRequest(
|
"Could not convert event to canonical json.",
|
||||||
ErrorKind::InvalidParam,
|
));
|
||||||
"Could not convert event to canonical json.",
|
|
||||||
));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let origin: OwnedServerName = serde_json::from_value(
|
let origin: OwnedServerName = serde_json::from_value(
|
||||||
|
|
|
@ -253,18 +253,17 @@ impl KeyValueDatabaseEngine for Arc<Engine> {
|
||||||
let options = BackupEngineOptions::new(path.unwrap())?;
|
let options = BackupEngineOptions::new(path.unwrap())?;
|
||||||
let mut engine = BackupEngine::open(&options, &self.env)?;
|
let mut engine = BackupEngine::open(&options, &self.env)?;
|
||||||
let ret = if self.config.database_backups_to_keep > 0 {
|
let ret = if self.config.database_backups_to_keep > 0 {
|
||||||
match engine.create_new_backup_flush(&self.rocks, true) {
|
if let Err(e) = engine.create_new_backup_flush(&self.rocks, true) {
|
||||||
Err(e) => return Err(Box::new(e)),
|
return Err(Box::new(e));
|
||||||
Ok(()) => {
|
|
||||||
let engine_info = engine.get_backup_info();
|
|
||||||
let info = &engine_info.last().unwrap();
|
|
||||||
info!(
|
|
||||||
"Created database backup #{} using {} bytes in {} files",
|
|
||||||
info.backup_id, info.size, info.num_files,
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let engine_info = engine.get_backup_info();
|
||||||
|
let info = &engine_info.last().unwrap();
|
||||||
|
info!(
|
||||||
|
"Created database backup #{} using {} bytes in {} files",
|
||||||
|
info.backup_id, info.size, info.num_files,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl<T> Drop for NonAliasingBox<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Engine {
|
pub(crate) struct Engine {
|
||||||
writer: Mutex<Connection>,
|
writer: Mutex<Connection>,
|
||||||
read_conn_tls: ThreadLocal<Connection>,
|
read_conn_tls: ThreadLocal<Connection>,
|
||||||
read_iterator_conn_tls: ThreadLocal<Connection>,
|
read_iterator_conn_tls: ThreadLocal<Connection>,
|
||||||
|
|
|
@ -52,12 +52,11 @@ impl service::rooms::search::Data for KeyValueDatabase {
|
||||||
.map(move |(key, _)| key[prefix3.len()..].to_vec())
|
.map(move |(key, _)| key[prefix3.len()..].to_vec())
|
||||||
});
|
});
|
||||||
|
|
||||||
let common_elements = match utils::common_elements(iterators, |a, b| {
|
let Some(common_elements) = utils::common_elements(iterators, |a, b| {
|
||||||
// We compare b with a because we reversed the iterator earlier
|
// We compare b with a because we reversed the iterator earlier
|
||||||
b.cmp(a)
|
b.cmp(a)
|
||||||
}) {
|
}) else {
|
||||||
Some(it) => it,
|
return Ok(None);
|
||||||
None => return Ok(None),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some((Box::new(common_elements), words)))
|
Ok(Some((Box::new(common_elements), words)))
|
||||||
|
|
|
@ -11,18 +11,15 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
return Ok(*short);
|
return Ok(*short);
|
||||||
}
|
}
|
||||||
|
|
||||||
let short = match self.eventid_shorteventid.get(event_id.as_bytes())? {
|
let short = if let Some(shorteventid) = self.eventid_shorteventid.get(event_id.as_bytes())? {
|
||||||
Some(shorteventid) => {
|
utils::u64_from_bytes(&shorteventid).map_err(|_| Error::bad_database("Invalid shorteventid in db."))?
|
||||||
utils::u64_from_bytes(&shorteventid).map_err(|_| Error::bad_database("Invalid shorteventid in db."))?
|
} else {
|
||||||
},
|
let shorteventid = services().globals.next_count()?;
|
||||||
None => {
|
self.eventid_shorteventid
|
||||||
let shorteventid = services().globals.next_count()?;
|
.insert(event_id.as_bytes(), &shorteventid.to_be_bytes())?;
|
||||||
self.eventid_shorteventid
|
self.shorteventid_eventid
|
||||||
.insert(event_id.as_bytes(), &shorteventid.to_be_bytes())?;
|
.insert(&shorteventid.to_be_bytes(), event_id.as_bytes())?;
|
||||||
self.shorteventid_eventid
|
shorteventid
|
||||||
.insert(&shorteventid.to_be_bytes(), event_id.as_bytes())?;
|
|
||||||
shorteventid
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.eventidshort_cache
|
self.eventidshort_cache
|
||||||
|
@ -79,17 +76,15 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
statekey_vec.push(0xFF);
|
statekey_vec.push(0xFF);
|
||||||
statekey_vec.extend_from_slice(state_key.as_bytes());
|
statekey_vec.extend_from_slice(state_key.as_bytes());
|
||||||
|
|
||||||
let short = match self.statekey_shortstatekey.get(&statekey_vec)? {
|
let short = if let Some(shortstatekey) = self.statekey_shortstatekey.get(&statekey_vec)? {
|
||||||
Some(shortstatekey) => utils::u64_from_bytes(&shortstatekey)
|
utils::u64_from_bytes(&shortstatekey).map_err(|_| Error::bad_database("Invalid shortstatekey in db."))?
|
||||||
.map_err(|_| Error::bad_database("Invalid shortstatekey in db."))?,
|
} else {
|
||||||
None => {
|
let shortstatekey = services().globals.next_count()?;
|
||||||
let shortstatekey = services().globals.next_count()?;
|
self.statekey_shortstatekey
|
||||||
self.statekey_shortstatekey
|
.insert(&statekey_vec, &shortstatekey.to_be_bytes())?;
|
||||||
.insert(&statekey_vec, &shortstatekey.to_be_bytes())?;
|
self.shortstatekey_statekey
|
||||||
self.shortstatekey_statekey
|
.insert(&shortstatekey.to_be_bytes(), &statekey_vec)?;
|
||||||
.insert(&shortstatekey.to_be_bytes(), &statekey_vec)?;
|
shortstatekey
|
||||||
shortstatekey
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.statekeyshort_cache
|
self.statekeyshort_cache
|
||||||
|
@ -170,18 +165,17 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
|
|
||||||
/// Returns (shortstatehash, already_existed)
|
/// Returns (shortstatehash, already_existed)
|
||||||
fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)> {
|
fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)> {
|
||||||
Ok(match self.statehash_shortstatehash.get(state_hash)? {
|
Ok(if let Some(shortstatehash) = self.statehash_shortstatehash.get(state_hash)? {
|
||||||
Some(shortstatehash) => (
|
(
|
||||||
utils::u64_from_bytes(&shortstatehash)
|
utils::u64_from_bytes(&shortstatehash)
|
||||||
.map_err(|_| Error::bad_database("Invalid shortstatehash in db."))?,
|
.map_err(|_| Error::bad_database("Invalid shortstatehash in db."))?,
|
||||||
true,
|
true,
|
||||||
),
|
)
|
||||||
None => {
|
} else {
|
||||||
let shortstatehash = services().globals.next_count()?;
|
let shortstatehash = services().globals.next_count()?;
|
||||||
self.statehash_shortstatehash
|
self.statehash_shortstatehash
|
||||||
.insert(state_hash, &shortstatehash.to_be_bytes())?;
|
.insert(state_hash, &shortstatehash.to_be_bytes())?;
|
||||||
(shortstatehash, false)
|
(shortstatehash, false)
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,16 +187,13 @@ impl service::rooms::short::Data for KeyValueDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64> {
|
fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64> {
|
||||||
Ok(match self.roomid_shortroomid.get(room_id.as_bytes())? {
|
Ok(if let Some(short) = self.roomid_shortroomid.get(room_id.as_bytes())? {
|
||||||
Some(short) => {
|
utils::u64_from_bytes(&short).map_err(|_| Error::bad_database("Invalid shortroomid in db."))?
|
||||||
utils::u64_from_bytes(&short).map_err(|_| Error::bad_database("Invalid shortroomid in db."))?
|
} else {
|
||||||
},
|
let short = services().globals.next_count()?;
|
||||||
None => {
|
self.roomid_shortroomid
|
||||||
let short = services().globals.next_count()?;
|
.insert(room_id.as_bytes(), &short.to_be_bytes())?;
|
||||||
self.roomid_shortroomid
|
short
|
||||||
.insert(room_id.as_bytes(), &short.to_be_bytes())?;
|
|
||||||
short
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,13 +77,12 @@ impl service::rooms::state_accessor::Data for KeyValueDatabase {
|
||||||
fn state_get_id(
|
fn state_get_id(
|
||||||
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
||||||
) -> Result<Option<Arc<EventId>>> {
|
) -> Result<Option<Arc<EventId>>> {
|
||||||
let shortstatekey = match services()
|
let Some(shortstatekey) = services()
|
||||||
.rooms
|
.rooms
|
||||||
.short
|
.short
|
||||||
.get_shortstatekey(event_type, state_key)?
|
.get_shortstatekey(event_type, state_key)?
|
||||||
{
|
else {
|
||||||
Some(s) => s,
|
return Ok(None);
|
||||||
None => return Ok(None),
|
|
||||||
};
|
};
|
||||||
let full_state = services()
|
let full_state = services()
|
||||||
.rooms
|
.rooms
|
||||||
|
|
|
@ -119,26 +119,25 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
|
||||||
using get_alias_helper to fetch room ID remotely"
|
using get_alias_helper to fetch room ID remotely"
|
||||||
);
|
);
|
||||||
|
|
||||||
let room_id = match services().rooms.alias.resolve_local_alias(&room_alias)? {
|
let room_id = if let Some(room_id) = services().rooms.alias.resolve_local_alias(&room_alias)? {
|
||||||
Some(room_id) => room_id,
|
room_id
|
||||||
None => {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
"We don't have this room alias to a room ID locally, attempting to fetch room ID over \
|
"We don't have this room alias to a room ID locally, attempting to fetch room ID over \
|
||||||
federation"
|
federation"
|
||||||
);
|
);
|
||||||
|
|
||||||
match get_alias_helper(room_alias).await {
|
match get_alias_helper(room_alias).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
debug!("Got federation response fetching room ID for room {room}: {:?}", response);
|
debug!("Got federation response fetching room ID for room {room}: {:?}", response);
|
||||||
response.room_id
|
response.room_id
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
"Failed to resolve room alias {room} to a room ID: {e}"
|
"Failed to resolve room alias {room} to a room ID: {e}"
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services().rooms.metadata.ban_room(&room_id, true)?;
|
services().rooms.metadata.ban_room(&room_id, true)?;
|
||||||
|
@ -352,14 +351,12 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
|
||||||
|
|
||||||
if disable_federation {
|
if disable_federation {
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
"Finished bulk room ban, banned {} total rooms, evicted all users, and disabled incoming \
|
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and disabled \
|
||||||
federation with the room.",
|
incoming federation with the room."
|
||||||
room_ban_count
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
"Finished bulk room ban, banned {} total rooms and evicted all users.",
|
"Finished bulk room ban, banned {room_ban_count} total rooms and evicted all users."
|
||||||
room_ban_count
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,26 +400,25 @@ pub(crate) async fn process(command: RoomModerationCommand, body: Vec<&str>) ->
|
||||||
using get_alias_helper to fetch room ID remotely"
|
using get_alias_helper to fetch room ID remotely"
|
||||||
);
|
);
|
||||||
|
|
||||||
let room_id = match services().rooms.alias.resolve_local_alias(&room_alias)? {
|
let room_id = if let Some(room_id) = services().rooms.alias.resolve_local_alias(&room_alias)? {
|
||||||
Some(room_id) => room_id,
|
room_id
|
||||||
None => {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
"We don't have this room alias to a room ID locally, attempting to fetch room ID over \
|
"We don't have this room alias to a room ID locally, attempting to fetch room ID over \
|
||||||
federation"
|
federation"
|
||||||
);
|
);
|
||||||
|
|
||||||
match get_alias_helper(room_alias).await {
|
match get_alias_helper(room_alias).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
debug!("Got federation response fetching room ID for room {room}: {:?}", response);
|
debug!("Got federation response fetching room ID for room {room}: {:?}", response);
|
||||||
response.room_id
|
response.room_id
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Ok(RoomMessageEventContent::text_plain(format!(
|
return Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
"Failed to resolve room alias {room} to a room ID: {e}"
|
"Failed to resolve room alias {room} to a room ID: {e}"
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services().rooms.metadata.ban_room(&room_id, false)?;
|
services().rooms.metadata.ban_room(&room_id, false)?;
|
||||||
|
|
|
@ -214,13 +214,10 @@ impl Service {
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let mxc_s = match mxc {
|
let Some(mxc_s) = mxc else {
|
||||||
Some(mxc) => mxc,
|
return Err(Error::bad_database(
|
||||||
None => {
|
"Parsed MXC URL unicode bytes from database but still is None",
|
||||||
return Err(Error::bad_database(
|
));
|
||||||
"Parsed MXC URL unicode bytes from database but still is None",
|
|
||||||
));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Parsed MXC key to URL: {}", mxc_s);
|
debug!("Parsed MXC key to URL: {}", mxc_s);
|
||||||
|
|
|
@ -314,9 +314,8 @@ impl Service {
|
||||||
Ok(ruma::signatures::Verified::Signatures) => {
|
Ok(ruma::signatures::Verified::Signatures) => {
|
||||||
// Redact
|
// Redact
|
||||||
warn!("Calculated hash does not match: {}", event_id);
|
warn!("Calculated hash does not match: {}", event_id);
|
||||||
let obj = match ruma::canonical_json::redact(value, room_version_id, None) {
|
let Ok(obj) = ruma::canonical_json::redact(value, room_version_id, None) else {
|
||||||
Ok(obj) => obj,
|
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Redaction failed"));
|
||||||
Err(_) => return Err(Error::BadRequest(ErrorKind::InvalidParam, "Redaction failed")),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip the PDU if it is redacted and we already have it as an outlier event
|
// Skip the PDU if it is redacted and we already have it as an outlier event
|
||||||
|
@ -373,12 +372,9 @@ impl Service {
|
||||||
// Build map of auth events
|
// Build map of auth events
|
||||||
let mut auth_events = HashMap::new();
|
let mut auth_events = HashMap::new();
|
||||||
for id in &incoming_pdu.auth_events {
|
for id in &incoming_pdu.auth_events {
|
||||||
let auth_event = match services().rooms.timeline.get_pdu(id)? {
|
let Some(auth_event) = services().rooms.timeline.get_pdu(id)? else {
|
||||||
Some(e) => e,
|
warn!("Could not find auth event {}", id);
|
||||||
None => {
|
continue;
|
||||||
warn!("Could not find auth event {}", id);
|
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_room_id(room_id, &auth_event)?;
|
self.check_room_id(room_id, &auth_event)?;
|
||||||
|
@ -525,20 +521,16 @@ impl Service {
|
||||||
|
|
||||||
let mut okay = true;
|
let mut okay = true;
|
||||||
for prev_eventid in &incoming_pdu.prev_events {
|
for prev_eventid in &incoming_pdu.prev_events {
|
||||||
let prev_event = if let Ok(Some(pdu)) = services().rooms.timeline.get_pdu(prev_eventid) {
|
let Ok(Some(prev_event)) = services().rooms.timeline.get_pdu(prev_eventid) else {
|
||||||
pdu
|
|
||||||
} else {
|
|
||||||
okay = false;
|
okay = false;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
let sstatehash = if let Ok(Some(s)) = services()
|
let Ok(Some(sstatehash)) = services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.pdu_shortstatehash(prev_eventid)
|
.pdu_shortstatehash(prev_eventid)
|
||||||
{
|
else {
|
||||||
s
|
|
||||||
} else {
|
|
||||||
okay = false;
|
okay = false;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1072,14 +1064,12 @@ impl Service {
|
||||||
{
|
{
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
info!("Got {} over federation", next_id);
|
info!("Got {} over federation", next_id);
|
||||||
let (calculated_event_id, value) =
|
let Ok((calculated_event_id, value)) =
|
||||||
match pdu::gen_event_id_canonical_json(&res.pdu, room_version_id) {
|
pdu::gen_event_id_canonical_json(&res.pdu, room_version_id)
|
||||||
Ok(t) => t,
|
else {
|
||||||
Err(_) => {
|
back_off((*next_id).to_owned()).await;
|
||||||
back_off((*next_id).to_owned()).await;
|
continue;
|
||||||
continue;
|
};
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if calculated_event_id != *next_id {
|
if calculated_event_id != *next_id {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -1616,21 +1606,18 @@ impl Service {
|
||||||
|
|
||||||
/// Returns Ok if the acl allows the server
|
/// Returns Ok if the acl allows the server
|
||||||
pub fn acl_check(&self, server_name: &ServerName, room_id: &RoomId) -> Result<()> {
|
pub fn acl_check(&self, server_name: &ServerName, room_id: &RoomId) -> Result<()> {
|
||||||
let acl_event =
|
let acl_event = if let Some(acl) =
|
||||||
match services()
|
services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.room_state_get(room_id, &StateEventType::RoomServerAcl, "")?
|
.room_state_get(room_id, &StateEventType::RoomServerAcl, "")?
|
||||||
{
|
{
|
||||||
Some(acl) => {
|
debug!("ACL event found: {acl:?}");
|
||||||
debug!("ACL event found: {acl:?}");
|
acl
|
||||||
acl
|
} else {
|
||||||
},
|
debug!("No ACL event found");
|
||||||
None => {
|
return Ok(());
|
||||||
info!("No ACL event found");
|
};
|
||||||
return Ok(());
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let acl_event_content: RoomServerAclEventContent = match serde_json::from_str(acl_event.content.get()) {
|
let acl_event_content: RoomServerAclEventContent = match serde_json::from_str(acl_event.content.get()) {
|
||||||
Ok(content) => {
|
Ok(content) => {
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl Arena {
|
||||||
|
|
||||||
/// Returns the first untraversed node, marking it as traversed in the
|
/// Returns the first untraversed node, marking it as traversed in the
|
||||||
/// process
|
/// process
|
||||||
pub fn first_untraversed(&mut self) -> Option<NodeId> {
|
fn first_untraversed(&mut self) -> Option<NodeId> {
|
||||||
if self.nodes.is_empty() {
|
if self.nodes.is_empty() {
|
||||||
None
|
None
|
||||||
} else if let Some(untraversed) = self.first_untraversed {
|
} else if let Some(untraversed) = self.first_untraversed {
|
||||||
|
@ -133,7 +133,7 @@ impl Arena {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds all the given nodes as children of the parent node
|
/// Adds all the given nodes as children of the parent node
|
||||||
pub fn push(&mut self, parent: NodeId, mut children: Vec<OwnedRoomId>) {
|
fn push(&mut self, parent: NodeId, mut children: Vec<OwnedRoomId>) {
|
||||||
if children.is_empty() {
|
if children.is_empty() {
|
||||||
self.traverse(parent);
|
self.traverse(parent);
|
||||||
} else if self.nodes.get(parent.index).is_some() {
|
} else if self.nodes.get(parent.index).is_some() {
|
||||||
|
@ -204,7 +204,7 @@ impl Arena {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(root: OwnedRoomId, max_depth: usize) -> Self {
|
fn new(root: OwnedRoomId, max_depth: usize) -> Self {
|
||||||
let zero_depth = max_depth == 0;
|
let zero_depth = max_depth == 0;
|
||||||
|
|
||||||
Arena {
|
Arena {
|
||||||
|
@ -229,11 +229,11 @@ impl Arena {
|
||||||
|
|
||||||
// Note: perhaps use some better form of token rather than just room count
|
// Note: perhaps use some better form of token rather than just room count
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct PagnationToken {
|
pub(crate) struct PagnationToken {
|
||||||
pub skip: UInt,
|
pub(crate) skip: UInt,
|
||||||
pub limit: UInt,
|
pub(crate) limit: UInt,
|
||||||
pub max_depth: UInt,
|
pub(crate) max_depth: UInt,
|
||||||
pub suggested_only: bool,
|
pub(crate) suggested_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for PagnationToken {
|
impl FromStr for PagnationToken {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use data::Data;
|
pub(crate) use data::Data;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::error::ErrorKind,
|
api::client::error::ErrorKind,
|
||||||
events::{
|
events::{
|
||||||
|
@ -43,9 +43,8 @@ impl Service {
|
||||||
.ok()
|
.ok()
|
||||||
.map(|(_, id)| id)
|
.map(|(_, id)| id)
|
||||||
}) {
|
}) {
|
||||||
let pdu = match services().rooms.timeline.get_pdu_json(&event_id)? {
|
let Some(pdu) = services().rooms.timeline.get_pdu_json(&event_id)? else {
|
||||||
Some(pdu) => pdu,
|
continue;
|
||||||
None => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let pdu: PduEvent = match serde_json::from_str(
|
let pdu: PduEvent = match serde_json::from_str(
|
||||||
|
@ -57,19 +56,16 @@ impl Service {
|
||||||
|
|
||||||
match pdu.kind {
|
match pdu.kind {
|
||||||
TimelineEventType::RoomMember => {
|
TimelineEventType::RoomMember => {
|
||||||
let membership_event = match serde_json::from_str::<RoomMemberEventContent>(pdu.content.get()) {
|
let Ok(membership_event) = serde_json::from_str::<RoomMemberEventContent>(pdu.content.get()) else {
|
||||||
Ok(e) => e,
|
continue;
|
||||||
Err(_) => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let state_key = match pdu.state_key {
|
let Some(state_key) = pdu.state_key else {
|
||||||
Some(k) => k,
|
continue;
|
||||||
None => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_id = match UserId::parse(state_key) {
|
let Ok(user_id) = UserId::parse(state_key) else {
|
||||||
Ok(id) => id,
|
continue;
|
||||||
Err(_) => continue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services()
|
services()
|
||||||
|
@ -355,12 +351,9 @@ impl Service {
|
||||||
&self, room_id: &RoomId, kind: &TimelineEventType, sender: &UserId, state_key: Option<&str>,
|
&self, room_id: &RoomId, kind: &TimelineEventType, sender: &UserId, state_key: Option<&str>,
|
||||||
content: &serde_json::value::RawValue,
|
content: &serde_json::value::RawValue,
|
||||||
) -> Result<StateMap<Arc<PduEvent>>> {
|
) -> Result<StateMap<Arc<PduEvent>>> {
|
||||||
let shortstatehash =
|
let Some(shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? else {
|
||||||
if let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
return Ok(HashMap::new());
|
||||||
current_shortstatehash
|
};
|
||||||
} else {
|
|
||||||
return Ok(HashMap::new());
|
|
||||||
};
|
|
||||||
|
|
||||||
let auth_events =
|
let auth_events =
|
||||||
state_res::auth_types_for_event(kind, sender, state_key, content).expect("content is a valid JSON object");
|
state_res::auth_types_for_event(kind, sender, state_key, content).expect("content is a valid JSON object");
|
||||||
|
|
|
@ -143,9 +143,8 @@ impl Service {
|
||||||
/// the room's history_visibility at that event's state.
|
/// the room's history_visibility at that event's state.
|
||||||
#[tracing::instrument(skip(self, user_id, room_id, event_id))]
|
#[tracing::instrument(skip(self, user_id, room_id, event_id))]
|
||||||
pub fn user_can_see_event(&self, user_id: &UserId, room_id: &RoomId, event_id: &EventId) -> Result<bool> {
|
pub fn user_can_see_event(&self, user_id: &UserId, room_id: &RoomId, event_id: &EventId) -> Result<bool> {
|
||||||
let shortstatehash = match self.pdu_shortstatehash(event_id)? {
|
let Some(shortstatehash) = self.pdu_shortstatehash(event_id)? else {
|
||||||
Some(shortstatehash) => shortstatehash,
|
return Ok(true);
|
||||||
None => return Ok(true),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(visibility) = self
|
if let Some(visibility) = self
|
||||||
|
|
|
@ -473,7 +473,7 @@ impl Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that a user only sees signatures from themselves and the target user
|
/// Ensure that a user only sees signatures from themselves and the target user
|
||||||
pub fn clean_signatures<F: Fn(&UserId) -> bool>(
|
pub(crate) fn clean_signatures<F: Fn(&UserId) -> bool>(
|
||||||
cross_signing_key: &mut serde_json::Value, sender_user: Option<&UserId>, user_id: &UserId, allowed_signatures: F,
|
cross_signing_key: &mut serde_json::Value, sender_user: Option<&UserId>, user_id: &UserId, allowed_signatures: F,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if let Some(signatures) = cross_signing_key
|
if let Some(signatures) = cross_signing_key
|
||||||
|
|
Loading…
Add table
Reference in a new issue