[BREAKING] Switch to database user pubkeys, remove config user pubkeys

This commit is contained in:
Mike Dilger 2025-02-11 08:35:57 +13:00
parent f02c071474
commit cb431b6b00
No known key found for this signature in database
GPG Key ID: 47581A78D4329BA4
6 changed files with 28 additions and 63 deletions

View File

@ -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;
}

View File

@ -23,8 +23,6 @@ pub struct FriendlyConfig {
pub contact: Option<String>,
pub public_key_hex: Option<String>,
pub open_relay: bool,
pub user_hex_keys: Vec<String>,
pub moderator_hex_keys: Vec<String>,
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<Pubkey> = 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<Pubkey> = 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<String>,
pub public_key: Option<Pubkey>,
pub open_relay: bool,
pub user_keys: Vec<Pubkey>,
pub user_hex_keys: Vec<String>,
pub moderator_keys: Vec<Pubkey>,
pub moderator_hex_keys: Vec<String>,
pub verify_events: bool,
pub allow_scraping: bool,
pub allow_scrape_if_limited_to: u32,

View File

@ -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<Option<bool>, 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<Vec<(Pubkey, bool)>, Error
pub fn add_authorized_user(store: &Store, pubkey: Pubkey, moderator: bool) -> Result<(), Error> {
let users = store
.extra_table("users")
.ok_or(Into::<Error>::into(ChorusError::MissingTable(
"users",
)))?;
.ok_or(Into::<Error>::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::<Error>::into(ChorusError::MissingTable(
"users",
)))?;
.ok_or(Into::<Error>::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<Option<bool>, Error> {
let users = store
.extra_table("users")
.ok_or(Into::<Error>::into(ChorusError::MissingTable(
"users",
)))?;
.ok_or(Into::<Error>::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<Vec<(Pubkey, bool)>, Error
let mut output: Vec<(Pubkey, bool)> = Vec::new();
let users = store
.extra_table("users")
.ok_or(Into::<Error>::into(ChorusError::MissingTable(
"users",
)))?;
.ok_or(Into::<Error>::into(ChorusError::MissingTable("users")))?;
let txn = store.read_txn()?;
for i in users.iter(&txn)? {
let (key, val) = i?;

View File

@ -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<Pubkey>) -> 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<Pubkey>) -> 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<Pubkey>) -> EventFlags {
}
}
if GLOBALS.config.read().user_keys.contains(&tagged_pk) {
if crate::is_authorized_user(tagged_pk) {
tags_an_authorized_user = true;
}
}

View File

@ -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<Incoming>) -> Result<AuthData, Error> {
}
// 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");
}

View File

@ -56,12 +56,7 @@ pub async fn check_auth(request: Request<Incoming>) -> Result<Value, Error> {
}
// 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");
}