feat(NIP-42): limit access to kind 4 DMs

This commit is contained in:
rorp 2023-02-25 17:57:04 -08:00 committed by Greg Heartsfield
parent c13961a5c4
commit 8e4e2d824b
3 changed files with 43 additions and 10 deletions

View File

@ -148,6 +148,8 @@ reject_future_seconds = 1800
#]
# Enable NIP-42 authentication
#nip42_auth = false
# Send DMs events (kind 4) only to their authenticated recipients
#nip42_dms = false
[verified_users]
# NIP-05 verification of users. Can be "enabled" to require NIP-05

View File

@ -80,6 +80,7 @@ pub struct Limits {
pub struct Authorization {
pub pubkey_whitelist: Option<Vec<String>>, // If present, only allow these pubkeys to publish events
pub nip42_auth: bool, // if true enables NIP-42 authentication
pub nip42_dms: bool, // if true send DMs only to their authenticated recipients
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -285,6 +286,7 @@ impl Default for Settings {
authorization: Authorization {
pubkey_whitelist: None, // Allow any address to publish
nip42_auth: false, // Disable NIP-42 authentication
nip42_dms: false, // Send DMs to everybody
},
pay_to_relay: PayToRelay {
enabled: false,

View File

@ -1029,6 +1029,31 @@ fn make_notice_message(notice: &Notice) -> Message {
Message::text(json.to_string())
}
fn allowed_to_send(event_str: &String, conn: &conn::ClientConn, settings: &Settings) -> bool {
// TODO: pass in kind so that we can avoid deserialization for most events
if settings.authorization.nip42_dms {
match serde_json::from_str::<Event>(event_str) {
Ok(event) => {
if event.kind == 4 {
match (conn.auth_pubkey(), event.tag_values_by_name("p").first()) {
(Some(auth_pubkey), Some(recipient_pubkey)) => {
recipient_pubkey == auth_pubkey || &event.pubkey == auth_pubkey
},
(_, _) => {
false
},
}
} else {
true
}
},
Err(_) => false
}
} else {
true
}
}
struct ClientInfo {
remote_ip: String,
user_agent: Option<String>,
@ -1151,12 +1176,14 @@ async fn nostr_server(
let send_str = format!("[\"EOSE\",\"{subesc}\"]");
ws_stream.send(Message::Text(send_str)).await.ok();
} else {
client_received_event_count += 1;
if allowed_to_send(&query_result.event, &conn, &settings) {
metrics.sent_events.with_label_values(&["db"]).inc();
client_received_event_count += 1;
// send a result
let send_str = format!("[\"EVENT\",\"{}\",{}]", subesc, &query_result.event);
ws_stream.send(Message::Text(send_str)).await.ok();
}
}
},
// TODO: consider logging the LaggedRecv error
Ok(global_event) = bcast_rx.recv() => {
@ -1169,13 +1196,15 @@ async fn nostr_server(
// TODO: serialize at broadcast time, instead of
// once for each consumer.
if let Ok(event_str) = serde_json::to_string(&global_event) {
if allowed_to_send(&event_str, &conn, &settings) {
// create an event response and send it
trace!("sub match for client: {}, sub: {:?}, event: {:?}",
cid, s,
global_event.get_event_id_prefix());
// create an event response and send it
let subesc = s.replace('"', "");
metrics.sent_events.with_label_values(&["realtime"]).inc();
ws_stream.send(Message::Text(format!("[\"EVENT\",\"{subesc}\",{event_str}]"))).await.ok();
}
} else {
warn!("could not serialize event: {:?}", global_event.get_event_id_prefix());
}