From cb431b6b004d1f1867d6723ca81bf687167688a5 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Tue, 11 Feb 2025 08:35:57 +1300 Subject: [PATCH] [BREAKING] Switch to database user pubkeys, remove config user pubkeys --- src/bin/chorus_moderate.rs | 2 +- src/config.rs | 24 ------------------------ src/lib.rs | 23 ++++++++--------------- src/nostr.rs | 32 +++++++++++++++++--------------- src/web/blossom/auth.rs | 3 +-- src/web/management/auth.rs | 7 +------ 6 files changed, 28 insertions(+), 63 deletions(-) diff --git a/src/bin/chorus_moderate.rs b/src/bin/chorus_moderate.rs index 4b464a0..4850eff 100644 --- a/src/bin/chorus_moderate.rs +++ b/src/bin/chorus_moderate.rs @@ -58,7 +58,7 @@ fn main() -> Result<(), Error> { } // Skip if the author is authorized user - if config.user_keys.contains(&event.pubkey()) { + if chorus::is_authorized_user(event.pubkey()) { continue; } diff --git a/src/config.rs b/src/config.rs index 3e7c096..e4a35ac 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,8 +23,6 @@ pub struct FriendlyConfig { pub contact: Option, pub public_key_hex: Option, pub open_relay: bool, - pub user_hex_keys: Vec, - pub moderator_hex_keys: Vec, pub verify_events: bool, pub allow_scraping: bool, pub allow_scrape_if_limited_to: u32, @@ -64,8 +62,6 @@ impl Default for FriendlyConfig { contact: None, public_key_hex: None, open_relay: false, - user_hex_keys: vec![], - moderator_hex_keys: vec![], verify_events: true, allow_scraping: false, allow_scrape_if_limited_to: 100, @@ -107,8 +103,6 @@ impl FriendlyConfig { contact, public_key_hex, open_relay, - user_hex_keys, - moderator_hex_keys, verify_events, allow_scraping, allow_scrape_if_limited_to, @@ -135,16 +129,6 @@ impl FriendlyConfig { public_key = Some(Pubkey::read_hex(pkh.as_bytes())?); }; - let mut user_keys: Vec = Vec::with_capacity(user_hex_keys.len()); - for pkh in user_hex_keys.iter() { - user_keys.push(Pubkey::read_hex(pkh.as_bytes())?); - } - - let mut moderator_keys: Vec = Vec::with_capacity(moderator_hex_keys.len()); - for pkh in moderator_hex_keys.iter() { - moderator_keys.push(Pubkey::read_hex(pkh.as_bytes())?); - } - let hostname = Host::parse(&hostname)?; let server_log_level = @@ -170,10 +154,6 @@ impl FriendlyConfig { contact, public_key, open_relay, - user_keys, - user_hex_keys, - moderator_keys, - moderator_hex_keys, verify_events, allow_scraping, allow_scrape_if_limited_to, @@ -214,10 +194,6 @@ pub struct Config { pub contact: Option, pub public_key: Option, pub open_relay: bool, - pub user_keys: Vec, - pub user_hex_keys: Vec, - pub moderator_keys: Vec, - pub moderator_hex_keys: Vec, pub verify_events: bool, pub allow_scraping: bool, pub allow_scrape_if_limited_to: u32, diff --git a/src/lib.rs b/src/lib.rs index fb06d12..a722524 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -478,7 +478,7 @@ impl WebSocketService { .get_event_by_offset(new_event_offset)?; let event_flags = nostr::event_flags(event, &self.user); - let authorized_user = nostr::authorized_user(&self.user); + let authorized_user = self.user.map(|pk| is_authorized_user(pk)).unwrap_or(false); 'subs: for (subid, filters) in self.subscriptions.iter() { for filter in filters.iter() { @@ -756,8 +756,9 @@ pub fn get_event_approval(store: &Store, id: Id) -> Result, Error> "approved-events", )))?; let txn = store.read_txn()?; - Ok(approved_events.get(&txn, id.as_slice())? - .map(|u| !u.is_empty() && u[0] != 0)) + Ok(approved_events + .get(&txn, id.as_slice())? + .map(|u| !u.is_empty() && u[0] != 0)) } /// Dump all event approval statuses @@ -839,9 +840,7 @@ pub fn dump_pubkey_approvals(store: &Store) -> Result, Error pub fn add_authorized_user(store: &Store, pubkey: Pubkey, moderator: bool) -> Result<(), Error> { let users = store .extra_table("users") - .ok_or(Into::::into(ChorusError::MissingTable( - "users", - )))?; + .ok_or(Into::::into(ChorusError::MissingTable("users")))?; let mut txn = store.write_txn()?; users.put(&mut txn, pubkey.as_slice(), &[moderator as u8])?; txn.commit()?; @@ -852,9 +851,7 @@ pub fn add_authorized_user(store: &Store, pubkey: Pubkey, moderator: bool) -> Re pub fn rm_authorized_user(store: &Store, pubkey: Pubkey) -> Result<(), Error> { let users = store .extra_table("users") - .ok_or(Into::::into(ChorusError::MissingTable( - "users", - )))?; + .ok_or(Into::::into(ChorusError::MissingTable("users")))?; let mut txn = store.write_txn()?; users.delete(&mut txn, pubkey.as_slice())?; txn.commit()?; @@ -865,9 +862,7 @@ pub fn rm_authorized_user(store: &Store, pubkey: Pubkey) -> Result<(), Error> { pub fn get_authorized_user(store: &Store, pubkey: Pubkey) -> Result, Error> { let users = store .extra_table("users") - .ok_or(Into::::into(ChorusError::MissingTable( - "users", - )))?; + .ok_or(Into::::into(ChorusError::MissingTable("users")))?; let txn = store.read_txn()?; Ok(users .get(&txn, pubkey.as_slice())? @@ -879,9 +874,7 @@ pub fn dump_authorized_users(store: &Store) -> Result, Error let mut output: Vec<(Pubkey, bool)> = Vec::new(); let users = store .extra_table("users") - .ok_or(Into::::into(ChorusError::MissingTable( - "users", - )))?; + .ok_or(Into::::into(ChorusError::MissingTable("users")))?; let txn = store.read_txn()?; for i in users.iter(&txn)? { let (key, val) = i?; diff --git a/src/nostr.rs b/src/nostr.rs index bd0cc26..446ac27 100644 --- a/src/nostr.rs +++ b/src/nostr.rs @@ -124,7 +124,10 @@ impl WebSocketService { } let user = self.user; - let authorized_user = authorized_user(&user); + let authorized_user = self + .user + .map(|pk| crate::is_authorized_user(pk)) + .unwrap_or(false); if user.is_none() { for filter in filters.iter() { @@ -292,7 +295,10 @@ impl WebSocketService { async fn event_inner(&mut self) -> Result<(), Error> { let user = self.user; - let authorized_user = authorized_user(&user); + let authorized_user = self + .user + .map(|pk| crate::is_authorized_user(pk)) + .unwrap_or(false); // Delineate the event back out of the session buffer let event = unsafe { Event::delineate(&self.buffer)? }; @@ -519,7 +525,10 @@ impl WebSocketService { } let user = self.user; - let authorized_user = authorized_user(&user); + let authorized_user = self + .user + .map(|pk| crate::is_authorized_user(pk)) + .unwrap_or(false); // Find all matching events let mut events: Vec<&Event> = Vec::new(); @@ -742,7 +751,7 @@ async fn screen_incoming_event( } // If the author is one of our users, always accept it - if GLOBALS.config.read().user_keys.contains(&event.pubkey()) { + if crate::is_authorized_user(event.pubkey()) { return Ok(true); } @@ -750,8 +759,8 @@ async fn screen_incoming_event( for mut tag in event.tags()?.iter() { if tag.next() == Some(b"p") { if let Some(value) = tag.next() { - for ukhex in &GLOBALS.config.read().user_hex_keys { - if value == ukhex.as_bytes() { + if let Ok(pk) = Pubkey::read_hex(value) { + if crate::is_authorized_user(pk) { return Ok(true); } } @@ -821,13 +830,6 @@ pub fn screen_outgoing_event( false } -pub fn authorized_user(user: &Option) -> bool { - match user { - None => false, - Some(pk) => GLOBALS.config.read().user_keys.contains(pk), - } -} - pub struct EventFlags { pub author_is_an_authorized_user: bool, pub author_is_current_user: bool, @@ -836,7 +838,7 @@ pub struct EventFlags { } pub fn event_flags(event: &Event, user: &Option) -> EventFlags { - let author_is_an_authorized_user = GLOBALS.config.read().user_keys.contains(&event.pubkey()); + let author_is_an_authorized_user = crate::is_authorized_user(event.pubkey()); let author_is_current_user = match user { None => false, @@ -857,7 +859,7 @@ pub fn event_flags(event: &Event, user: &Option) -> EventFlags { } } - if GLOBALS.config.read().user_keys.contains(&tagged_pk) { + if crate::is_authorized_user(tagged_pk) { tags_an_authorized_user = true; } } diff --git a/src/web/blossom/auth.rs b/src/web/blossom/auth.rs index e481716..7834a72 100644 --- a/src/web/blossom/auth.rs +++ b/src/web/blossom/auth.rs @@ -1,5 +1,4 @@ use crate::error::{ChorusError, Error}; -use crate::globals::GLOBALS; use base64::prelude::*; use http::header::AUTHORIZATION; use hyper::body::Incoming; @@ -68,7 +67,7 @@ fn verify_auth_inner(request: &Request) -> Result { } // Nostr event must be signed by a chorus user - if !GLOBALS.config.read().user_keys.contains(&event.pubkey()) { + if !crate::is_authorized_user(event.pubkey()) { return s_err("You are not an authorized user"); } diff --git a/src/web/management/auth.rs b/src/web/management/auth.rs index a15c091..3e076f7 100644 --- a/src/web/management/auth.rs +++ b/src/web/management/auth.rs @@ -56,12 +56,7 @@ pub async fn check_auth(request: Request) -> Result { } // Nostr event must be signed by a moderator - if !GLOBALS - .config - .read() - .moderator_keys - .contains(&event.pubkey()) - { + if !crate::is_moderator(event.pubkey()) { return s_err("Authorization failed as user is not a moderator"); }