added code for creating new owner accounts, and for dealing with some commandline arguments
This commit is contained in:
parent
34ac3709f7
commit
99ccb14bf2
@ -1,6 +1,8 @@
|
||||
extern crate chrono;
|
||||
extern crate clap;
|
||||
extern crate dotenv;
|
||||
extern crate getrandom;
|
||||
extern crate bcrypt;
|
||||
extern crate base64;
|
||||
|
||||
use std::net::SocketAddr;
|
||||
@ -16,7 +18,11 @@ use hyper::{
|
||||
service::{make_service_fn, service_fn}
|
||||
};
|
||||
use mysql_async::Pool;
|
||||
use mysql_async::prelude::Queryable;
|
||||
|
||||
use dotenv::dotenv;
|
||||
use clap::{Arg, App};
|
||||
use chrono::Utc;
|
||||
|
||||
mod auth;
|
||||
use auth::AuthReason;
|
||||
@ -24,12 +30,19 @@ use auth::AuthReason;
|
||||
mod routes;
|
||||
mod invites;
|
||||
mod channels;
|
||||
|
||||
mod members;
|
||||
use members::Member;
|
||||
|
||||
mod messages;
|
||||
mod http_params;
|
||||
mod perms;
|
||||
mod db_types;
|
||||
|
||||
const NO_ERR: u16 = 0;
|
||||
const CONFIG_ERR: u16 = 1;
|
||||
const SHUTDOWN_ERR: u16 = 2;
|
||||
|
||||
async fn route_dispatcher(pool: &Pool, resp: &mut Response<Body>, meth: &Method, path: &str, params: serde_json::Value) {
|
||||
// At some point we should have some way of hiding this obnoxious complexity
|
||||
use routes::resolve_dynamic_route;
|
||||
@ -109,11 +122,82 @@ async fn shutdown_signal() {
|
||||
.await
|
||||
.expect("Failed to capture ctrl-c signal");
|
||||
}
|
||||
|
||||
async fn start_server(ecode: u16) -> u16 {
|
||||
println!("Servering on localhost:8888");
|
||||
let addr = SocketAddr::from(([127,0,0,1], 8888));
|
||||
let service = make_service_fn(|_conn| async {
|
||||
Ok::<_, Infallible>(service_fn(main_responder))
|
||||
});
|
||||
let server = Server::bind(&addr).serve(service);
|
||||
let graceful_shutdown = server.with_graceful_shutdown(shutdown_signal());
|
||||
|
||||
if let Err(e) = graceful_shutdown.await {
|
||||
eprintln!("Server shutdown error: {}", e);
|
||||
return ecode | SHUTDOWN_ERR;
|
||||
}
|
||||
else {
|
||||
return ecode
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// we're only marking this as async because
|
||||
fn parse_options(eflags: u16) -> (u16, Option<Member>) {
|
||||
use std::env::set_var;
|
||||
let mut potential_owner: Option<Member> = None;
|
||||
|
||||
let args = App::new("Freechat Server")
|
||||
.version("0.1")
|
||||
.author("shockrah")
|
||||
.about("Decentralized chat system")
|
||||
.arg(Arg::with_name("db-url")
|
||||
.short("d")
|
||||
.long("db-url")
|
||||
.value_name("DATABASE URL")
|
||||
.help("Sets the DATABASE URL via an environment variable")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("create-owner")
|
||||
.short("c")
|
||||
.long("create-owner")
|
||||
.value_name("Owner")
|
||||
.help("Creates an account with full permissions in the SQL database."))
|
||||
.arg(Arg::with_name("server")
|
||||
.short("s")
|
||||
.long("server")
|
||||
.help("Starts the API server"))
|
||||
.get_matches();
|
||||
|
||||
if let Some(db_url) = args.value_of("db-url") {
|
||||
set_var("DATABASE_URL", db_url);
|
||||
}
|
||||
|
||||
if let Some(name) = args.value_of("create-owner") {
|
||||
use getrandom::getrandom;
|
||||
|
||||
let mut raw: Vec<u8> = vec![0;64];
|
||||
getrandom(&mut raw).unwrap();
|
||||
let raw_key = base64::encode_config(raw, base64::URL_SAFE);
|
||||
// this we can store in our db as a full string on its own
|
||||
let secret = bcrypt::hash(raw_key, auth::BCRYPT_COST).unwrap();
|
||||
|
||||
potential_owner = Some(Member {
|
||||
// id field is rather meaninglyless since the db takes care of this for us
|
||||
id: 0,
|
||||
secret: secret.to_string(),
|
||||
name: name.to_string(),
|
||||
joindate: Utc::now().timestamp(),
|
||||
status: 0,
|
||||
permissions: std::u64::MAX
|
||||
});
|
||||
}
|
||||
return (eflags, potential_owner);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), u16>{
|
||||
const NO_ERR: u16 = 0;
|
||||
const CONFIG_ERR: u16 = 1;
|
||||
const SHUTDOWN_ERR: u16 = 2;
|
||||
|
||||
let mut main_ret: u16 = 0;
|
||||
// setting up environment variables
|
||||
@ -124,21 +208,30 @@ async fn main() -> Result<(), u16>{
|
||||
main_ret |= CONFIG_ERR;
|
||||
}
|
||||
}
|
||||
if main_ret == NO_ERR {
|
||||
println!("Servering on localhost:8888");
|
||||
let addr = SocketAddr::from(([127,0,0,1], 8888));
|
||||
let service = make_service_fn(|_conn| async {
|
||||
Ok::<_, Infallible>(service_fn(main_responder))
|
||||
});
|
||||
let server = Server::bind(&addr).serve(service);
|
||||
let graceful_shutdown = server.with_graceful_shutdown(shutdown_signal());
|
||||
|
||||
if let Err(e) = graceful_shutdown.await {
|
||||
main_ret |= SHUTDOWN_ERR;
|
||||
eprintln!("Server shutdown error: {}", e);
|
||||
let (opt_res, potential_owner) = parse_options(main_ret);
|
||||
main_ret = opt_res; // pull out the return value from the option parsing stage
|
||||
// create a new owner account if we need to
|
||||
if let Some(owner) = potential_owner {
|
||||
let p = Pool::new(&env::var("DATABASE_URL").unwrap());
|
||||
// TODO: move this logic over to members.rs
|
||||
if let Ok(conn) = p.get_conn().await {
|
||||
let db_res = conn.prep_exec(
|
||||
"INSERT INTO members (secret, name, joindate, status, permissions)
|
||||
VALUES(:secret, :name, :joindate, :status, :permissions)",
|
||||
mysql_async::params!{
|
||||
"secret" => owner.secret,
|
||||
"name" => owner.name,
|
||||
"joindate" => owner.joindate,
|
||||
"status" => owner.status,
|
||||
"permissions" => owner.permissions
|
||||
}).await;
|
||||
}
|
||||
}
|
||||
|
||||
if main_ret == NO_ERR {
|
||||
main_ret = start_server(main_ret).await;
|
||||
}
|
||||
|
||||
if main_ret != 0 {
|
||||
// dumb as heck loggin method here
|
||||
if main_ret & CONFIG_ERR != 0 {println!("ERROR: Config was not setup properly => Missing {{DATABASE_URL}}");}
|
||||
|
Loading…
Reference in New Issue
Block a user