From 0172e9bdadf19e5669899eaf0e2f7851d48c5808 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Sun, 10 Mar 2024 23:28:41 +0100 Subject: [PATCH] feat: add basic commands for setting up --- Cargo.lock | 7 +++++ Cargo.toml | 1 + src/main.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index fe74be21..c04e7bbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -649,6 +649,7 @@ dependencies = [ "chrono", "dotenv", "futures-util", + "pico-args", "serde", "serde_json", "sqlx", @@ -1617,6 +1618,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.9" diff --git a/Cargo.toml b/Cargo.toml index cadef8ee..02eef84a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ actix-files = "0.6.5" askama_actix = "0.14.0" futures-util = "0.3.30" serde_json = "1.0.114" +pico-args = "0.5.0" diff --git a/src/main.rs b/src/main.rs index 4e541865..29326a9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ use std::env; +use std::io::{stdin, stdout, Write}; +use std::process::exit; use actix_identity::IdentityMiddleware; use actix_session::{storage::CookieSessionStore, SessionMiddleware}; @@ -8,17 +10,106 @@ use dotenv::dotenv; use sqlx::postgres::PgPool; use crate::auth::redirect; +use crate::auth::utils::generate_salt_and_hash_plain_password; +use crate::models::User; + mod auth; mod calendar; mod models; mod endpoints; +pub enum Command { + Migrate, + CreateAdmin +} + +pub struct Args { + command: Option +} + +fn parse_args() -> Result { + let mut pargs = pico_args::Arguments::from_env(); + + let command = pargs.free_from_str::(); + + let mut args = Args { + command: None + }; + + if let Ok(parsed) = command { + match parsed.trim() { + "migrate" => args.command = Some(Command::Migrate), + "createadmin" => args.command = Some(Command::CreateAdmin), + _ => () + } + } + + Ok(args) +} + +fn prompt(prompt: &str) -> anyhow::Result { + print!("{}: ", prompt); + stdout().flush()?; + + let mut input = String::new(); + stdin().read_line(&mut input)?; + + Ok(input.trim().to_string()) +} + #[actix_web::main] async fn main() -> anyhow::Result<()> { dotenv()?; + + let args = match parse_args() { + Ok(v) => v, + Err(err) => { + eprintln!("Error: {err}"); + std::process::exit(1); + } + }; + let pool = PgPool::connect(&env::var("DATABASE_URL")?).await?; let secret_key = Key::generate(); + match args.command { + Some(Command::Migrate) => { + sqlx::migrate!("./migrations") + .run(&pool) + .await?; + + exit(0); + }, + Some(Command::CreateAdmin) => { + let name = prompt("Full name of Admin")?; + let email = prompt("E-Mail of Admin (for login)")?; + let password = prompt("Password of Admin")?; + let retyped_password = prompt("Retype Passsword of Admin")?; + + if password != retyped_password { + eprintln!("Given passwords don't match!"); + exit(1) + } + + let (hash, salt) = generate_salt_and_hash_plain_password("admin")?; + + User::create( + &pool, + &name, + &email, + &hash, + &salt, + models::Role::Admin, + models::Function::Wachhabender, + 1, + ) + .await?; + + exit(0); + }, + None => () + }; + println!("Starting server on http://localhost:8080."); HttpServer::new(move || {