mirror of
https://github.com/scsibug/nostr-rs-relay.git
synced 2024-11-22 00:59:07 -05:00
fix: subscription event filtering bugs
Subscriptions properly filter using the authors tag. Petname/keys are correctly filtered (previously the event tags were incorrectly used).
This commit is contained in:
parent
54e6e0e5ce
commit
49598b2c9e
10
src/conn.rs
10
src/conn.rs
|
@ -45,15 +45,15 @@ impl ClientConn {
|
||||||
self.client_id.to_string().chars().take(8).collect()
|
self.client_id.to_string().chars().take(8).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the first subscription identifier that matches the event,
|
/// Find all matching subscriptions.
|
||||||
/// if any do.
|
pub fn get_matching_subscriptions(&self, e: &Event) -> Vec<&str> {
|
||||||
pub fn get_matching_subscription(&self, e: &Event) -> Option<&str> {
|
let mut v: Vec<&str> = vec![];
|
||||||
for (id, sub) in self.subscriptions.iter() {
|
for (id, sub) in self.subscriptions.iter() {
|
||||||
if sub.interested_in_event(e) {
|
if sub.interested_in_event(e) {
|
||||||
return Some(id);
|
v.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new subscription for this connection.
|
/// Add a new subscription for this connection.
|
||||||
|
|
|
@ -154,6 +154,11 @@ impl Event {
|
||||||
pub fn event_tag_match(&self, eventid: &str) -> bool {
|
pub fn event_tag_match(&self, eventid: &str) -> bool {
|
||||||
self.get_event_tags().contains(&eventid)
|
self.get_event_tags().contains(&eventid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a given event is referenced in an event tag.
|
||||||
|
pub fn pubkey_tag_match(&self, pubkey: &str) -> bool {
|
||||||
|
self.get_pubkey_tags().contains(&pubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -129,16 +129,16 @@ async fn nostr_server(
|
||||||
Ok(global_event) = bcast_rx.recv() => {
|
Ok(global_event) = bcast_rx.recv() => {
|
||||||
// an event has been broadcast to all clients
|
// an event has been broadcast to all clients
|
||||||
// first check if there is a subscription for this event.
|
// first check if there is a subscription for this event.
|
||||||
let sub_name_opt = conn.get_matching_subscription(&global_event);
|
let matching_subs = conn.get_matching_subscriptions(&global_event);
|
||||||
if let Some(sub_name) = sub_name_opt {
|
for s in matching_subs {
|
||||||
// TODO: serialize at broadcast time, instead of
|
// TODO: serialize at broadcast time, instead of
|
||||||
// once for each consumer.
|
// once for each consumer.
|
||||||
if let Ok(event_str) = serde_json::to_string(&global_event) {
|
if let Ok(event_str) = serde_json::to_string(&global_event) {
|
||||||
debug!("sub match: client: {}, sub: {}, event: {}",
|
debug!("sub match: client: {}, sub: {}, event: {}",
|
||||||
cid, sub_name,
|
cid, s,
|
||||||
global_event.get_event_id_prefix());
|
global_event.get_event_id_prefix());
|
||||||
// create an event response and send it
|
// create an event response and send it
|
||||||
let res = EventRes(sub_name.to_owned(),event_str);
|
let res = EventRes(s.to_owned(),event_str);
|
||||||
nostr_stream.send(res).await.ok();
|
nostr_stream.send(res).await.ok();
|
||||||
} else {
|
} else {
|
||||||
warn!("could not convert event to string");
|
warn!("could not convert event to string");
|
||||||
|
|
|
@ -105,17 +105,21 @@ impl Subscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReqFilter {
|
impl ReqFilter {
|
||||||
/// Check if this filter either matches, or does not care about an author.
|
/// Check for a match within the authors list.
|
||||||
fn author_match(&self, event: &Event) -> bool {
|
// TODO: Ambiguity; what if the array is empty? Should we
|
||||||
|
// consider that the same as null?
|
||||||
|
fn authors_match(&self, event: &Event) -> bool {
|
||||||
self.authors
|
self.authors
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|vs| vs.contains(&event.pubkey.to_owned()))
|
.map(|vs| vs.contains(&event.pubkey.to_owned()))
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
&& self
|
}
|
||||||
.author
|
/// Check for a specific author match
|
||||||
.as_ref()
|
fn author_match(&self, event: &Event) -> bool {
|
||||||
.map(|v| v == &event.pubkey)
|
self.author
|
||||||
.unwrap_or(true)
|
.as_ref()
|
||||||
|
.map(|v| v == &event.pubkey)
|
||||||
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
/// Check if this filter either matches, or does not care about the event tags.
|
/// Check if this filter either matches, or does not care about the event tags.
|
||||||
fn event_match(&self, event: &Event) -> bool {
|
fn event_match(&self, event: &Event) -> bool {
|
||||||
|
@ -125,6 +129,15 @@ impl ReqFilter {
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if this filter either matches, or does not care about
|
||||||
|
/// the pubkey/petname tags.
|
||||||
|
fn pubkey_match(&self, event: &Event) -> bool {
|
||||||
|
self.pubkey
|
||||||
|
.as_ref()
|
||||||
|
.map(|t| event.pubkey_tag_match(t))
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if this filter either matches, or does not care about the kind.
|
/// Check if this filter either matches, or does not care about the kind.
|
||||||
fn kind_match(&self, kind: u64) -> bool {
|
fn kind_match(&self, kind: u64) -> bool {
|
||||||
self.kind.map(|v| v == kind).unwrap_or(true)
|
self.kind.map(|v| v == kind).unwrap_or(true)
|
||||||
|
@ -136,6 +149,8 @@ impl ReqFilter {
|
||||||
&& self.since.map(|t| event.created_at > t).unwrap_or(true)
|
&& self.since.map(|t| event.created_at > t).unwrap_or(true)
|
||||||
&& self.kind_match(event.kind)
|
&& self.kind_match(event.kind)
|
||||||
&& self.author_match(event)
|
&& self.author_match(event)
|
||||||
|
&& self.authors_match(event)
|
||||||
|
&& self.pubkey_match(event)
|
||||||
&& self.event_match(event)
|
&& self.event_match(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user