mirror of
https://github.com/mikedilger/chorus.git
synced 2026-05-03 06:51:42 +00:00
Restructure handling code to ensure EVENT always gets an OK reply (except for early errors)
This commit is contained in:
parent
775f15e864
commit
a1c81acd8f
12
src/error.rs
12
src/error.rs
@ -25,6 +25,9 @@ pub enum ChorusError {
|
||||
// Auth failure
|
||||
AuthFailure,
|
||||
|
||||
// Auth required
|
||||
AuthRequired,
|
||||
|
||||
// Bad event id
|
||||
BadEventId,
|
||||
|
||||
@ -52,6 +55,9 @@ pub enum ChorusError {
|
||||
// End of Input
|
||||
EndOfInput,
|
||||
|
||||
// Event is Invalid
|
||||
EventIsInvalid(String),
|
||||
|
||||
// Http
|
||||
Http(hyper::http::Error),
|
||||
|
||||
@ -88,6 +94,9 @@ pub enum ChorusError {
|
||||
// No private key
|
||||
NoPrivateKey,
|
||||
|
||||
// Restricted
|
||||
Restricted,
|
||||
|
||||
// Rustls
|
||||
Rustls(tokio_rustls::rustls::Error),
|
||||
|
||||
@ -114,6 +123,7 @@ impl std::fmt::Display for ChorusError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ChorusError::AuthFailure => write!(f, "AUTH failure"),
|
||||
ChorusError::AuthRequired => write!(f, "AUTH required"),
|
||||
ChorusError::BadEventId => write!(f, "Bad event id, does not match hash"),
|
||||
ChorusError::BadHexInput => write!(f, "Bad hex input"),
|
||||
ChorusError::BufferTooSmall => write!(f, "Output buffer too small"),
|
||||
@ -123,6 +133,7 @@ impl std::fmt::Display for ChorusError {
|
||||
ChorusError::Crypto(e) => write!(f, "{e}"),
|
||||
ChorusError::Duplicate => write!(f, "Duplicate"),
|
||||
ChorusError::EndOfInput => write!(f, "End of input"),
|
||||
ChorusError::EventIsInvalid(s) => write!(f, "Event is invalid: {s}"),
|
||||
ChorusError::Http(e) => write!(f, "{e}"),
|
||||
ChorusError::Hyper(e) => write!(f, "{e}"),
|
||||
ChorusError::Io(e) => write!(f, "{e}"),
|
||||
@ -147,6 +158,7 @@ impl std::fmt::Display for ChorusError {
|
||||
),
|
||||
ChorusError::Lmdb(e) => write!(f, "{e}"),
|
||||
ChorusError::NoPrivateKey => write!(f, "Private Key Not Found"),
|
||||
ChorusError::Restricted => write!(f, "Restricted"),
|
||||
ChorusError::Rustls(e) => write!(f, "{e}"),
|
||||
ChorusError::Tungstenite(e) => write!(f, "{e}"),
|
||||
ChorusError::Scraper => write!(f, "Filter is underspecified. Scrapers are not allowed"),
|
||||
|
||||
77
src/nostr.rs
77
src/nostr.rs
@ -115,6 +115,8 @@ impl WebSocketService {
|
||||
}
|
||||
|
||||
pub async fn event(&mut self, msg: String, mut inpos: usize) -> Result<(), Error> {
|
||||
const PERSONAL_MSG: &str = "this personal relay only accepts events related to its users";
|
||||
|
||||
let input = msg.as_bytes();
|
||||
|
||||
eat_whitespace(input, &mut inpos);
|
||||
@ -123,54 +125,61 @@ impl WebSocketService {
|
||||
|
||||
// Read the event into the session buffer
|
||||
let (_incount, event) = Event::from_json(&input[inpos..], &mut self.buffer)?;
|
||||
let id = event.id();
|
||||
|
||||
let reply = match self.event_inner().await {
|
||||
Ok(()) => NostrReply::Ok(id, true, NostrReplyPrefix::None, "".to_string()),
|
||||
Err(e) => match e.inner {
|
||||
ChorusError::AuthRequired => NostrReply::Ok(
|
||||
id,
|
||||
false,
|
||||
NostrReplyPrefix::AuthRequired,
|
||||
PERSONAL_MSG.to_owned(),
|
||||
),
|
||||
ChorusError::Duplicate => {
|
||||
NostrReply::Ok(id, false, NostrReplyPrefix::Duplicate, "".to_string())
|
||||
}
|
||||
ChorusError::EventIsInvalid(why) => {
|
||||
NostrReply::Ok(id, false, NostrReplyPrefix::Invalid, why)
|
||||
}
|
||||
ChorusError::Restricted => NostrReply::Ok(
|
||||
id,
|
||||
false,
|
||||
NostrReplyPrefix::Restricted,
|
||||
PERSONAL_MSG.to_owned(),
|
||||
),
|
||||
_ => NostrReply::Ok(id, false, NostrReplyPrefix::Error, format!("{}", e)),
|
||||
},
|
||||
};
|
||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn event_inner(&mut self) -> Result<(), Error> {
|
||||
// Delineate the event back out of the session buffer
|
||||
let event = Event::delineate(&self.buffer)?;
|
||||
|
||||
if GLOBALS.config.read().await.verify_events {
|
||||
// Verify the event is valid (id is hash, signature is valid)
|
||||
if let Err(e) = event.verify() {
|
||||
let reply = NostrReply::Ok(
|
||||
event.id(),
|
||||
false,
|
||||
NostrReplyPrefix::Invalid,
|
||||
format!("{}", e),
|
||||
);
|
||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||
return Ok(());
|
||||
return Err(ChorusError::EventIsInvalid(format!("{}", e)).into());
|
||||
}
|
||||
}
|
||||
|
||||
// Screen the event to see if we are willing to accept it
|
||||
if !screen_event(&event, self.user).await? {
|
||||
let prefix = if self.user.is_some() {
|
||||
NostrReplyPrefix::Restricted
|
||||
if self.user.is_some() {
|
||||
return Err(ChorusError::Restricted.into());
|
||||
} else {
|
||||
NostrReplyPrefix::AuthRequired
|
||||
};
|
||||
let reply = NostrReply::Ok(
|
||||
event.id(),
|
||||
false,
|
||||
prefix,
|
||||
"this personal relay only accepts events related to its users".to_owned(),
|
||||
);
|
||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||
return Ok(());
|
||||
return Err(ChorusError::AuthRequired.into());
|
||||
}
|
||||
}
|
||||
|
||||
// Store and index the event
|
||||
let reply = match GLOBALS.store.get().unwrap().store_event(&event) {
|
||||
Ok(offset) => {
|
||||
GLOBALS.new_events.send(offset)?; // advertise the new event
|
||||
NostrReply::Ok(event.id(), true, NostrReplyPrefix::None, "".to_owned())
|
||||
}
|
||||
Err(e) => {
|
||||
if matches!(e.inner, ChorusError::Duplicate) {
|
||||
NostrReply::Ok(event.id(), true, NostrReplyPrefix::Duplicate, "".to_owned())
|
||||
} else {
|
||||
NostrReply::Ok(event.id(), false, NostrReplyPrefix::Error, format!("{e}"))
|
||||
}
|
||||
}
|
||||
};
|
||||
let offset = GLOBALS.store.get().unwrap().store_event(&event)?;
|
||||
GLOBALS.new_events.send(offset)?; // advertise the new event
|
||||
|
||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user