relay/src/state.rs

193 lines
5.4 KiB
Rust
Raw Normal View History

use crate::{
apub::AcceptedActors,
config::{Config, UrlKind},
db::Db,
error::MyError,
requests::Requests,
};
2020-03-15 02:05:40 +00:00
use activitystreams::primitives::XsdAnyUri;
use actix_web::web;
2020-03-15 02:05:40 +00:00
use futures::try_join;
2020-03-19 22:19:05 +00:00
use log::info;
2020-03-15 16:29:01 +00:00
use lru::LruCache;
2020-03-16 03:36:46 +00:00
use rand::thread_rng;
use rsa::{RSAPrivateKey, RSAPublicKey};
2020-03-15 02:05:40 +00:00
use std::{collections::HashSet, sync::Arc};
2020-03-15 16:29:01 +00:00
use tokio::sync::RwLock;
use ttl_cache::TtlCache;
2020-03-15 02:05:40 +00:00
2020-03-18 04:35:20 +00:00
pub type ActorCache = Arc<RwLock<TtlCache<XsdAnyUri, AcceptedActors>>>;
2020-03-15 02:05:40 +00:00
#[derive(Clone)]
pub struct State {
pub public_key: RSAPublicKey,
private_key: RSAPrivateKey,
config: Config,
2020-03-18 04:35:20 +00:00
actor_cache: ActorCache,
2020-03-15 16:29:01 +00:00
actor_id_cache: Arc<RwLock<LruCache<XsdAnyUri, XsdAnyUri>>>,
2020-03-15 17:49:27 +00:00
blocks: Arc<RwLock<HashSet<String>>>,
whitelists: Arc<RwLock<HashSet<String>>>,
2020-03-15 02:05:40 +00:00
listeners: Arc<RwLock<HashSet<XsdAnyUri>>>,
}
2020-03-16 03:36:46 +00:00
impl State {
2020-03-18 04:35:20 +00:00
pub fn requests(&self) -> Requests {
Requests::new(
self.config.generate_url(UrlKind::MainKey),
self.private_key.clone(),
2020-03-18 04:35:20 +00:00
self.actor_cache.clone(),
format!(
"{} {}",
self.config.software_name(),
self.config.software_version()
),
2020-03-18 04:35:20 +00:00
)
}
pub async fn bust_whitelist(&self, whitelist: &str) {
let hs = self.whitelists.clone();
2020-03-15 22:37:53 +00:00
let mut write_guard = hs.write().await;
write_guard.remove(whitelist);
}
pub async fn bust_block(&self, block: &str) {
let hs = self.blocks.clone();
2020-03-15 22:37:53 +00:00
let mut write_guard = hs.write().await;
write_guard.remove(block);
}
pub async fn bust_listener(&self, inbox: &XsdAnyUri) {
let hs = self.listeners.clone();
2020-03-15 22:37:53 +00:00
let mut write_guard = hs.write().await;
write_guard.remove(inbox);
2020-03-15 22:37:53 +00:00
}
pub async fn listeners_without(&self, inbox: &XsdAnyUri, domain: &str) -> Vec<XsdAnyUri> {
let hs = self.listeners.clone();
let read_guard = hs.read().await;
read_guard
.iter()
.filter_map(|listener| {
if let Some(host) = listener.as_url().host() {
if listener != inbox && host.to_string() != domain {
return Some(listener.clone());
}
}
None
})
.collect()
}
2020-03-15 17:49:27 +00:00
pub async fn is_whitelisted(&self, actor_id: &XsdAnyUri) -> bool {
if !self.config.whitelist_mode() {
2020-03-15 17:49:27 +00:00
return true;
}
let hs = self.whitelists.clone();
if let Some(host) = actor_id.as_url().host() {
let read_guard = hs.read().await;
return read_guard.contains(&host.to_string());
}
false
}
pub async fn is_blocked(&self, actor_id: &XsdAnyUri) -> bool {
let hs = self.blocks.clone();
if let Some(host) = actor_id.as_url().host() {
let read_guard = hs.read().await;
return read_guard.contains(&host.to_string());
}
true
}
pub async fn is_listener(&self, actor_id: &XsdAnyUri) -> bool {
let hs = self.listeners.clone();
let read_guard = hs.read().await;
read_guard.contains(actor_id)
}
2020-03-15 16:29:01 +00:00
pub async fn is_cached(&self, object_id: &XsdAnyUri) -> bool {
let cache = self.actor_id_cache.clone();
let read_guard = cache.read().await;
read_guard.contains(object_id)
2020-03-15 02:05:40 +00:00
}
pub async fn cache(&self, object_id: XsdAnyUri, actor_id: XsdAnyUri) {
2020-03-15 16:29:01 +00:00
let cache = self.actor_id_cache.clone();
2020-03-15 02:05:40 +00:00
2020-03-15 16:29:01 +00:00
let mut write_guard = cache.write().await;
write_guard.put(object_id, actor_id);
2020-03-15 02:05:40 +00:00
}
pub async fn cache_block(&self, host: String) {
2020-03-15 02:05:40 +00:00
let blocks = self.blocks.clone();
let mut write_guard = blocks.write().await;
write_guard.insert(host);
2020-03-15 02:05:40 +00:00
}
pub async fn cache_whitelist(&self, host: String) {
2020-03-15 02:05:40 +00:00
let whitelists = self.whitelists.clone();
let mut write_guard = whitelists.write().await;
write_guard.insert(host);
2020-03-15 02:05:40 +00:00
}
pub async fn cache_listener(&self, listener: XsdAnyUri) {
2020-03-15 02:05:40 +00:00
let listeners = self.listeners.clone();
let mut write_guard = listeners.write().await;
write_guard.insert(listener);
}
pub async fn hydrate(config: Config, db: &Db) -> Result<Self, MyError> {
2020-03-19 22:19:05 +00:00
let f1 = db.hydrate_blocks();
let f2 = db.hydrate_whitelists();
let f3 = db.hydrate_listeners();
2020-03-16 03:36:46 +00:00
let f4 = async move {
if let Some(key) = db.hydrate_private_key().await? {
Ok(key)
} else {
info!("Generating new keys");
let key = web::block(move || {
let mut rng = thread_rng();
RSAPrivateKey::new(&mut rng, 4096)
})
.await?;
db.update_private_key(&key).await?;
Ok(key)
}
};
let (blocks, whitelists, listeners, private_key) = try_join!(f1, f2, f3, f4)?;
let public_key = private_key.to_public_key();
2020-03-15 02:05:40 +00:00
Ok(State {
public_key,
private_key,
config,
2020-03-15 16:29:01 +00:00
actor_cache: Arc::new(RwLock::new(TtlCache::new(1024 * 8))),
actor_id_cache: Arc::new(RwLock::new(LruCache::new(1024 * 8))),
2020-03-15 02:05:40 +00:00
blocks: Arc::new(RwLock::new(blocks)),
whitelists: Arc::new(RwLock::new(whitelists)),
listeners: Arc::new(RwLock::new(listeners)),
})
}
}