From 28b32c81350b4aed84aec2fbb2fc11c4ded1b28f Mon Sep 17 00:00:00 2001 From: alemi Date: Tue, 9 May 2023 02:11:00 +0200 Subject: [PATCH] feat!: improved CLI: separated actions from backend --- src/main.rs | 111 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 41 deletions(-) diff --git a/src/main.rs b/src/main.rs index 71b2152..6c7add2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,14 @@ mod proto; mod entities; mod routes; mod persistence; +mod maintenance; use std::{collections::HashMap, sync::Arc}; use chrono::{DateTime, Utc, Duration}; -use clap::Parser; +use clap::{Parser, Subcommand}; use axum::{Router, routing::{get, post}, response::IntoResponse, Json, http::StatusCode}; +use routes::register::fill_missing_skins; use sea_orm::{DatabaseConnection, Database}; use tokio::sync::Mutex; use tracing_subscriber::filter::filter_fn; @@ -23,29 +25,48 @@ use crate::{routes::{ /// Reimplementation of legacy auth server for minecraft #[derive(Parser, Debug, Clone)] #[command(author, version, about, long_about = None)] -struct ConfigArgs { +struct CliArgs { /// Connection string for database database: String, - /// Address to bind web application onto - #[arg(short, long, default_value = "127.0.0.1:26656")] - bind_addr: String, + /// Action to run + #[clap(subcommand)] + action: CliAction, +} - /// How long an access token stays valid, in seconds - #[arg(long, default_value_t = 3600)] - token_duration: u32, +#[derive(Subcommand, Clone, Debug)] +enum CliAction { + /// run yggdrasil backend service + Serve { + /// Address to bind web application onto + #[arg(short, long, default_value = "127.0.0.1:26656")] + bind_addr: String, - /// How long an access token is refreshable, in hours - #[arg(long, default_value_t = 168)] - token_lifetime: u32, + /// How long an access token stays valid, in seconds + #[arg(long, default_value_t = 3600)] + token_duration: u32, - /// Valid time for join requests, in seconds - #[arg(short, long, default_value_t = 10)] - time_window: u32, + /// Valid time for join requests, in seconds + #[arg(short, long, default_value_t = 10)] + time_window: u32, + + /// Enable join request fallback to Microsoft + #[arg(long)] + fallback: bool, + }, + + /// remove expired tokens + Clean { + /// How long an access token is refreshable, in hours + #[arg(long, default_value_t = 168)] + token_lifetime: u32, + }, + + /// fetch missing skins + Skins { + + } - /// Enable join request fallback to Microsoft - #[arg(long)] - fallback: bool, } #[derive(Clone)] @@ -64,7 +85,7 @@ impl JoinAttempt { pub struct AppState { store: Arc>>, db: DatabaseConnection, - cfg: ConfigArgs, + cfg: CliArgs, secret: String, } @@ -76,37 +97,45 @@ async fn main() -> Result<(), Box> { .with(tracing_subscriber::fmt::layer()) .init(); - let cfg = ConfigArgs::parse(); + let cfg = CliArgs::parse(); let db = Database::connect(cfg.database.clone()).await?; - purge_expired_tokens(&db, Duration::hours(cfg.token_lifetime.into())).await?; + match cfg.action { + CliAction::Clean { token_lifetime } => { + purge_expired_tokens(&db, Duration::hours(token_lifetime.into())).await?; + }, + CliAction::Skins { } => { + fill_missing_skins(&db).await?; + }, + CliAction::Serve { bind_addr, token_duration, time_window, fallback } => { + let secret = load_secret(&db).await?; - let secret = load_secret(&db).await?; + let store = Arc::new(Mutex::new(HashMap::new())); // TODO do this as an Actor - let store = Arc::new(Mutex::new(HashMap::new())); // TODO do this as an Actor + let addr = bind_addr.parse()?; - let addr = cfg.bind_addr.parse()?; + let app = Router::new() + // AUTH + .route("/auth/authenticate", post(authenticate)) //in: username, pass; out: token + .route("/auth/validate", post(validate)) //in: token; out: boolean valid + .route("/auth/refresh", post(refresh)) //in: token out: refreshed token + // SESSION + .route("/session/minecraft/join", post(join)) + .route("/session/minecraft/hasJoined", get(has_joined_wrapper)) + .route("/session/minecraft/profile/:user_id", get(profile)) + // CUSTOM + .route("/register/unmigrated", post(register_unmigrated)) + .fallback(fallback_route) + .with_state(AppState { store, db, cfg, secret }); - let app = Router::new() - // AUTH - .route("/auth/authenticate", post(authenticate)) //in: username, pass; out: token - .route("/auth/validate", post(validate)) //in: token; out: boolean valid - .route("/auth/refresh", post(refresh)) //in: token out: refreshed token - // SESSION - .route("/session/minecraft/join", post(join)) - .route("/session/minecraft/hasJoined", get(has_joined_wrapper)) - .route("/session/minecraft/profile/:user_id", get(profile)) - // CUSTOM - .route("/register/unmigrated", post(register_unmigrated)) - .fallback(fallback_route) - .with_state(AppState { store, db, cfg, secret }); + info!(target: "MAIN", "serving Yggdrasil on {}", &addr); - info!(target: "MAIN", "serving Yggdrasil on {}", &addr); - - axum::Server::bind(&addr) - .serve(app.into_make_service()) - .await?; + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .await?; + }, + } Ok(()) }