mirror of
https://github.com/scsibug/nostr-rs-relay.git
synced 2024-11-14 06:59:07 -05:00
feat: send notices when authorization checks fail
This commit is contained in:
parent
77f35f9f43
commit
5913b9f87a
|
@ -80,6 +80,7 @@ reject_future_seconds = 1800
|
||||||
# metadata for event authors, "passive" to perform validation but
|
# metadata for event authors, "passive" to perform validation but
|
||||||
# never block publishing, or "disabled" to do nothing.
|
# never block publishing, or "disabled" to do nothing.
|
||||||
#mode = "disabled"
|
#mode = "disabled"
|
||||||
|
mode = "passive"
|
||||||
|
|
||||||
# Domain names that will be prevented from publishing events.
|
# Domain names that will be prevented from publishing events.
|
||||||
#domain_blacklist = ["wellorder.net"]
|
#domain_blacklist = ["wellorder.net"]
|
||||||
|
|
34
src/db.rs
34
src/db.rs
|
@ -27,6 +27,13 @@ use tokio::task;
|
||||||
|
|
||||||
pub type SqlitePool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
pub type SqlitePool = r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
pub type PooledConnection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
pub type PooledConnection = r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
|
|
||||||
|
/// Events submitted from a client, with a return channel for notices
|
||||||
|
pub struct SubmittedEvent {
|
||||||
|
pub event: Event,
|
||||||
|
pub notice_tx: tokio::sync::mpsc::Sender<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Database file
|
/// Database file
|
||||||
pub const DB_FILE: &str = "nostr.db";
|
pub const DB_FILE: &str = "nostr.db";
|
||||||
|
|
||||||
|
@ -76,7 +83,7 @@ pub fn build_conn(flags: OpenFlags) -> Result<Connection> {
|
||||||
|
|
||||||
/// Spawn a database writer that persists events to the SQLite store.
|
/// Spawn a database writer that persists events to the SQLite store.
|
||||||
pub async fn db_writer(
|
pub async fn db_writer(
|
||||||
mut event_rx: tokio::sync::mpsc::Receiver<Event>,
|
mut event_rx: tokio::sync::mpsc::Receiver<SubmittedEvent>,
|
||||||
bcast_tx: tokio::sync::broadcast::Sender<Event>,
|
bcast_tx: tokio::sync::broadcast::Sender<Event>,
|
||||||
metadata_tx: tokio::sync::broadcast::Sender<Event>,
|
metadata_tx: tokio::sync::broadcast::Sender<Event>,
|
||||||
mut shutdown: tokio::sync::broadcast::Receiver<()>,
|
mut shutdown: tokio::sync::broadcast::Receiver<()>,
|
||||||
|
@ -131,18 +138,20 @@ pub async fn db_writer(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut event_write = false;
|
let mut event_write = false;
|
||||||
let event = next_event.unwrap();
|
let subm_event = next_event.unwrap();
|
||||||
|
let event = subm_event.event;
|
||||||
|
let notice_tx = subm_event.notice_tx;
|
||||||
// check if this event is authorized.
|
// check if this event is authorized.
|
||||||
if let Some(allowed_addrs) = whitelist {
|
if let Some(allowed_addrs) = whitelist {
|
||||||
debug!("Checking against pubkey whitelist");
|
|
||||||
// if the event address is not in allowed_addrs.
|
// if the event address is not in allowed_addrs.
|
||||||
if !allowed_addrs.contains(&event.pubkey) {
|
if !allowed_addrs.contains(&event.pubkey) {
|
||||||
info!(
|
info!(
|
||||||
"Rejecting event {}, unauthorized author",
|
"Rejecting event {}, unauthorized author",
|
||||||
event.get_event_id_prefix()
|
event.get_event_id_prefix()
|
||||||
);
|
);
|
||||||
// TODO: define a channel that can send NOTICEs back to the client.
|
notice_tx
|
||||||
|
.try_send("pubkey is not allowed to publish to this relay".to_owned())
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,6 +180,12 @@ pub async fn db_writer(
|
||||||
uv.name.to_string(),
|
uv.name.to_string(),
|
||||||
event.get_author_prefix()
|
event.get_author_prefix()
|
||||||
);
|
);
|
||||||
|
notice_tx
|
||||||
|
.try_send(
|
||||||
|
"NIP-05 verification is no longer valid (expired/wrong domain)"
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,6 +194,9 @@ pub async fn db_writer(
|
||||||
"no verification records found for pubkey: {:?}",
|
"no verification records found for pubkey: {:?}",
|
||||||
event.get_author_prefix()
|
event.get_author_prefix()
|
||||||
);
|
);
|
||||||
|
notice_tx
|
||||||
|
.try_send("NIP-05 verification needed to publish events".to_owned())
|
||||||
|
.ok();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -207,6 +225,12 @@ pub async fn db_writer(
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("event insert failed: {:?}", err);
|
warn!("event insert failed: {:?}", err);
|
||||||
|
notice_tx
|
||||||
|
.try_send(
|
||||||
|
"relay experienced an error trying to publish the latest event"
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -13,6 +13,7 @@ use nostr_rs_relay::close::CloseCmd;
|
||||||
use nostr_rs_relay::config;
|
use nostr_rs_relay::config;
|
||||||
use nostr_rs_relay::conn;
|
use nostr_rs_relay::conn;
|
||||||
use nostr_rs_relay::db;
|
use nostr_rs_relay::db;
|
||||||
|
use nostr_rs_relay::db::SubmittedEvent;
|
||||||
use nostr_rs_relay::error::{Error, Result};
|
use nostr_rs_relay::error::{Error, Result};
|
||||||
use nostr_rs_relay::event::Event;
|
use nostr_rs_relay::event::Event;
|
||||||
use nostr_rs_relay::event::EventCmd;
|
use nostr_rs_relay::event::EventCmd;
|
||||||
|
@ -51,7 +52,7 @@ async fn handle_web_request(
|
||||||
pool: db::SqlitePool,
|
pool: db::SqlitePool,
|
||||||
remote_addr: SocketAddr,
|
remote_addr: SocketAddr,
|
||||||
broadcast: Sender<Event>,
|
broadcast: Sender<Event>,
|
||||||
event_tx: tokio::sync::mpsc::Sender<Event>,
|
event_tx: tokio::sync::mpsc::Sender<SubmittedEvent>,
|
||||||
shutdown: Receiver<()>,
|
shutdown: Receiver<()>,
|
||||||
) -> Result<Response<Body>, Infallible> {
|
) -> Result<Response<Body>, Infallible> {
|
||||||
match (
|
match (
|
||||||
|
@ -232,7 +233,8 @@ fn main() -> Result<(), Error> {
|
||||||
let (bcast_tx, _) = broadcast::channel::<Event>(settings.limits.broadcast_buffer);
|
let (bcast_tx, _) = broadcast::channel::<Event>(settings.limits.broadcast_buffer);
|
||||||
// validated events that need to be persisted are sent to the
|
// validated events that need to be persisted are sent to the
|
||||||
// database on via this channel.
|
// database on via this channel.
|
||||||
let (event_tx, event_rx) = mpsc::channel::<Event>(settings.limits.event_persist_buffer);
|
let (event_tx, event_rx) =
|
||||||
|
mpsc::channel::<SubmittedEvent>(settings.limits.event_persist_buffer);
|
||||||
// establish a channel for letting all threads now about a
|
// establish a channel for letting all threads now about a
|
||||||
// requested server shutdown.
|
// requested server shutdown.
|
||||||
let (invoke_shutdown, shutdown_listen) = broadcast::channel::<()>(1);
|
let (invoke_shutdown, shutdown_listen) = broadcast::channel::<()>(1);
|
||||||
|
@ -359,7 +361,7 @@ async fn nostr_server(
|
||||||
pool: db::SqlitePool,
|
pool: db::SqlitePool,
|
||||||
mut ws_stream: WebSocketStream<Upgraded>,
|
mut ws_stream: WebSocketStream<Upgraded>,
|
||||||
broadcast: Sender<Event>,
|
broadcast: Sender<Event>,
|
||||||
event_tx: tokio::sync::mpsc::Sender<Event>,
|
event_tx: mpsc::Sender<SubmittedEvent>,
|
||||||
mut shutdown: Receiver<()>,
|
mut shutdown: Receiver<()>,
|
||||||
) {
|
) {
|
||||||
// get a broadcast channel for clients to communicate on
|
// get a broadcast channel for clients to communicate on
|
||||||
|
@ -370,6 +372,9 @@ async fn nostr_server(
|
||||||
// Create a channel for receiving query results from the database.
|
// Create a channel for receiving query results from the database.
|
||||||
// we will send out the tx handle to any query we generate.
|
// we will send out the tx handle to any query we generate.
|
||||||
let (query_tx, mut query_rx) = mpsc::channel::<db::QueryResult>(256);
|
let (query_tx, mut query_rx) = mpsc::channel::<db::QueryResult>(256);
|
||||||
|
// Create channel for receiving NOTICEs
|
||||||
|
let (notice_tx, mut notice_rx) = mpsc::channel::<String>(32);
|
||||||
|
|
||||||
// maintain a hashmap of a oneshot channel for active subscriptions.
|
// maintain a hashmap of a oneshot channel for active subscriptions.
|
||||||
// when these subscriptions are cancelled, make a message
|
// when these subscriptions are cancelled, make a message
|
||||||
// available to the executing query so it knows to stop.
|
// available to the executing query so it knows to stop.
|
||||||
|
@ -408,9 +413,12 @@ async fn nostr_server(
|
||||||
// Send a ping
|
// Send a ping
|
||||||
ws_stream.send(Message::Ping(Vec::new())).await.ok();
|
ws_stream.send(Message::Ping(Vec::new())).await.ok();
|
||||||
},
|
},
|
||||||
|
Some(notice_msg) = notice_rx.recv() => {
|
||||||
|
let n = notice_msg.to_string().replace("\"", "");
|
||||||
|
ws_stream.send(Message::Text(format!("[\"NOTICE\",\"{}\"]", n))).await.ok();
|
||||||
|
},
|
||||||
Some(query_result) = query_rx.recv() => {
|
Some(query_result) = query_rx.recv() => {
|
||||||
// database informed us of a query result we asked for
|
// database informed us of a query result we asked for
|
||||||
//let res = EventRes(query_result.sub_id,query_result.event);
|
|
||||||
client_received_event_count += 1;
|
client_received_event_count += 1;
|
||||||
// send a result
|
// send a result
|
||||||
let subesc = query_result.sub_id.replace("\"", "");
|
let subesc = query_result.sub_id.replace("\"", "");
|
||||||
|
@ -474,14 +482,9 @@ async fn nostr_server(
|
||||||
Ok(e) => {
|
Ok(e) => {
|
||||||
let id_prefix:String = e.id.chars().take(8).collect();
|
let id_prefix:String = e.id.chars().take(8).collect();
|
||||||
debug!("successfully parsed/validated event: {:?} from client: {:?}", id_prefix, cid);
|
debug!("successfully parsed/validated event: {:?} from client: {:?}", id_prefix, cid);
|
||||||
// TODO: consider moving some/all
|
// Write this to the database.
|
||||||
// authorization checks here, instead
|
let submit_event = SubmittedEvent { event: e.clone(), notice_tx: notice_tx.clone() };
|
||||||
// of the DB module, so we can send a
|
event_tx.send(submit_event).await.ok();
|
||||||
// proper NOTICE back to the client if
|
|
||||||
// they are unable to write.
|
|
||||||
|
|
||||||
// Write this to the database
|
|
||||||
event_tx.send(e.clone()).await.ok();
|
|
||||||
client_published_event_count += 1;
|
client_published_event_count += 1;
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user