2024-05-27 16:58:51 +02:00
|
|
|
mod server;
|
2024-05-03 04:12:15 +02:00
|
|
|
mod model;
|
|
|
|
mod routes;
|
2024-04-06 18:03:13 +02:00
|
|
|
|
2024-05-03 04:12:15 +02:00
|
|
|
mod errors;
|
2024-05-06 01:09:14 +02:00
|
|
|
mod config;
|
|
|
|
|
|
|
|
#[cfg(feature = "cli")]
|
|
|
|
mod cli;
|
|
|
|
|
2024-04-06 18:03:13 +02:00
|
|
|
#[cfg(feature = "migrations")]
|
|
|
|
mod migrations;
|
|
|
|
|
|
|
|
#[cfg(feature = "migrations")]
|
|
|
|
use sea_orm_migration::MigratorTrait;
|
2024-05-11 22:47:29 +02:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use config::Config;
|
2024-04-06 18:03:13 +02:00
|
|
|
|
2024-03-16 03:29:06 +01:00
|
|
|
use clap::{Parser, Subcommand};
|
2024-04-30 16:48:28 +02:00
|
|
|
use sea_orm::{ConnectOptions, Database};
|
2024-03-16 03:29:06 +01:00
|
|
|
|
2024-03-28 04:52:17 +01:00
|
|
|
pub use errors::UpubResult as Result;
|
2024-04-13 22:31:46 +02:00
|
|
|
use tower_http::{cors::CorsLayer, trace::TraceLayer};
|
2024-03-28 04:52:17 +01:00
|
|
|
|
2024-03-25 05:02:20 +01:00
|
|
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
|
2024-03-16 03:29:06 +01:00
|
|
|
#[derive(Parser)]
|
|
|
|
/// all names were taken
|
2024-05-06 01:09:14 +02:00
|
|
|
struct Args {
|
2024-03-16 03:29:06 +01:00
|
|
|
#[clap(subcommand)]
|
|
|
|
/// command to run
|
2024-05-06 01:09:14 +02:00
|
|
|
command: Mode,
|
2024-03-16 03:29:06 +01:00
|
|
|
|
2024-05-11 22:47:29 +02:00
|
|
|
/// path to config file, leave empty to not use any
|
|
|
|
#[arg(short, long)]
|
|
|
|
config: Option<PathBuf>,
|
|
|
|
|
|
|
|
#[arg(long = "db")]
|
|
|
|
/// database connection uri, overrides config value
|
|
|
|
database: Option<String>,
|
2024-03-16 03:29:06 +01:00
|
|
|
|
2024-05-11 22:47:29 +02:00
|
|
|
#[arg(long)]
|
|
|
|
/// instance base domain, for AP ids, overrides config value
|
|
|
|
domain: Option<String>,
|
2024-03-20 08:56:35 +01:00
|
|
|
|
2024-03-16 03:29:06 +01:00
|
|
|
#[arg(long, default_value_t=false)]
|
|
|
|
/// run with debug level tracing
|
|
|
|
debug: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Subcommand)]
|
2024-05-06 01:09:14 +02:00
|
|
|
enum Mode {
|
2024-03-16 03:29:06 +01:00
|
|
|
/// run fediverse server
|
2024-05-27 06:20:54 +02:00
|
|
|
Serve {
|
|
|
|
#[arg(short, long, default_value="127.0.0.1:3000")]
|
|
|
|
/// addr to bind and serve onto
|
|
|
|
bind: String,
|
|
|
|
},
|
2024-05-11 22:47:29 +02:00
|
|
|
|
|
|
|
/// print current or default configuration
|
|
|
|
Config,
|
2024-03-16 03:29:06 +01:00
|
|
|
|
2024-04-06 18:03:13 +02:00
|
|
|
#[cfg(feature = "migrations")]
|
2024-03-16 03:29:06 +01:00
|
|
|
/// apply database migrations
|
|
|
|
Migrate,
|
2024-03-16 05:46:14 +01:00
|
|
|
|
2024-05-06 01:09:14 +02:00
|
|
|
#[cfg(feature = "cli")]
|
|
|
|
/// run maintenance CLI tasks
|
|
|
|
Cli {
|
|
|
|
#[clap(subcommand)]
|
|
|
|
/// task to run
|
|
|
|
command: cli::CliCommand,
|
2024-04-29 20:53:19 +02:00
|
|
|
},
|
2024-03-16 03:29:06 +01:00
|
|
|
}
|
2024-02-09 17:07:55 +01:00
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
2024-03-15 19:43:29 +01:00
|
|
|
|
2024-05-06 01:09:14 +02:00
|
|
|
let args = Args::parse();
|
2024-03-16 03:29:06 +01:00
|
|
|
|
|
|
|
tracing_subscriber::fmt()
|
|
|
|
.compact()
|
|
|
|
.with_max_level(if args.debug { tracing::Level::DEBUG } else { tracing::Level::INFO })
|
|
|
|
.init();
|
|
|
|
|
2024-05-11 22:47:29 +02:00
|
|
|
let config = Config::load(args.config);
|
|
|
|
|
|
|
|
let database = args.database.unwrap_or(config.datasource.connection_string.clone());
|
|
|
|
let domain = args.domain.unwrap_or(config.instance.domain.clone());
|
|
|
|
|
2024-03-22 17:54:49 +01:00
|
|
|
// TODO can i do connectoptions.into() or .connect() and skip these ugly bindings?
|
2024-05-11 22:47:29 +02:00
|
|
|
let mut opts = ConnectOptions::new(&database);
|
2024-03-22 17:54:49 +01:00
|
|
|
|
2024-03-16 05:45:58 +01:00
|
|
|
opts
|
2024-05-11 22:47:29 +02:00
|
|
|
.sqlx_logging_level(tracing::log::LevelFilter::Debug)
|
|
|
|
.max_connections(config.datasource.max_connections)
|
|
|
|
.min_connections(config.datasource.min_connections)
|
|
|
|
.acquire_timeout(std::time::Duration::from_secs(config.datasource.acquire_timeout_seconds))
|
|
|
|
.connect_timeout(std::time::Duration::from_secs(config.datasource.connect_timeout_seconds))
|
|
|
|
.sqlx_slow_statements_logging_settings(
|
|
|
|
if config.datasource.slow_query_warn_enable { tracing::log::LevelFilter::Warn } else { tracing::log::LevelFilter::Off },
|
|
|
|
std::time::Duration::from_secs(config.datasource.slow_query_warn_seconds)
|
|
|
|
);
|
2024-03-16 05:45:58 +01:00
|
|
|
|
|
|
|
let db = Database::connect(opts)
|
2024-03-16 03:29:06 +01:00
|
|
|
.await.expect("error connecting to db");
|
|
|
|
|
|
|
|
match args.command {
|
2024-04-06 18:03:13 +02:00
|
|
|
#[cfg(feature = "migrations")]
|
2024-05-06 01:09:14 +02:00
|
|
|
Mode::Migrate =>
|
2024-04-30 16:48:28 +02:00
|
|
|
migrations::Migrator::up(&db, None)
|
|
|
|
.await.expect("error applying migrations"),
|
2024-03-16 05:46:14 +01:00
|
|
|
|
2024-05-06 01:09:14 +02:00
|
|
|
#[cfg(feature = "cli")]
|
|
|
|
Mode::Cli { command } =>
|
2024-05-11 22:47:29 +02:00
|
|
|
cli::run(command, db, domain, config)
|
2024-05-06 01:09:14 +02:00
|
|
|
.await.expect("failed running cli task"),
|
2024-04-29 20:53:19 +02:00
|
|
|
|
2024-05-11 22:47:29 +02:00
|
|
|
Mode::Config => println!("{}", toml::to_string_pretty(&config).expect("failed serializing config")),
|
|
|
|
|
2024-05-27 06:20:54 +02:00
|
|
|
Mode::Serve { bind } => {
|
2024-05-11 22:47:29 +02:00
|
|
|
let ctx = server::Context::new(db, domain, config)
|
2024-04-09 04:35:57 +02:00
|
|
|
.await.expect("failed creating server context");
|
|
|
|
|
2024-04-11 00:29:32 +02:00
|
|
|
use routes::activitypub::ActivityPubRouter;
|
|
|
|
use routes::mastodon::MastodonRouter;
|
|
|
|
|
|
|
|
let router = axum::Router::new()
|
|
|
|
.ap_routes()
|
|
|
|
.mastodon_routes() // no-op if mastodon feature is disabled
|
2024-04-13 22:31:46 +02:00
|
|
|
.layer(CorsLayer::permissive())
|
|
|
|
.layer(TraceLayer::new_for_http())
|
2024-04-11 00:29:32 +02:00
|
|
|
.with_state(ctx);
|
2024-04-09 04:35:57 +02:00
|
|
|
|
|
|
|
// run our app with hyper, listening locally on port 3000
|
2024-05-27 06:20:54 +02:00
|
|
|
let listener = tokio::net::TcpListener::bind(bind)
|
2024-04-09 04:35:57 +02:00
|
|
|
.await.expect("could not bind tcp socket");
|
|
|
|
|
|
|
|
axum::serve(listener, router)
|
|
|
|
.await
|
|
|
|
.expect("failed serving application")
|
|
|
|
},
|
2024-03-15 19:43:29 +01:00
|
|
|
}
|
|
|
|
}
|