mirror of
https://github.com/shiroyashik/sculptor.git
synced 2025-12-06 13:01:12 +03:00
Limitations management and real-time MOTD update added.
- deleted unnecessary comments - korewaChino artefacts removed
This commit is contained in:
parent
c53c10cb0a
commit
cfea3e6e71
12 changed files with 79 additions and 84 deletions
38
src/auth.rs
38
src/auth.rs
|
|
@ -56,7 +56,6 @@ async fn verify(
|
|||
if let Some((uuid, auth_system)) = has_joined(&server_id, &username).await.unwrap() {
|
||||
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(),
|
||||
|
|
@ -66,7 +65,6 @@ async fn verify(
|
|||
auth_system,
|
||||
},
|
||||
);
|
||||
// link.insert(uuid, crate::AuthenticatedLink(server_id.clone())); // Реализация поиска пользователя в HashMap по UUID
|
||||
server_id.to_string()
|
||||
} else {
|
||||
String::from("failed to verify")
|
||||
|
|
@ -135,7 +133,6 @@ impl ToString for AuthSystem {
|
|||
}
|
||||
|
||||
/// Get UUID from JSON response
|
||||
// Written to be reusable so we don't have to specify the same complex code twice
|
||||
#[inline]
|
||||
fn get_id_json(json: &serde_json::Value) -> anyhow::Result<Uuid> {
|
||||
trace!("json: {json:#?}"); // For debugging, we'll get to this later!
|
||||
|
|
@ -143,8 +140,6 @@ fn get_id_json(json: &serde_json::Value) -> anyhow::Result<Uuid> {
|
|||
Ok(uuid)
|
||||
}
|
||||
|
||||
// Considering dropping ely.by support here, I don't really want to deal with it
|
||||
|
||||
#[inline]
|
||||
async fn fetch_json(
|
||||
url: &str,
|
||||
|
|
@ -181,39 +176,6 @@ pub async fn has_joined(
|
|||
server_id: &str,
|
||||
username: &str,
|
||||
) -> anyhow::Result<Option<(Uuid, AuthSystem)>> {
|
||||
// let client = reqwest::Client::new();
|
||||
// tokio::select! {
|
||||
// Ok(Some(res)) = async {
|
||||
// let res = client.clone().get(
|
||||
// format!("http://minecraft.ely.by/session/hasJoined?serverId={server_id}&username={username}")).send().await?;
|
||||
// debug!("{res:?}");
|
||||
// match res.status().as_u16() {
|
||||
// 200 => {
|
||||
// let json = serde_json::from_str::<serde_json::Value>(&res.text().await?)?;
|
||||
// let uuid = get_id_json(&json)?;
|
||||
// Ok(Some((uuid, AuthSystem::ElyBy)))
|
||||
// },
|
||||
// 401 => Ok(None),
|
||||
// _ => Err(anyhow::anyhow!("Unknown code: {}", res.status().as_u16()))
|
||||
// }
|
||||
// } => {Ok(Some(res))}
|
||||
// Ok(Some(res)) = async {
|
||||
// let res = client.clone().get(
|
||||
// format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?serverId={server_id}&username={username}")).send().await?;
|
||||
// debug!("{res:?}");
|
||||
// match res.status().as_u16() {
|
||||
// 200 => {
|
||||
// let json = serde_json::from_str::<serde_json::Value>(&res.text().await?)?;
|
||||
// let uuid = get_id_json(&json)?;
|
||||
// Ok(Some((uuid, AuthSystem::Mojang)))
|
||||
// },
|
||||
// 204 => Ok(None),
|
||||
// _ => Err(anyhow::anyhow!("Unknown code: {}", res.status().as_u16()))
|
||||
// }
|
||||
// } => {Ok(Some(res))}
|
||||
// else => {Err(anyhow!("Something went wrong in external apis request process"))}
|
||||
// }
|
||||
|
||||
tokio::select! {
|
||||
Ok(Some(res)) = fetch_json("http://minecraft.ely.by/session/hasJoined", server_id, username) => {Ok(Some(res))},
|
||||
Ok(Some(res)) = fetch_json("https://sessionserver.mojang.com/session/minecraft/hasJoined", server_id, username) => {Ok(Some(res))},
|
||||
|
|
|
|||
|
|
@ -3,14 +3,22 @@ use std::{io::Read, path::PathBuf};
|
|||
use serde::Deserialize;
|
||||
use toml::Table;
|
||||
|
||||
#[derive(Deserialize, Clone, Debug)]
|
||||
#[derive(Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
pub listen: String,
|
||||
pub motd: String,
|
||||
pub limitations: Limitations,
|
||||
pub advanced_users: Table,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Limitations {
|
||||
pub max_avatar_size: u64,
|
||||
pub max_avatars: u64,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn parse(path: PathBuf) -> Self {
|
||||
let mut file = std::fs::File::open(path).expect("Access denied or file doesn't exists!");
|
||||
|
|
|
|||
21
src/info.rs
21
src/info.rs
|
|
@ -1,6 +1,14 @@
|
|||
use axum::Json;
|
||||
use axum::{extract::State, Json};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
/// Assert health of the server
|
||||
/// If times out, the server is considered dead, so we can return basically anything
|
||||
pub async fn health_check() -> String {
|
||||
"ok".to_string()
|
||||
}
|
||||
|
||||
pub async fn version() -> Json<Value> {
|
||||
Json(json!({
|
||||
"release": "0.1.4",
|
||||
|
|
@ -8,7 +16,12 @@ pub async fn version() -> Json<Value> {
|
|||
}))
|
||||
}
|
||||
|
||||
pub async fn limits() -> Json<Value> {
|
||||
pub async fn motd(State(state): State<AppState>) -> String {
|
||||
state.config.lock().await.motd.clone()
|
||||
}
|
||||
|
||||
pub async fn limits(State(state): State<AppState>) -> Json<Value> {
|
||||
let state = &state.config.lock().await.limitations;
|
||||
Json(json!({
|
||||
"rate": {
|
||||
"pingSize": 1024,
|
||||
|
|
@ -18,8 +31,8 @@ pub async fn limits() -> Json<Value> {
|
|||
"upload": 1
|
||||
},
|
||||
"limits": {
|
||||
"maxAvatarSize": 100000,
|
||||
"maxAvatars": 10,
|
||||
"maxAvatarSize": state.max_avatar_size,
|
||||
"maxAvatars": state.max_avatars,
|
||||
"allowedBadges": {
|
||||
"special": [0,0,0,0,0,0],
|
||||
"pride": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
|
|
|
|||
37
src/main.rs
37
src/main.rs
|
|
@ -90,18 +90,10 @@ pub struct AppState {
|
|||
authenticated: Arc<Authenticated>, // <SHA1 serverId, Userinfo> NOTE: In the future, try it in a separate LockRw branch
|
||||
// Ping broadcasts for WebSocket connections
|
||||
broadcasts: Arc<DashMap<Uuid, broadcast::Sender<Vec<u8>>>>,
|
||||
// Advanced configured users
|
||||
advanced_users: Arc<Mutex<toml::Table>>,
|
||||
// Current configuration
|
||||
config: Arc<Mutex<config::Config>>,
|
||||
}
|
||||
|
||||
/// Assert health of the server
|
||||
/// If times out, the server is considered dead, so we can return basically anything
|
||||
async fn health_check() -> String {
|
||||
// tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
"ok".to_string()
|
||||
}
|
||||
|
||||
|
||||
const LOGGER_ENV: &str = "RUST_LOG";
|
||||
|
||||
#[tokio::main]
|
||||
|
|
@ -118,29 +110,30 @@ async fn main() -> Result<()> {
|
|||
|
||||
let config_file = std::env::var("CONFIG_PATH").unwrap_or_else(|_| "Config.toml".into());
|
||||
|
||||
info!("The Sculptor MMSI edition v{}", env!("CARGO_PKG_VERSION"));
|
||||
info!("The Sculptor v{}", env!("CARGO_PKG_VERSION"));
|
||||
// Config
|
||||
let config = config::Config::parse(config_file.clone().into());
|
||||
let listen = config.listen.as_str();
|
||||
let config = Arc::new(Mutex::new(config::Config::parse(config_file.clone().into())));
|
||||
let listen = config.lock().await.listen.clone();
|
||||
|
||||
// State
|
||||
let state = AppState {
|
||||
pending: Arc::new(DashMap::new()),
|
||||
authenticated: Arc::new(Authenticated::new()),
|
||||
broadcasts: Arc::new(DashMap::new()),
|
||||
advanced_users: Arc::new(Mutex::new(config.advanced_users)),
|
||||
config: config,
|
||||
};
|
||||
|
||||
// Automatic update of advanced_users while the server is running
|
||||
let advanced_users = state.advanced_users.clone();
|
||||
// Automatic update of configuration while the server is running
|
||||
let config_update = state.config.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
||||
|
||||
let new_config = config::Config::parse(config_file.clone().into()).advanced_users;
|
||||
let mut config = advanced_users.lock().await;
|
||||
let new_config = config::Config::parse(config_file.clone().into());
|
||||
let mut config = config_update.lock().await;
|
||||
|
||||
if new_config != *config {
|
||||
info!("Server configuration modification detected!");
|
||||
*config = new_config;
|
||||
}
|
||||
}
|
||||
|
|
@ -148,20 +141,20 @@ async fn main() -> Result<()> {
|
|||
|
||||
let api = Router::new()
|
||||
.nest("//auth", api_auth::router())
|
||||
.route("/limits", get(api_info::limits)) // TODO:
|
||||
.route("/limits", get(api_info::limits))
|
||||
.route("/version", get(api_info::version))
|
||||
.route("/motd", get(|| async { config.motd }))
|
||||
.route("/motd", get(api_info::motd))
|
||||
.route("/equip", post(api_profile::equip_avatar))
|
||||
.route("/:uuid", get(api_profile::user_info))
|
||||
.route("/:uuid/avatar", get(api_profile::download_avatar))
|
||||
.route("/avatar", put(api_profile::upload_avatar))
|
||||
.route("/avatar", delete(api_profile::delete_avatar)); // delete Avatar
|
||||
.route("/avatar", delete(api_profile::delete_avatar));
|
||||
|
||||
let app = Router::new()
|
||||
.nest("/api", api)
|
||||
.route("/api/", get(api_auth::status))
|
||||
.route("/ws", get(handler))
|
||||
.route("/health", get(health_check))
|
||||
.route("/health", get(api_info::health_check))
|
||||
.route_layer(from_extractor::<api_auth::Token>())
|
||||
.with_state(state)
|
||||
.layer(TraceLayer::new_for_http().on_request(()));
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use crate::{
|
|||
#[debug_handler]
|
||||
pub async fn user_info(
|
||||
Path(uuid): Path<Uuid>,
|
||||
State(state): State<AppState>, // FIXME: Variable doesn't using!
|
||||
State(state): State<AppState>,
|
||||
) -> Json<Value> {
|
||||
tracing::info!("Receiving profile information for {}", uuid);
|
||||
|
||||
|
|
@ -47,10 +47,10 @@ pub async fn user_info(
|
|||
},
|
||||
"version": "0.1.4+1.20.1",
|
||||
"banned": false,
|
||||
"authSystem": auth_system // add Trust
|
||||
"authSystem": auth_system
|
||||
});
|
||||
|
||||
if let Some(settings) = state.advanced_users.lock().await.get(&formatted_uuid) {
|
||||
if let Some(settings) = state.config.lock().await.advanced_users.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
|
||||
|
|
@ -141,7 +141,7 @@ pub async fn equip_avatar(Token(token): Token, State(state): State<AppState>) ->
|
|||
.is_err()
|
||||
{
|
||||
warn!("[WebSocket] Failed to send Event! Maybe there is no one to send")
|
||||
// FIXME: Засунуть в Handler
|
||||
// TODO: Put into Handler
|
||||
};
|
||||
"ok".to_string()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
|||
use ring::digest::{self, digest};
|
||||
use uuid::Uuid;
|
||||
|
||||
// Кор функции
|
||||
// Core functions
|
||||
pub fn rand() -> [u8; 50] {
|
||||
let mut rng = thread_rng();
|
||||
let distr = rand::distributions::Uniform::new_inclusive(0, 255);
|
||||
|
|
@ -15,6 +15,7 @@ pub fn rand() -> [u8; 50] {
|
|||
}
|
||||
nums
|
||||
}
|
||||
|
||||
//? What is this guy doing
|
||||
#[tracing::instrument]
|
||||
pub fn bytes_into_string(code: &[u8]) -> String {
|
||||
|
|
@ -27,7 +28,7 @@ pub fn bytes_into_string(code: &[u8]) -> String {
|
|||
|
||||
// String::from_utf8_lossy(code).to_string() // Tried this, causes corrupted string
|
||||
}
|
||||
// Конец кор функций
|
||||
// End of Core functions
|
||||
|
||||
pub fn _generate_hex_string(length: usize) -> String {
|
||||
// FIXME: Variable doesn't using!
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue