Add license, update readme and add docs for event_auth functions
This commit is contained in:
parent
789c814089
commit
ce2d5a0d9b
19
LICENSE
Normal file
19
LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020 Devin Ragotzy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
30
README.md
30
README.md
@ -12,20 +12,24 @@ struct StateEvent {
|
||||
/// A mapping of event type and state_key to some value `T`, usually an `EventId`.
|
||||
pub type StateMap<T> = BTreeMap<(EventType, String), T>;
|
||||
|
||||
/// A mapping of `EventId` to `T`, usually a `StateEvent`.
|
||||
pub type EventMap<T> = BTreeMap<EventId, T>;
|
||||
|
||||
struct StateResolution {
|
||||
// Should any information be kept or should all of it be fetched from the
|
||||
// StateStore trait?
|
||||
event_map: BTreeMap<EventId, StateEvent>,
|
||||
|
||||
// fields for temp storage during resolution??
|
||||
/// The events that conflict and their auth chains.
|
||||
conflicting_events: StateMap<Vec<EventId>>,
|
||||
// For now the StateResolution struct is empty. If "caching `event_map` between `resolve` calls
|
||||
// ends up being more efficient it may have an `event_map` field.
|
||||
}
|
||||
|
||||
impl StateResolution {
|
||||
/// The point of this all. Resolve the conflicting set of .
|
||||
fn resolve(&mut self, events: Vec<StateMap<EventId>>) -> StateMap<EventId> { }
|
||||
/// The point of this all, resolve the possibly conflicting sets of events.
|
||||
pub fn resolve(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
room_version: &RoomVersionId,
|
||||
state_sets: &[StateMap<EventId>],
|
||||
event_map: Option<EventMap<StateEvent>>,
|
||||
store: &dyn StateStore,
|
||||
) -> Result<ResolutionResult>;
|
||||
|
||||
}
|
||||
|
||||
@ -34,11 +38,9 @@ trait StateStore {
|
||||
/// Return a single event based on the EventId.
|
||||
fn get_event(&self, event_id: &EventId) -> Result<StateEvent, String>;
|
||||
|
||||
/// Returns the events that correspond to the `event_ids` sorted in the same order.
|
||||
fn get_events(&self, event_ids: &[EventId]) -> Result<Vec<StateEvent>, String>;
|
||||
|
||||
/// Returns a Vec of the related auth events to the given `event`.
|
||||
fn auth_event_ids(&self, room_id: &RoomId, event_ids: &[EventId]) -> Result<Vec<EventId>, String>;
|
||||
// There are 3 methods that have default implementations `get_events`, `auth_event_ids` and
|
||||
// `auth_chain_diff`. Each could be overridden if the user has an optimization with their database of
|
||||
// choice.
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -26,6 +26,8 @@ pub enum RedactAllowed {
|
||||
No,
|
||||
}
|
||||
|
||||
/// For the given event `kind` what are the relevant auth events
|
||||
/// that are needed to authenticate this `content`.
|
||||
pub fn auth_types_for_event(
|
||||
kind: EventType,
|
||||
sender: &UserId,
|
||||
@ -71,6 +73,10 @@ pub fn auth_types_for_event(
|
||||
auth_types
|
||||
}
|
||||
|
||||
/// Authenticate the incoming `event`. The steps of authentication are:
|
||||
/// * check that the event is being authenticated for the correct room
|
||||
/// * check that the events signatures are valid
|
||||
/// * then there are checks for specific event types
|
||||
pub fn auth_check(
|
||||
room_version: &RoomVersionId,
|
||||
event: &StateEvent,
|
||||
@ -107,7 +113,7 @@ pub fn auth_check(
|
||||
|
||||
// TODO do_size_check is false when called by `iterative_auth_check`
|
||||
// do_size_check is also mostly accomplished by ruma with the exception of checking event_type,
|
||||
// state_key, and json are below a certain size (255 and 65536 respectivly)
|
||||
// state_key, and json are below a certain size (255 and 65536 respectively)
|
||||
|
||||
// Implementation of https://matrix.org/docs/spec/rooms/v1#authorization-rules
|
||||
//
|
||||
@ -129,7 +135,7 @@ pub fn auth_check(
|
||||
.get("room_version")
|
||||
.cloned()
|
||||
// synapse defaults to version 1
|
||||
.unwrap_or(serde_json::json!("1")),
|
||||
.unwrap_or_else(|| serde_json::json!("1")),
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
@ -446,7 +452,7 @@ pub fn check_event_sender_in_room(
|
||||
)
|
||||
}
|
||||
|
||||
/// Is the user allowed to send a specific event.
|
||||
/// Is the user allowed to send a specific event based on the rooms power levels.
|
||||
pub fn can_send_event(event: &StateEvent, auth_events: &StateMap<StateEvent>) -> Option<bool> {
|
||||
let ple = auth_events.get(&(EventType::RoomPowerLevels, Some("".into())));
|
||||
|
||||
@ -661,6 +667,8 @@ pub fn check_membership(member_event: Option<&StateEvent>, state: MembershipStat
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to fetch a field, `name`, from a "m.room.power_level" event's content.
|
||||
/// or return `default` if no power level event is found or zero if no field matches `name`.
|
||||
pub fn get_named_level(auth_events: &StateMap<StateEvent>, name: &str, default: i64) -> i64 {
|
||||
let power_level_event = auth_events.get(&(EventType::RoomPowerLevels, Some("".into())));
|
||||
if let Some(pl) = power_level_event {
|
||||
@ -675,6 +683,8 @@ pub fn get_named_level(auth_events: &StateMap<StateEvent>, name: &str, default:
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to fetch a users default power level from a "m.room.power_level" event's `users`
|
||||
/// object.
|
||||
pub fn get_user_power_level(user_id: &UserId, auth_events: &StateMap<StateEvent>) -> i64 {
|
||||
if let Some(pl) = auth_events.get(&(EventType::RoomPowerLevels, Some("".into()))) {
|
||||
if let Ok(content) = pl.deserialize_content::<room::power_levels::PowerLevelsEventContent>()
|
||||
@ -706,6 +716,8 @@ pub fn get_user_power_level(user_id: &UserId, auth_events: &StateMap<StateEvent>
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to fetch the power level needed to send an event of type
|
||||
/// `e_type` based on the rooms "m.room.power_level" event.
|
||||
pub fn get_send_level(
|
||||
e_type: EventType,
|
||||
state_key: Option<String>,
|
||||
@ -720,7 +732,7 @@ pub fn get_send_level(
|
||||
.events
|
||||
.get(&e_type)
|
||||
.cloned()
|
||||
.unwrap_or(js_int::int!(50))
|
||||
.unwrap_or_else(|| js_int::int!(50))
|
||||
.into();
|
||||
let state_def: i64 = content.state_default.into();
|
||||
let event_def: i64 = content.events_default.into();
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(clippy::or_fun_call)]
|
||||
|
||||
use std::{
|
||||
cmp::Reverse,
|
||||
collections::{BTreeMap, BTreeSet, BinaryHeap},
|
||||
@ -266,7 +264,7 @@ impl StateResolution {
|
||||
"SEP {:?}",
|
||||
event_ids
|
||||
.iter()
|
||||
.map(|i| i.map(ToString::to_string).unwrap_or("None".into()))
|
||||
.map(|i| i.map(ToString::to_string).unwrap_or_else(|| "None".into()))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
@ -560,7 +558,7 @@ impl StateResolution {
|
||||
tracing::debug!("event to check {:?}", event.event_id().to_string());
|
||||
|
||||
if event_auth::auth_check(room_version, &event, auth_events, false)
|
||||
.ok_or("Auth check failed due to deserialization most likely".to_string())
|
||||
.ok_or_else(|| "Auth check failed due to deserialization most likely".to_string())
|
||||
.map_err(Error::TempString)?
|
||||
{
|
||||
// add event to resolved state map
|
||||
@ -713,7 +711,7 @@ impl StateResolution {
|
||||
while !state.is_empty() {
|
||||
// we just checked if it was empty so unwrap is fine
|
||||
let eid = state.pop().unwrap();
|
||||
graph.entry(eid.clone()).or_insert(vec![]);
|
||||
graph.entry(eid.clone()).or_insert_with(Vec::new);
|
||||
// prefer the store to event as the store filters dedups the events
|
||||
// otherwise it seems we can loop forever
|
||||
for aid in self
|
||||
|
Loading…
x
Reference in New Issue
Block a user