use std::convert::TryFrom; use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; use structopt::StructOpt; use geoffrey_models::logging::LogLevel; use geoffrey_models::models::parameters::add_token_params::AddTokenParams; use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::token::Permissions; use crate::commands::add_token::AddToken; use crate::commands::{command_filter, Command}; use crate::config::GeoffreyAPIConfig; use crate::context::Context; use crate::logging::init_logging; mod commands; mod config; mod context; mod helper; mod logging; pub type Result = std::result::Result; #[derive(Debug, StructOpt, Clone)] #[structopt(name = "GeoffreyAPI", about = "Geoffrey Central API")] struct Args { #[structopt(env = "GEOFFREY_CONFIG", parse(from_os_str))] config: PathBuf, #[structopt( short, long, env = "GEOFFREY_LOG_LEVEL", parse(from_str), default_value = "Info" )] log_level: LogLevel, #[structopt(subcommand)] command: GeoffreyApiCommand, } #[derive(Debug, PartialEq, StructOpt, Clone)] enum GeoffreyApiCommand { Run, CreateAdminToken(CreateTokenCommand), } #[derive(Debug, StructOpt, PartialEq, Clone)] struct CreateTokenCommand { #[structopt(parse(try_from_str = Permissions::try_from))] pub permissions: Vec, } async fn run_server(ctx: Arc) { let socket_addr = match SocketAddr::from_str(ctx.cfg.host.as_str()) { Ok(socket_addr) => socket_addr, Err(e) => { log::warn!("Error parsing {} as address: {}", ctx.cfg.host, e); return; } }; let api = command_filter(ctx.clone()); warp::serve(api).run(socket_addr).await; } fn create_token(ctx: Arc, perms: Vec) { match AddToken::run_command(ctx, &AddTokenParams { permissions: perms }, None) { Ok(token) => { // Don't log this to keep tokens out of the log println!("Added admin token with secret: {}", token.secret) } Err(e) => { log::warn!("Unable to create admin token: {}", e) } } } #[tokio::main] async fn main() { let args: Args = Args::from_args(); if let Err(e) = init_logging(args.log_level) { println!("Unable to initialize logger: {}", e); return; } let cfg = match GeoffreyAPIConfig::new(args.config.as_path()) { Ok(cfg) => cfg, Err(e) => { log::warn!("Error opening config: {}", e); return; } }; let ctx = Context::new(cfg).unwrap(); match args.command { GeoffreyApiCommand::Run => run_server(ctx).await, GeoffreyApiCommand::CreateAdminToken(perms) => create_token(ctx, perms.permissions), }; }