Added whitelist

This commit is contained in:
Kyler 2024-01-23 22:52:47 -07:00
parent 639018b4fa
commit fbebccc68c
2 changed files with 142 additions and 11 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ Cargo.lock
test_server/*
main_icon.png
motd.json
whitelist.json

View File

@ -1,7 +1,12 @@
// Yeahbut December 2023
use core::sync::atomic::{AtomicBool, Ordering};
use std::fs;
use std::time::{Duration, Instant};
use std::sync::{Arc, Mutex};
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
use serde_json::Value;
use lazy_static::lazy_static;
use purple_cello_mc_protocol::{
mc_types::{self, Result, Packet},
@ -9,6 +14,14 @@ use purple_cello_mc_protocol::{
login,
};
const EXPIRATION_DURATION: Duration = Duration::from_secs(3600);
struct CachedWhitelist {
whitelist_data: Value,
timestamp: Instant,
}
#[derive(PartialEq)]
struct Player {
name: String,
player_uuid: Option<u128>,
@ -19,17 +32,134 @@ enum PlayerAllowed {
False(String),
}
fn check_player(player: Player) -> Result<PlayerAllowed> {
static PARITY: AtomicBool = AtomicBool::new(true);
let parity: bool;
parity = PARITY.load(Ordering::Relaxed);
PARITY.store(!parity, Ordering::Relaxed);
if parity {
// if player.name.to_lowercase() == "yeahbut" {
Ok(PlayerAllowed::True(player))
} else {
Ok(PlayerAllowed::False("Testing blocking, try again.".to_string()))
fn load_whitelist() -> Value {
let file_path = "./whitelist.json";
let data = match fs::read_to_string(file_path) {
Ok(data) => data,
Err(_) => return Value::Null,
};
let whitelist_data: Value = match serde_json::from_str(&data) {
Ok(value) => value,
Err(_) => return Value::Null,
};
whitelist_data
}
fn get_whitelist() -> Vec<Player> {
lazy_static! {
static ref WHITELIST_CACHE: Arc<Mutex<Option<CachedWhitelist>>> =
Arc::new(Mutex::new(None));
}
let mut cache = WHITELIST_CACHE.lock().unwrap();
if let Some(cached_whitelist) = cache.as_ref() {
if cached_whitelist.timestamp.elapsed() >= EXPIRATION_DURATION {
println!("Refreshing whitelist cache");
*cache = Some(CachedWhitelist {
whitelist_data: load_whitelist(),
timestamp: Instant::now(),
});
}
} else {
*cache = Some(CachedWhitelist {
whitelist_data: load_whitelist(),
timestamp: Instant::now(),
});
}
let whitelist_data = cache.as_ref().unwrap().whitelist_data.clone();
std::mem::drop(cache);
if whitelist_data == Value::Null {
return Vec::new();
}
let whitelist_array = match whitelist_data.as_array() {
Some(whitelist) => whitelist,
None => { return Vec::new(); }
};
let mut whitelist: Vec<Player> = Vec::new();
for whitelisted_player in whitelist_array {
let player_map = match whitelisted_player.as_object() {
Some(whitelist) => whitelist,
None => { continue; }
};
let name = match player_map.get("name") {
Some(name) => {
match name.as_str() {
Some(name) => name,
None => { continue; }
}
},
None => { continue; }
};
let player_uuid = match player_map.get("uuid") {
Some(uuid) => {
match uuid.as_str() {
Some(uuid) => {
match u128::from_str_radix(uuid, 16) {
Ok(uuid) => uuid,
Err(_) => { continue; }
}
},
None => { continue; }
}
},
None => { continue; }
};
whitelist.push(Player {
name: name.to_string(),
player_uuid: Some(player_uuid),
})
}
whitelist
}
fn check_player_whitelist(player: Player) -> PlayerAllowed {
let whitelist = get_whitelist();
if player.player_uuid.is_none() {
return PlayerAllowed::False("Invalid UUID".to_string());
}
let mut invalid_uuid = false;
let mut invalid_username = false;
for wl_player in whitelist {
if wl_player == player {
return PlayerAllowed::True(player);
} else if wl_player.name == player.name {
invalid_uuid = true;
} else if wl_player.player_uuid == player.player_uuid {
invalid_username = true;
}
}
if invalid_uuid {
PlayerAllowed::False("Invalid UUID".to_string())
} else if invalid_username {
PlayerAllowed::False(
"Invalid Username, please contact the server admin to update your \
username: purplecelloserver@gmail.com".to_string()
)
} else {
PlayerAllowed::False("Not whitelisted on this server".to_string())
}
}
fn check_player(player: Player) -> Result<PlayerAllowed> {
Ok(check_player_whitelist(player))
}
pub async fn respond_login(