From 54e2cea83b3c200d895df02e15bcee2af32363fa Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 14:08:44 +0100 Subject: [PATCH 01/10] Start a setup script For now, it checks if the instance is ready, and if it is not starts the actual setup script. Only the first actual step of the script, checking for native dependencies, is implemented. --- Cargo.lock | 10 +++++++ Cargo.toml | 1 + src/main.rs | 19 ++++-------- src/setup.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 src/setup.rs 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 +} From 6916abca7e30ddb94f1aee1cd94116cd686fb2a0 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 15:18:40 +0100 Subject: [PATCH 02/10] Complete/simple setup type + Instance creation --- src/setup.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/src/setup.rs b/src/setup.rs index 42bf9855..e154162e 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -1,12 +1,13 @@ use colored::Colorize; use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}}; use dotenv::dotenv; +use std::fs; use std::io; use std::process::{exit, Command}; use DB_URL; use db_conn::DbConn; -use models::instance::Instance; +use models::instance::*; type PgPool = Pool>; @@ -24,19 +25,19 @@ pub fn check() -> PgPool { Ok(conn) => { let db_conn = DbConn(conn); if Instance::get_local(&*db_conn).is_none() { - run_setup(); + run_setup(Some(db_conn)); } } Err(_) => panic!("Couldn't connect to database") } pool } else { - run_setup(); + run_setup(None); init_pool().unwrap() } } -fn run_setup() { +fn run_setup(conn: Option) { println!("\n\n"); println!("{}\n{}\n{}\n\n{}", "Welcome in the Plume setup tool.".magenta(), @@ -46,8 +47,49 @@ fn run_setup() { ); read_line(); check_native_deps(); + setup_type(conn.expect("Couldn't connect to the Plume database")); } +fn setup_type(conn: DbConn) { + println!("\nDo you prefer a simple setup, or to customize everything?\n"); + println!(" 1 - Simple setup"); + println!(" 2 - Complete setup"); + match read_line().as_ref() { + "Simple" | "simple" | "s" | "S" | + "1" => quick_setup(conn), + "Complete" | "complete" | "c" | "C" | + "2" => complete_setup(conn), + x => { + println!("Invalid choice. Choose between '1' or '2'. {}", x); + setup_type(conn); + } + } +} + +fn quick_setup(conn: DbConn) { + println!("What is your instance domain?"); + let domain = read_line(); + write_to_dotenv("BASE_URL", domain); + + println!("\nWhat is your instance name?"); + let name = read_line(); + + let inst = Instance::insert(&*conn, NewInstance { + public_domain: domain, + name: name, + local: true + }); + + create_admin(); +} + +fn complete_setup(conn: DbConn) { + // TODO + quick_setup(conn); +} + +fn create_admin() {} + fn check_native_deps() { let mut not_found = Vec::new(); if !try_run("psql") { @@ -68,7 +110,7 @@ fn check_native_deps() { println!("\nRetry once you have installed them."); exit(1); } else { - println!("{}", "✔️ All native dependencies are present".green()) + println!("{}", " ✔️ All native dependencies are present.".green()) } } @@ -81,5 +123,10 @@ fn try_run(command: &'static str) -> bool { fn read_line() -> String { let mut input = String::new(); io::stdin().read_line(&mut input).expect("Unable to read line"); + input.retain(|c| c != '\n'); input } + +fn write_to_dotenv(var: &'static str, val: String) { + fs::write(".env", format!("{}\n{}={}", fs::read_to_string(".env").expect("Unable to read .env"), var, val)).expect("Unable to write .env"); +} From d00688e5263496a3089737a29c8609e52e71bfc8 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 16:14:52 +0100 Subject: [PATCH 03/10] Admin creation --- Cargo.lock | 12 ++++++++++++ Cargo.toml | 1 + src/main.rs | 1 + src/setup.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93008322..fc705f35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1024,6 +1024,7 @@ dependencies = [ "rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)", + "rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1291,6 +1292,16 @@ dependencies = [ "tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rpassword" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.7" @@ -2120,6 +2131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)" = "" +"checksum rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d127299b02abda51634f14025aec43ae87a7aa7a95202b6a868ec852607d1451" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" diff --git a/Cargo.toml b/Cargo.toml index 4f5b0f27..62865e72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ hyper = "*" lazy_static = "*" openssl = "0.10.6" reqwest = "0.8" +rpassword = "2.0" serde = "*" serde_derive = "1.0" serde_json = "1.0" diff --git a/src/main.rs b/src/main.rs index 3ad26d59..c9b18be1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ extern crate reqwest; extern crate rocket; extern crate rocket_contrib; extern crate rocket_i18n; +extern crate rpassword; extern crate serde; #[macro_use] extern crate serde_derive; diff --git a/src/setup.rs b/src/setup.rs index e154162e..c87fc0f3 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -4,10 +4,12 @@ use dotenv::dotenv; use std::fs; use std::io; use std::process::{exit, Command}; +use rpassword; use DB_URL; use db_conn::DbConn; use models::instance::*; +use models::users::*; type PgPool = Pool>; @@ -48,6 +50,12 @@ fn run_setup(conn: Option) { read_line(); check_native_deps(); setup_type(conn.expect("Couldn't connect to the Plume database")); + + println!("{}\n{}\n{}", + "Your Plume instance is now ready to be used.".magenta(), + "We hope you will enjoy it.".magenta(), + "If you ever encounter a problem, feel free to report it at https://github.com/Plume-org/Plume/issues/".magenta(), + ); } fn setup_type(conn: DbConn) { @@ -69,18 +77,20 @@ fn setup_type(conn: DbConn) { fn quick_setup(conn: DbConn) { println!("What is your instance domain?"); let domain = read_line(); - write_to_dotenv("BASE_URL", domain); + write_to_dotenv("BASE_URL", domain.clone()); println!("\nWhat is your instance name?"); let name = read_line(); - let inst = Instance::insert(&*conn, NewInstance { + let instance = Instance::insert(&*conn, NewInstance { public_domain: domain, name: name, local: true }); - create_admin(); + println!("{}\n", " ✔️ Your instance was succesfully created!".green()); + + create_admin(instance, conn); } fn complete_setup(conn: DbConn) { @@ -88,7 +98,30 @@ fn complete_setup(conn: DbConn) { quick_setup(conn); } -fn create_admin() {} +fn create_admin(instance: Instance, conn: DbConn) { + println!("{}\n\n", "You are now about to create your admin account".magenta()); + + println!("What is your username? (default: admin)"); + let name = read_line_or("admin"); + + println!("What is your email?"); + let email = read_line(); + + println!("What is your password?"); + let password = rpassword::read_password().expect("Couldn't read your password."); + + User::insert(&*conn, NewUser::new_local( + name.clone(), + name, + true, + format!("Admin of {}", instance.name), + email, + User::hash_pass(password), + instance.id + )).update_boxes(&*conn); + + println!("{}\n", " ✔️ Your account was succesfully created!".green()); +} fn check_native_deps() { let mut not_found = Vec::new(); @@ -127,6 +160,15 @@ fn read_line() -> String { input } +fn read_line_or(or: &str) -> String { + let input = read_line(); + if input.len() == 0 { + or.to_string() + } else { + input + } +} + fn write_to_dotenv(var: &'static str, val: String) { fs::write(".env", format!("{}\n{}={}", fs::read_to_string(".env").expect("Unable to read .env"), var, val)).expect("Unable to write .env"); } From f5d70ddfd451355774e534784056ca6583eded13 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 17:29:54 +0100 Subject: [PATCH 04/10] Database setup --- .env | 2 ++ src/setup.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 00000000..ee8fce89 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ + +BASE_URL=plu.me \ No newline at end of file diff --git a/src/setup.rs b/src/setup.rs index c87fc0f3..e171ba26 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -1,8 +1,9 @@ use colored::Colorize; use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}}; use dotenv::dotenv; -use std::fs; +use std::fs::{self, File}; use std::io; +use std::path::Path; use std::process::{exit, Command}; use rpassword; @@ -32,6 +33,7 @@ pub fn check() -> PgPool { } Err(_) => panic!("Couldn't connect to database") } + migrate(); pool } else { run_setup(None); @@ -49,7 +51,8 @@ fn run_setup(conn: Option) { ); read_line(); check_native_deps(); - setup_type(conn.expect("Couldn't connect to the Plume database")); + let conn = setup_db(conn); + setup_type(conn); println!("{}\n{}\n{}", "Your Plume instance is now ready to be used.".magenta(), @@ -58,6 +61,64 @@ fn run_setup(conn: Option) { ); } +fn setup_db(conn: Option) -> DbConn { + match conn { + Some(conn) => conn, + None => { + println!("\n{}\n", "We are going to setup the database.".magenta()); + println!("{}\n", "About to create a new PostgreSQL user named 'plume'".blue()); + Command::new("createuser") + .arg("-d") + .arg("-P") + .arg("plume") + .status() + .map(|s| { + if s.success() { + println!("{}\n", " ✔️ Done".green()); + } + }) + .expect("Couldn't create new user"); + + println!("{}\n", "About to create a new PostgreSQL table named 'plume'".blue()); + Command::new("createdb") + .arg("-O") + .arg("plume") + .arg("plume") + .status() + .map(|s| { + if s.success() { + println!("{}\n", " ✔️ Done".green()); + } + }) + .expect("Couldn't create new table"); + + migrate(); + + init_pool() + .expect("Couldn't init DB pool") + .get() + .map(|c| DbConn(c)) + .expect("Couldn't connect to the database") + } + } +} + +fn migrate() { + println!("{}\n", "Running migrations…".blue()); + Command::new("diesel") + .arg("migration") + .arg("run") + .arg("--database-url") + .arg(DB_URL.as_str()) + .status() + .map(|s| { + if s.success() { + println!("{}\n", " ✔️ Done".green()); + } + }) + .expect("Couldn't run migrations"); +} + fn setup_type(conn: DbConn) { println!("\nDo you prefer a simple setup, or to customize everything?\n"); println!(" 1 - Simple setup"); @@ -170,5 +231,9 @@ fn read_line_or(or: &str) -> String { } fn write_to_dotenv(var: &'static str, val: String) { + if !Path::new(".env").exists() { + File::create(".env").expect("Error while creating .env file"); + } + fs::write(".env", format!("{}\n{}={}", fs::read_to_string(".env").expect("Unable to read .env"), var, val)).expect("Unable to write .env"); } From a2816120519035ce7732757cff3e56196cd39778 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 18:23:26 +0100 Subject: [PATCH 05/10] Complex setup Also generate and save a Rocket secret key, which avoid deconnecting us when restarting the instance Other small improvements --- .env | 6 +++++- .gitignore | 1 + src/setup.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.env b/.env index ee8fce89..c17c78af 100644 --- a/.env +++ b/.env @@ -1,2 +1,6 @@ -BASE_URL=plu.me \ No newline at end of file +BASE_URL=plu.me +ROCKET_SECRET_KEY=7IdEGAf7EL7ehPjLNncCcE+2B0MTiywxDzr8KklU/VA= + +ROCKET_PORT=7878 +ROCKET_ADDRESS=0.0.0.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index a4c7fe2b..925d54ce 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ rls rls translations po/*.po~ +.env diff --git a/src/setup.rs b/src/setup.rs index e171ba26..788929f1 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -53,15 +53,20 @@ fn run_setup(conn: Option) { check_native_deps(); let conn = setup_db(conn); setup_type(conn); + dotenv().ok(); println!("{}\n{}\n{}", "Your Plume instance is now ready to be used.".magenta(), "We hope you will enjoy it.".magenta(), "If you ever encounter a problem, feel free to report it at https://github.com/Plume-org/Plume/issues/".magenta(), ); + + println!("\nPress Enter to start it.\n"); } fn setup_db(conn: Option) -> DbConn { + write_to_dotenv("DB_URL", DB_URL.as_str().to_string()); + match conn { Some(conn) => conn, None => { @@ -78,7 +83,7 @@ fn setup_db(conn: Option) -> DbConn { } }) .expect("Couldn't create new user"); - + println!("{}\n", "About to create a new PostgreSQL table named 'plume'".blue()); Command::new("createdb") .arg("-O") @@ -151,12 +156,29 @@ fn quick_setup(conn: DbConn) { println!("{}\n", " ✔️ Your instance was succesfully created!".green()); + // Generate Rocket secret key. + let key = Command::new("openssl") + .arg("rand") + .arg("-base64") + .arg("32") + .output() + .map(|o| String::from_utf8(o.stdout).expect("Invalid output from openssl")) + .expect("Couldn't generate secret key."); + write_to_dotenv("ROCKET_SECRET_KEY", key); + create_admin(instance, conn); } fn complete_setup(conn: DbConn) { - // TODO quick_setup(conn); + + println!("\nOn which port should Plume listen? (default: 7878)"); + let port = read_line_or("7878"); + write_to_dotenv("ROCKET_PORT", port); + + println!("\nOn which port should Plume listen? (default: 0.0.0.0)"); + let address = read_line_or("0.0.0.0"); + write_to_dotenv("ROCKET_ADDRESS", address); } fn create_admin(instance: Instance, conn: DbConn) { From dd152f260782568dcdc080d745200a6e47c8d0be Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 18:29:34 +0100 Subject: [PATCH 06/10] Remove old configuration code --- src/main.rs | 2 -- src/models/users.rs | 12 ++++++------ src/routes/instance.rs | 25 ------------------------- src/routes/user.rs | 11 +++++------ src/setup.rs | 6 +++--- 5 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/main.rs b/src/main.rs index c9b18be1..57ecff65 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,8 +73,6 @@ fn main() { routes::comments::create, routes::instance::index, - routes::instance::configure, - routes::instance::post_config, routes::instance::shared_inbox, routes::instance::nodeinfo, diff --git a/src/models/users.rs b/src/models/users.rs index 5b5b1c10..66b05b6b 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -485,16 +485,16 @@ impl Signer for User { impl NewUser { /// Creates a new local user pub fn new_local( + conn: &PgConnection, username: String, display_name: String, is_admin: bool, summary: String, email: String, - password: String, - instance_id: i32 - ) -> NewUser { + password: String + ) -> User { let (pub_key, priv_key) = gen_keypair(); - NewUser { + User::insert(conn, NewUser { username: username, display_name: display_name, outbox_url: String::from(""), @@ -503,11 +503,11 @@ impl NewUser { summary: SafeString::new(&summary), email: Some(email), hashed_password: Some(password), - instance_id: instance_id, + instance_id: Instance::local_id(conn), ap_url: String::from(""), public_key: String::from_utf8(pub_key).unwrap(), private_key: Some(String::from_utf8(priv_key).unwrap()), shared_inbox_url: None - } + }) } } diff --git a/src/routes/instance.rs b/src/routes/instance.rs index be1deb42..c8688dc7 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -33,31 +33,6 @@ fn index(conn: DbConn, user: Option) -> Template { } } -#[get("/configure")] -fn configure() -> Template { - Template::render("instance/configure", json!({})) -} - -#[derive(FromForm)] -struct NewInstanceForm { - name: String -} - -#[post("/configure", data = "")] -fn post_config(conn: DbConn, data: Form) -> Redirect { - let form = data.get(); - let inst = Instance::insert(&*conn, NewInstance { - public_domain: BASE_URL.as_str().to_string(), - name: form.name.to_string(), - local: true - }); - if inst.has_admin(&*conn) { - Redirect::to("/") - } else { - Redirect::to("/users/new") - } -} - #[post("/inbox", data = "")] fn shared_inbox(conn: DbConn, data: String) -> String { let act: serde_json::Value = serde_json::from_str(&data[..]).unwrap(); diff --git a/src/routes/user.rs b/src/routes/user.rs index 6b925c87..da0554fc 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -164,7 +164,6 @@ struct NewUserForm { #[post("/users/new", data = "")] fn create(conn: DbConn, data: Form) -> Result { - let inst = Instance::get_local(&*conn).unwrap(); let form = data.get(); if form.username.clone().len() < 1 { @@ -174,15 +173,15 @@ fn create(conn: DbConn, data: Form) -> Result { } else if form.password.clone().len() < 8 { Err(String::from("Password should be at least 8 characters long")) } else if form.password == form.password_confirmation { - User::insert(&*conn, NewUser::new_local( + NewUser::new_local( + &*conn, form.username.to_string(), form.username.to_string(), - !inst.has_admin(&*conn), + false, String::from(""), form.email.to_string(), - User::hash_pass(form.password.to_string()), - inst.id - )).update_boxes(&*conn); + User::hash_pass(form.password.to_string()) + ).update_boxes(&*conn); Ok(Redirect::to(format!("/@/{}/", data.get().username))) } else { Err(String::from("Passwords don't match")) diff --git a/src/setup.rs b/src/setup.rs index 788929f1..43fa6f8d 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -193,15 +193,15 @@ fn create_admin(instance: Instance, conn: DbConn) { println!("What is your password?"); let password = rpassword::read_password().expect("Couldn't read your password."); - User::insert(&*conn, NewUser::new_local( + NewUser::new_local( + &*conn, name.clone(), name, true, format!("Admin of {}", instance.name), email, User::hash_pass(password), - instance.id - )).update_boxes(&*conn); + ).update_boxes(&*conn); println!("{}\n", " ✔️ Your account was succesfully created!".green()); } From 7455a7cafbb88bf3efe637be9d2e5c5b44fc6e0f Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 18:35:38 +0100 Subject: [PATCH 07/10] Update installation documentation --- DEVELOPMENT.md | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index c82d7db0..391f3a72 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -42,46 +42,16 @@ Now, you can use the following command to start Postgres on a one-time basis. pg_ctl -D /usr/local/var/postgres start ``` -After starting Postgres, we need to enter [PSQL](http://postgresguide.com/utilities/psql.html), the interactive terminal for running postgres queries. We'll be running this as the user `postgres` which is an admin-type postgres user. - -``` -psql postgres -``` - -Now that you are in psql, enter the following queries to prepare the database for Plume. - -``` -CREATE DATABASE plume; -CREATE USER plume WITH PASSWORD 'plume'; -GRANT ALL PRIVILEGES ON DATABASE plume to plume; -\q -``` - -The final command `\q` lets us exit psql and returns us to the Terminal. Now, we will open psql again, this time as the `plume` user we just created. Then we'll give all privileges on all tables and sequences to our `plume` user. This is for local development use only and it's not recommend to give complete access to this user in a production environment. - -``` -psql plume -GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO plume; -GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO plume; -\q -``` +When you will launch Plume for the first time, it will setup the database by itself. #### Database Migration -Now that the Postgres database is set up and the `plume` user has the privileges it needs, we can set up the database using the diesel CLI. If this was your time installing Rust, you -will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. +To run migrations and correctly setup the database, Plume use the `diesel` CLI tool under the hood. Therefore you should install it before running Plume. If this was your time installing Rust, you will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. ``` cargo install diesel_cli ``` -The first time you run this, you can run setup. After that, every time you pull the repository you will want to run the migration command in case there were any migrations. Those commands are - -``` -diesel setup --database-url='postgres://localhost/plume' -diesel migration run --database-url='postgres://localhost/plume' -``` - #### Running Plume To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command @@ -92,7 +62,7 @@ cargo run #### Configuration -Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configure](http://localhost:8000/configure) page. You'll be able to change this name later. +The first time you'll run Plume, it will help you setup your instance through an interactive tool. Once you'll have answered all its question, your instance will start. #### Testing the federation From 554deb3ec06d3ef5f8da1d0788501c1f6f288a99 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 18:40:30 +0100 Subject: [PATCH 08/10] Remove some unused imports --- src/routes/instance.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/routes/instance.rs b/src/routes/instance.rs index c8688dc7..9463511f 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -1,9 +1,7 @@ use gettextrs::gettext; -use rocket::{request::Form, response::Redirect}; use rocket_contrib::{Json, Template}; use serde_json; -use BASE_URL; use activity_pub::inbox::Inbox; use db_conn::DbConn; use models::{ From 43034be4f6dd93b92c8619e1107cf7b3aae72c75 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 19 Jun 2018 22:26:54 +0100 Subject: [PATCH 09/10] Remove .env --- .env | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index c17c78af..00000000 --- a/.env +++ /dev/null @@ -1,6 +0,0 @@ - -BASE_URL=plu.me -ROCKET_SECRET_KEY=7IdEGAf7EL7ehPjLNncCcE+2B0MTiywxDzr8KklU/VA= - -ROCKET_PORT=7878 -ROCKET_ADDRESS=0.0.0.0 \ No newline at end of file From d6121735339059c800666fe9af21d60bbf73abc9 Mon Sep 17 00:00:00 2001 From: Bat Date: Wed, 20 Jun 2018 09:04:29 +0100 Subject: [PATCH 10/10] Fix some error in the messages of the setup script port -> address table -> database --- src/setup.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setup.rs b/src/setup.rs index 43fa6f8d..da366d09 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -84,7 +84,7 @@ fn setup_db(conn: Option) -> DbConn { }) .expect("Couldn't create new user"); - println!("{}\n", "About to create a new PostgreSQL table named 'plume'".blue()); + println!("{}\n", "About to create a new PostgreSQL database named 'plume'".blue()); Command::new("createdb") .arg("-O") .arg("plume") @@ -176,7 +176,7 @@ fn complete_setup(conn: DbConn) { let port = read_line_or("7878"); write_to_dotenv("ROCKET_PORT", port); - println!("\nOn which port should Plume listen? (default: 0.0.0.0)"); + println!("\nOn which address should Plume listen? (default: 0.0.0.0)"); let address = read_line_or("0.0.0.0"); write_to_dotenv("ROCKET_ADDRESS", address); }