diff --git a/Cargo.lock b/Cargo.lock index 1708ea54..93008322 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,6 +245,14 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "colored" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "comrak" version = "0.2.12" @@ -999,6 +1007,7 @@ dependencies = [ "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "bcrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "comrak 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1998,6 +2007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" +"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum comrak 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "053b26c8ce23b4c505a9479beace98f95899e0bf5c5255cf0219e9b0f48cf6ea" "checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" diff --git a/Cargo.toml b/Cargo.toml index 87c2e879..4f5b0f27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ ammonia = "1.1.0" array_tool = "1.0" base64 = "0.9" bcrypt = "0.2" +colored = "1.6" comrak = "0.2" dotenv = "*" failure = "0.1" diff --git a/src/main.rs b/src/main.rs index 5455d854..3ad26d59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ extern crate array_tool; extern crate base64; extern crate bcrypt; extern crate chrono; +extern crate colored; extern crate comrak; extern crate failure; #[macro_use] @@ -35,18 +36,17 @@ extern crate tera; extern crate url; extern crate webfinger; -use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}}; -use dotenv::dotenv; use rocket_contrib::Template; use std::env; mod activity_pub; mod db_conn; mod models; +mod safe_string; mod schema; +mod setup; mod routes; mod utils; -mod safe_string; lazy_static! { pub static ref BASE_URL: String = env::var("BASE_URL") @@ -56,17 +56,8 @@ lazy_static! { .unwrap_or(format!("postgres://plume:plume@localhost/{}", env::var("DB_NAME").unwrap_or(String::from("plume")))); } -type PgPool = Pool>; - -/// Initializes a database pool. -fn init_pool() -> PgPool { - dotenv().ok(); - - let manager = ConnectionManager::::new(DB_URL.as_str()); - Pool::new(manager).expect("DB pool error") -} - fn main() { + let pool = setup::check(); rocket::ignite() .mount("/", routes![ routes::blogs::details, @@ -133,7 +124,7 @@ fn main() { routes::errors::not_found, routes::errors::server_error ]) - .manage(init_pool()) + .manage(pool) .attach(Template::custom(|engines| { rocket_i18n::tera(&mut engines.tera); })) diff --git a/src/setup.rs b/src/setup.rs new file mode 100644 index 00000000..42bf9855 --- /dev/null +++ b/src/setup.rs @@ -0,0 +1,85 @@ +use colored::Colorize; +use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}}; +use dotenv::dotenv; +use std::io; +use std::process::{exit, Command}; + +use DB_URL; +use db_conn::DbConn; +use models::instance::Instance; + +type PgPool = Pool>; + +/// Initializes a database pool. +fn init_pool() -> Option { + dotenv().ok(); + + let manager = ConnectionManager::::new(DB_URL.as_str()); + Pool::new(manager).ok() +} + +pub fn check() -> PgPool { + if let Some(pool) = init_pool() { + match pool.get() { + Ok(conn) => { + let db_conn = DbConn(conn); + if Instance::get_local(&*db_conn).is_none() { + run_setup(); + } + } + Err(_) => panic!("Couldn't connect to database") + } + pool + } else { + run_setup(); + init_pool().unwrap() + } +} + +fn run_setup() { + println!("\n\n"); + println!("{}\n{}\n{}\n\n{}", + "Welcome in the Plume setup tool.".magenta(), + "It will help you setup your new instance, by asking you a few questions.".magenta(), + "Then you'll be able to enjoy Plume!".magenta(), + "First let's check that you have all the required dependencies. Press Enter to start." + ); + read_line(); + check_native_deps(); +} + +fn check_native_deps() { + let mut not_found = Vec::new(); + if !try_run("psql") { + not_found.push(("PostgreSQL", "sudo apt install postgres")); + } + if !try_run("gettext") { + not_found.push(("GetText", "sudo apt install gettext")) + } + if !try_run("diesel") { + not_found.push(("Diesel CLI", "cargo install diesel_cli")) + } + + if not_found.len() > 0 { + println!("{}\n", "Some native dependencies are missing:".red()); + for (dep, install) in not_found.into_iter() { + println!("{}", format!(" - {} (can be installed with `{}`, on Debian based distributions)", dep, install).red()) + } + println!("\nRetry once you have installed them."); + exit(1); + } else { + println!("{}", "✔️ All native dependencies are present".green()) + } +} + +fn try_run(command: &'static str) -> bool { + Command::new(command) + .output() + .is_ok() +} + +fn read_line() -> String { + let mut input = String::new(); + io::stdin().read_line(&mut input).expect("Unable to read line"); + input +}