mirror of
https://github.com/mikedilger/chorus.git
synced 2026-05-03 06:51:42 +00:00
Compare commits
No commits in common. "61fcbcf25747eee0699f3e158b9c8f883fed292b" and "72c874ff3708c35ab7ba1fbfdf393bdc38d724ad" have entirely different histories.
61fcbcf257
...
72c874ff37
1284
Cargo.lock
generated
1284
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "chorus"
|
||||
version = "2.0.1"
|
||||
version = "2.0.0"
|
||||
description = "A personal relay for nostr"
|
||||
authors = ["Mike Dilger <mike@mikedilger.com>"]
|
||||
license = "MIT"
|
||||
@ -9,7 +9,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.22"
|
||||
bitcoin_hashes = "0.19"
|
||||
bitcoin_hashes = { version = "0.16", features = [ "bitcoin-io" ] }
|
||||
dashmap = "6"
|
||||
env_logger = "0.11"
|
||||
futures = "0.3"
|
||||
@ -24,12 +24,12 @@ log = "0.4"
|
||||
mime-sniffer = "0.1"
|
||||
mime2ext = "0.1"
|
||||
negentropy = "0.5"
|
||||
pocket-types = { git = "https://github.com/mikedilger/pocket", ref = "43d35015f7caf1db48eb846a1d6916a5716048da" }
|
||||
pocket-db = { git = "https://github.com/mikedilger/pocket", ref = "43d35015f7caf1db48eb846a1d6916a5716048da" }
|
||||
pocket-types = { git = "https://github.com/mikedilger/pocket", branch = "master" }
|
||||
pocket-db = { git = "https://github.com/mikedilger/pocket", branch = "master" }
|
||||
parking_lot = "0.12"
|
||||
rustls-pki-types = "1.11"
|
||||
rustls-pemfile = "2.2"
|
||||
secp256k1 = { version = "0.31", features = [ "hashes", "global-context" ] }
|
||||
secp256k1 = { version = "0.30", features = [ "hashes", "global-context" ] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
speedy = "0.8"
|
||||
|
||||
@ -97,14 +97,6 @@ key_pem_path = "/opt/chorus/etc/tls/privkey.pem"
|
||||
# description = "A default config of the Chorus relay"
|
||||
|
||||
|
||||
# This is a banner URL pointing to an image representing your relay, displayed in the NIP-11
|
||||
# response.
|
||||
#
|
||||
# Default is not set
|
||||
#
|
||||
# banner_url =
|
||||
|
||||
|
||||
# This is an icon URL pointing to an image representing your relay, displayed in the NIP-11
|
||||
# response.
|
||||
#
|
||||
@ -113,20 +105,6 @@ key_pem_path = "/opt/chorus/etc/tls/privkey.pem"
|
||||
# icon_url =
|
||||
|
||||
|
||||
# This is an optional privacy policy as a blob of text (not a URL, not HTML).
|
||||
#
|
||||
# Default is not set
|
||||
#
|
||||
# privacy_policy = ""
|
||||
|
||||
|
||||
# This is an optional terms of service document as a blob of text (not a URL, not HTML).
|
||||
#
|
||||
# Default is not set
|
||||
#
|
||||
# terms_of_service = ""
|
||||
|
||||
|
||||
# This is an optional contact for your relay, displayed in the NIP-11 response.
|
||||
#
|
||||
# Default is not set
|
||||
|
||||
@ -94,22 +94,10 @@ This is an optional description for your relay, displayed in the NIP-11 response
|
||||
|
||||
Default is "A default config of the Chorus relay".
|
||||
|
||||
### banner_url
|
||||
|
||||
This is an optional URL for an graphical banner representing your relay, displayed in the NIP-11 response.
|
||||
|
||||
### icon_url
|
||||
|
||||
This is an optional URL for an graphical icon representing your relay, displayed in the NIP-11 response.
|
||||
|
||||
### privacy_policy
|
||||
|
||||
This is an optional privacy policy as a blob of text (not a URL, not HTML).
|
||||
|
||||
### terms_of_service
|
||||
|
||||
This is an optional terms of service document as a blob of text (not a URL, not HTML).
|
||||
|
||||
### contact
|
||||
|
||||
This is an optional administrative contact for your relay, displayed in the NIP-11 response.
|
||||
|
||||
@ -83,8 +83,7 @@ Go ahead and edit that file to your liking. In particular:
|
||||
- Change the `ip_address` to your internet-accessible IP address (if you are running directly)
|
||||
or to 127.0.0.1 with a local port like 8080 (if you are proxying behind nginx)
|
||||
- Change the port if necessary
|
||||
- Change the name, description, banner_url, icon_url, privacy_policy, terms_of_service and
|
||||
contact (e.g. your email address) as desired
|
||||
- Change the name, description, icon_url and contact (e.g. your email address) as desired
|
||||
- Set your contact_public_key_hex (it is an option, so use `Some()`)
|
||||
- Set hex keys of users for which this relay will act as a personal relay
|
||||
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
2) Users and moderators are now dynamically configured in the database. Use `chorus_cmd` to
|
||||
manage them from the command line:
|
||||
|
||||
* Adding a user: `chorus_cmd <chorus.toml> add_user <pubkey> 0`
|
||||
* Adding a moderator: `chorus_cmd <chorus.toml> add_user <pubkey> 1`
|
||||
* Removing a user or moderator: `chorus_cmd <chorus.toml> rm_user <pubkey>`
|
||||
* Listing users and moderators: `chorus_cmd <chorus.toml> dump_users`
|
||||
* Adding a user: `chorus_cmd add_user <pubkey> 0`
|
||||
* Adding a moderator: `chorus_cmd add_user <pubkey> 1`
|
||||
* Removing a user or moderator: `chorus_cmd rm_user <pubkey>`
|
||||
* Listing users and moderators: `chorus_cmd dump_users`
|
||||
|
||||
3) Remove the following from your config file as these are no longer used:
|
||||
|
||||
|
||||
@ -10,8 +10,6 @@ certchain_pem_path = "tls/fullchain.pem"
|
||||
key_pem_path = "tls/privkey.pem"
|
||||
name = "Chorus Sample"
|
||||
description = "A sample run of the Chorus relay"
|
||||
privacy_policy = "This relay guarantees nothing. Privacy is your concern, not ours."
|
||||
terms_of_service = "This relay guarantees nothing. Use at your own risk."
|
||||
# icon_url =
|
||||
open_relay = false
|
||||
admin_hex_keys = [
|
||||
|
||||
@ -10,7 +10,7 @@ fn main() -> Result<(), Error> {
|
||||
// Get args (config path)
|
||||
let mut args = env::args();
|
||||
if args.len() <= 1 {
|
||||
panic!("USAGE: chorus_cmd <config_path> <command> [args...]");
|
||||
panic!("USAGE: chorus_moderate <config_path>");
|
||||
}
|
||||
let _ = args.next(); // ignore program name
|
||||
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
use chorus::error::Error;
|
||||
use chorus::globals::GLOBALS;
|
||||
use std::env;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Error> {
|
||||
// Get args (config path)
|
||||
let mut args = env::args();
|
||||
if args.len() <= 1 {
|
||||
panic!("USAGE: chorus <config_path>");
|
||||
}
|
||||
let _ = args.next(); // ignore program name
|
||||
let config_path = args.next().unwrap();
|
||||
|
||||
let config = chorus::load_config(&config_path)?;
|
||||
|
||||
chorus::setup_logging(&config);
|
||||
|
||||
// Log host name
|
||||
log::info!(target: "Server", "HOSTNAME = {}", config.hostname);
|
||||
|
||||
chorus::setup_store(&config)?;
|
||||
|
||||
let _ = GLOBALS.store.get().unwrap().sync();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -19,10 +19,7 @@ pub struct FriendlyConfig {
|
||||
pub key_pem_path: String,
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub banner_url: Option<String>,
|
||||
pub icon_url: Option<String>,
|
||||
pub privacy_policy: Option<String>,
|
||||
pub terms_of_service: Option<String>,
|
||||
pub contact: Option<String>,
|
||||
#[serde(alias = "public_key_hex")]
|
||||
pub contact_public_key_hex: Option<String>,
|
||||
@ -63,10 +60,7 @@ impl Default for FriendlyConfig {
|
||||
key_pem_path: "/opt/chorus/etc/tls/privkey.pem".to_string(),
|
||||
name: Some("Chorus Default".to_string()),
|
||||
description: Some("A default config of the Chorus relay".to_string()),
|
||||
banner_url: None,
|
||||
icon_url: None,
|
||||
privacy_policy: None,
|
||||
terms_of_service: None,
|
||||
contact: None,
|
||||
contact_public_key_hex: None,
|
||||
open_relay: false,
|
||||
@ -108,10 +102,7 @@ impl FriendlyConfig {
|
||||
key_pem_path,
|
||||
name,
|
||||
description,
|
||||
banner_url,
|
||||
icon_url,
|
||||
privacy_policy,
|
||||
terms_of_service,
|
||||
contact,
|
||||
contact_public_key_hex,
|
||||
open_relay,
|
||||
@ -168,10 +159,7 @@ impl FriendlyConfig {
|
||||
key_pem_path,
|
||||
name,
|
||||
description,
|
||||
banner_url,
|
||||
icon_url,
|
||||
privacy_policy,
|
||||
terms_of_service,
|
||||
contact,
|
||||
contact_public_key,
|
||||
open_relay,
|
||||
@ -213,10 +201,7 @@ pub struct Config {
|
||||
pub key_pem_path: String,
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub banner_url: Option<String>,
|
||||
pub icon_url: Option<String>,
|
||||
pub privacy_policy: Option<String>,
|
||||
pub terms_of_service: Option<String>,
|
||||
pub contact: Option<String>,
|
||||
pub contact_public_key: Option<Pubkey>,
|
||||
pub open_relay: bool,
|
||||
@ -253,8 +238,6 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Get the URI for our server matching the inner Uri, overridden with either
|
||||
/// our base_url parts or our hostname/port.
|
||||
pub fn uri_parts(&self, inner: Uri, http: bool) -> Result<http::uri::Parts, Error> {
|
||||
let mut uri_parts = inner.into_parts();
|
||||
|
||||
|
||||
34
src/error.rs
34
src/error.rs
@ -45,7 +45,7 @@ pub enum ChorusError {
|
||||
BannedUser,
|
||||
|
||||
// Base64 Decode Error
|
||||
Base64Decode(base64::DecodeError), // 24b
|
||||
Base64Decode(base64::DecodeError),
|
||||
|
||||
// Blocked IP
|
||||
BlockedIp,
|
||||
@ -54,16 +54,16 @@ pub enum ChorusError {
|
||||
BlossomAuthFailure(String),
|
||||
|
||||
// Channel Recv
|
||||
ChannelRecv(tokio::sync::broadcast::error::RecvError), // 24b
|
||||
ChannelRecv(tokio::sync::broadcast::error::RecvError),
|
||||
|
||||
// Channel Send
|
||||
ChannelSend(tokio::sync::broadcast::error::SendError<u64>), // 16b
|
||||
ChannelSend(tokio::sync::broadcast::error::SendError<u64>),
|
||||
|
||||
// Config
|
||||
Config(Box<toml::de::Error>), // 16b
|
||||
Config(toml::de::Error),
|
||||
|
||||
// Crypto
|
||||
Crypto(secp256k1::Error), // 16b
|
||||
Crypto(secp256k1::Error),
|
||||
|
||||
// Closing on error(s)
|
||||
ErrorClose,
|
||||
@ -72,16 +72,16 @@ pub enum ChorusError {
|
||||
EventIsInvalid(String),
|
||||
|
||||
// From hex
|
||||
FromHex(hex::FromHexError), // 24b
|
||||
FromHex(hex::FromHexError),
|
||||
|
||||
// From UTF8
|
||||
FromUtf8(Box<std::string::FromUtf8Error>),
|
||||
FromUtf8(std::string::FromUtf8Error),
|
||||
|
||||
// General
|
||||
General(String),
|
||||
|
||||
// Http
|
||||
Http(Box<hyper::http::Error>),
|
||||
Http(hyper::http::Error),
|
||||
|
||||
// Hyper
|
||||
Hyper(hyper::Error),
|
||||
@ -126,7 +126,7 @@ pub enum ChorusError {
|
||||
PocketDb(pocket_db::Error),
|
||||
|
||||
// Pocket Db Heed Error
|
||||
PocketDbHeed(Box<pocket_db::heed::Error>),
|
||||
PocketDbHeed(pocket_db::heed::Error),
|
||||
|
||||
// Pocket Types Error
|
||||
PocketType(pocket_types::Error),
|
||||
@ -141,7 +141,7 @@ pub enum ChorusError {
|
||||
Restricted,
|
||||
|
||||
// Rustls
|
||||
Rustls(Box<tokio_rustls::rustls::Error>),
|
||||
Rustls(tokio_rustls::rustls::Error),
|
||||
|
||||
// Filter is underspecified
|
||||
Scraper,
|
||||
@ -165,7 +165,7 @@ pub enum ChorusError {
|
||||
TooManySubscriptions,
|
||||
|
||||
// Tungstenite
|
||||
Tungstenite(Box<hyper_tungstenite::tungstenite::error::Error>),
|
||||
Tungstenite(hyper_tungstenite::tungstenite::error::Error),
|
||||
|
||||
// URL Parse
|
||||
UrlParse(url::ParseError),
|
||||
@ -382,7 +382,7 @@ impl From<toml::de::Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: toml::de::Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::Config(Box::new(err)),
|
||||
inner: ChorusError::Config(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
@ -402,7 +402,7 @@ impl From<hyper::http::Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: hyper::http::Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::Http(Box::new(err)),
|
||||
inner: ChorusError::Http(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
@ -472,7 +472,7 @@ impl From<pocket_db::heed::Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: pocket_db::heed::Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::PocketDbHeed(Box::new(err)),
|
||||
inner: ChorusError::PocketDbHeed(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
@ -492,7 +492,7 @@ impl From<tokio_rustls::rustls::Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: tokio_rustls::rustls::Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::Rustls(Box::new(err)),
|
||||
inner: ChorusError::Rustls(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
@ -502,7 +502,7 @@ impl From<hyper_tungstenite::tungstenite::error::Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: hyper_tungstenite::tungstenite::error::Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::Tungstenite(Box::new(err)),
|
||||
inner: ChorusError::Tungstenite(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
@ -572,7 +572,7 @@ impl From<std::string::FromUtf8Error> for Error {
|
||||
#[track_caller]
|
||||
fn from(err: std::string::FromUtf8Error) -> Self {
|
||||
Error {
|
||||
inner: ChorusError::FromUtf8(Box::new(err)),
|
||||
inner: ChorusError::FromUtf8(err),
|
||||
location: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
|
||||
47
src/lib.rs
47
src/lib.rs
@ -180,9 +180,9 @@ async fn handle_http_request(
|
||||
}
|
||||
|
||||
let mut web_socket_config = WebSocketConfig::default();
|
||||
web_socket_config.max_write_buffer_size = 1024 * 1024; // 1 MB
|
||||
web_socket_config.max_write_buffer_size = 1024 * 1024; // 1 MB
|
||||
web_socket_config.max_message_size = Some(1024 * 1024); // 1 MB
|
||||
web_socket_config.max_frame_size = Some(1024 * 1024); // 1 MB
|
||||
web_socket_config.max_frame_size = Some(1024 * 1024); // 1 MB
|
||||
|
||||
let (mut response, websocket) =
|
||||
hyper_tungstenite::upgrade(&mut request, Some(web_socket_config))?;
|
||||
@ -220,7 +220,7 @@ async fn websocket_thread(peer: HashedPeer, websocket: HyperWebsocket, origin: S
|
||||
last_message: Instant::now(),
|
||||
burst_tokens: GLOBALS.config.read().throttling_burst,
|
||||
challenge: TextNonce::new().into_string(),
|
||||
authed_as: Vec::new(),
|
||||
user: None,
|
||||
error_punishment: 0.0,
|
||||
replied: false,
|
||||
negentropy_sub: None,
|
||||
@ -254,30 +254,21 @@ async fn websocket_thread(peer: HashedPeer, websocket: HyperWebsocket, origin: S
|
||||
// Handle the websocket
|
||||
if let Err(e) = ws_service.handle_websocket_stream().await {
|
||||
match e.inner {
|
||||
ChorusError::Tungstenite(ref t) => {
|
||||
match *t.as_ref() {
|
||||
tungstenite::error::Error::Protocol(
|
||||
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake,
|
||||
) => {
|
||||
// So they disconnected ungracefully.
|
||||
// No big deal, still SessionExit::Ok
|
||||
ChorusError::Tungstenite(tungstenite::error::Error::Protocol(
|
||||
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake,
|
||||
)) => {
|
||||
// So they disconnected ungracefully.
|
||||
// No big deal, still SessionExit::Ok
|
||||
msg = "Reset";
|
||||
}
|
||||
ChorusError::Tungstenite(tungstenite::error::Error::Io(ref ioerror)) => {
|
||||
match ioerror.kind() {
|
||||
std::io::ErrorKind::ConnectionReset
|
||||
| std::io::ErrorKind::ConnectionAborted
|
||||
| std::io::ErrorKind::UnexpectedEof => {
|
||||
// no biggie.
|
||||
msg = "Reset";
|
||||
}
|
||||
tungstenite::error::Error::Io(ref ioerror) => {
|
||||
match ioerror.kind() {
|
||||
std::io::ErrorKind::ConnectionReset
|
||||
| std::io::ErrorKind::ConnectionAborted
|
||||
| std::io::ErrorKind::UnexpectedEof => {
|
||||
// no biggie.
|
||||
msg = "Reset";
|
||||
}
|
||||
_ => {
|
||||
log::error!(target: "Client", "{}: {}", peer, e);
|
||||
session_exit = SessionExit::ErrorExit;
|
||||
msg = "Error Exited";
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::error!(target: "Client", "{}: {}", peer, e);
|
||||
session_exit = SessionExit::ErrorExit;
|
||||
@ -365,7 +356,7 @@ struct WebSocketService {
|
||||
pub last_message: Instant,
|
||||
pub burst_tokens: usize,
|
||||
pub challenge: String,
|
||||
pub authed_as: Vec<Pubkey>,
|
||||
pub user: Option<Pubkey>,
|
||||
pub error_punishment: f32,
|
||||
pub replied: bool,
|
||||
pub negentropy_sub: Option<String>,
|
||||
@ -482,8 +473,8 @@ impl WebSocketService {
|
||||
.unwrap()
|
||||
.get_event_by_offset(new_event_offset)?;
|
||||
|
||||
let event_flags = nostr::event_flags(event, self.authed_as.as_slice());
|
||||
let authorized_user = self.authed_as.iter().any(|u| is_authorized_user(*u));
|
||||
let event_flags = nostr::event_flags(event, &self.user);
|
||||
let authorized_user = self.user.map(is_authorized_user).unwrap_or(false);
|
||||
|
||||
'subs: for (subid, filters) in self.subscriptions.iter() {
|
||||
for filter in filters.iter() {
|
||||
|
||||
38
src/nostr.rs
38
src/nostr.rs
@ -124,9 +124,10 @@ impl WebSocketService {
|
||||
return Err(ChorusError::TooManySubscriptions.into());
|
||||
}
|
||||
|
||||
let authorized_user = self.authed_as.iter().any(|u| crate::is_authorized_user(*u));
|
||||
let user = self.user;
|
||||
let authorized_user = self.user.map(crate::is_authorized_user).unwrap_or(false);
|
||||
|
||||
if self.authed_as.is_empty() {
|
||||
if user.is_none() {
|
||||
for filter in filters.iter() {
|
||||
// If any DM kinds were requested, complain.
|
||||
// But if NO kinds were requested, we will just silently not return DMs (elsewhere)
|
||||
@ -162,7 +163,7 @@ impl WebSocketService {
|
||||
|
||||
for filter in filters.iter() {
|
||||
let screen = |event: &Event| -> ScreenResult {
|
||||
let event_flags = event_flags(event, self.authed_as.as_slice());
|
||||
let event_flags = event_flags(event, &user);
|
||||
screen_outgoing_event(event, &event_flags, authorized_user)
|
||||
};
|
||||
let (filter_events, was_redacted) = {
|
||||
@ -316,12 +317,13 @@ impl WebSocketService {
|
||||
}
|
||||
|
||||
async fn event_inner(&mut self) -> Result<(), Error> {
|
||||
let authorized_user = self.authed_as.iter().any(|u| crate::is_authorized_user(*u));
|
||||
let user = self.user;
|
||||
let authorized_user = self.user.map(crate::is_authorized_user).unwrap_or(false);
|
||||
|
||||
// Delineate the event back out of the session buffer
|
||||
let event = unsafe { Event::delineate(&self.buffer)? };
|
||||
|
||||
let event_flags = event_flags(event, self.authed_as.as_slice());
|
||||
let event_flags = event_flags(event, &user);
|
||||
|
||||
if GLOBALS.config.read().verify_events {
|
||||
// Verify the event is valid (id is hash, signature is valid)
|
||||
@ -345,10 +347,10 @@ impl WebSocketService {
|
||||
|
||||
// Screen the event to see if we are willing to accept it
|
||||
if !screen_incoming_event(event, event_flags, authorized_user).await? {
|
||||
if self.authed_as.is_empty() {
|
||||
return Err(ChorusError::AuthRequired.into());
|
||||
} else {
|
||||
if self.user.is_some() {
|
||||
return Err(ChorusError::Restricted.into());
|
||||
} else {
|
||||
return Err(ChorusError::AuthRequired.into());
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +463,7 @@ impl WebSocketService {
|
||||
}
|
||||
|
||||
// They are now authenticated
|
||||
self.authed_as.push(event.pubkey());
|
||||
self.user = Some(event.pubkey());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -540,12 +542,13 @@ impl WebSocketService {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let authorized_user = self.authed_as.iter().any(|u| crate::is_authorized_user(*u));
|
||||
let user = self.user;
|
||||
let authorized_user = self.user.map(crate::is_authorized_user).unwrap_or(false);
|
||||
|
||||
// Find all matching events
|
||||
let mut events: Vec<&Event> = Vec::new();
|
||||
let screen = |event: &Event| -> ScreenResult {
|
||||
let event_flags = event_flags(event, self.authed_as.as_slice());
|
||||
let event_flags = event_flags(event, &user);
|
||||
screen_outgoing_event(event, &event_flags, authorized_user)
|
||||
};
|
||||
let (filter_events, _redacted) = {
|
||||
@ -868,10 +871,13 @@ pub struct EventFlags {
|
||||
pub tags_current_user: bool,
|
||||
}
|
||||
|
||||
pub fn event_flags(event: &Event, authed_as: &[Pubkey]) -> EventFlags {
|
||||
pub fn event_flags(event: &Event, user: &Option<Pubkey>) -> EventFlags {
|
||||
let author_is_an_authorized_user = crate::is_authorized_user(event.pubkey());
|
||||
|
||||
let author_is_current_user = authed_as.iter().any(|u| *u == event.pubkey());
|
||||
let author_is_current_user = match user {
|
||||
None => false,
|
||||
Some(pk) => event.pubkey() == *pk,
|
||||
};
|
||||
|
||||
let mut tags_an_authorized_user = false;
|
||||
let mut tags_current_user = false;
|
||||
@ -881,8 +887,10 @@ pub fn event_flags(event: &Event, authed_as: &[Pubkey]) -> EventFlags {
|
||||
if let Some(b"p") = tag.next() {
|
||||
if let Some(value) = tag.next() {
|
||||
if let Ok(tagged_pk) = Pubkey::read_hex(value) {
|
||||
if authed_as.contains(&tagged_pk) {
|
||||
tags_current_user = true;
|
||||
if let Some(current_user) = user {
|
||||
if *current_user == tagged_pk {
|
||||
tags_current_user = true;
|
||||
}
|
||||
}
|
||||
|
||||
if crate::is_authorized_user(tagged_pk) {
|
||||
|
||||
@ -53,36 +53,6 @@ pub async fn serve_http(
|
||||
|
||||
let uri = request.uri().to_owned();
|
||||
|
||||
if p == "/privacy-policy" {
|
||||
let config = &*GLOBALS.config.read();
|
||||
if let Some(pp) = &config.privacy_policy {
|
||||
let response = Response::builder()
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Headers", "Authorization, *")
|
||||
.header("Access-Control-Allow-Methods", "*")
|
||||
.header("Allow", "OPTIONS, GET, HEAD")
|
||||
.header("Content-Type", "text/plain")
|
||||
.status(StatusCode::OK)
|
||||
.body(Full::new(pp.clone().into()).map_err(|e| e.into()).boxed())?;
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
if p == "/terms-of-service" {
|
||||
let config = &*GLOBALS.config.read();
|
||||
if let Some(tos) = &config.terms_of_service {
|
||||
let response = Response::builder()
|
||||
.header("Access-Control-Allow-Origin", "*")
|
||||
.header("Access-Control-Allow-Headers", "Authorization, *")
|
||||
.header("Access-Control-Allow-Methods", "*")
|
||||
.header("Allow", "OPTIONS, GET, HEAD")
|
||||
.header("Content-Type", "text/plain")
|
||||
.status(StatusCode::OK)
|
||||
.body(Full::new(tos.clone().into()).map_err(|e| e.into()).boxed())?;
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
// Try blossom if enabled
|
||||
if GLOBALS.config.read().blossom_directory.is_some() {
|
||||
match blossom::handle(request).await {
|
||||
|
||||
@ -5,7 +5,6 @@ use crate::ip::HashedPeer;
|
||||
use http_body_util::combinators::BoxBody;
|
||||
use http_body_util::{BodyExt, Full};
|
||||
use hyper::body::Bytes;
|
||||
use hyper::http::uri::Uri;
|
||||
use hyper::{Response, StatusCode};
|
||||
|
||||
pub async fn serve_nip11(peer: HashedPeer) -> Result<Response<BoxBody<Bytes, Error>>, Error> {
|
||||
@ -81,62 +80,24 @@ fn build_rid(config: &Config) -> String {
|
||||
rid.push_str(description);
|
||||
rid.push('\"');
|
||||
}
|
||||
if let Some(banner_url) = &config.banner_url {
|
||||
rid.push(',');
|
||||
rid.push_str("\"banner\":\"");
|
||||
rid.push_str(banner_url);
|
||||
rid.push('\"');
|
||||
}
|
||||
if let Some(icon_url) = &config.icon_url {
|
||||
rid.push(',');
|
||||
rid.push_str("\"icon\":\"");
|
||||
rid.push_str(icon_url);
|
||||
rid.push('\"');
|
||||
}
|
||||
if let Some(pubkey) = &config.contact_public_key {
|
||||
let mut pkh: [u8; 64] = [0; 64];
|
||||
pubkey.write_hex(&mut pkh).unwrap();
|
||||
rid.push(',');
|
||||
rid.push_str("\"pubkey\":\"");
|
||||
rid.push_str(unsafe { std::str::from_utf8_unchecked(pkh.as_slice()) });
|
||||
rid.push('\"');
|
||||
}
|
||||
if let Some(contact) = &config.contact {
|
||||
rid.push(',');
|
||||
rid.push_str("\"contact\":\"");
|
||||
rid.push_str(contact);
|
||||
rid.push('\"');
|
||||
}
|
||||
if config.privacy_policy.is_some() {
|
||||
if let Some(pubkey) = &config.contact_public_key {
|
||||
let mut pkh: [u8; 64] = [0; 64];
|
||||
pubkey.write_hex(&mut pkh).unwrap();
|
||||
rid.push(',');
|
||||
rid.push_str("\"privacy_policy\":\"");
|
||||
let url = match config.uri_parts(
|
||||
Uri::from_static("https://authority-will-be-replaced/privacy-policy"),
|
||||
true,
|
||||
) {
|
||||
Ok(parts) => match Uri::from_parts(parts) {
|
||||
Ok(uri) => format!("{}", uri),
|
||||
Err(_) => "".to_owned(),
|
||||
},
|
||||
Err(_) => "".to_owned(),
|
||||
};
|
||||
rid.push_str(&url);
|
||||
rid.push('\"');
|
||||
}
|
||||
if config.terms_of_service.is_some() {
|
||||
rid.push(',');
|
||||
rid.push_str("\"terms_of_service\":\"");
|
||||
let url = match config.uri_parts(
|
||||
Uri::from_static("https://authority-will-be-replaced/terms-of-service"),
|
||||
true,
|
||||
) {
|
||||
Ok(parts) => match Uri::from_parts(parts) {
|
||||
Ok(uri) => format!("{}", uri),
|
||||
Err(_) => "".to_owned(),
|
||||
},
|
||||
Err(_) => "".to_owned(),
|
||||
};
|
||||
rid.push_str(&url);
|
||||
rid.push_str("\"pubkey\":\"");
|
||||
rid.push_str(unsafe { std::str::from_utf8_unchecked(pkh.as_slice()) });
|
||||
rid.push('\"');
|
||||
}
|
||||
|
||||
|
||||
@ -18,12 +18,6 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ADD ADMIN AS A USER ------------
|
||||
|
||||
echo "Adding user..."
|
||||
PUBKEY=12bb541d03bfc3cab0f4a8e4db28947f60faae6fca4e315eb27f809c6eff9a0b
|
||||
../target/release/chorus_cmd ./config.toml add_user $PUBKEY 0
|
||||
|
||||
# UPLOAD TEST ------------
|
||||
|
||||
FILE="./Example.png"
|
||||
|
||||
3
test_with_relay_tester/.gitignore
vendored
3
test_with_relay_tester/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
data
|
||||
relay-tester
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
# Testing Chorus with relay-tester
|
||||
|
||||
First, git clone https://github.com/mikedilger/relay-tester and build that project
|
||||
(cargo build --release).
|
||||
|
||||
Then copy that target/release/relay-tester binary into this directory.
|
||||
|
||||
Then run from two different shells, in this order:
|
||||
|
||||
shell1: ./test_chorus.sh
|
||||
|
||||
shell2: ./run_relay_tester.sh
|
||||
@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -x relay-tester ] ; then
|
||||
echo "You must build https://github.com/mikedilge/relay-tester and copy the "
|
||||
echo "resultant target/release/relay-tester binary into this directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./relay-tester \
|
||||
ws://localhost:8080/ \
|
||||
nsec16xfd467kyd3xpu9x5u4933u00v73xrl0jyq9rk5ktd9t2j38k20qtwxuj3 \
|
||||
nsec1l50yuf6uxm2l5qxm87fkm56z3m7g88jnfy5s6az5wscxpu5l2yqq6qwk88
|
||||
@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Use ws://localhost:8080/ as the relay url"
|
||||
|
||||
cargo build --release
|
||||
rm -rf ./data/
|
||||
../target/release/chorus_init ./test_chorus.toml
|
||||
../target/release/chorus_cmd ./test_chorus.toml add_user de16d3ed2d5ceb91d33e39dbe30585164e0c19f3f2e2a5b121def086b447a2e5 0
|
||||
../target/release/chorus_cmd ./test_chorus.toml add_user 35d6bbcf17fc31a9c4f7a2f68aa40ad32c8f9de1ae77505dc5eb3722d8b2987d 0
|
||||
../target/release/chorus ./test_chorus.toml
|
||||
@ -1,40 +0,0 @@
|
||||
# See contrib/chorus.toml for a documented config file
|
||||
|
||||
data_directory = "./data"
|
||||
ip_address = "127.0.0.1"
|
||||
port = 8080
|
||||
hostname = "localhost"
|
||||
chorus_is_behind_a_proxy = false
|
||||
use_tls = false
|
||||
certchain_pem_path = "tls/fullchain.pem"
|
||||
key_pem_path = "tls/privkey.pem"
|
||||
name = "Chorus Sample"
|
||||
description = "A sample run of the Chorus relay"
|
||||
#icon_url =
|
||||
open_relay = false
|
||||
admin_hex_keys = [
|
||||
"ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49",
|
||||
|
||||
# npub1mctd8mfdtn4er5e788d7xpv9ze8qcx0n7t32tvfpmmcgddz85tjsuyxe7z
|
||||
"de16d3ed2d5ceb91d33e39dbe30585164e0c19f3f2e2a5b121def086b447a2e5",
|
||||
|
||||
# npub1xhtthnchlsc6n38h5tmg4fq26vkgl80p4em4qhw9avmj9k9jnp7sm78ql6
|
||||
"35d6bbcf17fc31a9c4f7a2f68aa40ad32c8f9de1ae77505dc5eb3722d8b2987d"
|
||||
]
|
||||
verify_events = true
|
||||
allow_scraping = false
|
||||
allow_scrape_if_limited_to = 100
|
||||
allow_scrape_if_max_seconds = 7200
|
||||
max_subscriptions = 128
|
||||
serve_ephemeral = true
|
||||
serve_relay_lists = true
|
||||
server_log_level = "Info"
|
||||
library_log_level = "Info"
|
||||
client_log_level = "Debug"
|
||||
enable_ip_blocking = false
|
||||
minimum_ban_seconds = 1
|
||||
timeout_seconds = 60
|
||||
max_connections_per_ip = 5
|
||||
throttling_bytes_per_second = 131072
|
||||
throttling_burst = 4194304
|
||||
enable_negentropy = true
|
||||
Loading…
x
Reference in New Issue
Block a user