2021-02-13 15:36:39 +00:00
|
|
|
use comunic_server::{cleanup_thread, server};
|
2021-05-08 17:17:33 +00:00
|
|
|
use comunic_server::data::admin::NewAdmin;
|
2020-05-20 17:05:59 +00:00
|
|
|
use comunic_server::data::config::{conf, Config};
|
2021-05-04 17:51:18 +00:00
|
|
|
use comunic_server::data::error::Res;
|
|
|
|
use comunic_server::data::user::UserID;
|
2021-05-08 17:17:33 +00:00
|
|
|
use comunic_server::helpers::{account_helper, admin_account_helper, database};
|
2021-05-04 17:36:31 +00:00
|
|
|
use comunic_server::utils::date_utils::current_year;
|
2020-05-22 06:51:15 +00:00
|
|
|
|
2021-05-04 17:51:18 +00:00
|
|
|
type MainActionFunction = Res;
|
2021-05-04 17:18:47 +00:00
|
|
|
|
|
|
|
struct Action {
|
|
|
|
name: String,
|
|
|
|
description: String,
|
|
|
|
arguments: Vec<String>,
|
2021-05-04 17:51:18 +00:00
|
|
|
function: Box<dyn Fn(Vec<String>) -> MainActionFunction>,
|
2021-05-04 17:36:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn get_actions() -> Vec<Action> {
|
|
|
|
vec![
|
|
|
|
// Start server
|
|
|
|
Action {
|
|
|
|
name: "serve".to_string(),
|
|
|
|
description: "Start the Comunic Server (default action)".to_string(),
|
|
|
|
arguments: vec![],
|
|
|
|
function: Box::new(serve),
|
|
|
|
},
|
|
|
|
|
|
|
|
// Show help
|
|
|
|
Action {
|
|
|
|
name: "help".to_string(),
|
|
|
|
description: "Show this help".to_string(),
|
|
|
|
arguments: vec![],
|
|
|
|
function: Box::new(help),
|
2021-05-04 17:51:18 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Reset password
|
|
|
|
Action {
|
|
|
|
name: "reset_password".to_string(),
|
|
|
|
description: "Create a password reset URL for a user".to_string(),
|
|
|
|
arguments: vec!["user_id".to_string()],
|
|
|
|
function: Box::new(reset_password),
|
2021-05-08 17:17:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Create a new administrator
|
|
|
|
Action {
|
|
|
|
name: "create_admin".to_string(),
|
|
|
|
description: "Create a new administrator account".to_string(),
|
|
|
|
arguments: vec!["name".to_string(), "email".to_string()],
|
|
|
|
function: Box::new(create_admin),
|
|
|
|
},
|
2021-05-08 17:22:47 +00:00
|
|
|
|
|
|
|
// Create a reset token for an admin
|
|
|
|
Action {
|
|
|
|
name: "create_admin_reset_token".to_string(),
|
|
|
|
description: "Create a new reset token to register a new access key to an admin account".to_string(),
|
|
|
|
arguments: vec!["email".to_string()],
|
|
|
|
function: Box::new(create_admin_reset_token),
|
|
|
|
},
|
2021-05-04 17:36:31 +00:00
|
|
|
]
|
2021-05-04 17:18:47 +00:00
|
|
|
}
|
|
|
|
|
2020-05-21 13:28:07 +00:00
|
|
|
#[actix_rt::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
2021-05-04 17:18:47 +00:00
|
|
|
let args: Vec<String> = std::env::args().collect();
|
|
|
|
let conf_file = match args.get(1) {
|
|
|
|
Some(el) => el.to_string(),
|
2021-05-04 17:51:18 +00:00
|
|
|
None => {
|
|
|
|
eprintln!("Please specify configuration file as first argument!");
|
|
|
|
std::process::exit(-3);
|
|
|
|
}
|
2021-02-12 16:35:26 +00:00
|
|
|
};
|
2020-05-20 17:05:59 +00:00
|
|
|
|
|
|
|
// Load configuration
|
2021-02-12 16:35:26 +00:00
|
|
|
Config::load(&conf_file).expect("Could not load configuration!");
|
2020-05-20 17:05:59 +00:00
|
|
|
|
2020-05-21 07:21:58 +00:00
|
|
|
// Connect to the database
|
|
|
|
database::connect(&conf().database).expect("Could not connect to database!");
|
2020-05-20 17:05:59 +00:00
|
|
|
|
2021-05-04 17:18:47 +00:00
|
|
|
// Get selected action
|
|
|
|
let action = args
|
|
|
|
.get(2)
|
|
|
|
.map(|a| a.as_str())
|
|
|
|
.unwrap_or("serve")
|
|
|
|
.to_string();
|
|
|
|
|
2021-05-04 17:36:31 +00:00
|
|
|
let actions = get_actions();
|
|
|
|
|
|
|
|
let selected_action = actions
|
|
|
|
.iter()
|
|
|
|
.filter(|p| p.name.eq(&action))
|
|
|
|
.next();
|
|
|
|
|
|
|
|
let selected_action = match selected_action {
|
|
|
|
None => {
|
|
|
|
eprintln!("Action {} invalid! For more information try 'help'!", action);
|
|
|
|
std::process::exit(-1);
|
|
|
|
}
|
|
|
|
Some(a) => a
|
|
|
|
};
|
|
|
|
|
2021-05-04 17:51:18 +00:00
|
|
|
if !selected_action.arguments.is_empty() && selected_action.arguments.len() + 3 != args.len() {
|
2021-05-04 17:36:31 +00:00
|
|
|
eprintln!("Invalid number of arguments!");
|
|
|
|
std::process::exit(-2);
|
|
|
|
}
|
|
|
|
|
2021-05-05 05:38:40 +00:00
|
|
|
let args = match args.len() {
|
|
|
|
0 | 1 | 2 => vec![],
|
|
|
|
_ => (&args[3..]).to_vec()
|
|
|
|
};
|
2021-05-04 17:51:18 +00:00
|
|
|
|
|
|
|
let res = (selected_action.function)(args.to_vec());
|
|
|
|
res.expect("Failed to execute action!");
|
2021-05-04 17:36:31 +00:00
|
|
|
Ok(())
|
2020-05-20 15:46:05 +00:00
|
|
|
}
|
2021-05-04 17:18:47 +00:00
|
|
|
|
|
|
|
/// Start Comunic Server (main action)
|
2021-05-04 17:51:18 +00:00
|
|
|
fn serve(_a: Vec<String>) -> Res {
|
2021-05-04 17:18:47 +00:00
|
|
|
let t = std::thread::spawn(|| {
|
|
|
|
let sys = actix::System::new("sys");
|
|
|
|
|
|
|
|
let promise = async {
|
|
|
|
// Start cleanup thread
|
|
|
|
cleanup_thread::start().expect("Failed to start cleanup thread!");
|
|
|
|
|
|
|
|
// Start the server
|
|
|
|
server::start_server(conf()).await
|
|
|
|
};
|
|
|
|
|
|
|
|
tokio::runtime::Runtime::new().unwrap().block_on(promise)
|
|
|
|
.expect("Failed to start server!");
|
|
|
|
|
|
|
|
let _ = sys.run();
|
|
|
|
});
|
|
|
|
|
|
|
|
t.join().unwrap();
|
2021-05-04 17:36:31 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-05-04 17:51:18 +00:00
|
|
|
fn help(_a: Vec<String>) -> Res {
|
2021-05-04 17:36:31 +00:00
|
|
|
println!("Comunic API v3 Server - (c) Pierre HUBERT 2012 - {}", current_year());
|
|
|
|
|
2021-05-04 17:51:18 +00:00
|
|
|
|
|
|
|
println!("Usage: {} [conf-file] [action] [args...]", std::env::args().next().unwrap());
|
2021-05-04 17:36:31 +00:00
|
|
|
println!("Available actions:");
|
|
|
|
for action in get_actions() {
|
|
|
|
println!("\t{}\t{} - {}",
|
|
|
|
action.name,
|
|
|
|
action.arguments.iter().map(|s| format!("[{}]", s)).collect::<Vec<String>>().join(" "),
|
|
|
|
action.description
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-05-04 17:51:18 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reset_password(args: Vec<String>) -> Res {
|
|
|
|
let user_id = UserID::new(args[0].parse::<u64>()?);
|
|
|
|
let token = account_helper::generate_password_reset_token(&user_id)?;
|
|
|
|
|
|
|
|
println!("{}", conf().password_reset_url.replace("{TOKEN}", &token));
|
|
|
|
|
2021-05-08 17:17:33 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_admin(args: Vec<String>) -> Res {
|
|
|
|
let new_admin = NewAdmin {
|
|
|
|
name: args[0].to_string(),
|
|
|
|
email: args[1].to_string(),
|
|
|
|
};
|
|
|
|
|
|
|
|
if !mailchecker::is_valid(&new_admin.email) {
|
|
|
|
eprintln!("Specified email address is not valid!");
|
|
|
|
std::process::exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
let id = admin_account_helper::create(&new_admin)
|
|
|
|
.expect("Failed to create account!");
|
|
|
|
|
|
|
|
println!("* New admin ID: {}", id.id());
|
|
|
|
|
2021-05-08 17:22:47 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_admin_reset_token(args: Vec<String>) -> Res {
|
|
|
|
let admin = admin_account_helper::find_admin_by_email(&args[0])
|
|
|
|
.expect("Failed to load admin information!");
|
|
|
|
|
|
|
|
println!("Generate a new reset token for {} ({})", admin.name, admin.email);
|
|
|
|
|
|
|
|
let token = admin_account_helper::create_new_reset_token(admin.id)
|
|
|
|
.expect("Failed to create admin reset token!");
|
|
|
|
|
|
|
|
println!("Reset token: {}", token.token);
|
|
|
|
|
2021-05-04 17:18:47 +00:00
|
|
|
Ok(())
|
|
|
|
}
|