2020-03-15 22:37:53 +00:00
|
|
|
use activitystreams::{actor::apub::Application, context, endpoint::EndpointProperties};
|
2020-03-18 04:35:20 +00:00
|
|
|
use actix_web::{middleware::Logger, web, App, HttpResponse, HttpServer, Responder};
|
2020-03-15 02:05:40 +00:00
|
|
|
use bb8_postgres::tokio_postgres;
|
2020-03-16 04:15:50 +00:00
|
|
|
use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature};
|
2020-03-16 03:36:46 +00:00
|
|
|
use rsa_pem::KeyExt;
|
2020-03-16 04:15:50 +00:00
|
|
|
use sha2::{Digest, Sha256};
|
2020-03-15 02:05:40 +00:00
|
|
|
|
|
|
|
mod apub;
|
2020-03-16 17:56:26 +00:00
|
|
|
mod db;
|
2020-03-15 02:05:40 +00:00
|
|
|
mod db_actor;
|
2020-03-16 03:36:46 +00:00
|
|
|
mod error;
|
2020-03-15 02:05:40 +00:00
|
|
|
mod inbox;
|
|
|
|
mod label;
|
2020-03-16 17:56:26 +00:00
|
|
|
mod notify;
|
2020-03-17 17:15:16 +00:00
|
|
|
mod requests;
|
2020-03-15 02:05:40 +00:00
|
|
|
mod state;
|
2020-03-16 04:15:50 +00:00
|
|
|
mod verifier;
|
2020-03-16 03:36:46 +00:00
|
|
|
mod webfinger;
|
2020-03-15 02:05:40 +00:00
|
|
|
|
2020-03-15 22:37:53 +00:00
|
|
|
use self::{
|
2020-03-16 03:36:46 +00:00
|
|
|
apub::PublicKey,
|
2020-03-18 04:35:20 +00:00
|
|
|
db_actor::Db,
|
2020-03-16 03:36:46 +00:00
|
|
|
error::MyError,
|
2020-03-15 22:37:53 +00:00
|
|
|
label::ArbiterLabelFactory,
|
|
|
|
state::{State, UrlKind},
|
2020-03-16 04:15:50 +00:00
|
|
|
verifier::MyVerify,
|
|
|
|
webfinger::RelayResolver,
|
2020-03-15 22:37:53 +00:00
|
|
|
};
|
2020-03-15 02:05:40 +00:00
|
|
|
|
2020-03-18 05:01:14 +00:00
|
|
|
pub fn ok<T>(item: T) -> HttpResponse
|
2020-03-17 17:15:16 +00:00
|
|
|
where
|
|
|
|
T: serde::ser::Serialize,
|
|
|
|
{
|
|
|
|
HttpResponse::Ok()
|
|
|
|
.content_type("application/activity+json")
|
|
|
|
.json(item)
|
|
|
|
}
|
|
|
|
|
2020-03-18 05:01:14 +00:00
|
|
|
pub fn accepted<T>(item: T) -> HttpResponse
|
|
|
|
where
|
|
|
|
T: serde::ser::Serialize,
|
|
|
|
{
|
|
|
|
HttpResponse::Accepted()
|
|
|
|
.content_type("application/activity+json")
|
|
|
|
.json(item)
|
|
|
|
}
|
|
|
|
|
2020-03-15 02:05:40 +00:00
|
|
|
async fn index() -> impl Responder {
|
|
|
|
"hewwo, mr obama"
|
|
|
|
}
|
|
|
|
|
2020-03-15 22:37:53 +00:00
|
|
|
async fn actor_route(state: web::Data<State>) -> Result<impl Responder, MyError> {
|
|
|
|
let mut application = Application::default();
|
|
|
|
let mut endpoint = EndpointProperties::default();
|
|
|
|
|
2020-03-16 04:44:46 +00:00
|
|
|
endpoint.set_shared_inbox(state.generate_url(UrlKind::Inbox))?;
|
2020-03-15 22:37:53 +00:00
|
|
|
|
|
|
|
application
|
|
|
|
.object_props
|
|
|
|
.set_id(state.generate_url(UrlKind::Actor))?
|
|
|
|
.set_summary_xsd_string("AodeRelay bot")?
|
|
|
|
.set_name_xsd_string("AodeRelay")?
|
|
|
|
.set_url_xsd_any_uri(state.generate_url(UrlKind::Actor))?
|
|
|
|
.set_context_xsd_any_uri(context())?;
|
|
|
|
|
|
|
|
application
|
|
|
|
.ap_actor_props
|
|
|
|
.set_preferred_username("relay")?
|
|
|
|
.set_followers(state.generate_url(UrlKind::Followers))?
|
|
|
|
.set_following(state.generate_url(UrlKind::Following))?
|
|
|
|
.set_inbox(state.generate_url(UrlKind::Inbox))?
|
2020-03-17 13:55:55 +00:00
|
|
|
.set_outbox(state.generate_url(UrlKind::Outbox))?
|
2020-03-15 22:37:53 +00:00
|
|
|
.set_endpoints(endpoint)?;
|
|
|
|
|
2020-03-16 03:36:46 +00:00
|
|
|
let public_key = PublicKey {
|
|
|
|
id: state.generate_url(UrlKind::MainKey).parse()?,
|
|
|
|
owner: state.generate_url(UrlKind::Actor).parse()?,
|
|
|
|
public_key_pem: state.settings.public_key.to_pem_pkcs8()?,
|
|
|
|
};
|
|
|
|
|
2020-03-18 05:01:14 +00:00
|
|
|
Ok(ok(public_key.extend(application)))
|
2020-03-15 22:37:53 +00:00
|
|
|
}
|
|
|
|
|
2020-03-15 02:05:40 +00:00
|
|
|
#[actix_rt::main]
|
|
|
|
async fn main() -> Result<(), anyhow::Error> {
|
|
|
|
dotenv::dotenv().ok();
|
|
|
|
pretty_env_logger::init();
|
|
|
|
|
|
|
|
let pg_config: tokio_postgres::Config = std::env::var("DATABASE_URL")?.parse()?;
|
2020-03-15 22:37:53 +00:00
|
|
|
let hostname: String = std::env::var("HOSTNAME")?;
|
|
|
|
let use_whitelist = std::env::var("USE_WHITELIST").is_ok();
|
|
|
|
let use_https = std::env::var("USE_HTTPS").is_ok();
|
|
|
|
|
2020-03-15 02:05:40 +00:00
|
|
|
let arbiter_labeler = ArbiterLabelFactory::new();
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
let db = Db::new(pg_config.clone());
|
2020-03-15 02:05:40 +00:00
|
|
|
arbiter_labeler.clone().set_label();
|
|
|
|
|
2020-03-18 04:35:20 +00:00
|
|
|
let state: State = db
|
|
|
|
.execute_inline(move |pool| State::hydrate(use_https, use_whitelist, hostname, pool))
|
2020-03-15 02:05:40 +00:00
|
|
|
.await??;
|
|
|
|
|
2020-03-16 17:56:26 +00:00
|
|
|
let _ = notify::NotifyHandler::start_handler(state.clone(), pg_config.clone());
|
|
|
|
|
2020-03-15 02:05:40 +00:00
|
|
|
HttpServer::new(move || {
|
|
|
|
arbiter_labeler.clone().set_label();
|
2020-03-18 04:35:20 +00:00
|
|
|
let state = state.clone();
|
|
|
|
let actor = Db::new(pg_config.clone());
|
2020-03-15 02:05:40 +00:00
|
|
|
|
|
|
|
App::new()
|
2020-03-15 22:37:53 +00:00
|
|
|
.wrap(Logger::default())
|
2020-03-15 02:05:40 +00:00
|
|
|
.data(actor)
|
|
|
|
.data(state.clone())
|
2020-03-18 04:35:20 +00:00
|
|
|
.data(state.requests())
|
2020-03-15 02:05:40 +00:00
|
|
|
.service(web::resource("/").route(web::get().to(index)))
|
2020-03-16 04:26:31 +00:00
|
|
|
.service(
|
|
|
|
web::resource("/inbox")
|
|
|
|
.wrap(VerifyDigest::new(Sha256::new()))
|
|
|
|
.wrap(VerifySignature::new(
|
2020-03-18 04:35:20 +00:00
|
|
|
MyVerify(state.requests()),
|
2020-03-16 04:26:31 +00:00
|
|
|
Default::default(),
|
|
|
|
))
|
|
|
|
.route(web::post().to(inbox::inbox)),
|
|
|
|
)
|
2020-03-15 22:37:53 +00:00
|
|
|
.service(web::resource("/actor").route(web::get().to(actor_route)))
|
2020-03-16 04:15:50 +00:00
|
|
|
.service(actix_webfinger::resource::<_, RelayResolver>())
|
2020-03-15 02:05:40 +00:00
|
|
|
})
|
2020-03-16 23:17:27 +00:00
|
|
|
.bind("0.0.0.0:8080")?
|
2020-03-15 02:05:40 +00:00
|
|
|
.run()
|
|
|
|
.await?;
|
|
|
|
Ok(())
|
|
|
|
}
|