mirror of
https://github.com/mikedilger/chorus.git
synced 2026-01-03 06:15:33 +00:00
Updates for pocket ScreenResult (including sending 'redacted' with some CLOSED)
This commit is contained in:
parent
dccf8afcf5
commit
db8b29dfc4
@ -1,4 +1,5 @@
|
||||
use chorus::error::{ChorusError, Error};
|
||||
use pocket_db::ScreenResult;
|
||||
use pocket_types::{Filter, Id, Pubkey, Tags};
|
||||
use std::env;
|
||||
|
||||
@ -50,7 +51,8 @@ fn main() -> Result<(), Error> {
|
||||
let mut filter_buffer: [u8; 128] = [0; 128];
|
||||
let filter =
|
||||
Filter::from_parts(&[], &[pk], &[], tags, None, None, None, &mut filter_buffer)?;
|
||||
let events = store.find_events(filter, true, 0, 0, |_| true)?;
|
||||
let (events, _redacted) =
|
||||
store.find_events(filter, true, 0, 0, |_| ScreenResult::Match)?;
|
||||
for event in events.iter() {
|
||||
store.remove_event(event.id())?;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use chorus::error::Error;
|
||||
use pocket_db::ScreenResult;
|
||||
use pocket_types::{Event, Filter};
|
||||
use std::env;
|
||||
|
||||
@ -23,9 +24,9 @@ fn main() -> Result<(), Error> {
|
||||
|
||||
let mut buffer: [u8; 128] = [0; 128];
|
||||
let (_incount, _outcount, filter) = Filter::from_json(b"{}", &mut buffer)?;
|
||||
let screen = |_: &Event| -> bool { true };
|
||||
let screen = |_: &Event| -> ScreenResult { ScreenResult::Match };
|
||||
|
||||
let mut events = store.find_events(
|
||||
let (mut events, _redacted) = store.find_events(
|
||||
filter,
|
||||
config.allow_scraping,
|
||||
config.allow_scrape_if_limited_to,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use chorus::error::Error;
|
||||
use pocket_db::ScreenResult;
|
||||
use pocket_types::{Event, Filter, Kind};
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
@ -33,9 +34,9 @@ fn main() -> Result<(), Error> {
|
||||
|
||||
let mut buffer: [u8; 128] = [0; 128];
|
||||
let (_incount, _outcount, filter) = Filter::from_json(b"{}", &mut buffer)?;
|
||||
let screen = |_: &Event| -> bool { true };
|
||||
let screen = |_: &Event| -> ScreenResult { ScreenResult::Match };
|
||||
|
||||
let mut events = store.find_events(
|
||||
let (mut events, _redacted) = store.find_events(
|
||||
filter,
|
||||
config.allow_scraping,
|
||||
config.allow_scrape_if_limited_to,
|
||||
|
||||
26
src/lib.rs
26
src/lib.rs
@ -27,7 +27,7 @@ use hyper_tungstenite::tungstenite;
|
||||
use hyper_tungstenite::{HyperWebsocket, WebSocketStream};
|
||||
use hyper_util::rt::TokioIo;
|
||||
use neg_storage::NegentropyStorageVector;
|
||||
use pocket_db::Store;
|
||||
use pocket_db::{ScreenResult, Store};
|
||||
use pocket_types::{Id, OwnedFilter, Pubkey};
|
||||
use speedy::{Readable, Writable};
|
||||
use std::borrow::Cow;
|
||||
@ -482,15 +482,21 @@ impl WebSocketService {
|
||||
|
||||
'subs: for (subid, filters) in self.subscriptions.iter() {
|
||||
for filter in filters.iter() {
|
||||
if filter.event_matches(event)?
|
||||
&& nostr::screen_outgoing_event(event, &event_flags, authorized_user)
|
||||
{
|
||||
let message = NostrReply::Event(subid, event);
|
||||
// note, this is not currently counted in throttling
|
||||
self.websocket
|
||||
.send(Message::text(message.as_json()))
|
||||
.await?;
|
||||
continue 'subs;
|
||||
if filter.event_matches(event)? {
|
||||
let screen_result =
|
||||
nostr::screen_outgoing_event(event, &event_flags, authorized_user);
|
||||
if screen_result == ScreenResult::Redacted {
|
||||
// TBD: Update subscription so the final close can
|
||||
// let them know there were redactions from
|
||||
// the post-EOSE data
|
||||
} else if screen_result == ScreenResult::Match {
|
||||
let message = NostrReply::Event(subid, event);
|
||||
// note, this is not currently counted in throttling
|
||||
self.websocket
|
||||
.send(Message::text(message.as_json()))
|
||||
.await?;
|
||||
continue 'subs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
src/nostr.rs
48
src/nostr.rs
@ -5,6 +5,7 @@ use crate::reply::{NostrReply, NostrReplyPrefix};
|
||||
use crate::WebSocketService;
|
||||
use hyper_tungstenite::tungstenite::Message;
|
||||
use negentropy::{Bytes, Negentropy};
|
||||
use pocket_db::ScreenResult;
|
||||
use pocket_types::json::{eat_whitespace, json_unescape, verify_char};
|
||||
use pocket_types::{read_hex, Event, Filter, Hll8, Kind, OwnedFilter, Pubkey, Time};
|
||||
use url::Url;
|
||||
@ -148,6 +149,8 @@ impl WebSocketService {
|
||||
|
||||
let completes = filters.iter().all(|f| f.completes());
|
||||
|
||||
let mut redacted: bool = false;
|
||||
|
||||
// NOTE on private events (DMs, GiftWraps)
|
||||
// As seen above, we will send CLOSED auth-required if they ask for DMs and are not
|
||||
// AUTHed yet.
|
||||
@ -159,11 +162,11 @@ impl WebSocketService {
|
||||
let mut events: Vec<&Event> = Vec::new();
|
||||
|
||||
for filter in filters.iter() {
|
||||
let screen = |event: &Event| {
|
||||
let screen = |event: &Event| -> ScreenResult {
|
||||
let event_flags = event_flags(event, &user);
|
||||
screen_outgoing_event(event, &event_flags, authorized_user)
|
||||
};
|
||||
let filter_events = {
|
||||
let (filter_events, was_redacted) = {
|
||||
let config = &*GLOBALS.config.read();
|
||||
GLOBALS.store.get().unwrap().find_events(
|
||||
filter,
|
||||
@ -174,6 +177,7 @@ impl WebSocketService {
|
||||
)?
|
||||
};
|
||||
events.extend(filter_events);
|
||||
redacted = redacted || was_redacted;
|
||||
}
|
||||
|
||||
// sort
|
||||
@ -204,7 +208,15 @@ impl WebSocketService {
|
||||
|
||||
if completes {
|
||||
// Closed
|
||||
let reply = NostrReply::Closed(subid, NostrReplyPrefix::None, "".to_owned());
|
||||
let reply = if redacted {
|
||||
NostrReply::Closed(subid, NostrReplyPrefix::None, "".to_owned())
|
||||
} else {
|
||||
NostrReply::Closed(
|
||||
subid,
|
||||
NostrReplyPrefix::Redacted,
|
||||
"Some matching events could not be served to you.".to_owned(),
|
||||
)
|
||||
};
|
||||
self.send(Message::text(reply.as_json())).await?;
|
||||
} else {
|
||||
// EOSE
|
||||
@ -531,11 +543,11 @@ impl WebSocketService {
|
||||
|
||||
// Find all matching events
|
||||
let mut events: Vec<&Event> = Vec::new();
|
||||
let screen = |event: &Event| {
|
||||
let screen = |event: &Event| -> ScreenResult {
|
||||
let event_flags = event_flags(event, &user);
|
||||
screen_outgoing_event(event, &event_flags, authorized_user)
|
||||
};
|
||||
let filter_events = {
|
||||
let (filter_events, _redacted) = {
|
||||
let config = &*GLOBALS.config.read();
|
||||
GLOBALS.store.get().unwrap().find_events(
|
||||
&filter,
|
||||
@ -775,59 +787,63 @@ pub fn screen_outgoing_event(
|
||||
event: &Event,
|
||||
event_flags: &EventFlags,
|
||||
authorized_user: bool,
|
||||
) -> bool {
|
||||
) -> ScreenResult {
|
||||
// Forbid if it is a private event (DM or GiftWrap) and theey are neither the recipient
|
||||
// nor the author
|
||||
if event.kind() == Kind::from(4) || event.kind() == Kind::from(1059) {
|
||||
return event_flags.tags_current_user || event_flags.author_is_current_user;
|
||||
if event_flags.tags_current_user || event_flags.author_is_current_user {
|
||||
return ScreenResult::Match;
|
||||
} else {
|
||||
return ScreenResult::Redacted;
|
||||
}
|
||||
}
|
||||
|
||||
// Forbid (and delete) if it has an expired expiration tag
|
||||
if matches!(event.is_expired(), Ok(true)) {
|
||||
let _ = GLOBALS.store.get().unwrap().remove_event(event.id());
|
||||
return false;
|
||||
return ScreenResult::Mismatch;
|
||||
}
|
||||
|
||||
// Allow if an open relay
|
||||
if GLOBALS.config.read().open_relay {
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Allow Relay Lists
|
||||
if GLOBALS.config.read().serve_relay_lists
|
||||
&& (event.kind() == Kind::from(10002) || event.kind() == Kind::from(10050))
|
||||
{
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Allow if event kind ephemeral
|
||||
if event.kind().is_ephemeral() && GLOBALS.config.read().serve_ephemeral {
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Allow if an authorized_user is asking
|
||||
if authorized_user {
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Everybody can see events from our authorized users
|
||||
if event_flags.author_is_an_authorized_user {
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Allow if event is explicitly approved
|
||||
if let Ok(Some(true)) = crate::get_event_approval(GLOBALS.store.get().unwrap(), event.id()) {
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Allow if author is explicitly approved
|
||||
if let Ok(Some(true)) = crate::get_pubkey_approval(GLOBALS.store.get().unwrap(), event.pubkey())
|
||||
{
|
||||
return true;
|
||||
return ScreenResult::Match;
|
||||
}
|
||||
|
||||
// Do not allow the rest
|
||||
false
|
||||
ScreenResult::Redacted
|
||||
}
|
||||
|
||||
pub struct EventFlags {
|
||||
|
||||
@ -9,6 +9,7 @@ pub enum NostrReplyPrefix {
|
||||
Duplicate,
|
||||
Blocked,
|
||||
RateLimited,
|
||||
Redacted,
|
||||
Restricted,
|
||||
Invalid,
|
||||
Error,
|
||||
@ -23,6 +24,7 @@ impl fmt::Display for NostrReplyPrefix {
|
||||
NostrReplyPrefix::Duplicate => write!(f, "duplicate: "),
|
||||
NostrReplyPrefix::Blocked => write!(f, "blocked: "),
|
||||
NostrReplyPrefix::RateLimited => write!(f, "rate-limited: "),
|
||||
NostrReplyPrefix::Redacted => write!(f, "redacted: "),
|
||||
NostrReplyPrefix::Restricted => write!(f, "restricted: "),
|
||||
NostrReplyPrefix::Invalid => write!(f, "invalid: "),
|
||||
NostrReplyPrefix::Error => write!(f, "error: "),
|
||||
|
||||
@ -5,6 +5,7 @@ use http_body_util::combinators::BoxBody;
|
||||
use http_body_util::{BodyExt, Full};
|
||||
use hyper::body::{Bytes, Incoming};
|
||||
use hyper::{Request, Response, StatusCode};
|
||||
use pocket_db::ScreenResult;
|
||||
use pocket_types::{Event, Filter, Id, Kind, Pubkey};
|
||||
use serde::Serialize;
|
||||
use serde_json::{json, Map, Value};
|
||||
@ -340,15 +341,21 @@ pub fn handle_inner(pubkey: Pubkey, command: Value) -> Result<Option<Value>, Err
|
||||
let (_incount, _outcount, filter) = Filter::from_json(b"{}", &mut buffer)?;
|
||||
filter
|
||||
};
|
||||
let screen = |e: &Event| -> bool {
|
||||
!allowed_kinds.contains(&e.kind())
|
||||
&& !e.kind().is_ephemeral()
|
||||
&& !crate::is_authorized_user(e.pubkey())
|
||||
let screen = |e: &Event| -> ScreenResult {
|
||||
if allowed_kinds.contains(&e.kind()) {
|
||||
ScreenResult::Mismatch
|
||||
} else if e.kind().is_ephemeral() {
|
||||
ScreenResult::Mismatch
|
||||
} else if crate::is_authorized_user(e.pubkey()) {
|
||||
ScreenResult::Mismatch
|
||||
} else {
|
||||
ScreenResult::Match
|
||||
}
|
||||
};
|
||||
|
||||
let mut need_moderation: Vec<EventNeedingModeration> = Vec::new();
|
||||
|
||||
let mut events = GLOBALS
|
||||
let (mut events, _redacted) = GLOBALS
|
||||
.store
|
||||
.get()
|
||||
.unwrap()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user