diff --git a/Cargo.toml b/Cargo.toml index d439120..700d99c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ serde_json = "1" tracing-subscriber = "0.3" uuid = "1" chrono = "0.4" +tracing = "0.1" diff --git a/README.md b/README.md index 1329b71..73b6362 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ # HOW TO USE Add to java args (on client/server) ``` --Dminecraft.api.auth.host=http://localhost:8081/auth --Dminecraft.api.account.host=http://localhost:8081/account --Dminecraft.api.session.host=http://localhost:8081/session --Dminecraft.api.services.host=http://localhost:8081/services +-Dminecraft.api.auth.host=https://ygddrasil.fantabos.co/auth +-Dminecraft.api.session.host=https://yggdrasil.fantabos.co + +-Dminecraft.api.account.host=http://yggdrasil.fantabos.co/account +-Dminecraft.api.services.host=http://yggdrasil.fantabos.co/services + ``` ## TODO diff --git a/src/main.rs b/src/main.rs index dcbd44e..98819ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ mod proto; mod entities; -use std::{net::SocketAddr, collections::HashMap, sync::Arc}; +use std::{collections::HashMap, sync::Arc}; use chrono::{DateTime, Utc, Duration}; use clap::Parser; @@ -10,6 +10,9 @@ use proto::{Error, AuthenticateRequest, AuthenticateResponse, JoinRequest, JoinR use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, DatabaseConnection, Database, ActiveValue::NotSet, Set}; use tokio::sync::Mutex; use uuid::Uuid; +use tracing::{info, warn}; + +use crate::proto::Property; /// Reimplementation of legacy auth server for minecraft #[derive(Parser, Debug, Clone)] @@ -18,18 +21,13 @@ struct ConfigArgs { /// Connection string for database database: String, - // /// Listen address - // #[arg(short, long, default_value_t = )] - // listen_addr: String, - - /// Listen port - #[arg(short, long, default_value_t = 25556)] - listen_port: u16, + /// Address to bind web application onto + #[arg(short, long, default_value = "127.0.0.1:26656")] + bind_addr: String, /// Valid time for join requests, in seconds #[arg(short, long, default_value_t = 10)] time_window: u32, - } #[derive(Clone)] @@ -60,19 +58,21 @@ async fn main() -> Result<(), Box> { let db = Database::connect(cfg.database.clone()).await?; let store = Arc::new(Mutex::new(HashMap::new())); + let addr = cfg.bind_addr.parse()?; + let app = Router::new() - .route("/", get(root)) - .route("/authenticate", post(authenticate)) - .route("/validate", post(validate)) - .route("/refresh", post(refresh)) + .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 // .route("/signout", post(signout)) // .route("/invalidate", post(invalidate)) - .route("/join", post(join)) - .route("/hasJoined", get(has_joined)) + .route("/session/minecraft/join", post(join)) + .route("/session/minecraft/hasJoined", get(has_joined)) .route("/register", post(register_tmp)) + .fallback(fallback_route) .with_state(AppState { store, db, cfg }); - let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); // TODO parse strings from CLI + info!(target: "MAIN", "serving app..."); axum::Server::bind(&addr) .serve(app.into_make_service()) @@ -81,11 +81,11 @@ async fn main() -> Result<(), Box> { Ok(()) } -async fn root() -> impl IntoResponse { +async fn fallback_route() -> impl IntoResponse { let error = Error { - error: "No route specified".into(), - errorMessage: "No route specified".into(), - cause: "No route specified".into(), + error: "No valid route specified".into(), + errorMessage: "No route requested or invalid route specified".into(), + cause: "Routing".into(), }; (StatusCode::OK, Json(error)) @@ -124,8 +124,8 @@ async fn refresh(State(state): State, Json(payload): Json, Json(payload): Json, Json(payload): Json) -> StatusCode { let user = entities::user::Entity::find().filter( - entities::user::Column::Uuid.eq(payload.selectedProfile) + entities::user::Column::Uuid.eq(payload.selectedProfile.id) ).one(&state.db).await.unwrap().unwrap(); let tokens = entities::token::Entity::find().filter( @@ -187,9 +187,11 @@ async fn join(State(state): State, Json(payload): Json) - ).all(&state.db).await.unwrap(); if tokens.iter().any(|x| x.access_token == payload.accessToken) { - state.store.lock().await.insert(payload.selectedProfile, JoinAttempt::new(payload.serverId)); + state.store.lock().await.insert(payload.selectedProfile.id, JoinAttempt::new(payload.serverId.clone())); + info!(target: "JOIN", "user {} has joined server {}", payload.selectedProfile.name, payload.serverId); StatusCode::OK } else { + warn!(target: "JOIN", "user {} attempted to join server {} without a valid token", payload.selectedProfile.name, payload.serverId); StatusCode::UNAUTHORIZED } } @@ -211,18 +213,31 @@ async fn has_joined(State(state): State, Query(query): Query {:?}", response); Ok(Json(response)) } else { + warn!(target: "hasJOINED", "server found user but join was late or for another server"); Err(StatusCode::NOT_FOUND) } }, - None => Err(StatusCode::NOT_FOUND), + None => { + warn!(target: "hasJOINED", "server didn't find user"); + Err(StatusCode::NOT_FOUND) + }, } }, - None => Err(StatusCode::NOT_FOUND), + None => { + warn!(target: "hasJOINED", "invalid UUID"); + Err(StatusCode::NOT_FOUND) + }, } } diff --git a/src/proto.rs b/src/proto.rs index 91c6ca4..2a7417a 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -16,7 +16,7 @@ pub struct Agent { pub version: u32, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub struct Property { pub name: String, pub value: String, @@ -88,11 +88,11 @@ pub struct SignoutRequest { #[derive(Serialize, Deserialize)] pub struct JoinRequest { pub accessToken: String, - pub selectedProfile: Uuid, + pub selectedProfile: Profile, pub serverId: String, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub struct JoinResponse { pub id: Uuid, pub name: String,