2020-03-20 18:40:18 +00:00
|
|
|
use actix_web::{
|
|
|
|
http::header::{ContentType, Expires},
|
|
|
|
middleware::Logger,
|
|
|
|
web, App, HttpResponse, HttpServer,
|
|
|
|
};
|
2020-03-15 02:05:40 +00:00
|
|
|
use bb8_postgres::tokio_postgres;
|
2020-03-20 18:40:18 +00:00
|
|
|
use log::error;
|
|
|
|
use std::{
|
|
|
|
io::BufWriter,
|
|
|
|
time::{Duration, SystemTime},
|
|
|
|
};
|
2020-03-15 02:05:40 +00:00
|
|
|
|
2020-03-20 00:55:11 +00:00
|
|
|
mod actor;
|
2020-03-15 02:05:40 +00:00
|
|
|
mod apub;
|
2020-03-20 00:55:11 +00:00
|
|
|
mod args;
|
|
|
|
mod config;
|
2020-03-16 17:56:26 +00:00
|
|
|
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;
|
2020-03-16 17:56:26 +00:00
|
|
|
mod notify;
|
2020-03-20 15:22:56 +00:00
|
|
|
mod rehydrate;
|
2020-03-17 17:15:16 +00:00
|
|
|
mod requests;
|
2020-03-20 00:55:11 +00:00
|
|
|
mod responses;
|
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-20 18:40:18 +00:00
|
|
|
use self::{
|
|
|
|
args::Args, config::Config, db::Db, error::MyError, state::State,
|
|
|
|
templates::statics::StaticFile, webfinger::RelayResolver,
|
|
|
|
};
|
2020-03-20 04:06:16 +00:00
|
|
|
|
2020-03-20 18:40:18 +00:00
|
|
|
async fn index(
|
|
|
|
state: web::Data<State>,
|
|
|
|
config: web::Data<Config>,
|
|
|
|
) -> Result<HttpResponse, MyError> {
|
2020-03-20 04:06:16 +00:00
|
|
|
let listeners = state.listeners().await;
|
|
|
|
|
2020-03-20 18:40:18 +00:00
|
|
|
let mut buf = BufWriter::new(Vec::new());
|
|
|
|
|
|
|
|
templates::index(&mut buf, &listeners, &config)?;
|
|
|
|
let buf = buf.into_inner().map_err(|e| {
|
|
|
|
error!("Error rendering template, {}", e.error());
|
|
|
|
MyError::FlushBuffer
|
|
|
|
})?;
|
2020-03-20 04:06:16 +00:00
|
|
|
|
2020-03-20 18:40:18 +00:00
|
|
|
Ok(HttpResponse::Ok().content_type("text/html").body(buf))
|
|
|
|
}
|
|
|
|
|
|
|
|
static FAR: Duration = Duration::from_secs(60 * 60 * 24);
|
|
|
|
|
|
|
|
async fn static_file(filename: web::Path<String>) -> HttpResponse {
|
|
|
|
if let Some(data) = StaticFile::get(&filename.into_inner()) {
|
|
|
|
let far_expires = SystemTime::now() + FAR;
|
|
|
|
HttpResponse::Ok()
|
|
|
|
.set(Expires(far_expires.into()))
|
|
|
|
.set(ContentType(data.mime.clone()))
|
|
|
|
.body(data.content)
|
|
|
|
} else {
|
|
|
|
HttpResponse::NotFound()
|
|
|
|
.reason("No such static file.")
|
|
|
|
.finish()
|
|
|
|
}
|
2020-03-15 02:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::main]
|
|
|
|
async fn main() -> Result<(), anyhow::Error> {
|
|
|
|
dotenv::dotenv().ok();
|
|
|
|
|
2020-03-20 00:55:11 +00:00
|
|
|
let config = Config::build()?;
|
2020-03-15 22:37:53 +00:00
|
|
|
|
2020-03-20 00:55:11 +00:00
|
|
|
if config.debug() {
|
|
|
|
std::env::set_var("RUST_LOG", "debug")
|
|
|
|
} else {
|
|
|
|
std::env::set_var("RUST_LOG", "info")
|
|
|
|
}
|
|
|
|
|
2020-03-20 15:09:42 +00:00
|
|
|
if config.pretty_log() {
|
|
|
|
pretty_env_logger::init();
|
|
|
|
} else {
|
|
|
|
env_logger::init();
|
|
|
|
}
|
2020-03-20 00:55:11 +00:00
|
|
|
|
|
|
|
let pg_config: tokio_postgres::Config = config.database_url().parse()?;
|
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-20 00:55:11 +00:00
|
|
|
let args = Args::new();
|
|
|
|
|
|
|
|
if !args.blocks().is_empty() || !args.whitelists().is_empty() {
|
|
|
|
if args.undo() {
|
|
|
|
db.remove_blocks(args.blocks()).await?;
|
|
|
|
db.remove_whitelists(args.whitelists()).await?;
|
|
|
|
} else {
|
|
|
|
db.add_blocks(args.blocks()).await?;
|
|
|
|
db.add_whitelists(args.whitelists()).await?;
|
|
|
|
}
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let state = State::hydrate(config.clone(), &db).await?;
|
2020-03-15 02:05:40 +00:00
|
|
|
|
2020-03-20 15:22:56 +00:00
|
|
|
rehydrate::spawn(db.clone(), state.clone());
|
|
|
|
|
2020-03-16 17:56:26 +00:00
|
|
|
let _ = notify::NotifyHandler::start_handler(state.clone(), pg_config.clone());
|
|
|
|
|
2020-03-20 00:55:11 +00:00
|
|
|
let bind_address = config.bind_address();
|
2020-03-15 02:05:40 +00:00
|
|
|
HttpServer::new(move || {
|
|
|
|
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-20 00:55:11 +00:00
|
|
|
.data(config.clone())
|
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")
|
2020-03-20 00:55:11 +00:00
|
|
|
.wrap(config.digest_middleware())
|
|
|
|
.wrap(config.signature_middleware(state.requests()))
|
2020-03-16 04:26:31 +00:00
|
|
|
.route(web::post().to(inbox::inbox)),
|
|
|
|
)
|
2020-03-20 00:55:11 +00:00
|
|
|
.service(web::resource("/actor").route(web::get().to(actor::route)))
|
2020-03-20 20:35:08 +00:00
|
|
|
.service(web::resource("/nodeinfo/2.0.json").route(web::get().to(nodeinfo::route)))
|
2020-03-19 19:05:16 +00:00
|
|
|
.service(
|
|
|
|
web::scope("/.well-known")
|
|
|
|
.service(actix_webfinger::scoped::<_, RelayResolver>())
|
|
|
|
.service(web::resource("/nodeinfo").route(web::get().to(nodeinfo::well_known))),
|
|
|
|
)
|
2020-03-20 18:40:18 +00:00
|
|
|
.service(web::resource("/static/{filename}").route(web::get().to(static_file)))
|
2020-03-15 02:05:40 +00:00
|
|
|
})
|
2020-03-20 00:55:11 +00:00
|
|
|
.bind(bind_address)?
|
2020-03-15 02:05:40 +00:00
|
|
|
.run()
|
|
|
|
.await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-03-20 18:40:18 +00:00
|
|
|
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
|