2023-02-19 17:56:01 +05:30
|
|
|
use crate::{
|
|
|
|
objects::{person::DbUser, post::DbPost},
|
|
|
|
Error,
|
|
|
|
};
|
|
|
|
use activitypub_federation::config::{FederationConfig, UrlVerifier};
|
2023-03-02 04:49:10 +05:30
|
|
|
use anyhow::anyhow;
|
2023-02-19 17:56:01 +05:30
|
|
|
use async_trait::async_trait;
|
2023-03-02 19:48:06 +05:30
|
|
|
use std::{
|
|
|
|
str::FromStr,
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
};
|
2023-02-19 17:56:01 +05:30
|
|
|
use url::Url;
|
|
|
|
|
2023-06-20 15:24:14 +05:30
|
|
|
pub async fn new_instance(
|
2023-03-02 04:49:10 +05:30
|
|
|
hostname: &str,
|
|
|
|
name: String,
|
|
|
|
) -> Result<FederationConfig<DatabaseHandle>, Error> {
|
2023-06-12 17:02:54 +05:30
|
|
|
let mut system_user = DbUser::new(hostname, "system".into())?;
|
|
|
|
system_user.ap_id = Url::parse(&format!("http://{}/", hostname))?.into();
|
|
|
|
|
2023-03-02 04:49:10 +05:30
|
|
|
let local_user = DbUser::new(hostname, name)?;
|
|
|
|
let database = Arc::new(Database {
|
2023-06-12 17:02:54 +05:30
|
|
|
system_user: system_user.clone(),
|
2023-03-02 04:49:10 +05:30
|
|
|
users: Mutex::new(vec![local_user]),
|
|
|
|
posts: Mutex::new(vec![]),
|
|
|
|
});
|
|
|
|
let config = FederationConfig::builder()
|
|
|
|
.domain(hostname)
|
2023-06-12 17:02:54 +05:30
|
|
|
.signed_fetch_actor(&system_user)
|
2023-03-02 04:49:10 +05:30
|
|
|
.app_data(database)
|
2024-04-09 14:58:22 +05:30
|
|
|
.url_verifier(Box::new(MyUrlVerifier()))
|
2023-03-02 04:49:10 +05:30
|
|
|
.debug(true)
|
2023-06-20 15:24:14 +05:30
|
|
|
.build()
|
|
|
|
.await?;
|
2023-03-02 04:49:10 +05:30
|
|
|
Ok(config)
|
|
|
|
}
|
|
|
|
|
2023-02-19 17:56:01 +05:30
|
|
|
pub type DatabaseHandle = Arc<Database>;
|
|
|
|
|
2023-03-08 03:31:36 +05:30
|
|
|
/// Our "database" which contains all known posts and users (local and federated)
|
2023-02-19 17:56:01 +05:30
|
|
|
pub struct Database {
|
2023-06-12 17:02:54 +05:30
|
|
|
pub system_user: DbUser,
|
2023-02-19 17:56:01 +05:30
|
|
|
pub users: Mutex<Vec<DbUser>>,
|
|
|
|
pub posts: Mutex<Vec<DbPost>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Use this to store your federation blocklist, or a database connection needed to retrieve it.
|
|
|
|
#[derive(Clone)]
|
|
|
|
struct MyUrlVerifier();
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl UrlVerifier for MyUrlVerifier {
|
2023-11-20 16:12:47 +05:30
|
|
|
async fn verify(&self, url: &Url) -> Result<(), activitypub_federation::error::Error> {
|
2023-02-19 17:56:01 +05:30
|
|
|
if url.domain() == Some("malicious.com") {
|
2023-11-20 16:12:47 +05:30
|
|
|
Err(activitypub_federation::error::Error::Other(
|
|
|
|
"malicious domain".into(),
|
|
|
|
))
|
2023-02-19 17:56:01 +05:30
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-02 19:48:06 +05:30
|
|
|
pub enum Webserver {
|
|
|
|
Axum,
|
|
|
|
ActixWeb,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for Webserver {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(match s {
|
|
|
|
"axum" => Webserver::Axum,
|
|
|
|
"actix-web" => Webserver::ActixWeb,
|
|
|
|
_ => panic!("Invalid webserver parameter, must be either `axum` or `actix-web`"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn listen(
|
|
|
|
config: &FederationConfig<DatabaseHandle>,
|
|
|
|
webserver: &Webserver,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
match webserver {
|
|
|
|
Webserver::Axum => crate::axum::http::listen(config)?,
|
|
|
|
Webserver::ActixWeb => crate::actix_web::http::listen(config)?,
|
2023-02-19 17:56:01 +05:30
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Database {
|
|
|
|
pub fn local_user(&self) -> DbUser {
|
|
|
|
let lock = self.users.lock().unwrap();
|
|
|
|
lock.first().unwrap().clone()
|
|
|
|
}
|
2023-03-02 04:49:10 +05:30
|
|
|
|
|
|
|
pub fn read_user(&self, name: &str) -> Result<DbUser, Error> {
|
|
|
|
let db_user = self.local_user();
|
|
|
|
if name == db_user.name {
|
|
|
|
Ok(db_user)
|
|
|
|
} else {
|
|
|
|
Err(anyhow!("Invalid user {name}").into())
|
|
|
|
}
|
|
|
|
}
|
2023-02-19 17:56:01 +05:30
|
|
|
}
|