diff --git a/src/auth.rs b/src/auth.rs index 86634e2..c06085b 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,10 +1,17 @@ -use anyhow::anyhow; -use axum::{async_trait, debug_handler, extract::{FromRequestParts, Query, State}, http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, routing::get, Router}; -use log::{debug, info, trace}; -use serde::Deserialize; -use ring::digest::{self, digest}; -use uuid::Uuid; use crate::utils::*; +use anyhow::anyhow; +use axum::{ + async_trait, debug_handler, + extract::{FromRequestParts, Query, State}, + http::{request::Parts, StatusCode}, + response::{IntoResponse, Response}, + routing::get, + Router, +}; +use log::{debug, info, trace}; +use ring::digest::{self, digest}; +use serde::Deserialize; +use uuid::Uuid; use crate::AppState; @@ -14,27 +21,33 @@ pub fn router() -> Router { .route("/verify", get(verify)) } - // Web #[derive(Deserialize)] -struct Id {username: String} +struct Id { + username: String, +} #[debug_handler] -async fn id( // First stage of authentication +async fn id( + // First stage of authentication Query(query): Query, State(state): State, ) -> String { - let server_id = bytes_into_string(&digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &rand()).as_ref()[0 .. 20]); + let server_id = + bytes_into_string(&digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, &rand()).as_ref()[0..20]); let state = state.pending; state.insert(server_id.clone(), query.username); server_id } #[derive(Deserialize)] -struct Verify {id: String} +struct Verify { + id: String, +} #[debug_handler] -async fn verify( // Second stage of authentication +async fn verify( + // Second stage of authentication Query(query): Query, State(state): State, ) -> String { @@ -44,7 +57,15 @@ async fn verify( // Second stage of authentication info!("[Authorization] {username} logged in using {auth_system:?}"); let authenticated = state.authenticated; // let link = state.authenticated_link.lock().await; // // Реализация поиска пользователя в HashMap по UUID - authenticated.insert(uuid, server_id.clone(), crate::Userinfo { username, uuid, auth_system }); + authenticated.insert( + uuid, + server_id.clone(), + crate::Userinfo { + username, + uuid, + auth_system, + }, + ); // link.insert(uuid, crate::AuthenticatedLink(server_id.clone())); // Реализация поиска пользователя в HashMap по UUID server_id.to_string() } else { @@ -52,10 +73,7 @@ async fn verify( // Second stage of authentication } } -pub async fn status( - Token(token): Token, - State(state): State, -) -> Response { +pub async fn status(Token(token): Token, State(state): State) -> Response { match token { Some(token) => { if state.authenticated.contains_token(&token) { @@ -65,16 +83,15 @@ pub async fn status( // format!("unauthorized") // 401 (StatusCode::UNAUTHORIZED, "unauthorized".to_string()).into_response() } - }, + } None => { // format!("bad request") // 400 (StatusCode::BAD_REQUEST, "bad request".to_string()).into_response() - }, + } } } // Web End - // It's an extractor that pulls a token from the Header. #[derive(PartialEq, Debug)] pub struct Token(pub Option); @@ -117,7 +134,10 @@ impl ToString for AuthSystem { } } -pub async fn has_joined(server_id: &str, username: &str) -> anyhow::Result> { +pub async fn has_joined( + server_id: &str, + username: &str, +) -> anyhow::Result> { let client = reqwest::Client::new(); tokio::select! { Ok(Some(res)) = async { @@ -151,4 +171,4 @@ pub async fn has_joined(server_id: &str, username: &str) -> anyhow::Result {Err(anyhow!("Something went wrong in external apis request process"))} } } -// End of work with external APIs \ No newline at end of file +// End of work with external APIs diff --git a/src/config.rs b/src/config.rs index 4570a12..784f449 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,6 @@ pub struct Config { pub advanced_users: Table, } - impl Config { pub fn parse(path: PathBuf) -> Self { let mut file = std::fs::File::open(path).expect("Access denied or file doesn't exists!"); @@ -20,4 +19,4 @@ impl Config { toml::from_str(&data).unwrap() } -} \ No newline at end of file +} diff --git a/src/info.rs b/src/info.rs index 5233f42..33d650d 100644 --- a/src/info.rs +++ b/src/info.rs @@ -1,7 +1,6 @@ use axum::Json; use serde_json::{json, Value}; - pub async fn version() -> Json { Json(json!({ "release": "0.1.4", diff --git a/src/profile.rs b/src/profile.rs index d64d44a..1677555 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -1,18 +1,31 @@ use anyhow_http::{http_error_ret, response::Result}; -use axum::{body::Bytes, debug_handler, extract::{Path, State}, Json}; +use axum::{ + body::Bytes, + debug_handler, + extract::{Path, State}, + Json, +}; use log::{debug, warn}; use serde_json::{json, Value}; -use tokio::{fs, io::{AsyncReadExt, BufWriter, self}}; +use tokio::{ + fs, + io::{self, AsyncReadExt, BufWriter}, +}; use uuid::Uuid; -use crate::{auth::Token, utils::{calculate_file_sha256, format_uuid, get_correct_array}, ws::S2CMessage, AppState}; +use crate::{ + auth::Token, + utils::{calculate_file_sha256, format_uuid, get_correct_array}, + ws::S2CMessage, + AppState, +}; #[debug_handler] pub async fn user_info( Path(uuid): Path, State(state): State, // FIXME: Variable doesn't using! ) -> Json { - log::info!("Receiving profile information for {}",uuid); + log::info!("Receiving profile information for {}", uuid); let formatted_uuid = format_uuid(&uuid); @@ -40,36 +53,40 @@ pub async fn user_info( if let Some(settings) = state.advanced_users.lock().await.get(&formatted_uuid) { let pride = get_correct_array(settings.get("pride").unwrap()); let special = get_correct_array(settings.get("special").unwrap()); - let badges = user_info_response.get_mut("equippedBadges").and_then(Value::as_object_mut).unwrap(); - badges.append(json!({ - "special": special, - "pride": pride - }).as_object_mut().unwrap()) + let badges = user_info_response + .get_mut("equippedBadges") + .and_then(Value::as_object_mut) + .unwrap(); + badges.append( + json!({ + "special": special, + "pride": pride + }) + .as_object_mut() + .unwrap(), + ) } if fs::metadata(&avatar_file).await.is_ok() { - if let Some(equipped) = user_info_response.get_mut("equipped").and_then(Value::as_array_mut){ - match calculate_file_sha256(&avatar_file){ - Ok(hash) => { - equipped.push(json!({ - "id": "avatar", - "owner": &formatted_uuid, - "hash": hash - })) - } + if let Some(equipped) = user_info_response + .get_mut("equipped") + .and_then(Value::as_array_mut) + { + match calculate_file_sha256(&avatar_file) { + Ok(hash) => equipped.push(json!({ + "id": "avatar", + "owner": &formatted_uuid, + "hash": hash + })), Err(_e) => {} } - - } } Json(user_info_response) } #[debug_handler] -pub async fn download_avatar( - Path(uuid): Path, -) -> Result> { +pub async fn download_avatar(Path(uuid): Path) -> Result> { let uuid = format_uuid(&uuid); log::info!("Requesting an avatar: {}", uuid); let mut file = if let Ok(file) = fs::File::open(format!("avatars/{}.moon", uuid)).await { @@ -92,8 +109,7 @@ pub async fn upload_avatar( Token(token): Token, State(state): State, body: Bytes, -) -> Result { - +) -> Result { let request_data = body; let token = match token { @@ -102,39 +118,48 @@ pub async fn upload_avatar( }; if let Some(user_info) = state.authenticated.get(&token) { - log::info!("{} ({}) trying to upload an avatar",user_info.uuid,user_info.username); - let avatar_file = format!("avatars/{}.moon",user_info.uuid); + log::info!( + "{} ({}) trying to upload an avatar", + user_info.uuid, + user_info.username + ); + let avatar_file = format!("avatars/{}.moon", user_info.uuid); let mut file = BufWriter::new(fs::File::create(&avatar_file).await?); io::copy(&mut request_data.as_ref(), &mut file).await?; } Ok("ok".to_string()) } -pub async fn equip_avatar( - Token(token): Token, - State(state): State, -) -> String { +pub async fn equip_avatar(Token(token): Token, State(state): State) -> String { debug!("[API] S2C : Equip"); let uuid = state.authenticated.get(&token.unwrap()).unwrap().uuid; - if state.broadcasts.get(&uuid).unwrap().send(S2CMessage::Event(uuid).to_vec()).is_err() { - warn!("[WebSocket] Failed to send Event! Maybe there is no one to send") // FIXME: Засунуть в Handler + if state + .broadcasts + .get(&uuid) + .unwrap() + .send(S2CMessage::Event(uuid).to_vec()) + .is_err() + { + warn!("[WebSocket] Failed to send Event! Maybe there is no one to send") + // FIXME: Засунуть в Handler }; "ok".to_string() } -pub async fn delete_avatar( - Token(token): Token, - State(state): State, -) -> Result { +pub async fn delete_avatar(Token(token): Token, State(state): State) -> Result { let token = match token { Some(t) => t, None => http_error_ret!(UNAUTHORIZED, "Authentication error!"), }; if let Some(user_info) = state.authenticated.get(&token) { - log::info!("{} ({}) is trying to delete the avatar",user_info.uuid,user_info.username); - let avatar_file = format!("avatars/{}.moon",user_info.uuid); + log::info!( + "{} ({}) is trying to delete the avatar", + user_info.uuid, + user_info.username + ); + let avatar_file = format!("avatars/{}.moon", user_info.uuid); fs::remove_file(avatar_file).await?; } // let avatar_file = format!("avatars/{}.moon",user_info.uuid); Ok("ok".to_string()) -} \ No newline at end of file +} diff --git a/src/ws/c2s.rs b/src/ws/c2s.rs index fc39c76..607ba64 100644 --- a/src/ws/c2s.rs +++ b/src/ws/c2s.rs @@ -88,4 +88,4 @@ impl<'a> From> for Box<[u8]> { }; a } -} \ No newline at end of file +} diff --git a/src/ws/errors.rs b/src/ws/errors.rs index bd48020..ed8aa94 100644 --- a/src/ws/errors.rs +++ b/src/ws/errors.rs @@ -39,4 +39,4 @@ fn message_load_error_display() { BadLength("bar", 17, true, 19).to_string(), "buffer wrong size for bar: must be exactly 17 bytes, got 19" ); -} \ No newline at end of file +} diff --git a/src/ws/handler.rs b/src/ws/handler.rs index 9e1632a..6c05145 100644 --- a/src/ws/handler.rs +++ b/src/ws/handler.rs @@ -1,17 +1,26 @@ use std::sync::Arc; -use axum::{extract::{ws::{Message, WebSocket}, State, WebSocketUpgrade}, response::Response}; +use axum::{ + extract::{ + ws::{Message, WebSocket}, + State, WebSocketUpgrade, + }, + response::Response, +}; use dashmap::DashMap; use log::{debug, error, info, trace, warn}; -use tokio::sync::{broadcast::{self, Receiver}, mpsc, Notify}; +use tokio::sync::{ + broadcast::{self, Receiver}, + mpsc, Notify, +}; use uuid::Uuid; -use crate::{ws::{C2SMessage, S2CMessage}, AppState}; +use crate::{ + ws::{C2SMessage, S2CMessage}, + AppState, +}; -pub async fn handler( - ws: WebSocketUpgrade, - State(state): State, -) -> Response { +pub async fn handler(ws: WebSocketUpgrade, State(state): State) -> Response { ws.on_upgrade(|socket| handle_socket(socket, state)) } @@ -66,7 +75,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { // Next is the code for processing msg let msg_vec = msg.clone().into_data(); let msg_array = msg_vec.as_slice(); - + let newmsg = match C2SMessage::try_from(msg_array) { Ok(data) => data, Err(e) => { @@ -78,9 +87,9 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { return; }, }; - + debug!("[WebSocket{}] Raw: {newmsg:?}", owner.name()); - + match newmsg { C2SMessage::Token(token) => { debug!("[WebSocket{}] C2S : Token", owner.name()); @@ -127,7 +136,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { if uuid == owner.0.clone().unwrap().uuid { continue; }; - + let rx = match state.broadcasts.get(&uuid) { Some(rx) => rx.to_owned().subscribe(), None => { @@ -154,7 +163,7 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { continue; }, } - + // Sending message debug!("[WebSocket{}] Answering: {msg:?}", owner.name()); if socket.send(msg).await.is_err() { @@ -185,7 +194,11 @@ async fn handle_socket(mut socket: WebSocket, state: AppState) { } } -async fn subscribe(socket: mpsc::Sender>, mut rx: Receiver>, shutdown: Arc) { +async fn subscribe( + socket: mpsc::Sender>, + mut rx: Receiver>, + shutdown: Arc, +) { loop { tokio::select! { _ = shutdown.notified() => { @@ -204,5 +217,8 @@ async fn subscribe(socket: mpsc::Sender>, mut rx: Receiver>, shu fn into_s2c_ping(buf: Vec, uuid: Uuid) -> Vec { use std::iter::once; - once(1).chain(uuid.into_bytes().iter().copied()).chain(buf.as_slice()[1..].iter().copied()).collect() -} \ No newline at end of file + once(1) + .chain(uuid.into_bytes().iter().copied()) + .chain(buf.as_slice()[1..].iter().copied()) + .collect() +} diff --git a/src/ws/mod.rs b/src/ws/mod.rs index 0baa991..c9ad8f7 100644 --- a/src/ws/mod.rs +++ b/src/ws/mod.rs @@ -1,9 +1,9 @@ mod c2s; -mod s2c; -mod handler; mod errors; +mod handler; +mod s2c; pub use c2s::C2SMessage; -pub use s2c::S2CMessage; +pub use errors::MessageLoadError; pub use handler::handler; -pub use errors::MessageLoadError; \ No newline at end of file +pub use s2c::S2CMessage;