relay/src/main.rs

132 lines
4 KiB
Rust
Raw Normal View History

2020-03-18 22:49:56 +00:00
use activitystreams::{
actor::Application, context, endpoint::EndpointProperties, ext::Extensible,
2020-03-19 17:09:33 +00:00
object::properties::ObjectProperties, security,
2020-03-18 22:49:56 +00:00
};
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;
mod db;
2020-03-16 03:36:46 +00:00
mod error;
2020-03-15 02:05:40 +00:00
mod inbox;
2020-03-19 19:05:16 +00:00
mod nodeinfo;
mod notify;
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-19 22:19:05 +00:00
db::Db,
2020-03-16 03:36:46 +00:00
error::MyError,
2020-03-15 22:37:53 +00:00
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
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> {
2020-03-18 22:49:56 +00:00
let mut application = Application::full();
2020-03-15 22:37:53 +00:00
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
2020-03-18 22:49:56 +00:00
let props: &mut ObjectProperties = application.as_mut();
props
2020-03-15 22:37:53 +00:00
.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))?
2020-03-19 17:09:33 +00:00
.set_many_context_xsd_any_uris(vec![context(), security()])?;
2020-03-15 22:37:53 +00:00
application
2020-03-18 22:49:56 +00:00
.extension
2020-03-15 22:37:53 +00:00
.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-19 01:57:39 +00:00
Ok(ok(application.extend(public_key.to_ext())))
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-19 22:19:05 +00:00
let db = Db::build(pg_config.clone()).await?;
2020-03-15 02:05:40 +00:00
2020-03-19 22:19:05 +00:00
let state = State::hydrate(use_https, use_whitelist, hostname, &db).await?;
2020-03-15 02:05:40 +00:00
let _ = notify::NotifyHandler::start_handler(state.clone(), pg_config.clone());
2020-03-15 02:05:40 +00:00
HttpServer::new(move || {
2020-03-18 04:35:20 +00:00
let state = state.clone();
2020-03-15 02:05:40 +00:00
App::new()
2020-03-15 22:37:53 +00:00
.wrap(Logger::default())
2020-03-19 22:19:05 +00:00
.data(db.clone())
2020-03-15 02:05:40 +00:00
.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)))
.service(
web::resource("/inbox")
.wrap(VerifyDigest::new(Sha256::new()))
.wrap(VerifySignature::new(
2020-03-18 04:35:20 +00:00
MyVerify(state.requests()),
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-19 19:05:16 +00:00
.service(web::resource("/nodeinfo/2.0").route(web::get().to(nodeinfo::route)))
.service(
web::scope("/.well-known")
.service(actix_webfinger::scoped::<_, RelayResolver>())
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))),
)
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(())
}