mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Created banned words file
By default, it's an empty list
This commit is contained in:
parent
9195c06c95
commit
d5e9e19881
115
server/src/alias_validator.rs
Normal file
115
server/src/alias_validator.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AliasValidator {
|
||||
banned_substrings: Vec<String>,
|
||||
}
|
||||
|
||||
impl AliasValidator {
|
||||
pub fn new(banned_substrings: Vec<String>) -> Self {
|
||||
let banned_substrings = banned_substrings
|
||||
.iter()
|
||||
.map(|string| string.to_lowercase())
|
||||
.collect();
|
||||
|
||||
AliasValidator { banned_substrings }
|
||||
}
|
||||
|
||||
pub fn validate(&self, alias: &str) -> Result<(), ValidatorError> {
|
||||
let lowercase_alias = alias.to_lowercase();
|
||||
|
||||
for banned_word in self.banned_substrings.iter() {
|
||||
if lowercase_alias.contains(banned_word) {
|
||||
return Err(ValidatorError::Forbidden(
|
||||
alias.to_owned(),
|
||||
banned_word.to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ValidatorError {
|
||||
Forbidden(String, String),
|
||||
}
|
||||
|
||||
impl Display for ValidatorError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Forbidden(name, _) => write!(
|
||||
formatter,
|
||||
"Character name \"{}\" contains a banned word",
|
||||
name
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn multiple_matches() {
|
||||
let banned_substrings = vec!["bad".to_owned(), "worse".to_owned()];
|
||||
let validator = AliasValidator::new(banned_substrings);
|
||||
|
||||
let bad_alias = "Badplayery Mc WorsePlayeryFace";
|
||||
let result = validator.validate(bad_alias);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(ValidatorError::Forbidden(
|
||||
bad_alias.to_owned(),
|
||||
"bad".to_owned()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_lowercase_match() {
|
||||
let banned_substrings = vec!["blue".to_owned()];
|
||||
let validator = AliasValidator::new(banned_substrings);
|
||||
|
||||
let bad_alias = "blueName";
|
||||
let result = validator.validate(bad_alias);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(ValidatorError::Forbidden(
|
||||
bad_alias.to_owned(),
|
||||
"blue".to_owned()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_case_insensitive_match() {
|
||||
let banned_substrings = vec!["GrEEn".to_owned()];
|
||||
let validator = AliasValidator::new(banned_substrings);
|
||||
|
||||
let bad_alias = "gReenName";
|
||||
let result = validator.validate(bad_alias);
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(ValidatorError::Forbidden(
|
||||
bad_alias.to_owned(),
|
||||
"green".to_owned()
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mp_matches() {
|
||||
let banned_substrings = vec!["orange".to_owned()];
|
||||
let validator = AliasValidator::new(banned_substrings);
|
||||
|
||||
let good_alias = "ReasonableName";
|
||||
let result = validator.validate(good_alias);
|
||||
|
||||
assert_eq!(result, Ok(()));
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#![allow(clippy::option_map_unit_fn)]
|
||||
#![feature(drain_filter, option_zip)]
|
||||
|
||||
pub mod alias_validator;
|
||||
pub mod auth_provider;
|
||||
pub mod chunk_generator;
|
||||
pub mod client;
|
||||
@ -20,6 +21,7 @@ pub mod sys;
|
||||
pub use crate::{error::Error, events::Event, input::Input, settings::ServerSettings};
|
||||
|
||||
use crate::{
|
||||
alias_validator::AliasValidator,
|
||||
auth_provider::AuthProvider,
|
||||
chunk_generator::ChunkGenerator,
|
||||
client::{Client, RegionSubscription},
|
||||
@ -137,6 +139,30 @@ impl Server {
|
||||
state.ecs_mut().register::<RegionSubscription>();
|
||||
state.ecs_mut().register::<Client>();
|
||||
|
||||
//Alias validator
|
||||
let banned_words_paths = &settings.banned_words_files;
|
||||
let mut banned_words = Vec::new();
|
||||
for path in banned_words_paths {
|
||||
let mut list = match std::fs::File::open(&path) {
|
||||
Ok(file) => match ron::de::from_reader(&file) {
|
||||
Ok(vec) => vec,
|
||||
Err(error) => {
|
||||
tracing::warn!(?error, ?file, "Couldn't deserialize banned words file");
|
||||
return Err(Error::Other(error.to_string()));
|
||||
},
|
||||
},
|
||||
Err(error) => {
|
||||
tracing::warn!(?error, ?path, "couldn't open banned words file");
|
||||
return Err(Error::Other(error.to_string()));
|
||||
},
|
||||
};
|
||||
banned_words.append(&mut list);
|
||||
}
|
||||
let banned_words_count = banned_words.len();
|
||||
tracing::debug!(?banned_words_count);
|
||||
tracing::trace!(?banned_words);
|
||||
state.ecs_mut().insert(AliasValidator::new(banned_words));
|
||||
|
||||
#[cfg(feature = "worldgen")]
|
||||
let world = World::generate(settings.world_seed, WorldOpts {
|
||||
seed_elements: true,
|
||||
|
@ -25,6 +25,7 @@ pub struct ServerSettings {
|
||||
pub map_file: Option<FileOpts>,
|
||||
pub persistence_db_dir: String,
|
||||
pub max_view_distance: Option<u32>,
|
||||
pub banned_words_files: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for ServerSettings {
|
||||
@ -63,6 +64,7 @@ impl Default for ServerSettings {
|
||||
whitelist: Vec::new(),
|
||||
persistence_db_dir: "saves".to_owned(),
|
||||
max_view_distance: Some(30),
|
||||
banned_words_files: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::SysTimer;
|
||||
use crate::{
|
||||
auth_provider::AuthProvider, client::Client, persistence::character::CharacterLoader,
|
||||
ServerSettings, CLIENT_TIMEOUT,
|
||||
alias_validator::AliasValidator, auth_provider::AuthProvider, client::Client,
|
||||
persistence::character::CharacterLoader, ServerSettings, CLIENT_TIMEOUT,
|
||||
};
|
||||
use common::{
|
||||
comp::{
|
||||
@ -55,6 +55,7 @@ impl Sys {
|
||||
players: &mut WriteStorage<'_, Player>,
|
||||
controllers: &mut WriteStorage<'_, Controller>,
|
||||
settings: &Read<'_, ServerSettings>,
|
||||
alias_validator: &ReadExpect<'_, AliasValidator>,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
loop {
|
||||
let msg = client.recv().await?;
|
||||
@ -347,7 +348,14 @@ impl Sys {
|
||||
}
|
||||
},
|
||||
ClientMsg::CreateCharacter { alias, tool, body } => {
|
||||
if let Some(player) = players.get(entity) {
|
||||
if let Err(error) = alias_validator.validate(&alias) {
|
||||
tracing::debug!(
|
||||
?error,
|
||||
?alias,
|
||||
"denied alias as it contained a banned word"
|
||||
);
|
||||
client.notify(ServerMsg::CharacterActionError(error.to_string()));
|
||||
} else if let Some(player) = players.get(entity) {
|
||||
character_loader.create_character(
|
||||
entity,
|
||||
player.uuid().to_string(),
|
||||
@ -413,6 +421,7 @@ impl<'a> System<'a> for Sys {
|
||||
WriteStorage<'a, Client>,
|
||||
WriteStorage<'a, Controller>,
|
||||
Read<'a, ServerSettings>,
|
||||
ReadExpect<'a, AliasValidator>,
|
||||
);
|
||||
|
||||
#[allow(clippy::match_ref_pats)] // TODO: Pending review in #587
|
||||
@ -443,6 +452,7 @@ impl<'a> System<'a> for Sys {
|
||||
mut clients,
|
||||
mut controllers,
|
||||
settings,
|
||||
alias_validator,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
timer.start();
|
||||
@ -502,6 +512,7 @@ impl<'a> System<'a> for Sys {
|
||||
&mut players,
|
||||
&mut controllers,
|
||||
&settings,
|
||||
&alias_validator,
|
||||
).fuse() => err,
|
||||
)
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user